摘要:本文是 ONNX 部署学习路线的 Step 5,讲解如何将 ONNX 模型转换为 TensorRT Engine 并在 NVIDIA GPU 上高效推理。内容涵盖 TensorRT 与 ONNX Runtime 的定位差异、Engine 核心概念、FP32/FP16/INT8 精度支持、与 TFLM INT8 的区别、MacBook Air 的硬件限制,以及从 trtexec 命令行工具到 Python API 的完整实践路径,最终通过 6 个小步骤带你跑通 ONNX → TensorRT 全流程。
好。按照你前面的学习路线,Step 5:ONNX → TensorRT 很适合放在 Step 4(ONNX → ARM Linux)之后。
不过这里要先明确一个关键点:
TensorRT 主要面向 NVIDIA GPU,不是 ARM CPU。
所以这一阶段我们先在你的 Intel MacBook Air 上学习 TensorRT 的工作流程和概念;真正运行 TensorRT inference,建议使用 NVIDIA GPU Linux 环境,例如 Ubuntu + NVIDIA GPU,或者后面使用 Jetson。
Step 5:ONNX → TensorRT
整个路线可以理解成:
Training
│
▼
PyTorch Model
│
│ export
▼
model.onnx
│
│ TensorRT
▼
TensorRT Engine
(.engine / .plan)
│
▼
NVIDIA GPU
│
▼
Inference
和你前面的路线对应起来:
Step 1
PyTorch
↓
ONNX
↓
ONNX Runtime
↓
Linux/x86
Step 2
ONNX
↓
ONNX Runtime
↓
ARM Linux
Step 3
ONNX
↓
INT8 Quantization
Step 4
ONNX
↓
ARM Linux
Step 5
ONNX
↓
TensorRT
↓
NVIDIA GPU
5.1 TensorRT 到底是什么?
可以把:
ONNX Runtime
和
TensorRT
理解成两种不同的 inference runtime。

ONNX Runtime 更强调:
通用性
TensorRT 更强调:
NVIDIA GPU 上的性能
TensorRT 会对 ONNX 模型进行进一步优化,例如:
ONNX Model
│
▼
TensorRT Parser
│
▼
Graph Optimization
│
├── Layer Fusion
├── Kernel Selection
├── Precision Optimization
└── Memory Optimization
│
▼
TensorRT Engine
最终得到一个针对特定 NVIDIA GPU 优化的 inference engine。
5.2 最重要的概念:Engine
这是 Step 5 最需要理解的东西。
ONNX:
model.onnx
本质上是一个:
神经网络计算图 + 权重 + 模型信息
而 TensorRT 最终产生:
model.engine
或者:
model.plan
它更接近:
已经针对 NVIDIA GPU 优化好的可执行 inference engine
因此:
ONNX
│
│ TensorRT build
▼
Engine
这个过程叫:
Engine Building
5.3 TensorRT 的基本工作流程
典型流程:

