ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

无人机与机器人端侧深度学习优化:从算力瓶颈到部署实战

无人机与机器人端侧深度学习优化:从算力瓶颈到部署实战 我最近和赵开勇聊了一个下午主题只有一件事无人机和机器人上的深度学习到底该怎么优化。这个问题被问到的频率几乎和“飞行平台怎么选”一样高。做算法的人说模型在服务器上测得很准做嵌入式的人说板子一跑就发热降频做控制的人说感知输出抖得厉害根本不敢接进环。最后项目卡在“原型能跑产品不能用”的尴尬阶段。这篇就把这次专访里的核心观点整理出来再结合我自己的实战体会从高性能计算、深度学习、嵌入式部署几个角度把无人机和机器人开发中的优化思路讲透。适合正好在折腾Jetson、RK3588这类端侧平台的开发者也适合算法转部署、控制转AI的跨界选手。1. 先搞清楚无人机和机器人上的深度学习难点到底在哪1.1 算力墙与功耗墙为什么高性能计算在这里不是“堆显卡”赵开勇一上来就说很多人对高性能计算的理解还停留在数据中心的GPU服务器集群上这个观念放到无人机和机器人领域会出大问题。数据中心优化追求的是吞吐量你有5块A100就上5块功耗和体积不是主要约束。但无人机和机器人的计算平台第一约束是“背着上天”或者“带着跑路”的能力。以常见的Jetson Orin NX为例整块模组的功耗在10W到25W之间性能释放和散热直接相关。而一张桌面级GPU的功耗动辄300W起这中间差了十几倍。小型无人机的整机功耗预算可能只有100W左右飞控、电调、图传、云台都要分一杯羹留给深度学习的功率余量往往只有十几瓦。你要在十几瓦里面跑出一个实时可靠的感知结果这就是典型的“算力墙加功耗墙”双重约束。所以赵开勇强调无人机和机器人领域的高性能计算研究的核心不是峰值算力而是能效比和算力利用率。一台落后芯片如果能把利用率跑到90%以上实际效果可能比一台强芯片只跑到20%利用率更好。很多时候项目卡住不是芯片不行而是代码压根没有把芯片喂饱GPU利用率低、CPU与GPU之间频繁拷贝、内存带宽被浪费这些才是真正的敌人。1.2 实时性不是“快”而是“稳”在服务器上做深度学习推理一帧图片处理200毫秒还是400毫秒看起来只是体验问题。到了无人机和机器人这里这个问题变成了安全问题和稳定性问题。飞行器的姿态控制通常在1000Hz左右运行感知系统不需要这么快但姿态环要的感知结果必须“按时到达”。避障和路径规划往往在10Hz到30Hz之间一旦感知延迟从30毫秒跳变到150毫秒控制环拿到的就是过期的世界状态轻则路径抖动重则撞机。赵开勇给我举了一个特别直观的例子平均延迟50毫秒的感知系统P99延迟却到了200毫秒那这个系统在绝大多数时间里表现正常但每100帧里就有1帧“卡顿”。对于一台以10Hz运行的决策系统这1帧异常延迟会直接导致决策跳变可能刚好发生在贴近障碍物的时候。所以他说做嵌入式深度学习优化一定要建立这样一个习惯不只看平均耗时还要统计P95、P99甚至观察耗时分布直方图。这种“实时性等于稳定性”的思路和传统互联网后端说的SLA延迟目标非常像。你需要把深度学习推理当作一个必须满足截止时间的“实时任务”来管理而不是当作一个尽力而为的普通计算任务。后续所有优化手段包括模型压缩、算子融合、显存管理、线程调度其实都在围绕“降低延迟峰值”和“保证时间段内的确定性”展开。1.3 精度与速度的平衡一切优化的最终约束深度学习模型天然有一个精度指标检测任务看mAP分割任务看mIoU分类任务看Top-1 Accuracy。但部署到无人机和机器人上之后精度指标不能单独看必须和速度、功耗、稳定性放在一起看。赵开勇的观点很直接“优化不是把模型做得越准越好而是把模型做到刚好满足任务需求同时把资源占用压到最低。”这里有个很关键的词叫“任务需求精度”。比如一个农业植保无人机的作物检测任务可能只需要分辨出作物行和杂草区域0.5米的误差完全在可接受范围那就没必要用一个大模型。相反一个用于电力巡检的无人机可能需要识别毫米级的销钉缺陷阈值就得定得很高。所以他的建议是在项目开始前先和算法团队、业务团队一起把“可接受精度下限”写清楚把它当作优化工作的锚点。没有这个锚点优化过程会变成无休止的“再提一点精度”最后板子跑不动项目也黄了。精度、速度、功耗、稳定性这四个维度在无人机和机器人场景下互相牵扯。你压缩模型速度提升了但精度可能掉你开启INT8量化功耗降了但某些层误差放大你为了稳定性固定推理引擎的算子策略可能放弃了动态shape带来的灵活性。赵开勇说高手和普通开发者的区别不是懂得多少花哨技巧而是能在这些矛盾指标之间根据实际场景找到那个可接受的平衡点。2. 从模型到硬件一套完整的端侧深度学习优化路线2.1 优化不是单点作战而是链路协同很多工程师一上来就想着换模型YOLOv5不行换YOLOv8YOLOv8不行再换RT-DETR。赵开勇觉得这种思路太浪费了。他说一次完整的工程优化至少应该覆盖四个层面模型层面、推理引擎层面、算子与指令集层面、系统调度与硬件资源层面。只改其中一个层面收益通常有限真正可观的性能提升来自几个层面的协同。打个比方如果把深度学习推理比作一家餐厅出餐模型结构决定菜谱推理引擎决定后厨流程算子和指令集决定厨师的手速系统调度决定服务员和传菜通道的配合。你只把菜谱改简单了但后厨流程混乱、传菜通道拥堵出餐速度依然上不去。实际表现就是模型FLOPs降了一大截端侧跑起来却没快多少原因就在其他环节成了新瓶颈。所以赵开勇推荐的优化路径是“从基线开始逐层找瓶颈”。先用最常规的部署流程把一个能跑通的模型放到板子上测出基线性能然后用Profiling工具像Nsight Systems、Perfetto看时间到底花在哪一层。如果发现GPU Kernel只占了30%时间剩下都在数据拷贝和后处理那你去压缩模型根本没有意义正确动作应该是优化预处理管线。先找准瓶颈再动用对应工具这是整套优化路线的第一步。2.2 模型压缩剪枝、量化、蒸馏怎么选模型压缩是端侧深度学习部署的常规操作常见手段有剪枝、量化、知识蒸馏但很多开发者对怎么选、怎么配参数比较头疼。赵开勇给了一个很实用的判断框架先看硬件支持什么再看任务精度余量有多少最后再看团队的部署调试能力。剪枝适合模型结构冗余度较高的场景。比如你从YOLOv5m换成YOLOv5s后精度还是超了这时候可以尝试结构化剪枝。结构化剪枝会把不重要的通道或层直接删掉压缩后的模型在硬件上有实际加速效果。关键参数包括剪枝比例、粒度通道/层和重训练策略。我个人踩过坑一上来就把剪枝比例拉到0.5结果精度掉了8个点模型直接废了。后来学乖了从0.2到0.3小步加每剪一次重训练几十个epoch观察回稳情况。不同层的敏感度不一样像检测头里的通道比Backbone敏感得多剪的时候最好分组实验。量化是端侧部署收益最明显的一招。FP32转FP16通常几乎无损INT8则可能带来1%到2%甚至更高的精度损失具体取决于模型和校准数据。INT8量化最关键的参数是校准集用来统计每层激活值的分布从而确定量化范围。校准集尽量贴近真实场景最好有几百到上千张覆盖各种光照、角度、目标形态的图片。如果量化后精度掉得厉害优先检查是不是某些算子对量化不友好比如SiLU激活在部分硬件上量化损失就比ReLU明显。知识蒸馏适合你有一个精度不错的“教师模型”但学生模型怎么缩都缩不回来精度的场景。赵开勇的观点是蒸馏不是简单的让输出对齐还要考虑中间层特征的对齐。实际操作用得比较多的有 logits蒸馏和feature蒸馏两类。Logits蒸馏实现简单feature蒸馏效果上限高但训练代码复杂度也会上几个台阶。我的经验是小项目先试logits蒸馏配上温度参数TT取3到5之间通常效果不错如果还不够再考虑feature蒸馏。2.3 编译与推理引擎TensorRT/ONNX Runtime怎么用模型压缩做完之后下一步就是通过推理引擎把性能压榨出来。在NVIDIA平台上TensorRT几乎是绕不过去的工具。它会把模型结构解析成计算图然后对可融合的算子做层融合、精度校准、内核自动调优生成高度优化过的推理引擎。一个典型的TensorRT部署流程大概是先把PyTorch模型导出成ONNX再用trtexec或者TensorRT Python API读取ONNX并构建engine构建时根据需求选择FP32、FP16或INT8精度最后用生成的engine做推理。这里需要特别注意动态shape的问题。如果输入尺寸会变化需要配置动态维度和优化范围但动态shape可能导致引擎在运行时重新选择tactic造成延迟抖动。赵开勇特别提到如果任务输入尺寸基本固定比如无人机航拍检测的输入就是640x640那最好固定shape把运行期的不确定性降到最低。ONNX Runtime在非NVIDIA平台上用得更多比如瑞芯微、地平线、晶晨这些平台。ONNX Runtime支持CPU、CUDA、TensorRT等多种执行后端切换执行后端往往只需要改一行配置适合快速验证。但它的算子融合能力和极致性能优化通常不如各家厂家自己提供的runtime比如TensorRT和RKNN的差距还是存在的。所以我的建议是先用ONNX Runtime做性能基线摸底再切到平台的原生推理栈做深度优化两条腿走路。2.4 算子级优化和网络结构选择当模型和推理引擎都定了还可以往下一层看算子和网络结构。赵开勇说很多开发者选网络只看精度排行榜忽略了某些结构在端侧硬件上天然吃亏。比如常规卷积和深度可分离卷积在不同硬件上的加速比差异很大有些轻量化网络在GPU上跑得快到了某些NPU上反而被反超。原因是不同硬件对内存访问模式、卷积实现方式的支持不同。所以选网络结构一定要结合目标平台实测不要只看论文里的FLOPs。如果确实需要自己改网络结构可以关注几个点一是减少使用对硬件不友好的算子比如动态卷积、某些自定义算子它们往往会导致推理引擎无法做层融合二是尽量用标准卷积、标准归一化、标准激活这样导出的ONNX能被更高效率地解析和优化三是注意张量形状和内存排布尽量让张量在内存中连续减少拷贝和转置。这些细节在单帧推理中可能只差几毫秒但在一秒钟要处理几十帧的实时系统里差距就会被放大到不可忽视的程度。3. 训练侧的高性能计算让模型在源头就“适合部署”3.1 数据准备与合成数据别忽略“数据计算”这件事赵开勇反复强调一个观点“训练侧的高性能计算不只发生在GPU上。”数据管线如果设计得不好GPU再强也白搭。很多开源训练脚本默认用单线程读图、在线解码、随机裁剪在一个数据量大的数据集上GPU会频繁处于等待状态整体吞吐被数据供给卡住。我自己的经验是训练管线至少要保证“CPU负责取数GPU负责计算”的流水线不中断。PyTorch里面设置DataLoader的num_workers、prefetch_factor开启pin_memory都是很基础但很有效的手段。更进一步的方案是先把所有图片预处理成内存映射格式比如TFRecord或者WebDataset减少小文件随机读取对文件系统的压力。如果训练数据里包含大量合成图像还可以直接把部分增强操作在数据导出时提前做掉相当于“把计算从训练循环里挪出去”。合成数据在无人机和机器人领域越来越重要但赵开勇泼了一盆冷水合成数据最大的问题不是“不像”而是“太干净”。如果你在仿真环境里生成一堆理想光照、理想纹理的图片模型在仿真里精度很高一到真实世界的逆光、雨雾、运动模糊场景就崩。他建议在合成阶段就加入域随机化随机光照方向、随机纹理贴图、随机天气粒子、随机相机畸变尽量让模型在训练阶段就见过“不理想”的世界。3.2 混合精度训练与分布式训练高性能计算的基本功训练侧的高性能计算最典型的两个关键词就是混合精度训练和分布式训练。混合精度训练利用GPU的Tensor Core能力用FP16做前向和梯度计算用FP32做主权重更新。这里的核心技巧是Loss Scaling因为FP16能表示的数值范围比FP32小很多梯度值过小会直接变成0所以需要把Loss放大若干倍完成梯度回传后再缩小回来。PyTorch的AMPAutomatic Mixed Precision已经把这些封装好了GradScaler会自动处理缩放逻辑。分布式训练在无人机和机器人领域不像大语言模型那样动辄上千卡但也非常常见。比如你在公司服务器上用4卡甚至8卡训练一个视觉模型用DistributedDataParallelDDP就能得到接近线性的加速比。使用DDP时需要注意学习率缩放数据并行会让全局Batch Size变大如果不相应调大学习率收敛速度会显著变慢。一个常见做法是线性缩放规则比如单卡Batch Size为32时学习率是0.014卡后全局Batch Size变成128学习率可以对应调整到0.04附近再配合warmup缓解早期不稳定。赵开勇给了一个特别提醒不是所有模型都适合盲目开混合精度和分布式。如果你的模型里有很多对数值范围敏感的算子或者数据量很小AMP可能带来训练不稳定。他开始一个新训练任务时通常先跑一个很小的实验子集对比FP32和AMP的收敛曲线确认没有异常再全量开放。分布式训练同理数据量只有几千张时单卡已经能跑完再开多卡增加同步开销反而得不偿失。3.3 Sim-to-Real仿真环境里训出来的模型怎么落地仿真训练是无人机和机器人领域躲避不开的话题。原理很简单在仿真环境里你可以拿到完美的地面真值标签可以生成各种极端场景成本远低于真实采集。但仿真和真实之间的“域差距”是最大的坑。一个在虚幻引擎里训练出的目标检测模型拿到真实户外场景里经常出现漏检、误检。赵开勇对这个问题的态度很务实“仿真不是用来替代真实数据的是用来补充真实数据覆盖不到的边界情况的。”他建议在训练策略上做两层处理。第一层仿真数据的类型要尽量贴近任务场景比如任务主要面向低空俯视视角的检测仿真里就多生成低空俯视视角的样本而不是各种花哨角度堆在一起。第二层训练完成后一定要拿一小部分真实数据做微调哪怕只有几百张也能把域差距拉回来很多。针对机器人控制类任务还有一种更“物理”的Sim-to-Real手段叫Domain Randomization在仿真里随机化机器人质量、摩擦系数、关节阻尼等物理参数。让策略在“泛化到各种物理参数”的过程中学到鲁棒的控制规律。这样迁移到真实机器人上时即使真实物理参数和仿真设定有偏差策略也不会崩。赵开勇说投入产出比最高的做法是把物理参数随机化范围设置到真实系统参数的大致区间内而不是随机到离谱的边界。4. 端侧部署实战从算法到飞控/机器人系统的集成4.1 典型硬件平台选型与适配端侧深度学习平台选型赵开勇给出的建议很明确先定功耗再定算力然后看生态。NVIDIA Jetson系列胜在生态完善TensorRT、CUDA、cuDNN这些配套工具链比较成熟社区资料多很多算法可以直接从桌面端平移到端侧。瑞芯微、地平线等国产平台的优势是功耗和成本更低但工具链的成熟度、算子支持范围、排错资料相对弱一些适合产品形态稳定、团队有嵌入式开发经验的场景。如果只看TOPS每秒万亿次操作容易掉进营销陷阱。赵开勇说TOPS只是理论峰值实际吞吐受内存带宽、算子实现效率、数据拷贝开销的共同制约。同样标称100TOPS的两块芯片跑同一个YOLO模型实测帧率可能差出一倍。所以选型阶段他一定要求团队做“带真实模型的基准测试”用目标模型在候选板卡上跑一遍记录延迟、功耗、发热情况再决定选哪个。拿到板子后的第一件事是配置好功耗模式。NVIDIA Jetson平台可以用nvpmodel命令设置运行模式。比如Jetson Orin系列默认模式可能限制在15W跑大一点的模型有些吃力。如果功耗预算有余切到20W或25W模式性能提升会非常明显。配合jetson_clocks脚本可以把CPU/GPU频率拉满但要注意发热温度过高会触发降频性能反而可能更差。我用Orin NX时习惯先用nvpmodel定功耗档位再通过实际跑测看温度曲线找到热平衡点。4.2 管线设计感知、决策、控制怎么接力无人机和机器人的软件架构通常是一条感知-决策-控制的接力管道。感知模块跑深度学习模型输出目标位置或障碍物信息决策模块根据这些信息做路径规划或任务判断控制模块最终输出电机指令。深度学习在这条管道里只是其中一环但它的时序问题会影响全局。赵开勇分享了一个典型的接力设计思路。在Jetson平台感知线程负责抓取图像、做预处理、调用GPU推理、后处理然后以固定频率比如20Hz把结果写入一块共享内存。决策和控制线程不直接等感知结果而是以更高频率读取共享内存里的最新状态并记录时间戳。这样即使感知偶尔晚了一点控制线程也不会阻塞只是决策会基于旧数据。关键在于感知线程要保证“只写最新状态”避免因为锁等待引入额外延迟。实现上建议用多线程加锁或无锁队列数据拷贝尽可能少。常用的技巧包括用cudaMemcpyAsync把GPU上的结果异步拷回CPU用双缓冲避免CPU和GPU互相等待把后处理逻辑中的循环尽量向量化。我在一个机器人项目里把感知结果从“结构体通过队列传递”改成“固定内存地址加原子标志位更新”端到端延迟降低了5毫秒左右抖动也小了很多。这种优化不太起眼但真实系统里经常比换一个模型更见效。4.3 性能评测延迟、吞吐、功耗、抖动怎么测很多团队到项目中期才发现性能问题就是因为没有从一开始建立评测标准。赵开勇建议从拿到板子和模型的第一天起就固定一套评测流程把延迟、吞吐、功耗、温度、CPU/GPU占用率这些指标全部记录下来。之后每次改动都能和基线对比避免“优化半天不知道是变好了还是变坏了”。延迟测试不能只跑一两次。神经网络推理受到调度、缓存、频率等多种因素影响单次测量没有意义。正确做法是循环推理几百甚至上千次记录每轮耗时然后计算平均值、P50、P95、P99。我在测试TensorRT引擎时会先预热几十次让GPU进入稳定状态再开始计时避免第一次推理的初始化开销污染数据。脚本里可以用Python的time.perf_counter但更专业的做法是用Nsight Systems这样的工具抓取时间线按GPU kernel维度分析耗时。功耗测试同样重要。Jetson平台可以用tegrastats工具实时监控CPU/GPU频率、温度、功耗。长时间跑测会得到一条功耗和温度曲线如果曲线显示温度持续上升并出现频率下降说明散热设计不足即使算法优化得再好实际性能也上不去。赵开勇特别提示性能评测一定要在“热稳定状态”下测冷机和热机的推理延迟可能差出20%。先把板子跑热再记录数据这样得到的指标才贴近真实长期运行的结果。4.4 常见问题排查实录做端侧部署久了总有一些反复踩坑的经典问题。我把这次专访里聊到的几个高频问题整理成了排查表方便大家对照现象可能原因排查方向与解决办法推理偶尔卡顿延迟抖动大动态shape触发重新规划、CPU频率调度、显存碎片固定输入shape配置CPU调频策略预热显存分配GPU利用率低但整体帧率上不去数据拷贝耗时、预处理在CPU上耗时过长用CUDA预处理减少CPU-GPU拷贝用流水线并行量化后精度明显下降校准集不合适、部分算子不支持量化换校准集检查算子支持情况对敏感层保持FP16模型在仿真里好真实环境掉点域差距太大增加域随机化采集少量真实数据微调感知结果正常但控制响应很顿感知-控制之间队列阻塞或锁竞争改共享内存加时间戳降低锁粒度检查最坏延迟这些问题的共性在于表面看是“速度不够”实际往往是“瓶颈不在你以为的地方”。所以赵开勇反复强调Profiling的重要性。看到卡顿不要先猜先去抓时间线看延迟到底花在哪个环节。他用一个很形象的比喻“你生病了不会直接开药先做检查。性能优化也一样Profiling就是检查报告。”5. 从这次专访里带走的三条实战经验5.1 先量化瓶颈再谈优化这是赵开勇说得最重的一句话“不要拍脑袋优化。”很多人拿到一个速度慢的模型第一反应是换成更小的Backbone或者把输入分辨率从640降到416效果可能有一点但往往没有解决真正的问题。正确做法是先用Profiling工具跑出延迟分布把耗时占比最高的模块找出来。可能是某个自定义预处理函数跑了20毫秒也可能是后处理的NMS实现太烂还可能是内存拷贝频繁导致的等待。针对瓶颈做优化效率远比盲目压缩模型高得多。5.2 优化要按“系统视角”而不是“模型视角”推进模型只是整个系统的一部分。传感器、预处理、推理、后处理、决策、控制这个链路每一环都可能成为瓶颈。赵开勇在专访里纠正了一个错误观念“你不能只看模型FLOPs降低就觉得优化完事了。”系统视角要求你同时关注CPU负载、内存带宽、GPU利用率、功耗温度甚至线程调度策略。一个真正跑得稳的无人机感知系统是算法工程师、嵌入式工程师、控制工程师三方协同的结果。如果你只有算法背景至少要学会读Profiling工具的输出能听懂嵌入式工程师在说什么。5.3 把性能评估固化成团队日常工作流最后一条经验最容易被忽视。赵开勇强调性能优化不是一次性的项目而是持续迭代的过程。模型更新、框架升级、硬件调整任何一次改动都可能让性能回退。如果团队里没有一套自动化的性能回归测试等发现问题时往往已经浪费了几周时间。他建议把基准测试脚本和结果记录纳入代码仓库每次改动都自动跑一遍关键指标并和上次结果对比。这样优化工作才是可持续的而不是每次从零开始。我自己在这次专访后给团队定了三条硬规矩第一所有的模型改动必须附带端侧性能测试报告第二报告里必须包含延迟分布的P50和P99第三任何优化上线前必须和基线做对比精度和速度指标同时回看。最开始大家觉得麻烦但坚持几个月后项目的可预测性明显提高了那种“上线前突然发现卡顿”的救火场景少了很多。优化这件事说到底拼的不是某个灵光一现的招数而是扎扎实实的工程习惯和数据意识。
返回列表