第四章:TensorRT入门

TensorRT是什么?

先说说TensorRT到底是什么。简单点讲,它是一个推理优化引擎,专门用来加速深度学习模型的推理过程。不是训练,是推理。

我刚开始接触TensorRT时,有个误解——以为它就是个模型格式转换工具。后来才发现,它远不止如此。TensorRT本质上是一个推理运行时,它把你的模型吃进去,吐出一个高度优化的推理引擎。这个引擎可以在NVIDIA的GPU上跑得飞快。

你想想看,训练好的模型就像一本厚厚的菜谱。TensorRT不是帮你重新写菜谱,而是帮你把做菜的流程优化到极致——哪些步骤可以合并,哪些材料可以提前准备好,哪些工具可以同时用。最终,你做一道菜的时间大大缩短。

核心要点:TensorRT = 模型优化器 + 推理运行时。它不负责训练,只负责让推理更快。

TensorRT的推理加速原理

加速原理其实不复杂,我拆成几个关键点来讲。

1. 层融合(Layer Fusion)

这是最直观的优化。模型里有很多连续的层,比如Conv + BN + ReLU。在TensorRT里,这些层会被合并成一个kernel。合并之后,数据不用反复在显存和计算单元之间搬来搬去。

我在项目中遇到过这样一个案例:一个ResNet-50模型,光靠层融合这一步,推理速度就提升了30%以上。说白了,减少数据搬运就是减少时间。

2. 精度校准(Precision Calibration)

TensorRT支持FP32、FP16、INT8三种精度。FP16和INT8的推理速度远快于FP32。为什么?因为数据量小了,计算单元一次能处理更多数据。

但精度降低会带来精度损失。TensorRT通过校准(Calibration)来最小化这个损失。它会用一小批真实数据跑一遍,找到最佳的量化参数。

我的经验:INT8量化时,校准数据集最好用500-1000张真实场景的图片。用训练集做校准效果往往不好,因为训练集和真实场景的分布可能有差异。

3. 内存优化

TensorRT会做内存复用。同一个显存块,在不同时间可以被不同张量使用。这听起来简单,但实现起来很复杂。我见过一些模型,优化前显存占用2GB,优化后降到800MB。省下来的显存,可以跑更大的batch size。

4. 自动调优(Auto-tuning)

TensorRT会为每个算子尝试不同的kernel实现,然后选最快的那个。这个过程叫builder config中的setTacticSources。嗯,这里要注意,自动调优的时间可能很长,尤其是第一次构建引擎时。

// 一个典型的TensorRT构建配置示例
IBuilder* builder = createInferBuilder(gLogger);
IBuilderConfig* config = builder->createBuilderConfig();
config->setMemoryPoolLimit(MemoryPoolType::kWORKSPACE, 1 << 30); // 1GB工作空间
config->setFlag(BuilderFlag::kFP16); // 启用FP16

TensorRT的安装与配置

安装TensorRT,说实话,曾经让我头疼过一阵子。版本依赖关系比较复杂。我总结一下最稳妥的方式。

安装方式一:Deb包安装(推荐)

如果你用的是Ubuntu,这是最省心的方式。去NVIDIA官网下载对应CUDA版本的Deb包。

# 以TensorRT 8.6.1 for CUDA 11.8为例
os="ubuntu2204"
arch="x86_64"
version="8.6.1-1+cuda11.8"

# 安装
dpkg -i nv-tensorrt-local-repo-${os}-${version}_${arch}.deb
apt-get update
apt-get install tensorrt

我曾经踩过的坑:安装前一定要确认CUDA版本和TensorRT版本匹配。不匹配的话,编译时会出现各种奇怪的链接错误。我建议先查一下NVIDIA的兼容性矩阵。

安装方式二:Tar包安装

如果你需要自定义安装路径,或者要在多台机器上部署,Tar包更灵活。

# 解压到指定目录
tar -xzvf TensorRT-8.6.1.6.Linux.x86_64-gnu.cuda-11.8.tar.gz -C /opt/

# 设置环境变量
export LD_LIBRARY_PATH=/opt/TensorRT-8.6.1.6/lib:$LD_LIBRARY_PATH
export PATH=/opt/TensorRT-8.6.1.6/bin:$PATH

验证安装

安装完成后,跑一下自带的样例,这是最直接的验证方式。

# 进入样例目录
cd /opt/TensorRT-8.6.1.6/samples/sampleOnnxMNIST

# 编译并运行
make
./sample_onnx_mnist

如果看到输出结果和预期一致,说明安装成功了。

支持的硬件与精度

TensorRT不是所有NVIDIA GPU都支持。我整理了一个表格,方便你对照。

GPU架构 代表型号 支持精度 备注
Turing RTX 20系列、T4 FP32、FP16、INT8 支持Tensor Core
Ampere RTX 30系列、A100 FP32、FP16、INT8、TF32 TF32是Ampere新增的
Hopper H100 FP32、FP16、INT8、FP8 FP8是Hopper新增的
Volta V100 FP32、FP16、INT8 第一代Tensor Core
Maxwell/Kepler M40、K80 FP32 不支持INT8量化

重要提醒:如果你用的是Maxwell或Kepler架构的GPU,INT8量化就别想了。我有个朋友在K80上折腾了三天INT8,最后发现硬件不支持。嗯,查文档很重要。

精度选择建议

我个人习惯这样选:

  • FP32:追求精度,不追求速度。或者模型本身很小,不需要优化。
  • FP16:大多数场景的首选。速度提升1.5-2倍,精度损失几乎可以忽略。
  • INT8:对延迟要求极高的场景。速度提升3-4倍,但需要做校准,精度可能下降1-2%。
  • TF32/FP8:新架构的特有精度,目前生态还在完善中。

你想想看,如果你的模型在FP32下推理延迟是10ms,换成FP16可能降到5ms,换成INT8可能降到2.5ms。这个提升,在很多实时场景下是决定性的。

我的建议:刚开始接触TensorRT时,先从FP16入手。它最容易上手,效果也最明显。等熟悉了流程,再尝试INT8量化。别一上来就搞INT8,坑比较多。

好了,这一章的内容就到这里。TensorRT的核心概念、加速原理、安装配置、硬件支持,我都讲了一遍。下一章我们会真正动手,把一个ONNX模型编译成TensorRT引擎。到时候你会看到,这些理论知识是怎么落地的。