☰
TensorRT 官方快速入门指南(中文):用 trtexec 把 ONNX ResNet 跑成推理引擎
2026/9/25 21:47:39 网站建设 项目流程

1. 从 ONNX 到 TensorRT 引擎:为什么 trtexec 是入门首选

如果你手里已经有一个训练好的 ONNX 模型,想快速验证它在 GPU 上的推理表现,最省事的路径不是写 C++ 或 Python 构建代码,而是直接用 TensorRT 自带的命令行工具 trtexec。它能一条命令完成 ONNX 解析、网络优化、引擎序列化,还能顺手跑一遍性能测试,非常适合做推理链路的可行性验证。

TensorRT 的核心思路是把训练框架里的模型,转换成一种针对特定 GPU 架构深度优化过的「引擎」(engine)。这个引擎里包含了算子融合、精度校准、内存复用等优化结果,运行时开销比原始框架小很多。整个流程可以概括为五步:导出模型、选择精度、转换模型、部署模型、验证性能。trtexec 覆盖了中间最关键的转换和验证环节。

这篇内容面向的是想快速跑通 GPU 推理链路的开发者,假设你已经有一个 ONNX 格式的 ResNet 模型,或者知道怎么从 PyTorch 导出。我会把重点放在可复制的 trtexec 命令、输入输出配置骨架,以及精度与吞吐的对比验证上。配套的 AI 工具 Key 和 API 通道管理,我会在第二节说明怎么用 TaoToken 统一处理。

2. TaoToken 前置:统一管理配套 AI 工具的 Key 与 API 通道

做推理部署时,除了 TensorRT 本身,往往还会用到一些辅助工具,比如模型转换脚本、性能分析工具、或者调用云端 API 做结果比对。这些工具如果各自维护一套 Key 和接入地址,配置起来很零散。TaoToken 提供的是一个统一的 Key/API 通道管理入口,把模型对话、编码辅助、API 调用这些能力收敛到一处。

你可以先到官网了解整体能力:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。如果只是想在转换过程中用模型对话确认一些参数含义,可以直接走模型对话入口;如果是要长期做编码和 Agent 类工作,Coding Plan 更合适。API 层面的接入地址是 https://taotoken.net/api ,Key 的创建和管理在 console 里完成。

注意:TaoToken 在这里的角色是配套 AI 工具的通道管理,不是 TensorRT 的替代品。TensorRT 的引擎构建和推理仍然在本地 GPU 环境完成。

具体操作上,你可以在 console 里创建一个 Key,然后在需要调用 API 的脚本或工具里统一使用这个 Key。接入文档里有不同语言的最小示例,照着填 base_url 和 api_key 即可。这样做的实际好处是,当你同时用多个 AI 辅助工具时,不用每个都去单独申请和轮换 Key。

3. 可复制配置:trtexec 转换 ONNX ResNet 的完整命令

3.1 环境确认与模型准备

先确认 TensorRT 和 CUDA 环境可用。trtexec 通常随 TensorRT 一起安装,在容器里一般直接可用。执行trtexec --help能看到版本和参数列表就说明环境没问题。

模型方面,如果你还没有 ONNX 文件,可以从 PyTorch 导出。下面这段代码把 torchvision 的 ResNet-50 导出为 ONNX,输入固定为 1x3x224x224:

import torch import torchvision.models as models resnet50 = models.resnet50(pretrained=True, progress=False).eval() dummy_input = torch.randn(1, 3, 224, 224) torch.onnx.export( resnet50, dummy_input, "resnet50.onnx", input_names=["input"], output_names=["output"], opset_version=13 )

导出后确认一下文件存在,大小通常在 90MB 到 100MB 左右。如果是从 ONNX Model Zoo 下载的 resnet50.tar.gz,解压后路径一般是resnet50/model.onnx。

3.2 基础转换命令

最简转换命令只需要指定输入 ONNX 和输出 engine 路径:

trtexec --onnx=resnet50.onnx --saveEngine=resnet50_fp32.engine

这条命令会以 FP32 精度构建引擎,并保存到resnet50_fp32.engine。构建过程会打印解析日志、优化信息和构建耗时。如果看到Engine built successfully或类似输出,说明转换成功。

3.3 精度与形状参数配置

实际部署时通常需要控制精度和输入形状。下面这条命令同时指定 FP16 精度和动态形状范围:

trtexec \ --onnx=resnet50.onnx \ --saveEngine=resnet50_fp16.engine \ --fp16 \ --minShapes=input:1x3x224x224 \ --optShapes=input:8x3x224x224 \ --maxShapes=input:16x3x224x224

这里--fp16开启半精度,--minShapes、--optShapes、--maxShapes分别定义输入张量的最小、最优、最大形状。最优形状是 TensorRT 做 kernel 选择时的重点优化目标,建议设成你实际业务中最常见的 batch size。

参数作用建议值
--onnx输入 ONNX 模型路径必填
--saveEngine输出 engine 路径必填
--fp16开启 FP16 精度有 Tensor Core 的卡建议开
--int8开启 INT8 精度需要校准集
--minShapes动态形状下限按业务最小 batch
--optShapes优化目标形状按常见 batch
--maxShapes动态形状上限按业务最大 batch
--workspace工作空间大小(MB)复杂模型适当调大

注意:TensorRT 10.x 之后--workspace参数的行为有变化,部分版本不再支持直接指定。如果遇到 workspace 相关报错,先确认你的 TensorRT 版本,再决定是否加这个参数。

3.4 构建并直接跑性能测试

