ARTICLE DETAIL

资讯详情

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

Jetson NX部署YOLOv5实战:TensorRT加速边缘目标检测

Jetson NX部署YOLOv5实战:TensorRT加速边缘目标检测 硬件层面最让我满意的一点是NX系列对板级AI算力的定位非常明确。它不像台式机显卡那样动辄几百瓦的功耗Jetson Xavier NX满载大概15瓦到20瓦却提供了大约21 TOPS的INT8算力后来的Jetson Orin NX 8GB在相近功耗下能干到100 TOPS级别。这个能效比意味着你可以在小车、机械臂、无人零售柜旁边直接跑目标检测不用往数据中心搬数据也不用忍受公网传输延迟。我这次用的就是Xavier NX8GB内存版本刷的是JetPack 5.1后面讲的很多命令和参数在Orin NX上同样适用只是软件版本和推理速度有差异。整条部署链路我提炼一下就四步刷机装系统配置推理环境把模型从PyTorch导出成ONNX再转成TensorRT引擎最后写一个推理程序跑摄像头实时检测。你不需要在NX上训练模型那既慢又折磨人。模型在PC上训练好直接把权重文件拷过来NX只负责高效推理这才是边缘设备的正确用法。整个文章我会按实操顺序来尽量把每个环节的坑都标出来适合刚接触嵌入式AI的新手也适合想从PyTorch迁移到TensorRT的老手。1. 项目概述与整体设计思路1.1 为什么选英伟达NX开发板目标检测部署在边缘设备上有很多选择树莓派能跑Jetson系列也能跑一些国产的RK3588、算能盒子同样可以。但如果你想要一套生态成熟、踩坑资料多、踩坑之后还能顺利爬出来的方案NX系列是阻力最小的一条路。先看一组对比我用实际体验和公开数据整理过设备AI算力内存峰值功耗部署难点树莓派4B约0.1 TOPS4-8GB约7WCPU推理太慢实时性差Jetson Xavier NX21 TOPS8GB约15-20W环境配置稍复杂Jetson Orin NX 8GB100 TOPS8GB约10-25W价格偏高便携式笔记本几十到几百TOPS16GB以上45W以上体积大、功耗高、不嵌入式Xavier NX虽然已经算不上最新但胜在成熟稳定二手价格也降下来了。它搭载的Volta架构GPU原生支持TensorCore和INT8推理TensorRT能把这些算力吃得很透。Orin NX则是未来两年内更值得选的方案Ampere架构在Transformer类模型上也更友好如果你想在上面跑最新的大模型变体或者Vision TransformerOrin NX的下限更高。选NX还有一个隐藏优势NVIDIA把JetPack这个打包好的SDK做得很完整CUDA、cuDNN、TensorRT、OpenCV全部预编译进去你不需要像在树莓派上那样一个个源码编译省下来的时间非常可观。1.2 目标检测算法选型目标检测的算法谱系很长从早期的Faster R-CNN到后来的SSD再到YOLO系列和DETR系列部署难度和精度表现差异巨大。在开发板这类嵌入式设备上我首选还是YOLO系列。原因有三。第一YOLO是单阶段检测器没有RPN那种多阶段流程推理时特征提取一次、回归和分类各一次结构上更适合TensorRT这种编译型优化。第二社区生态太好了导出ONNX的脚本、TensorRT推理模板、各种预训练权重到处都是遇到问题搜索一下就有答案。第三模型体积可以按算力量身定制从YOLOv5n到YOLOv5x参数量差一个数量级开发板算力强就上大模型算力弱就上小模型取舍空间很大。我这次用的是YOLOv5s输入分辨率640x640参数量大概7.2M在Coco数据集上mAP 50-95约37左右。这个精度在边缘端做人员检测、车辆检测、安全帽检测这类任务完全够用。如果你要追求更高精度可以换成YOLOv5m代价是推理时间大概翻倍如果精度要求不高但需要跑更高帧率YOLOv5n会更合适。1.3 整体部署链路很多新手第一次接触边缘部署时容易把注意力全放在“怎么把算法跑起来”上结果陷在环境依赖里出不来。正确的方式是先站在高处把链路画出来明确每一步的输入输出然后再动手。整条链路是这样的第一步模型训练。在PC上用PyTorch训练YOLOv5得到.pt权重文件。这个文件里包含了网络结构和参数。第二步格式转换。把.pt转成.onnxONNX是一个模型交换格式它把PyTorch的动态图结构固化成静态计算图这样才能被TensorRT解析。第三步引擎优化。将ONNX交给TensorRT进行层融合、精度校准、内存复用生成一个高度优化过的.engine文件。这个文件是针对当前设备、当前TensorRT版本、当前精度模式生成的换一台机器或者换一个JetPack版本都要重新生成。第四步推理部署。写一个Python或者C程序加载.engine文件把输入图像做预处理送入引擎推理再对输出做后处理得到检测框并显示或传输。我见过不少人跳过第二步和第三步直接用PyTorch在开发板上推理结果帧率只有两三帧然后就开始怀疑硬件性能不行。实际不是硬件不行而是软件没有做针对性优化。2. 环境准备与硬件初始化2.1 硬件清单与刷机操作这次部署我准备了这么一套硬件Jetson Xavier NX开发板核心板加底板8GB版本64GB以上microSD卡建议用A2级别读写速度直接影响系统流畅度5V 3A或者5V 4A电源适配器具体要看底板供电要求USB摄像头或者CSI摄像头我用的是一个普通免驱USB摄像头Type-C数据线用来做烧录和调试刷机有两个主流方案。方案一是用NVIDIA官方SDK Manager它会通过USB连接开发板把Ubuntu系统刷到板载存储或者SD卡里。方案二是直接把官方镜像写到SD卡开发板跳过SDK Manager启动。我这次用的是方案二因为不用额外准备一台装了Ubuntu的PCSD卡插上就能用。具体步骤不复杂把官方L4T系统镜像下载下来用balenaEtcher这个工具把.img文件写入SD卡。写完之后插卡接显示器上电开机第一次启动会进入系统配置界面设置用户名、密码、时区这些。等它自动完成安装你就能看到一个精简版的Ubuntu桌面了。刷机这里有个很典型的坑SD卡写入速度慢会直接导致系统启动后异常卡顿开个终端都要等半天很多人误以为是开发板坏掉了。另外如果你用的是EMMC版本NX那就必须老老实实用SDK Manager通过网络刷机方式完全不同。2.2 系统基础配置与环境变量系统起来之后第一件事不是急着装机器学习库而是先把基础环境理顺。查看当前JetPack版本、L4T版本以及系统架构用一条命令就能搞定sudo apt update sudo apt upgrade dpkg-query --show nvidia-l4t-core如果你拿到的是带完整JetPack的官方镜像CUDA、cuDNN、TensorRT其实已经装好了只是它们不在默认的/usr/local路径下也不在系统环境变量里需要手动配置。我在~/.bashrc里添加了这么几行export PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH export CUDA_HOME/usr/local/cuda添加之后执行source ~/.bashrc然后运行nvcc -V看到CUDA版本信息就说明环境变量生效了。Xavier NX的Ubuntu系统是aarch64架构这跟你平时用的x86_64 PC架构不一样很多预编译的Python包根本没有aarch64版本所以后面装PyTorch的时候千万别直接pip install torch那样大概率会提示找不到匹配的安装包或者给你装一个CPU版本没法利用GPU算力。2.3 Python虚拟环境与JetPack自带依赖我建议在开发板上用一个独立的Python虚拟环境避免把系统Python搞乱。JetPack 5.1自带的是Python 3.8可以参考下面这种方式创建虚拟环境sudo apt install python3-venv python3-pip mkdir ~/yolo cd ~/yolo python3 -m venv venv source venv/bin/activate虚拟环境里安装pip包之前先升级pip不然会遇到一些旧版本的依赖解析问题pip install --upgrade pip setuptools wheel接下来最关键的一步安装PyTorch。不能直接pip install而是要下载NVIDIA官方为Jetson platform编译好的PyTorch轮子。它们的命名类似torch-1.14.0a044dac51c.nv22.09-cp38-cp38-linux_aarch64.whl对应的Python版本是3.8aarch64架构。这个轮子可以在NVIDIA官方L4T PyTorch发布页找到。安装命令是pip install torch-xxx-cp38-cp38-linux_aarch64.whl装完之后验证一下GPU能否使用python -c import torch; print(torch.__version__); print(torch.cuda.is_available())这里有个小细节Jetson上的torch.cuda.is_available()不会只返回True它还会打印一行“True”和warn信息提示TensorRT可以通过torch的扩展使用。看到True就说明CUDA引擎能用了。3. 模型选型与部署方案设计3.1 训练与推理的职责分离很多从零开始的人最大的误区是打算直接在开发板上又训练又推理。开发板确实能训练小模型但训练耗时是PC的数倍而且内存吃紧一个YOLOv5s训练任务可能直接让系统OOM。我的建议非常明确训练放到PC或者云服务器上完成。开发板只做一件事加载训练好的权重完成前向推理。这也是边缘计算的主流架构模型在云端生成在边缘分发执行。如果你没有自己的训练数据想先跑通流程直接下载官方预训练权重就行。YOLOv5官方仓库在GitHub上直接用git clone拉取代码然后下载yolov5s.pt这个权重文件。3.2 推理引擎选型对比同样的模型在NX上有几种跑法性能差异很大。我实际测试过三种方案对应数据供参考推理方式单帧耗时YOLOv5s640分辨率说明纯PyTorch推理200ms以上状态较差CPU占满ONNX Runtime CPU150ms左右无GPU加速无法发挥NX算力ONNX Runtime GPU60ms左右有一定提升但仍有优化空间TensorRT FP1640ms左右利用TensorCore融合算子、减少显存占用TensorRT INT820ms左右需要校准数据集精度会小幅下降从这个表格能清晰看出来TensorRT FP16是性价比最高的选择精度几乎无损速度却比PyTorch翻了四五倍。INT8极限更快但要处理精度衰减问题我在后面的章节会单独说。3.3 TensorRT的优化原理是什么你可能好奇TensorRT凭什么能把同一套模型跑得比PyTorch快那么多我用大白话解释一下。PyTorch的推理过程是把模型当做一个一个算子按顺序执行的GPU每次启动一个kernel处理一个层算完再进入下一个层层与层之间很多临时数据都要反复读写显存。TensorRT不一样它会先对整个模型的计算图做静态分析然后把能合并的层合并掉。比如卷积层后面的批归一化层、ReLU激活层正常情况下是三个独立的计算步骤但TensorRT会把这几个层融合成一个kernel一次计算直接输出最终结果。这就像你做菜正常流程是洗菜切菜炒菜分开干TensorRT则是把几个能一起处理的步骤合并中间省掉了“把菜装盘端来端去”的过程。另外TensorRT还会为每层自动选择最适合GPU的kernel实现根据输入尺寸、显存带宽、算子组合条件去自动调优。这些都是标准运行时做不到的。4. 核心实操TensorRT模型转换与加速部署4.1 导出ONNX文件先进入YOLOv5目录激活虚拟环境然后用官方脚本导出ONNX。YOLOv5的export脚本封装得很完善基本一条命令就能搞定。source ~/yolo/venv/bin/activate cd ~/yolo/yolov5 python export.py --weights yolov5s.pt --include onnx --img 640 --batch 1 --opset 13解释一下几个关键参数。--weights指定权重文件--img指定导出模型的输入分辨率需要和后续TensorRT构建时的输入尺寸保持一致--batch这个参数很关键如果设为1导出的ONNX是固定batch的静态模型后续TensorRT只能一次处理一张图如果省略batch参数或者用--dynamic导出的是动态维度模型后续可以在TensorRT构建时指定动态batch范围。导出完成后会生成yolov5s.onnx文件可以用onnxruntime再验证一遍模型能否正常推理确认之前导出的计算图没有问题。如果这一步报错说缺少onnx包用pip install onnx onnxruntime装上就行。4.2 使用trtexec将ONNX转成TensorRT引擎ONNX是给人友好的中间格式TensorRT引擎才是给硬件跑的最终形态。NX上JetPack自带了trtexec这个命令行工具它是我见过最省事的TensorRT工具比写一堆Python脚本转换要直观得多。通过以下命令生成FP16引擎/usr/src/tensorrt/bin/trtexec \ --onnxyolov5s.onnx \ --saveEngineyolov5s_fp16.engine \ --fp16 \ --workspace4096 \ --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 \ --maxShapesimages:8x3x640x640如果导出ONNX时用了固定batch那么minShapes和maxShapes可能不需要传如果你导出时用了动态shape这三个参数就必须一起传。workspace参数控制构建引擎时可用的显存上限单位是MB设得大一点能让TensorRT有更多空间做层融合优化我习惯设4096。构建过程会打印一长串日志重点看最后几行里面有网络吞吐量数据比如Throughput。这个数字可以用来预估推理性能。产出yolov5s_fp16.engine之后部署文件就有了。它在Xavier NX上只能由当前JetPack版本的TensorRT使用跨设备跨版本都要重新构建。4.3 Python方式构建引擎如果你不想用命令行或者需要在程序里动态构建引擎也可以用TensorRT的Python API。下面这段代码可以复用到大多数TensorRT部署项目里它的作用是加载ONNX、配置builder、静态生成FP16引擎并保存到磁盘import tensorrt as trt logger trt.Logger(trt.Logger.WARNING) builder trt.Builder(logger) network builder.create_network(1 int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)) parser trt.OnnxParser(network, logger) with open(yolov5s.onnx, rb) as f: parser.parse(f.read()) config builder.create_builder_config() config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 4 20) # 4GB注意单位是字节 config.set_flag(trt.BuilderFlag.FP16) engine builder.build_serialized_network(network, config) with open(yolov5s_fp16.engine, wb) as f: f.write(engine)注意set_memory_pool_limit的参数单位是字节我用4 20这个写法容易误导人其实那是4MB。要设4GB应该写4 30。所以这里提醒一下真的想设4GB请写4 30。这段代码在转换一些结构特殊的模型时可能会报错比如某个算子TensorRT不支持。遇到这种情况要么升级ONNX算子集要么手动把模型里的某些层替换成TensorRT兼容的等价实现。4.4 加载TensorRT引擎进行推理引擎文件生成之后剩下的就是推理代码了。TensorRT的推理流程和普通深度学习框架有些区别它需要你自己管理显存中的输入输出缓冲区。下面这段代码是我在Xavier NX上实际验证过的最小推理流程它加载引擎准备一个随机输入执行一次前向推理打印输出形状。把它改造成真实图像输入时只要把decode_image函数换成你自己的图像读取和预处理即可。import numpy as np import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit class TRTInference: def __init__(self, engine_path): self.logger trt.Logger(trt.Logger.WARNING) with open(engine_path, rb) as f, trt.Runtime(self.logger) as runtime: self.engine runtime.deserialize_cuda_engine(f.read()) self.context self.engine.create_execution_context() self.stream cuda.Stream() self.allocate_buffers() def allocate_buffers(self): self.inputs [] self.outputs [] self.bindings [] for i in range(self.engine.num_io_tensors): name self.engine.get_tensor_name(i) dtype trt.nptype(self.engine.get_tensor_dtype(name)) shape self.engine.get_tensor_shape(name) size trt.volume(shape) host_mem cuda.pagelocked_empty(size, dtype) device_mem cuda.mem_alloc(host_mem.nbytes) self.bindings.append(int(device_mem)) if self.engine.get_tensor_mode(name) trt.TensorIOMode.INPUT: self.inputs.append((name, host_mem, device_mem, shape)) else: self.outputs.append((name, host_mem, device_mem, shape)) def __call__(self, input_np): input_name, host_mem, device_mem, shape self.inputs[0] host_mem[:] input_np.reshape(-1) cuda.memcpy_htod_async(device_mem, host_mem, self.stream) self.context.execute_async_v2(bindingsself.bindings, stream_handleself.stream.handle) cuda.memcpy_dtoh_async(self.outputs[0][1], self.outputs[0][2], self.stream) self.stream.synchronize() output self.outputs[0][1].copy().reshape(self.outputs[0][3]) return output这里我刻意没有做后处理因为YOLOv5的输出包含多个尺度的特征图需要经过解码、过滤低置信度框、NMS这些步骤逻辑比较复杂。实际项目中你可以直接用YOLOv5仓库里的detect.py然后把它里面的模型加载部分替换成TensorRT引擎这样后处理代码可以全部复用。4.5 INT8量化初体验如果你希望推理速度更进一步可以尝试INT8。TensorRT的INT8不是简单把权重转换成INT8就行它需要校准数据集统计真实输入在每一层上的激活值范围然后再把FP16或者FP32的模型映射到INT8。YOLOv5提供了现成的PyTorch左右量化方案但如果你走TensorRT用Python写校准器会多一点。大致流程是准备几十张到一百张没有标注的图片作为校准集推荐和推理场景的图片分布接近实现一个calibrator类由TensorRT的IInt8Calibrator继承构建builder时加上config.set_flag(trt.BuilderFlag.INT8)并传入calibrator构建完成后保存engineINT8带来的性能提升是实打实的我在Xavier NX上测试YOLOv5sFP16大概40ms一帧INT8能压到20ms左右。代价是模型精度可能波动有些人脸检测、车牌识别这种要求高的场景INT8的漏检率会上升。我的建议是先在PC上评估INT8模型的mAP下降幅度再决定是否要在设备上使用。5. 实时推理与性能调优实战5.1 接入摄像头实现视频流检测模型能跑单张图只是第一步真正落地还要接视频流。在NX上接入USB摄像头最直接的方式是OpenCV的VideoCapture。JetPack自带OpenCV但它是为aarch64优化的版本解码性能比通用版本好一些。测试代码非常简单import cv2 cap cv2.VideoCapture(0) if not cap.isOpened(): print(camera open failed) exit() while True: ret, frame cap.read() if not ret: break # 将frame送入TRTInference做检测 # 绘制检测框后显示 cv2.imshow(result, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()如果你用的是CSI摄像头那就没法直接用VideoCapture需要走GStreamer pipeline。JetPack里的gst插件已经支持CSI摄像头了pipeline大致长这样gst-launch-1.0 nvarguscamerasrc ! video/x-raw(memory:NVMM),width1280,height720,framerate30/1 ! nvvidconv flip-method2 ! videoconvert ! appsink把这条pipeline传给OpenCV的VideoCapture就能在应用里读取CSI摄像头帧了。这里flip-method参数用来做画面翻转不同的摄像头安装角度需要对应不同的值。5.2 性能瓶颈分析与调优手段一帧一帧跑通之后就要关注性能了。我在Xavier NX上对YOLOv5s做过一轮完整调优按下面的顺序逐步排查模型推理耗时是最大头。先用trtexec测试引擎纯推理时间比如40ms。如果这个数字就很高说明模型尺寸或者精度配置需要调整后处理怎么优化都没用。预处理耗时。图像从BGR转RGB、从HWC转CHW、缩放填充到640x640这些操作如果全用Python纯循环做耗时可能超过20ms。正确做法是先用OpenCV把图像resize到640再做数据类型转换和归一化最后用numpy做transpose和copy。这一步在GPU上其实就是一次memcpy和一次算子调用不会太慢。后处理耗时。NMS如果实现得不好对小目标多的场景可能很慢。可以把置信度阈值调高一点比如0.25以上需要过滤的候选框少了NMS自然就快。除了代码层面NX还有硬件层面的性能开关。nvpmodel命令用来切换CPU/GPU的电源模式我一般会切到最高性能模式模式编号要查你当前JetPack版本的支持列表。jetson_clocks命令用来固定CPU和GPU频率跑实际性能测试时建议打开它不然频率自动调节会让测试数据忽高忽低。我实测过一组优化前后的数据很有参考价值优化阶段单帧总耗时帧率初始版本PyTorch无优化220ms约4FPSTensorRT FP16固定输入55ms约18FPS优化预处理调高置信度阈值48ms约20FPSINT8模型25ms约40FPS在Xavier NX上用YOLOv5s做到40FPS实际项目中已经很能打了。如果你换Orin NX同一套代码性能还能再翻一倍以上。5.3 把自己的检测逻辑封装成服务做完一帧帧的检测最后要落地成一个可对外调用的服务。最轻量的方式是写一个HTTP接口用Flask把TensorRT推理封装起来。这样另一个进程、另一台设备、甚至一个Web页面都能通过HTTP调用检测能力。核心代码非常短from flask import Flask, request, jsonify import numpy as np import base64 import cv2 app Flask(__name__) trt_infer TRTInference(yolov5s_fp16.engine) app.route(/detect, methods[POST]) def detect(): data request.json img_b64 data.get(image_base64, ) img_bytes base64.b64decode(img_b64) img_np np.frombuffer(img_bytes, dtypenp.uint8) img cv2.imdecode(img_np, cv2.IMREAD_COLOR) # 预处理推理后处理 results trt_infer.detect(img) return jsonify({boxes: results}) if __name__ __main__: app.run(host0.0.0.0, port8080)如果你想让这个服务在开发板开机时就自动运行可以写一个systemd服务文件把启动命令指向这个Flask应用。这样开发板每次重启检测服务都能自动拉起来不用手动登录再执行脚本。这个设计我在实际项目中用了很久稳定性很好。6. 常见问题与排查技巧实录6.1 新手最容易踩的五个坑第一次在NX上部署模型的人遇到的问题通常集中在几个固定方向上这里按出现频率从高到低列一下。第一个坑是内存不足。Xavier NX只有8GB统一内存CPU和GPU共享。跑检测服务还好但如果你同时开启桌面环境、浏览器、多个终端、TensorRT构建引擎内存分分钟被打满。解决办法是构建引擎时关掉图形桌面只用文本模式通过SSH操作。另外可以设置一个swap文件让系统内存不够时用SD卡或SSD顶一顶。第二个坑是TensorRT引擎跨版本不可用。你在PC上生成一个engine拷到NX上加载十有八九报错。NVIDIA的优化策略是把引擎和GPU架构、TensorRT版本强绑定别人给不了你你也给不了别人。遇到这个情况别慌删掉engine在NX上用trtexec重新生成一份。第三个坑是Python版本混用。系统自带Python 3.8如果你自己又装了Miniconda或者从源码编译Python 3.10很容易出现pip安装在解释器A里、运行时却用解释器B调用的情况最终报一些看不懂的缺失模块错误。我的习惯是全程用虚拟环境并且在实际运行之前打印sys.executable确认解释器路径。第四个坑是YOLO后处理和TensorRT输出组织方式不一致。YOLOv5在PyTorch推理时输出已经做了解码可以直接得到框坐标但TensorRT原样输出的是模型的原始feature map需要自己解码。如果没理清楚很容易把检测结果画得满屏都是错框。YOLOv5仓库的detect.py里这段逻辑可以直接参考不要自己硬写。第五个坑是把编译类任务都压在开发板上做。如果你需要从源码编译某个依赖建议先看看有没有aarch64的wheel包比如pycuda这种就用pip装预编译的。如果必须源码编译尽量在测试机或者CI服务器编译好再拷贝过去。6.2 常见问题速查表错误现象可能原因解决方案CUDA error: no kernel image available当前PyTorch版本和数据格式不匹配重新安装NVIDIA官方为Jetson编译的PyTorch轮子engine file not found路径写错或engine未生成用绝对路径先用trtexec验证Cannot allocate memory内存不足尤其是构建引擎时关闭图形界面增加swap减少workspaceonnx: OpenGL is not supportedOpenCV显示问题不是核心错误改用SSH模式测试用imwrite保存结果推理速度比预期差很多CPU锁频或者电源管理模式不对运行nvpmodel -q查看模式改用性能模式再配合jetson_clocks摄像头打开失败被其他进程占用或驱动问题拔插USB检查ls /dev/video*关闭桌面预览程序6.3 我的独家避坑经验最后分享几条我踩过很多次之后才总结出来的经验。第一条开发板上尽量少用容器化方案。虽然热词里大家都在聊dockerNX也支持docker而且NVIDIA有l4t容器专门用来跑PyTorch和TensorRT。但我个人觉得在8GB内存的Xavier NX上跑容器资源损耗和依赖冲突的排查成本都不低还不如直接使用实际环境来得靠谱。Orin NX内存普遍是16GB起步容器化体验会好一些那时再上docker也不迟。第二条模型转换失败时先不要怀疑是TensorRT的问题先回退一步用onnxruntime做一次推理确认ONNX本身的输出是正确的。如果ONNX输出有问题那就是PyTorch导出环节的锅跟TensorRT无关。这个排查思路能帮你把问题快速隔离在一个环节里不会陷入无休止的调试循环。第三条构建引擎或者做跑分时一定要开jetson_clocks同时把CPU频率和GPU频率拉满。否则系统降频会导致测试数据波动很大本来能跑30FPS的场景可能因为一次降频变成20FPS你还满世界找代码漏洞。性能调优的前提是硬件状态可复现。第四条如果你要长时间运行检测服务给开发板配一个主动散热风扇比什么优化都管用。Xavier NX在高负载下芯片温度很容易升到85度以上过热降频是性能杀手。我在室外场景部署的时候吃了这个亏后来换了金属外壳加风扇温度控制在70度以内才勉强谈得上稳定性。就我个人的感受来说用英伟达NX开发板部署目标检测算法这件事难点从来不在“模型怎么训练”上——那是PC上的老本行而在于把一个训练好的模型折腾成在这个小功耗设备上每秒跑几十帧的高效引擎。这个过程会逼着你把模型计算图、算子的GPU执行方式、图像预处理这些底层细节全部过一遍等彻底跑通之后你对深度学习框架的理解会完全不一样。如果这篇记录能帮你少熬一两个通宵那它就是有价值的。最后再啰嗦一句万事开头难第一次刷机失败、第一次构建引擎报错都非常正常你只需要保持耐心把每一步的日志和状态记清楚碰到问题就知道往哪个方向查。
返回列表