电脑上单张图片推理很快,放到机器人连续跑半小时后,检测结果却越来越晚。TensorRT 会解析 ONNX、融合算子、选择 kernel 和内存布局,再为目标 GPU 构建 engine;FP16/INT8 只解决其中一部分计算成本,队列、温度和其他节点仍可能让结果过期。
先排除预处理和版本差异
导出正确:固定 opset、输入名称、坐标约定和前后处理。很多“推理精度下降”其实是 RGB/BGR、归一化、letterbox 或 NMS 参数和训练时不一致。
形状可控:如果模型有动态 batch 或动态分辨率,构建 engine 时需要为输入设置优化 profile。profile 覆盖的形状越宽,运行时适应性越高,但可能牺牲特定尺寸的最优 kernel。机器人若只使用一种相机分辨率,固定形状通常更容易获得稳定时延。
精度可验:FP16 通常是较稳妥的第一步。INT8 需要有代表性的校准数据,且要分别统计关键类别的漏检、误检和距离/姿态误差;不能只比较一个总体 mAP。
版本不可混用:序列化 engine 通常与 GPU 架构、TensorRT 版本、CUDA 驱动和构建配置相关。将 A 设备上生成的 engine 直接拷到 B 设备,可能无法加载,也可能性能不如本机构建。
先看哪一段在等
稳定延迟依赖稳定的内存生命周期。每帧 cudaMalloc、创建 execution context、从默认流同步、在 CPU 与 GPU 之间来回拷贝,都会引入可变成本。较好的做法是启动时创建 context 和 CUDA stream,预分配输入/输出 buffer,做足预热,再在同一 stream 上异步投递工作。
1 | context->setInputShape("images", input_dims); |
这段接口只展示 TensorRT 的核心调用。实际项目还要管输入何时可读、输出何时可用,以及异常时怎样丢掉过期帧。控制侧不应等待已经过期的推理结果。
把 benchmark 和机器人时间分开
至少记录五个时间点:相机采集、进入预处理、开始 GPU 推理、推理完成、控制/规划模块消费结果。由此可以同时看出模型计算时间、排队时间和感知年龄。
1 | frame_age = decision_time - camera_stamp |
若 gpu_time 稳定而 frame_age 却不断增加,应优先处理队列与丢帧策略;若 GPU 时间随温度变大,则检查功耗模式、热设计和其他 CUDA 任务;若精度在弱光下失效,则要回到数据和模型,而不是盲目调 TensorRT。
参考:NVIDIA TensorRT Documentation · TensorRT API Reference
证据边界:本文给出 TensorRT 部署的测量方法,没有给出特定模型、GPU 或 JetPack 版本的性能和精度结果。engine 兼容性、功耗、温度和 P99 延迟需要在目标设备上重新记录。