Technical note

RTX 2080 Ti上ONNX与TensorRT的精度和性能对比

同一个YOLOv8检测模型导出为ONNX和TensorRTEngine后,在RTX 2080 Ti上比较了FP32、FP16和INT8。结果基本确认了TensorRT的速度优势,但也暴露出两个不能忽略的问题:INT8Engine的精度损失较大,ONNX INT8在两套测试中的耗时相差悬殊。

这组数据只适用于当时的模型和环境。测试使用CUDA11.8、cuDNN8.9.7和ONNXRuntimeGPU1.16.3,TensorRT版本、输入尺寸和完整硬件状态没有记录,因此不适合拿这些数字预测其他机器的性能。

单图推理耗时

性能脚本对同一张图片预热10轮,再执行100轮。表中的FPS是按平均推理耗时换算的数值,不是包含图片读取、预处理和后处理的端到端吞吐量。

格式加载耗时(ms)平均耗时(ms)P50(ms)P95(ms)P99(ms)换算FPS
ONNX FP3247.0810.809.0518.0724.0792.58
ONNX FP1649.7411.309.7819.7723.7688.46
ONNX INT840.2813.3312.1421.5427.0475.02
Engine FP3267.737.896.5115.4817.23126.79
Engine FP1647.655.514.3614.0115.37181.59
Engine INT839.424.213.925.637.89237.44

在这次单图测试中,三个TensorRTEngine都比对应精度的ONNX模型快。FP32、FP16和INT8的平均耗时分别下降26.9%、51.2%和68.4%。这个百分比描述的是延迟下降;如果用吞吐量比值表达,则分别约为1.37倍、2.05倍和3.17倍,两种口径不能混用。

ONNX的结果并没有随着数值精度降低而变快,INT8反而最慢。仅凭这组输出不能把原因归结为ONNXRuntime的量化开销:还需要检查量化方式、节点分配、CUDAExecutionProvider是否完整接管计算,以及基准脚本是否包含额外的数据转换。

完整数据集上的精度

精度测试使用同一套图片和标签,并记录mAP、Precision、Recall与平均推理耗时。数据集规模和类别分布没有留在记录里,因此这里看同一测试集内的相对变化,不把指标外推到其他数据。

模型mAP@0.5mAP@0.5:0.95PrecisionRecallF1推理(ms)换算FPS
PyTorch FP320.90700.60800.89620.93940.917310.298.3
ONNX FP320.90700.60830.89660.93920.917412.381.2
ONNX FP160.90690.60790.89670.93890.917313.474.6
ONNX INT80.56870.25090.50980.88540.647091.410.9
Engine FP320.90700.60830.89660.93920.91748.7115.4
Engine FP160.90690.60840.89690.93910.91756.0165.4
Engine INT80.74800.50360.97820.77830.86685.5180.2

FP32和FP16的精度几乎没有变化,TensorRTEngine的耗时更低。其中FP16Engine相对PyTorch基线降低了41.2%的推理耗时,mAP和F1仍在同一水平,是这组模型里更稳妥的部署选择。

INT8Engine虽然最快,但代价很明显。它的mAP@0.5比PyTorch基线低0.1590,Recall低0.1611;Precision升至0.9782,并不能说明模型整体更准,而是漏检增加后留下的预测更保守。对检测任务来说,这种变化不能只靠更高的FPS抵消。

ONNX INT8结果不能直接采用

ONNX INT8在单图测试中的平均耗时是13.33ms,在完整数据集测试中却变成91.4ms,同时精度也远低于其他格式。两次测试不是同一测量路径,差异已经大到不能当作普通波动处理。

重新导出后数据仍然异常,但当时没有继续定位到具体原因。因此这项结果只能标记为异常,不能据此得出“ONNX INT8天然更慢”或“ONNXRuntime不适合INT8”的结论。继续排查时至少需要固定以下条件:

  • 使用完全相同的输入尺寸、预处理和后处理;
  • 记录每个ExecutionProvider实际承接的节点,确认没有意外回退到CPU;
  • 分开统计模型推理、量化转换和数据复制耗时;
  • 保存量化方式、校准集、算子类型以及导出日志;
  • 在同一数据集上重复测试,并同时观察GPU利用率和显存占用。

基于现有数据,FP16Engine应作为优先选择。INT8Engine只有在重新校准并确认Recall下降可以接受后才值得采用,ONNX INT8则需要先把精度和耗时异常查清楚。