如果不想分两步,可以在转换的同时跑一遍性能测试:

trtexec \ --onnx=resnet50.onnx \ --saveEngine=resnet50_fp16.engine \ --fp16 \ --shapes=input:8x3x224x224 \ --iterations=100 \ --warmUp=500 \ --duration=10

--iterations指定测试迭代次数,--warmUp是预热时间(毫秒),--duration是正式测试时长(秒)。跑完后会输出吞吐量(Throughput)和延迟(Latency)统计,这是验证推理性能最直接的依据。

4. 验证请求与成功结果:吞吐、延迟与精度对比

4.1 性能数据解读

trtexec 跑完后,输出里最值得关注的是这几项:

[I] Throughput: 1250.3 qps [I] Latency: min = 0.62 ms, max = 0.81 ms, mean = 0.65 ms, median = 0.64 ms [I] GPU Compute Time: min = 0.58 ms, max = 0.76 ms, mean = 0.61 ms

Throughput 是每秒处理的请求数,Latency 是单次推理耗时。GPU Compute Time 只统计 GPU 上的计算时间,不含数据拷贝。对比 FP32 和 FP16 两份结果,通常能看到 FP16 的吞吐有明显提升,延迟下降,而精度损失在 ResNet-50 这种分类任务上通常很小。

4.2 精度验证骨架

trtexec 本身不做精度比对,但你可以用 Python 加载 engine 跑一遍推理,和 ONNX Runtime 的结果做对比。下面是一个最小验证骨架:

import numpy as np import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit logger = trt.Logger(trt.Logger.WARNING) with open("resnet50_fp16.engine", "rb") as f: engine = trt.Runtime(logger).deserialize_cuda_engine(f.read()) context = engine.create_execution_context() input_shape = (1, 3, 224, 224) dummy = np.random.randn(*input_shape).astype(np.float32) # 分配设备内存并拷贝输入 d_input = cuda.mem_alloc(dummy.nbytes) cuda.memcpy_htod(d_input, dummy) context.set_tensor_address("input", int(d_input)) # 分配输出内存 output = np.empty((1, 1000), dtype=np.float32) d_output = cuda.mem_alloc(output.nbytes) context.set_tensor_address("output", int(d_output)) # 执行推理 stream = cuda.Stream() context.execute_async_v3(stream_handle=stream.handle) cuda.memcpy_dtoh(output, d_output) stream.synchronize() print("Top-1 class:", np.argmax(output))

把同样的输入喂给 ONNX Runtime,对比 top-1 类别和置信度差异。如果 top-1 一致、置信度差异在 1% 以内,基本可以认为 FP16 转换没有引入有意义的精度损失。

4.3 成功结果判断标准

一次成功的转换和验证,应该满足:engine 文件正常生成且大小合理;trtexec 性能测试能跑完并输出吞吐/延迟数据;Python 加载 engine 后推理结果与原始模型一致。三者都通过,说明这条 ONNX 到 TensorRT 的链路是通的。

5. 本篇常见错排查

5.1 找不到 ArgMax 节点实现

报错信息类似Could not find any implementation for node ArgMax_260。这通常出现在带 argmax 输出的分割模型上,原因是 workspace 不够。可以尝试加--workspace=4096重新构建。但要注意,TensorRT 10.5 之后部分版本不再支持这个参数,如果加了报参数错误,就说明你的版本已经不需要手动指定 workspace,直接去掉即可。

5.2 动态形状相关报错

如果报Input shape not set或Cannot infer shape,检查是否在构建时指定了--minShapes、--optShapes、--maxShapes。对于动态形状模型,这三个参数至少要给 optShapes,否则 TensorRT 无法确定优化目标。另外,运行时设置输入形状时,要确保在 min 和 max 范围内。

5.3 精度下降明显

FP16 转换后如果精度掉得厉害,先确认模型里有没有对数值范围敏感的算子,比如 softmax 前的 logits 特别大。可以尝试对特定层保持 FP32,或者改用 INT8 加校准集的方式。ResNet 这类分类模型一般 FP16 损失很小,如果掉点严重,更可能是输入预处理不一致导致的,检查归一化参数是否和训练时一致。

5.4 engine 加载失败

deserialize_cuda_engine返回 None,常见原因是 engine 文件和当前 TensorRT 版本不匹配。engine 是跟版本和 GPU 架构绑定的,换环境后需要重新构建。另外确认文件读取时用的是二进制模式,且文件没有损坏。

5.5 性能不如预期

如果吞吐上不去,先看 batch size 是否太小。GPU 利用率低的时候,适当增大 batch 能明显提升吞吐。其次确认是否开了 FP16 或 INT8,FP32 在支持 Tensor Core 的卡上浪费了算力。最后检查--optShapes是否设成了实际业务中最常见的形状,设错了会导致 kernel 选择不是最优。

6. 配套工具链的 Key 与 API 统一管理

推理链路跑通之后,日常工作中还会涉及模型对话确认参数、编码辅助写部署脚本、以及调用 API 做结果比对。这些环节如果各自维护 Key,时间长了容易乱。TaoToken 的 console 里可以集中创建和管理 Key,API 接入地址统一用 https://taotoken.net/api ,接入文档里有各语言的最小调用示例。

如果你主要是做模型对话类的辅助确认,走模型对话入口;如果是长期写代码和搭 Agent,Coding Plan 更贴合。API Keys 的创建在 console 里完成,创建后复制到你的环境变量或配置文件里即可。这样一套 Key 可以覆盖多个配套工具,省去反复申请和轮换的麻烦。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询