云计算百科
云计算领域专业知识百科平台

轻松学习ONNX_day5

摘要:本文是 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

下面把三种精度的关键指标汇总成一张更完整的对比表:

精度Throughput (qps)Latency (ms)模型大小精度损失(MSE)
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

这一整条链串起来了。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 轻松学习ONNX_day5
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!