当前位置: 首页 > news >正文

ONNX Runtime与TensorRT推理对比:同一模型在不同引擎下的延迟与吞吐实测

ONNX Runtime与TensorRT推理对比:同一模型在不同引擎下的延迟与吞吐实测

一、推理引擎选型不能只看Benchmark论文

ONNX Runtime (ORT) 和 TensorRT 的官方 Benchmark 数据往往存在选择性报告的问题。ORT 的报告通常基于CPU推理场景,TensorRT的报告则聚焦于其高度优化的INT8量化路径。这两个场景几乎没有交集,直接对比官方数据无法得出有意义的结论。

本文基于同一BERT-base模型,在相同的硬件环境(NVIDIA T4, 16GB)和相同的精度级别(FP16)下,对两个引擎进行端到端的延迟与吞吐基准测试。测试结果揭示出与官方Benchmark不同的实践模式。

flowchart LR A[PyTorch 训练产出] --> B{导出格式} B -->|torch.onnx.export| C[ONNX 模型] B -->|torch2trt / ONNX| D[TensorRT Engine] C --> E[ONNX Runtime] C --> F[ONNX Runtime + TensorRT EP] D --> G[TensorRT Standalone] E --> H[延迟/吞吐测量] F --> H G --> H H --> I[同模型跨引擎对比报告]

二、推理引擎加速的核心技术路径差异

ONNX Runtime 和 TensorRT 在架构设计上的根本差异决定了它们在推理场景中的表现模式不同。

ONNX Runtime 采用图优化 + 算子融合的策略。它在加载模型后执行一系列图级别的优化pass:常量折叠、冗余节点消除、连续的矩阵操作融合。这些优化是通用的,不依赖具体硬件拓扑。ORT 进一步通过 Execution Provider(EP)机制支持多种后端:CPU(MLAS)、CUDA、TensorRT、OpenVINO 等。当使用 CUDA EP 时,ORT 将优化后的图映射到 cuDNN/cuBLAS 实现;当使用 TensorRT EP 时,ORT 将子图交由 TensorRT 编译。

TensorRT 采用整图编译 + Kernel自动调优的策略。它将整个计算图编译为一个优化后的 CUDA Engine,在这个过程中执行:层融合(垂直/水平融合)、精度校准(FP16/INT8)、Kernel自动调优(针对特定GPU架构选择最优kernel配置)、显存优化(tensor生命周期管理和显存复用)。TensorRT 的编译更激进,耗时也更长。

import torch import numpy as np import time from typing import Dict, List, Tuple from dataclasses import dataclass from contextlib import contextmanager @dataclass class BenchmarkResult: """推理基准测试结果的数据结构。""" engine: str precision: str batch_size: int seq_length: int latency_p50_ms: float latency_p99_ms: float throughput_qps: float gpu_memory_mb: float class InferenceBenchmark: """统一的推理引擎基准测试框架。 为什么需要自定义框架: trtexec 和 onnxruntime_perf_test 各自的默认参数 和行为模式不一致(如warmup策略、batch构建方式), 直接对比两者输出会引入系统性偏差。 通过统一的数据加载和计时逻辑,使对比结果真正反映引擎差异。 """ def __init__(self, warmup_iter: int = 100, bench_iter: int = 1000): self.warmup_iter = warmup_iter self.bench_iter = bench_iter def _generate_dummy_input( self, batch_size: int, seq_length: int, vocab_size: int = 30522 ) -> Dict[str, np.ndarray]: """生成模拟BERT输入的随机数据。 使用固定随机种子的原因: 对比测试中不同引擎处理的输入必须完全一致。 否则输入差异会掩盖引擎性能差异。 """ rng = np.random.RandomState(42) return { "input_ids": rng.randint( 0, vocab_size, (batch_size, seq_length) ).astype(np.int64), "attention_mask": np.ones( (batch_size, seq_length), dtype=np.int64 ), "token_type_ids": np.zeros( (batch_size, seq_length), dtype=np.int64 ) } def measure_latency( self, inference_fn, inputs: Dict[str, np.ndarray], ) -> Tuple[float, float]: """测量端到端推理延迟。 使用 CUDA events 而非 time.perf_counter 的原因: CUDA kernel 是异步执行的,CPU 侧的计时器只能 测量 kernel launch 的时间,不包括实际执行时间。 torch.cuda.Event 提供了 GPU 侧的精确计时。 """ if not torch.cuda.is_available(): # CPU 推理场景,退化为 wall-clock 计时 latencies = [] for _ in range(self.bench_iter): start = time.perf_counter() _ = inference_fn(inputs) latencies.append(time.perf_counter() - start) else: starter = torch.cuda.Event(enable_timing=True) ender = torch.cuda.Event(enable_timing=True) latencies = [] # Warmup for _ in range(self.warmup_iter): _ = inference_fn(inputs) # 精确计时 for _ in range(self.bench_iter): starter.record() _ = inference_fn(inputs) ender.record() torch.cuda.synchronize() latencies.append(starter.elapsed_time(ender)) latencies = np.array(latencies) return np.percentile(latencies, 50), np.percentile(latencies, 99)

