4、TensorRT 引擎构建(trtexec):trtexec 命令行工具详解,常用参数(--fp16、--int8、--workspace),构建过程中的显存爆炸问题
4.1 trtexec 到底是什么?
说实话,很多刚接触 TensorRT 的同学,第一反应就是去翻 Python API。但在我个人习惯里,trtexec 才是真正的好东西。它是个命令行工具,TensorRT 安装包里自带。你不需要写一行代码,就能完成模型转换、精度校准、性能测试。
说白了,trtexec 就是 TensorRT 的瑞士军刀。我经常用它来做快速验证——模型能不能转、性能大概多少、显存够不够,一条命令就能试出来。
核心定位:trtexec 是 TensorRT 官方提供的命令行工具,用于构建引擎、运行推理、测试性能。它不依赖任何第三方框架,直接操作 TensorRT 底层 API。
4.2 常用参数详解
trtexec 的参数很多,但真正生产环境常用的,其实就那么几个。我一个个说。
4.2.1 --fp16 和 --int8:精度选择
这两个参数决定了你的模型用哪种精度跑。FP16 是半精度浮点,INT8 是 8 位整型。精度越低,模型越小,速度越快,但精度损失也越大。
我在项目中遇到过一个问题:有个客户非要用 INT8,结果模型精度掉了 5 个点,业务直接崩了。后来我建议他先用 FP16 试试,精度只掉了 0.3%,速度也快了 1.8 倍。你想想看,有时候不是精度越低越好,得看业务容忍度。
| 参数 | 说明 | 适用场景 |
|---|---|---|
| --fp16 | 启用 FP16 精度 | 大部分生产场景,精度损失小,速度提升明显 |
| --int8 | 启用 INT8 精度 | 对精度要求不高,追求极致性能的场景 |
| --best | 自动选择最优精度组合 | 新手推荐,但可能不是最优解 |
我的建议:第一次构建引擎时,先用 --fp16 跑一遍。如果性能达标,就别折腾 INT8 了。INT8 需要校准数据集,搞不好还会掉精度,得不偿失。
4.2.2 --workspace:显存控制
这个参数太重要了。它控制 TensorRT 在构建引擎时能用的最大显存。单位是 MB。默认值通常是 1GB,但很多模型根本不够用。
为什么会这样?因为 TensorRT 在构建引擎时,需要临时存储中间计算结果、图优化后的临时张量、以及各种缓存。如果 workspace 设得太小,构建过程就会失败,报显存不足。
我曾经遇到一个客户,模型是 ResNet-152,batch size 设了 64。他用默认 workspace 构建,结果直接 OOM。我让他改成 --workspace=8192,问题就解决了。嗯,这里要注意:workspace 不是越大越好,设太大可能会影响其他进程。
# 基本用法
trtexec --onnx=model.onnx --fp16 --workspace=4096
# 指定 batch size
trtexec --onnx=model.onnx --fp16 --workspace=4096 --shapes=input:1x3x224x224
# 测试性能
trtexec --loadEngine=model.engine --shapes=input:1x3x224x224 --duration=60
4.3 构建过程中的显存爆炸问题
这是生产环境里最头疼的问题,没有之一。我见过太多团队,模型在开发机上跑得好好的,一到生产服务器就炸了。原因很简单:显存不够。
4.3.1 为什么会显存爆炸?
TensorRT 构建引擎时,需要做几件事:
- 图解析:把 ONNX 模型解析成 TensorRT 内部图结构
- 图优化:做算子融合、内存复用、布局优化
- 临时张量:优化过程中需要存储中间结果
- 校准缓存:INT8 校准需要额外的显存
这些操作加起来,显存消耗可能是最终引擎的 2-3 倍。你想想看,一个 1GB 的模型,构建时可能需要 3GB 显存。如果服务器只有 8GB,再跑个别的进程,很容易就爆了。
避坑指南:我曾经在生产环境遇到过,一个 500MB 的 BERT 模型,构建时直接吃掉了 4GB 显存。后来排查发现,是因为 batch size 设得太大,导致中间张量爆炸。解决方案:先用小 batch size 构建,再用大 batch size 推理。
4.3.2 解决方案
我总结了几个实战经验,你可以直接拿去用:
- 降低 batch size:构建时用 batch size=1,推理时再动态调整
- 限制 workspace:用 --workspace 参数控制最大显存,比如设成 4096MB
- 分步构建:先构建 FP16 引擎,再构建 INT8 引擎,不要一次搞完
- 使用 --minShapes 和 --optShapes:指定动态 shape 的范围,减少优化空间
- 监控显存:用 nvidia-smi 实时监控,发现异常立即终止
# 推荐的生产环境构建命令
trtexec --onnx=model.onnx \
--fp16 \
--workspace=4096 \
--minShapes=input:1x3x224x224 \
--optShapes=input:8x3x224x224 \
--maxShapes=input:16x3x224x224 \
--saveEngine=model.engine
4.4 知识体系结构图
下面这张图,是我自己总结的 trtexec 构建引擎的核心流程。你看一眼就能明白整个链路。
4.5 实战经验总结
最后,我把自己踩过的坑总结成几条原则,你记一下:
- 先小后大:构建时用小 batch size,推理时用大 batch size
- 先 FP16 后 INT8:FP16 够用就别上 INT8,省心省力
- 监控显存:构建过程中用 nvidia-smi 盯着,发现异常立刻停
- 保存引擎:构建好的引擎用 --saveEngine 保存,下次直接加载,不用重新构建
- 测试性能:用 --duration=60 跑一分钟,看平均延迟和吞吐量
一个小技巧:如果你不确定 workspace 该设多大,可以先设成 2048,然后逐步增加。每次增加 1024,直到构建成功。这样既能找到最小值,又不会浪费显存。