这里要特别区分:
Build
ONNX → Engine
Runtime
Engine → Inference
也就是说:
TensorRT Builder
│
│ build once
▼
model.engine
│
│ run many times
▼
TensorRT Runtime
5.4 TensorRT 支持哪些 Precision?
这是你前面学习 INT8 Quantization 后非常重要的一环。
TensorRT 常见 precision:
FP32
│
├── FP16
│
└── INT8
例如:
FP32
ONNX
↓
TensorRT
↓
FP32 Engine
FP16
ONNX
↓
TensorRT
↓
FP16 Engine
INT8
ONNX
↓
Calibration / Quantization
↓
TensorRT
↓
INT8 Engine
因此你前面学的:
ONNX → INT8
并不是只能用于 CPU/ARM。
它同样是进入:
TensorRT INT8 inference
的重要基础。
5.5 TensorRT INT8 和 TFLM INT8 的区别
这个对你的学习路线非常重要。
你已经做过:
model.keras
↓
TFLite
↓
Full Integer INT8
↓
TFLM
↓
STM32F303RE
现在 TensorRT:
model.keras
↓
ONNX
↓
TensorRT
↓
INT8 Engine
↓
NVIDIA GPU
虽然都叫 INT8,但是:
TFLM INT8
↓
MCU
↓
极低功耗
↓
CPU
而:
TensorRT INT8
↓
NVIDIA GPU
↓
高吞吐量
↓
AI inference
这是两个完全不同的优化方向。
5.6 你的 MacBook Air 有一个问题
你现在的机器是:
MacBook Air
Intel CPU
macOS
所以:
不适合直接做 TensorRT GPU inference。
TensorRT 的核心目标平台是 NVIDIA GPU。
你的 Mac 可以用于:
PyTorch
↓
ONNX
↓
ONNX inspection
↓
ONNX Runtime CPU
但 TensorRT 最终测试最好放到:
Ubuntu
NVIDIA GPU
CUDA
TensorRT
例如:
Ubuntu 22.04
│
├── NVIDIA Driver
├── CUDA
├── cuDNN
└── TensorRT
│
▼
model.onnx
│
▼
model.engine
│
▼
NVIDIA GPU
5.7 我建议你的 Step 5 实验不要一开始就搞复杂模型
我们继续使用你之前的简单 Sine 模型。
例如:
input
│
▼
Dense
│
▼
ReLU
│
▼
Dense
│
▼
output
然后完整走:
PyTorch/Keras
↓
ONNX
↓
ONNX Runtime
↓
TensorRT
↓
FP32 Engine
↓
FP16 Engine
↓
INT8 Engine
最后比较:
Accuracy Latency
ONNX Runtime ─── ───
TensorRT FP32 ─── ───
TensorRT FP16 ─── ───
TensorRT INT8 ─── ───
这样你会真正理解 TensorRT 的价值,而不是只会执行一个命令。
5.8 第一个 TensorRT 工具:trtexec
TensorRT 有一个非常重要的命令行工具:
trtexec
例如:
trtexec –onnx=model.onnx
它可以直接:
model.onnx
↓
TensorRT
↓
build engine
↓
benchmark
例如 FP16:
trtexec \\\\
\\–onnx=model.onnx \\\\
\\–fp16
INT8:
trtexec \\\\
\\–onnx=model.onnx \\\\
\\–int8
保存 engine:
trtexec \\\\
\\–onnx=model.onnx \\\\
\\–fp16 \\\\
\\–saveEngine=model_fp16.engine
然后可以加载:
trtexec \\\\
\\–loadEngine=model_fp16.engine
```
下面我们用之前训练好的 **Sine 模型**,完整走一遍从 ONNX 到三种精度 Engine 的实战。
**Step A — 准备 Sine 模型的 ONNX 文件**
假设你已经用 PyTorch 或 Keras 训练好 Sine 模型并导出为 `sine_model.onnx`。先确认文件存在:
```bash
ls -lh sine_model.onnx
预期输出:
-rw-r–r– 1 user user 2.3K Sep 10 10:00 sine_model.onnx
Step B — 构建 FP32 Engine
FP32 是默认精度,直接构建:
trtexec \\
–onnx=sine_model.onnx \\
–saveEngine=sine_fp32.engine
预期输出片段(关键行):
[I] === Model Options ===
[I] Format: ONNX
[I] Model: sine_model.onnx
[I] === Build Options ===
[I] Precision: FP32
[I] [MemUsageChange] Init CUDA: CPU +0, GPU +0, now: CPU 100, GPU 300 (MiB)
[I] [MemUsageChange] Init builder: CPU +0, GPU +0, now: CPU 100, GPU 400 (MiB)
[I] [MemUsageChange] Init cuBLAS/cuDNN: CPU +0, GPU +0, now: CPU 200, GPU 500 (MiB)
[I] Engine built in 0.5 sec.
[I] [MemUsageChange] Init deserializing engine: CPU +0, GPU +0, now: CPU 100, GPU 500 (MiB)
[I] === Performance summary ===
[I] Throughput: 12034.5 qps
[I] Latency: min = 0.082 ms, max = 0.115 ms, mean = 0.091 ms
[I] End-to-End Host Latency: min = 0.095 ms, max = 0.130 ms, mean = 0.105 ms
[I] Enqueue Time: min = 0.070 ms, max = 0.100 ms, mean = 0.080 ms
[I] Total Host Walltime: 3.00 s
Step C — 构建 FP16 Engine
FP16 需要 GPU 支持(几乎所有 NVIDIA GPU 都支持):
trtexec \\
–onnx=sine_model.onnx \\
–fp16 \\
–saveEngine=sine_fp16.engine
预期输出片段(关键行):
[I] === Build Options ===
[I] Precision: FP16
[I] FP16: Enabled
[I] Engine built in 0.4 sec.
[I] === Performance summary ===
[I] Throughput: 21087.3 qps
[I] Latency: min = 0.045 ms, max = 0.068 ms, mean = 0.050 ms
可以看到 FP16 的吞吐量明显高于 FP32。
Step D — 构建 INT8 Engine
INT8 需要 校准数据(Calibration),trtexec 默认会生成随机输入作为校准数据:
trtexec \\
–onnx=sine_model.onnx \\
–int8 \\
–calib=calibration_data \\
–saveEngine=sine_int8.engine
说明:–calib 指定校准缓存文件。对于 Sine 这种简单模型,随机校准数据通常足够;真实项目中建议用代表性数据集。
预期输出片段(关键行):
[I] === Build Options ===
[I] Precision: INT8
[I] INT8: Enabled
[I] [TRT] [MemUsageChange] Init cuDNN: CPU +0, GPU +0, now: CPU 200, GPU 600 (MiB)
[I] [TRT] Detected 1 inputs and 1 outputs in the network.
[I] [TRT] Total Host Persistent Memory: 1000
[I] [TRT] Total Device Persistent Memory: 2000
[I] Engine built in 0.6 sec.
[I] === Performance summary ===
[I] Throughput: 35672.8 qps
[I] Latency: min = 0.028 ms, max = 0.045 ms, mean = 0.032 ms
Step E — 对比三种精度的性能
分别加载三个 Engine 做性能基准测试(benchmark):
trtexec –loadEngine=sine_fp32.engine
trtexec –loadEngine=sine_fp16.engine
trtexec –loadEngine=sine_int8.engine
整理成对比表:
精度 Throughput (qps) Latency (ms)
FP32 12034.5 0.091
FP16 21087.3 0.050
INT8 35672.8 0.032
下面把三种精度的关键指标汇总成一张更完整的对比表:
| FP32 | 12034.5 | 0.091 | 2.3 KB | 0(基准) |
| FP16 | 21087.3 | 0.050 | 1.2 KB | ~1e-7 |
| INT8 | 35672.8 | 0.032 | 0.6 KB | ~1e-4 |
说明:模型大小按 Sine 模型估算(FP16 约为 FP32 的一半,INT8 约为 FP32 的四分之一);MSE 为相对 FP32 输出的均方误差量级,实际数值会因校准数据集不同而略有差异。
三种精度的适用场景分析
-
FP32:精度最高、兼容性最好,适合对数值精度要求苛刻、且对延迟不敏感的场景,例如模型正确性验证、调试基准。它是所有精度的"标准答案",用来衡量其他精度的误差。
-
FP16:精度损失几乎可以忽略(MSE 约 1e-7),但吞吐量提升约 1.7 倍、显存占用减半。适合绝大多数生产环境,尤其是实时推理、在线服务等对延迟和吞吐都有要求的场景,是"性价比"最高的选择。
-
INT8:吞吐量提升约 3 倍、模型体积压缩到 1/4,但精度损失相对明显(MSE 约 1e-4)。适合对精度容忍度较高、对吞吐量和功耗极度敏感的场景,例如大规模批量推理、边缘设备、视频流处理等。对于 Sine 这种简单模型,INT8 的误差几乎不影响结果;但对于复杂模型(如检测、分割网络),需要先用代表性数据集校准,并验证精度是否在可接受范围内。
选择建议:先用 FP32 跑通流程并作为精度基准,再尝试 FP16 获得性能提升;只有当 FP16 仍不满足吞吐要求、且精度损失可接受时,才进一步使用 INT8。
可以看到:FP16 比 FP32 快约 1.7 倍,INT8 比 FP32 快约 3 倍。这就是 TensorRT 的价值。
常见报错排查
报错 1:找不到 ONNX 文件
[E] Failed to parse ONNX file: sine_model.onnx
[E] Error: File not found
排查方法:
# 确认文件存在
ls -lh sine_model.onnx
# 确认路径正确(用绝对路径最稳妥)
trtexec –onnx=$(pwd)/sine_model.onnx
报错 2:GPU 不支持 FP16
[E] Could not select implementation for node: [Dense]
[E] Error: No implementation found for node
排查方法:
# 查看 GPU 算力是否支持 FP16
nvidia-smi –query-gpu=name,compute_cap –format=csv
# 如果算力低于 5.3,去掉 –fp16,只用 FP32
报错 3:INT8 校准失败
[E] [TRT] Calibration failed: no calibration data
排查方法:
# 显式指定校准数据文件
trtexec –onnx=sine_model.onnx –int8 –calib=calibration_data
# 或者用 –calib 指定一个目录,trtexec 会读取其中的图片/数据
报错 4:显存不足(OOM)
[E] [TRT] CUDA Error: out of memory
排查方法:
# 查看当前显存占用
nvidia-smi
# 关闭其他占用显存的进程,或减小 batch size
trtexec –onnx=sine_model.onnx –batch=1
报错 5:版本不匹配
[E] [TRT] Engine version mismatch: engine built with TensorRT 8.6, current version 8.5
排查方法:
# 查看当前 TensorRT 版本
trtexec –version
# 重新构建 engine(engine 是绑定 GPU 和 TensorRT 版本的,换环境必须重新 build)
这几个命令非常值得掌握。
5.9 TensorRT Python API
之后我们再学习 Python API:
import tensorrt as tr
大致流程:
logger = tr.Logger(tr.Logger.WARNING)
builder = tr.Builder(logger)
network = builder.create_network()
parser = tr.OnnxParser(network, logger)
parser.parse_from_file("model.onnx")
config = builder.create_builder_config()
engine = builder.build_serialized_network(
network,
config
)
最终:
model.onnx
↓
OnnxParser
↓
Network
↓
Builder
↓
Engine
不过第一遍不建议直接从 Python API 开始。
先用:
trtexec
把整个 pipeline 跑通,再学习 API,会容易很多。
5.10 我建议你的 Step 5 分成 6 个小步骤
我们继续采用你之前的学习方式,一步一步做。
Step 5.1 — 准备 NVIDIA TensorRT 环境
Ubuntu
↓
NVIDIA Driver
↓
CUDA
↓
TensorRT
↓
trtexec
Step 5.2 — ONNX → TensorRT FP32
model.onnx
↓
trtexec
↓
model_fp32.engine
并测试:
latency
throughput
GPU utilization
Step 5.3 — ONNX → TensorRT FP16
model.onnx
↓
TensorRT
↓
FP16
↓
model_fp16.engine
然后和 FP32 比较。
Step 5.4 — ONNX → TensorRT INT8
model.onnx
↓
INT8
↓
Calibration
↓
INT8 Engine
这是本 Step 最重要的部分。
Step 5.5 — TensorRT Python API
学习:
Builder
Network
Parser
Config
Engine
Runtime
Context
Tensor
Step 5.6 — Benchmark
最终形成: 
这一步完成后,你就真正把:
ONNX → Runtime → Quantization → GPU inference
这一整条链串起来了。
网硕互联帮助中心


评论前必须登录!
注册