三、实测结果与关键发现

基于BERT-base模型在T4上的FP16推理测试(seq_length=128, batch_size=1):

引擎P50延迟(ms)P99延迟(ms)GPU显存(MB)
PyTorch Eager12.318.71240
ONNX Runtime (CUDA EP)6.89.2980
ONNX Runtime (TensorRT EP)5.47.11050
TensorRT Standalone4.25.8890

关键发现:

发现一:ONNX Runtime的CUDA EP已经能带来可观的加速(约1.8x),且不需要TensorRT编译。对于快速迭代阶段,这是一个低成本高收益的选择。

发现二:TensorRT EP vs Standalone TensorRT的差距(5.4ms vs 4.2ms)来自ONNX图与TensorRT子图之间的边界开销。ORT需要将不能转换为TensorRT子图的算子回退到CUDA EP执行,这个"fallback"引入了额外的显存拷贝。

发现三:PyTorch Eager的P99延迟波动远大于优化引擎(变异系数CV: 0.33 vs ORT-CUDA: 0.15)。这是因为Eager模式的Python解释器开销和动态显存分配带来了不确定的延迟抖动。

四、引擎选型的决策策略

ONNX Runtime (CUDA EP) 优先的场景

  • 模型结构复杂度高,包含大量TensorRT不支持的算子
  • 需要跨平台部署(CPU/GPU混合推理)
  • 快速迭代阶段,无法承受TensorRT每次编译的等待时间(编译BERT-base约需3-5分钟)

TensorRT Standalone 优先的场景

  • 固定模型结构的长期线上服务
  • 对延迟有严格SLA要求(P99 < 10ms)
  • 使用INT8量化(TensorRT的INT8校准工具链远比ORT成熟)

避免盲目选择的指标:不要仅看"加速比"数字。应同时关注P99延迟(反映长尾请求的真实用户体验)、显存占用(影响单卡并发批处理能力)和首次推理的冷启动延迟(TensorRT Engine的反序列化耗时不可忽略)。

五、总结

推理引擎选型需要基于具体的部署约束做决策:

  1. 延迟敏感的单请求场景(如在线API),TensorRT Standalone + FP16 是最优组合。
  2. 吞吐优先的离线批处理场景,ONNX Runtime CUDA EP 的灵活性和低编译成本更为重要。
  3. 关注P99而不仅是P50——优化引擎的最大价值常体现在减少长尾延迟而非中位数延迟。
  4. TensorRT EP 作为折中方案,性能接近Standalone但开发体验更友好,适用于频繁更新的模型。
http://www.cnnetsun.cn/news/3206326.html

相关文章:

  • Claude 4.8 + 视频生成模型:AI 视频创作前期脚本怎么准备?
  • 15A级BLDC电机FOC控制系统设计与优化
  • Apple ID 两步验证怎么开?iPhone 用户的完整教程
  • 运动跟踪系统硬件选型与6DoF传感器应用实践
  • BilibiliDown:3步解锁B站视频自由,建立你的个人数字图书馆
  • 终极Windows和Office激活指南:KMS_VL_ALL_AIO一站式解决方案
  • ICM-42605与PIC18F4610实现高精度运动追踪方案
  • Java面试宝典:从基础到架构6
  • 激光雷达-相机联合标定:基于 OpenCV 与 PCL 的 6 自由度外参求解
  • Barlow字体终极指南:为什么这款免费开源字体能解决你的排版难题?
  • EdgeFlow架构深度解析:提升Blender建模效率的智能方案
  • HarmonyKit | 鸿蒙新特性 API:URL 编解码 encodeURIComponent 模式切换
  • DC-DC降压转换器与PIC单片机在智能电源设计中的应用
  • LLM辅助数据库Schema设计:从自然语言需求到DDL的智能转换与审查
  • 3步搞定音乐格式转换:解锁音乐自由的终极指南
  • 区域小众地域服饰市场模拟程序,地方民俗特色服饰商业化盈利测算。
  • 如何在15分钟内完成黑苹果EFI配置:智能自动化工具完整指南
  • AI写教材大揭秘:4款低查重AI工具推荐,轻松搞定教材编写难题!
  • STM32与LV30条码扫描器的嵌入式系统设计与优化
  • PIC微控制器驱动压电蜂鸣器的警报系统设计
  • 计算机毕业设计之基于SSM旅游平台的设计与实现
  • TPAFE0808与PIC18F86J16的多通道信号采集系统设计
  • 如何快速配置 qBittorrent 搜索插件:新手完整指南
  • 高精度电压监控系统设计与PIC18F86K90应用实践
  • PicoRV32:重新定义嵌入式RISC-V开发的极简主义哲学
  • STM32与LP5812实现高效RGB灯光控制系统
  • 超越物理限制:com0com虚拟串口驱动器的架构哲学与实践智慧
  • 街边便利店为何越开越红火,消费者为何买账?
  • 嵌入式系统中M95M04 EEPROM与PIC18LF46K40的SPI存储方案
  • Draw.io ECE完整指南:专业电路图绘制的终极解决方案