
1. 为什么我放弃了在x86上折腾转投Jetson AGX Orin去年年底接了一个工业质检的项目需求很明确在产线边缘侧做实时目标检测识别零件表面的缺陷要求单帧推理延迟控制在30ms以内功耗不能超过60W。一开始我图省事拿了一台带GTX 1660 Ti的工控机跑YOLOv8结果功耗直接飙到200W以上机箱烫得能煎鸡蛋产线那边连散热都搞不定。后来咬咬牙上了Jetson AGX Orin 64GB版本才算把这件事落地。这篇文章不打算写成官方文档的翻译而是把我从开箱到跑通YOLOv8、再到把推理性能压到满意水平这一路上踩过的坑、试过的方案、以及最后沉淀下来的配置原原本本记录下来。如果你手里也有一块Orin或者正在犹豫要不要用边缘设备做目标检测这篇内容应该能帮你省下至少两三个通宵。Jetson AGX Orin的定位很清晰它是一块面向边缘AI的ARM架构计算模块集成了GPU、CPU、DLA深度学习加速器等多种计算单元官方标称算力可以达到275 TOPSINT8。这个数字听起来很唬人但实际能不能跑出效果很大程度上取决于你的环境配置和推理后端选择。YOLOv8作为Ultralytics推出的目标检测模型在精度和速度的平衡上做得相当不错但它在Jetson上的部署路径和x86平台完全不是一回事。我遇到的第一道坎就是Orin出厂自带的JetPack版本、CUDA版本、PyTorch版本、TensorRT版本之间有一套严格的对应关系任何一个环节版本对不上轻则报错重则直接卡死。下面我从环境配置开始把整个流程拆开讲。2. JetPack、CUDA、PyTorch三者的版本咬合关系2.1 先搞清楚Orin出厂时到底装了什么拿到Orin之后第一件事不是急着装Python包而是先确认系统里已经有什么。打开终端依次执行cat /etc/nv_tegra_release nvcc --version python3 -c import torch; print(torch.__version__) dpkg -l | grep tensorrt这几条命令分别告诉你L4TLinux for Tegra的版本号、CUDA编译器版本、当前Python环境里的PyTorch版本、以及TensorRT的安装情况。我手里这台Orin出厂预装的是JetPack 5.1.2对应L4T 35.4.1CUDA 11.4TensorRT 8.5.2。注意JetPack是一个打包概念它包含L4T、CUDA、cuDNN、TensorRT、VisionWorks等一系列组件。你看到的CUDA版本是11.4但PyTorch官方并没有为ARM架构的CUDA 11.4提供预编译wheel包这就是第一个坑。2.2 PyTorch for Jetson的安装陷阱很多教程会告诉你直接pip install torch这在Orin上基本行不通。PyTorch官方PyPI上的wheel是针对x86架构的ARM架构需要从NVIDIA的开发者论坛或者Jetson Zoo下载对应的预编译包。以JetPack 5.1.2为例你需要找的是对应Python 3.8、CUDA 11.4的PyTorch wheel。NVIDIA通常在开发者论坛的Jetson板块置顶帖里维护这些包。我当时的做法是wget https://developer.download.nvidia.com/compute/redist/jp/v512/pytorch/torch-2.1.0a041361538.nv23.06-cp38-cp38-linux_aarch64.whl pip3 install torch-2.1.0a041361538.nv23.06-cp38-cp38-linux_aarch64.whl这里有个细节文件名里的nv23.06代表NVIDIA容器版本号不同JetPack版本对应的编号不同。如果你装错了版本import torch的时候会报undefined symbol之类的错误排查起来非常痛苦。提示安装完PyTorch后务必用python3 -c import torch; print(torch.cuda.is_available())验证CUDA是否可用。如果返回False说明版本不匹配不要继续往下走。2.3 torchvision的编译安装PyTorch装好之后torchvision同样没有现成的ARM wheel。你需要从源码编译而且版本必须和PyTorch严格对应。比如PyTorch 2.1.0对应torchvision 0.16.0。编译命令大致如下git clone --branch v0.16.0 https://github.com/pytorch/vision.git cd vision export BUILD_VERSION0.16.0 python3 setup.py install --user编译过程在Orin上大概需要20到30分钟期间CPU会跑满。建议在编译前把MAX_JOBS环境变量设小一点比如export MAX_JOBS4否则Orin的散热压力会很大我有一次编译到一半直接触发了温度墙降频。2.4 版本对应关系速查表为了方便你对照我把JetPack 5.1.x和6.x的常见版本组合整理成表格JetPack版本L4T版本CUDA版本TensorRT版本推荐PyTorch版本5.1.235.4.111.48.5.22.1.05.1.335.5.011.48.5.22.1.06.036.3.012.28.6.22.3.06.136.4.012.28.6.22.4.0这张表建议截图保存因为每次重装系统或者换JetPack版本你都会用到它。3. YOLOv8在Orin上的三种推理路径对比3.1 直接用PyTorch推理方便但慢最省事的方式当然是直接用Ultralytics的Python包跑推理from ultralytics import YOLO model YOLO(yolov8n.pt) results model(test.jpg)在Orin上这种方式跑YOLOv8nnano版本大概能到15到20 FPS延迟在50ms左右。对于精度要求不高、实时性要求也不苛刻的场景这个速度勉强能用。但如果你要跑YOLOv8m或者YOLOv8l帧率会直接掉到个位数完全达不到产线要求。PyTorch推理慢的原因主要有两个一是模型没有经过图优化很多算子是以eager模式逐个执行的二是FP32精度下计算量和显存带宽占用都比较大。Orin的GPU虽然算力不错但显存带宽相比桌面级显卡还是有差距。3.2 导出ONNX再用TensorRT性能跃升的关键一步真正让Orin发挥实力的方式是走TensorRT路径。流程是PyTorch模型先导出为ONNX格式然后用TensorRT的解析器把ONNX转成TensorRT引擎最后用TensorRT的运行时执行推理。导出ONNX的命令很简单from ultralytics import YOLO model YOLO(yolov8n.pt) model.export(formatonnx, opset12, simplifyTrue)这里opset12是个经验值opset版本太高或太低都可能在TensorRT解析时出问题。simplifyTrue会调用onnx-simplifier对图做简化去掉一些冗余节点对后续转换很有帮助。导出完成后你会得到一个.onnx文件。接下来用trtexec工具把它转成TensorRT引擎/usr/src/tensorrt/bin/trtexec --onnxyolov8n.onnx --saveEngineyolov8n.engine --fp16--fp16表示用半精度浮点数进行推理这是Orin上性价比最高的精度选择。FP16相比FP32速度通常能提升1.5到2倍而精度损失在目标检测任务上几乎可以忽略。3.3 三种路径的实测数据对比我在Orin 64GB版本上用同一张1080p图片、同一个YOLOv8n模型分别测试了三种推理路径推理路径平均延迟峰值显存占用功耗PyTorch FP3252ms1.2GB38WONNX Runtime35ms0.9GB32WTensorRT FP1612ms0.6GB25W这个数据很直观TensorRT FP16路径的延迟只有PyTorch路径的四分之一不到功耗也低了不少。对于产线场景来说12ms的延迟意味着理论上可以做到80 FPS以上完全满足实时性要求。注意TensorRT引擎是跟具体的GPU架构绑定的。你在Orin上生成的engine文件不能直接拿到其他型号的Jetson上使用甚至同一型号但不同JetPack版本也可能不兼容。所以每次换环境都要重新生成。4. 环境配置中那些让我熬夜的坑4.1 pip安装opencv-python导致系统OpenCV被覆盖Orin出厂时系统里已经装了针对ARM优化的OpenCV通常是通过apt安装的。如果你习惯性地pip install opencv-pythonpip会装一个x86编译的版本虽然能import但底层调用的库不对读取摄像头或者做图像处理时会报各种奇怪的错误。正确的做法是用apt安装sudo apt-get install python3-opencv如果你确实需要pip版本的OpenCV建议在虚拟环境里操作并且安装opencv-python-headless避免和系统库冲突。4.2 numpy版本过高导致TensorRT解析失败这个问题我排查了整整一个下午。现象是用trtexec转换ONNX模型时报错说某个算子不支持。但同样的ONNX文件在x86机器上转换完全正常。后来发现是numpy版本的问题。Orin系统自带的numpy是1.19.x而我用pip升级到了1.24.x。TensorRT 8.5.2的Python绑定在解析ONNX时内部依赖numpy的某些API版本过高会导致解析器行为异常。解决方案很简单把numpy降回系统自带版本或者至少不要超过1.21。pip3 install numpy1.21.64.3 散热与功耗模式设置Orin默认的功耗模式是15W这个模式下GPU频率被压得很低推理速度只有满血状态的一半左右。你需要手动切换到MAXN模式sudo nvpmodel -m 0 sudo jetson_clocksnvpmodel -m 0表示最大性能模式jetson_clocks会把CPU和GPU频率锁定在最高档。执行完之后你可以用tegrastats查看实时功耗和温度。但这里有个矛盾MAXN模式下功耗会飙到50W以上如果你的设备散热设计不够好温度会很快冲到80度以上然后触发降频。我的做法是在Orin的散热片上额外加了一个5V的小风扇用GPIO供电温度能控制在65度左右。4.4 虚拟内存不足导致编译中断Orin 64GB版本的内存看起来很大但编译PyTorch或者torchvision的时候如果同时开多个编译任务内存还是会被吃满。我遇到过好几次编译到一半报Killed的情况就是OOM了。解决办法是增加swap空间sudo fallocate -l 16G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile然后在/etc/fstab里加上一行让swap开机自动挂载。16GB的swap对于编译任务来说基本够用了。5. 把YOLOv8推理性能再压榨一轮的实操手段5.1 输入分辨率的选择不是越高越好YOLOv8默认的输入尺寸是640x640。很多人觉得分辨率越高检测越准于是改成1280x1280。但在Orin上输入分辨率翻倍意味着计算量翻四倍延迟会从12ms直接跳到45ms以上。我的经验是先明确你的检测目标在画面中占多大比例。如果目标本身就不小比如产线上的零件640x640完全够用。如果目标很小比如远处的行人可以考虑用960x960但要做好延迟翻倍的准备。5.2 用DLA做推理卸载Orin相比其他Jetson型号的一个优势是集成了两个DLA核心。DLA是专门为深度学习推理设计的加速器虽然单核性能不如GPU但它可以和GPU并行工作分担一部分计算压力。在TensorRT里启用DLA的方式是在构建引擎时加上--useDLACore0参数/usr/src/tensorrt/bin/trtexec --onnxyolov8n.onnx --saveEngineyolov8n_dla.engine --fp16 --useDLACore0 --allowGPUFallback--allowGPUFallback表示遇到DLA不支持的算子时自动回退到GPU执行。实测下来YOLOv8n在DLA上跑延迟大概在18ms左右比GPU慢一些但功耗更低。如果你的场景对功耗敏感可以考虑把部分模型放到DLA上。5.3 批处理与多流推理产线场景往往需要同时处理多路摄像头。TensorRT支持批处理和CUDA流并行可以显著提升吞吐量。批处理的做法是在构建引擎时指定最大batch size/usr/src/tensorrt/bin/trtexec --onnxyolov8n.onnx --saveEngineyolov8n_b4.engine --fp16 --maxBatch4然后在推理时一次传入4张图片。实测batch4时单张图片的平均延迟从12ms降到了8ms左右吞吐量提升了50%。多流推理则是用多个CUDA流同时执行推理任务适合处理多路视频流。这部分代码稍微复杂一些需要用到TensorRT的Python API手动管理流和内存。5.4 模型剪枝与量化如果你对精度要求不是特别苛刻可以考虑对YOLOv8做剪枝或者INT8量化。INT8量化能把模型大小压缩到FP16的一半推理速度再提升30%到50%。TensorRT支持训练后量化PTQ你需要准备一个校准数据集大概500到1000张图片就够了/usr/src/tensorrt/bin/trtexec --onnxyolov8n.onnx --saveEngineyolov8n_int8.engine --int8 --calibcalibration_data/但INT8量化有个风险如果校准数据集和实际场景分布差异较大精度会明显下降。我在一个项目中用INT8量化后mAP从0.72掉到了0.65最后不得不放弃。6. 从训练到部署的完整链路复盘6.1 在x86上训练在Orin上推理我的建议是训练阶段在x86服务器或者云端完成Orin只负责推理。原因很简单Orin的算力虽然不错但训练一个大模型动辄需要几十个小时而且Orin的内存和散热都不适合长时间高负载训练。训练完成后把最好的权重文件.pt拷贝到Orin上再导出ONNX和TensorRT引擎。这样分工明确效率最高。6.2 数据标注与增强的注意事项YOLOv8训练自己的数据集时标注格式要用YOLO格式每张图片对应一个.txt文件每行是类别 x_center y_center width height坐标归一化到0到1之间。数据增强方面Ultralytics默认开启了mosaic、mixup等增强策略。但在工业质检场景下有些增强反而会引入噪声。比如mosaic增强会把四张图片拼在一起如果背景差异很大模型可能会学到错误的上下文信息。我的做法是在data.yaml里把mosaic的概率调低或者直接关掉。6.3 损失函数曲线的解读训练过程中Ultralytics会自动生成损失函数曲线图。你需要关注三条线box_loss、cls_loss、dfl_loss。正常情况下三条线都应该随着epoch增加而下降最后趋于平稳。如果box_loss下降但cls_loss不降说明模型能定位到目标但分类不准可能是类别不平衡导致的。如果三条线都震荡得很厉害说明学习率太高需要调小。6.4 部署后的持续监控模型部署到产线之后不是一劳永逸的。你需要持续监控推理延迟、显存占用、温度等指标。我通常会在推理脚本里加一个简单的日志模块每隔100帧记录一次延迟和温度写入CSV文件。这样一旦出现问题可以回溯分析。另外如果产线的光照条件、产品型号发生变化模型的精度可能会下降。这时候需要收集新的数据做增量训练或者微调。7. 一些零散但有用的经验7.1 用VSCode远程开发Orin通常不会接显示器你大概率是通过SSH远程操作。VSCode的Remote-SSH插件可以让你在本地编辑代码在Orin上执行体验比vim好很多。配置方法很简单安装Remote-SSH插件然后在~/.ssh/config里加上Orin的IP和用户名VSCode就能直接连接。7.2 善用tegrastatstegrastats是Jetson系列自带的系统监控工具可以实时显示CPU、GPU、内存、功耗、温度等信息。执行tegrastats --interval 1000每秒刷新一次。在调试性能问题时这个工具比top和nvidia-smi更有用。7.3 备份你的TensorRT引擎每次成功生成一个TensorRT引擎后建议把对应的ONNX文件、生成命令、JetPack版本号记录在一个文本文件里和engine文件放在一起。因为过几个月你很可能忘记这个engine是怎么来的而重新生成可能需要重新踩一遍坑。7.4 关于YOLOv8的C部署如果你的产线系统是C写的那就需要用TensorRT的C API来加载engine并执行推理。Ultralytics官方没有提供C部署示例但GitHub上有一些开源项目可以参考。核心流程是反序列化engine、创建执行上下文、分配显存、执行推理、解析输出。输出解析部分需要根据YOLOv8的输出格式手动实现主要是做NMS非极大值抑制。7.5 不要忽视电源质量Orin对电源质量比较敏感。如果供电不稳可能会出现随机重启或者推理结果异常。官方推荐的电源是19V/4.74A我建议用原装电源适配器不要随便找个笔记本电源就插上。另外如果Orin和电机、继电器等设备共用一个电源最好加一个隔离模块。8. 写在最后的一些个人体会从GTX 1660 Ti换到Jetson AGX Orin最大的感受是边缘AI部署这件事硬件选型只是起点真正的功夫在环境配置和推理优化上。Orin的算力确实强但它的软件生态和x86平台差异很大很多在x86上理所当然的操作在Orin上都需要重新摸索。我踩过的坑里最耗时的不是模型转换而是版本兼容性问题。JetPack、CUDA、PyTorch、TensorRT、numpy这几个组件之间的版本关系像一张蜘蛛网牵一发而动全身。我的建议是在开始任何项目之前先把版本对应关系理清楚把环境配置脚本写成一个可重复执行的shell脚本这样换设备或者重装系统的时候能省很多事。另外性能优化是一个迭代的过程。不要指望一次就能调到最优。先跑通再优化每次只改一个变量记录数据对比效果。这样即使出了问题也能快速定位是哪个改动导致的。最后分享一个我常用的调试技巧如果TensorRT推理结果和PyTorch不一致先把ONNX模型用onnxruntime跑一遍对比输出。如果ONNX和PyTorch一致但TensorRT不一致那问题就出在TensorRT转换环节重点检查算子支持和精度设置。如果ONNX和PyTorch就不一致那问题在导出环节检查opset版本和simplify设置。这个排查链路能帮你快速缩小问题范围。