我在一个Physical AI的Demo项目里被卡了整整一周:一台AGV小车,一个USB摄像头,后端用云端GPU做障碍物识别。网络一抖动,车就急刹;网络一断,车直接原地宕机。后来我把视觉模型从云端推到边缘,跑在Jetson Orin Nano上,平均延迟从320ms降到41ms,断网时系统也能靠纯本地推理维持运行。这篇文章就是那次迁移的完整记录。如果你正在做机器人、无人车、工业质检这类“必须和物理世界实时交互”的系统,并且被云端推理的延迟和断网问题折磨,这篇入门实战值得看完。
我会从“为什么必须做边缘化”讲起,接着聊小参数视觉模型的选型、Jetson上的完整部署链路、INT8量化加速,再讲边缘优先架构怎么同时解决延迟和断网两个问题,最后附上实测数据和我踩过的坑。全程不会有太多花哨理论,尽量是能直接抄作业的东西。
1. 云端推理的三大死穴:延迟、断网和带宽税
1.1 那50毫秒的延迟,足够撞上货架
很多刚接触Physical AI的人会问:云端的GPU那么强,为什么还要把模型跑到边缘?我的回答很直接:物理世界不等网络。
先拆一下云端推理的完整链路。摄像头采集一帧图像,先做编码压缩,通过Wi-Fi或4G/5G上传到云端GPU,云端跑一次模型推理,把结果序列化传回来,边缘设备解析结果再过给执行机构。每一步都有看得见和看不见的开销。即便实验室里的5G网络非常理想,公网RTT也要10到20ms;一旦经过弱网、基站切换、路由器拥塞,端到端延迟冲到150ms以上是家常便饭。
更可怕的是延迟的不确定性。做控制系统的人都知道,固定100ms延迟可以补偿,但要是延迟在60ms到300ms之间随机跳动,控制器的稳定性会大打折扣。我当时的AGV小车速度是0.8m/s,300ms延迟意味着它已经走了24cm。这不光躲不过障碍物,反而可能一头撞进货架。
1.2 断网不是故障,是运行条件
很多项目方案书里默认网络“基本可用”,但真正跑到现场就会发现,断网不是一个If,而是When。产线角落里信号被金属机架屏蔽、农业大棚里运营商信号时有时无、地下车库直接没网——这些场景我都见过。
云端推理一旦断网,整个系统就是睁眼瞎。最尴尬的是恢复网络的那几秒,设备要先重连、再补传帧、然后重新推理,系统状态有一个明显的真空期。对一台正在作业的AGV来说,这种真空期就是安全隐患。
所以在Physical AI里,我应该把“断网”理解为一种正常的工作条件,而不是异常故障。边缘端必须至少保留最低限度的自主决策能力,云端的连接可以断,但感知和判断不能断。
1.3 隐私与带宽:被忽略的隐形账单
除了延迟和稳定性,云端推理还有一笔隐性成本:带宽和存储。
如果一台设备有4路1080p摄像头,每路每秒2Mbps码流,7x24小时往云端传,一个月下来是近2TB的流量。这还只是一台设备。工厂里20台设备,流量费、存储费、回看费用直接爆炸。更不用说很多项目有数据合规要求,视频不能出园区。为了隐私保护,只能在园区内部署一台服务器,那其实也是私有化边缘,和“上云”的距离很远。
所以我们说的“把视觉模型推到边缘”,本质上是在延迟、可用性和经济性三个维度上作出更务实的选择。云端不是被淘汰,而是退到它该待的位置:训练、聚合、冷数据存储和复杂全局决策。
2. 模型瘦身决策:不是所有视觉模型都适合边缘
2.1 别被大模型叙事绑架
Physical AI的常见视觉任务,无非是目标检测、实例分割、姿态估计、异常分类。这类任务未必需要几十亿参数的模型。开源社区的YOLOv8n、YOLOv8s、RTMDet-tiny、MobileNetV3-SSD、EfficientDet-Lite等小参数模型,在COCO类别的检测精度上已经能覆盖大多数工业场景。
我见过不少团队一上来就想在Jetson上跑YOLOv8x甚至更大规模的模型,结果帧率只有个位数,要不就是显存不够。真没必要。做Physical AI部署,第一课就是“用最小的模型满足业务约束”,而不是“把SOTA模型塞进设备里证明技术实力”。
小参数模型的好处不只是快,还包括内存占用低、启动加载快、功耗低。Orin Nano这种设备可以长期在10W-25W功耗档位下运行,这一点对电池供电的移动机器人非常关键。
2.2 一张选型表帮你少走弯路
我把我实测过的几个常用模型整理成了对照表,按“Jetson Orin Nano 8GB,TensorRT FP16,输入640x640”这一档来算,帧率是近似值,实际会有浮动:
| 模型 | 参数量 | COCO mAP50-95(约) | 实测帧率 | 适合场景 |
|---|---|---|---|---|
| YOLOv8n | 3.2M | 37.3 | 90-110 FPS | 轻量实时检测,边缘最佳入门 |
| YOLOv8s | 11.2M | 44.9 | 55-70 FPS | 精度更高,算力富余时可上 |
| RTMDet-tiny | 4.8M | 41.0 | 75-90 FPS | 高分辨率输入,小目标场景 |
| MobileNetV3-SSD | 5.6M | 22.0左右 | 120+ FPS | 极致性能要求,检测类别少 |
| EfficientDet-Lite3 | 8.4M | 33.0左右 | 60-80 FPS | 端侧部署,与TFLite生态兼容 |
这个表不是让你背数字,而是告诉你一个规律:在边缘侧,检测器参数量在3M到10M之间是一个甜点区。再小的模型,精度损失严重;再大的模型,边际收益低于算力开销。真正上线前,一定要用自己的业务数据重新评测,COCO精度只能作为参考。
2.3 先跑通再优化,不要一上来就上TensorRT
我见过一个很常见的失误:拿到Jetson后第一件事就装TensorRT,直接把YOLOv8的pt文件丢进去导出engine,结果跑出来的检测框全乱了,然后开始怀疑硬件有问题。
正确的顺序是:先用原生PyTorch在桌面环境确认模型权重在你的业务数据上没问题,然后导出ONNX,再转TensorRT。每一步都做一次全流程评估。如果PyTorch阶段精度就不满足,后面再怎么量化、剪枝都白搭。
我在项目中会专门留一个“精度回归脚本”,准备500张有代表性的真实场景图,跑推理后算mAP或业务指标(比如漏检率)。从PyTorch到ONNX,从ONNX到FP16,从FP16到INT8,每一步都跑一遍这500张图。只有指标没有明显恶化,才继续往前走。这个习惯帮我排掉了不少看着像是“玄学”的问题。
3. 边缘部署全流程:以Jetson Orin Nano跑通YOLOv8n为例
3.1 硬件与软件栈:为什么选Orin Nano
Jetson Orin Nano是目前物理AI入门非常合适的平台之一。它有1024个CUDA核心、32个Tensor Core,8GB显存版本能够轻松吃下YOLOv8n这类模型,接口齐全,CSI相机、GPIO、CAN、Ethernet都有,官方JetPack SDK对传感器、多媒体、推理库支持得很完整。
入门阶段建议直接用官方SDK Manager刷机,选择JetPack 6.0或者相对稳定的5.1.2版本。刷完系统后,需要安装几个核心组件:
# 更新系统并安装pip环境 sudo apt update && sudo apt upgrade -y sudo apt install python3-pip python3-dev -y pip3 install --upgrade pip # 安装ultralytics标签库,便于训练和导出 pip3 install ultralytics # 安装TensorRT自带的onnxgraphsurgeon工具(JetPack已内置)注意PyTorch在Jetson上不是通过pip直接装的,要用NVIDIA官方提供的PyTorch wheel,或者直接使用JetPack自带的容器镜像。否则装了一个CPU版,白白浪费CUDA算力。
3.2 从PyTorch到TensorRT:一条经典导出链路
我自己常用的链路:ultralytics训练或下载的YOLOv8n.pt -> ONNX -> TensorRT engine。
先导出ONNX:
yolo export model=yolov8n.pt format=onnx opset=12 simplify=True然后使用TensorRT自带的trtexec转成engine。如果你希望使用INT8量化,需要准备一个校准数据集,通常几百到几千张即可,但必须和业务场景同分布。
# FP16版本 trtexec --onnx=yolov8n.onnx --saveEngine=yolov8n_fp16.engine --fp16 # INT8版本,需要指定校准缓存 trtexec --onnx=yolov8n.onnx --saveEngine=yolov8n_int8.engine \ --int8 --calib=/path/to/calib_cache这里有一个很容易踩的坑:trtexec生成的engine绑定的是当前的GPU架构和TensorRT版本,换一台设备或者升级JetPack之后不能直接复用。所以你部署到多台设备时,要么每台设备各自生成engine,要么用容器锁定版本,否则系统里会静默出现“Engine could not be loaded”的报错。
3.3 运行时优化:把硬件真正用起来
很多人以为导出engine就完事了,其实运行时还有一堆可以榨干的点。
第一,图像预处理要尽量和TensorRT并行。resize、归一化、letterbox这些操作如果都放在CPU上,每帧会白白增加几毫秒到十几毫秒。可以用Jetson的GPU算子或者CUDA预处理,把HWC转CHW、归一化都合并到一次核函数里。实测下来,预处理从CPU版12ms降到GPU版2ms。
第二,开启多线程和流。TensorRT是异步的,可以在多路摄像头场景里同时提交多个推理任务。一个小技巧是把enqueue和fetch放在不同线程里,等待结果期间CPU可以处理业务逻辑或控制指令。
第三,如果要用DLA(Deep Learning Accelerator),务必确认你的模型算子都被DLA支持。YOLOv8里有不少不支持的层,最终部分算子还是会落到GPU跑,整体收益有限。入门阶段先不用折腾DLA,把FP16或INT8的TensorRT跑顺就已经能解决大部分速度问题。
部署完成后,用TensorRT自带的Python绑定做个简单耗时测试:
import pycuda.autoinit import tensorrt as trt import numpy as np # 简单测试脚本,省略engine加载细节 # ... # 统计1000次推理的时间分布 # 预期结果:INT8 engine平均约36ms,P95约40ms这里提醒一下:Jetson设备有CPU和GPU共享内存的架构特点,大模型推理时显存容易溢出。别一次性开太多worker线程,先压测不同并发下的稳定性,再定生产参数。
4. 边缘优先架构:延迟与断网的双重解法
4.1 “边缘实时决策,云端异步聚合”的拆分思路
用一句话概括边缘优先架构的核心:把模型从云端推到边缘,并不是彻底抛弃云端,而是重新划分职责。
在AGV项目里,我最终做的方案是:Jetson边缘端运行YOLOv8n的TensorRT engine,负责每一帧目标检测和测距决策,结果直接传给下位机控制单元;云端负责模型版本管理、自动标注数据、定期聚合更新模型。网络正常时,边缘端会异步把抽帧后的低分辨率图像和检测结果加密上传;断网时,这些数据先存在本地缓存,等网络恢复再补传。
这个架构的好处是,即使云端完全不可达,边缘设备也能独立完成业务闭环。云端从“实时推理中心”降级为“训练和运维中枢”,压力和成本也随之下降。
4.2 断网时的本地缓存与降级策略
断网不是只有“网络断开”一种表象,也可能是信号弱导致丢包率升高。这时候如果边缘设备还按照完整帧率做推理,算力可能不够,所以需要一套可调节的降级策略。
我实践中比较有效的方案是:引入滑动窗口滤波器来处理检测结果的时序不稳。具体做法是维护一个长度为5到10帧的检测结果缓存,只有当某个目标连续在M帧中出现,才认为它是稳定目标;一旦目标消失,也要连续N帧后才判定为离开。这个策略能过滤掉单帧误检和闪烁,但同时会引入一点输出延迟。针对不同任务要调节窗口大小,比如AGV前向避障我用的是3帧确认,货物定位用的是5帧确认。
边缘端的帧率也可以动态调节。网络差的时候,把推理帧率从30FPS降到10FPS,CPU和GPU负载降低,发热减少,能够延长电池续航。如果边缘端完全暂停不了,还有一种做法是“安全停驶策略”:连续丢失检测结果的时间超过阈值,系统主动减速并停在安全位置,而不是继续乱跑。
4.3 多节点协同:边缘去重与结果聚合
当场景里有多个摄像头或多台机器人同时看到同一个目标时,每个边缘节点会独立给出检测框和置信度。如果不做处理,上层调度平台会看到一个目标被重复上报很多次,影响路径规划和任务调度。
入门阶段建议先做一个简单的“时间窗去重”:给每个检测目标加一个tracking ID,只在上层汇总时保留置信度最高或最近一次的记录。更进一步的话,可以在多个边缘节点的检测结果上做加权融合,本质上就是边缘高斯聚合的思路——每个节点给出置信度作为高斯权重,对一些篡改或偏移大的结果做鲁棒处理。目前业界也有用边缘引导注意力模块来处理多源视觉融合的方案,不过这块已经超出入门范围,先掌握时间窗和加权融合就够了。
这种架构的价值不只是应对断网,它还能降低单点故障的影响。一台边缘节点宕机,不影响其他节点;一台摄像头离线,会有相邻的节点视野做兜底。对Physical AI这种强依赖感知可靠性的系统,这个优势比延迟降低更重要。
5. 实测数据与避坑清单:一次AGV避障迁移复盘
5.1 同一段测试序列的延迟对比
我拿了一段包含仓库货架、人员走动、叉车经过的测试视频,总共1000帧,对三种方案做了延迟统计。云端方案走的是4G公网,GPU用的是云厂商推理实例;边缘方案分别是FP16和INT8的TensorRT engine。结果如下:
| 方案 | 平均端到端延迟 | P95延迟 | 断网时是否可用 | 每帧数据量 |
|---|---|---|---|---|
| 云端GPU(4G公网) | 318ms | 542ms | 否 | 上传原始帧+结果下载 |
| 边缘FP16 | 62ms | 71ms | 是 | 仅上传抽帧结果 |
| 边缘INT8 | 36ms | 40ms | 是 | 仅上传抽帧结果 |
这个数据很有说服力。INT8的延迟只有云端的九分之一,而且由于推理在本地完成,网络抖动对端到端延迟几乎零影响。代价是INT8模型在夜间暗光环境下漏检率比FP16高了约2.4%,需要通过增加补光灯和优化校准集来弥补。
5.2 我踩过的四个坑,每个都是真实教训
第一个坑是预处理成为瓶颈。刚开始部署时,我把图像预处理放在CPU上做letterbox和归一化,导致整体帧率只有12FPS。后来把图像处理改成GPU上的cuda算子,帧率直接翻倍。别小看预处理,在低算力设备上它可能吃掉一半的算力。
第二个坑是INT8量化时校准集和实际场景分布不一致。我用白天仓库的500张图片做校准集,结果夜间运行时检测框明显变飘。后来重新采集了包含夜间、逆光、暗角等场景的1000张图,重新校准后才恢复。校准集质量几乎决定了INT8模型的实际表现。
第三个坑是TensorRT engine和自定义CUDA上下文打架。我在引擎初始化和推理时用了显式的CUDA stream,偶尔会出现“Misaligned address”的崩溃,折腾很久才发现是共享内存的兼容问题。解决方法是统一使用torch.cuda.stream或者推断引擎自带的stream,不要混用两套上下文。
第四个坑是断网恢复后,云端老任务和边缘新任务冲突。网络恢复时,云端会立刻下发一批旧的检测结果和控制指令,如果边缘端没有做仲裁,机器人会执行“过期的指令”。所以一定要在边缘端加一层指令时间戳校验,只执行时间窗口内的指令,比云端优先级更高的还是要以本地为准。
5.3 下一步:从单机到多机
单机边缘部署跑通之后,我建议你再往两个方向扩展。一是把边缘设备接入车规级或工业级服务网关,统一管理远程固件升级、日志回传和模型热更新;二是搭建一个简单的模型版本管理服务,让云端训练好的新模型可以推送到边缘设备,并支持灰度发布。这样系统就从一个Demo变成了一套可长期维护的边缘AI系统。
最后的体感
真要我说一句实在话:把视觉模型从云端推到边缘,不是技术上的倒退,而是从演示原型走向真实产品之间必须偿还的工程债。延迟和断网这两个问题,表面看是网络环境差,实质上是架构设计没有尊重物理世界的节奏。边缘设备再弱,只要它能在本地完成关键决策,就是系统里最可信赖的一块基石。我到现在仍然会习惯性给每个新项目先问一句:如果网络下一秒就断了,这套系统还能不能正常干活?这个问题逼出了很多隐藏的脆弱点,也帮我省下了不少半夜去现场救火的麻烦。