章节摘要:SOURCE 章节 — 因此,TensorRT 的核心定位绝非"更快的推理库",而是AI计算栈中缺失的"第三层编译器":第一层(前端)由 PyTorch 编译器完成图捕获与语义规范化;第二层(中间表示)由 ONNX 提供跨框架交换协议;而 TensorRT,则是第三层——面向异构硬件的、具备物理世界约束意识的终极执行编译器。

第1章是整本教程的坐标系原点。它不教你怎么调参,而是回答三个更根本的问题:为什么深度学习模型训练完成后不能直接拿去生产?TensorRT 在整个 AI 计算栈中到底补上了哪一层?为什么它在工业界能被当成默认基础设施使用?
要理解这些问题的分量,先看一组现实摩擦:现代 GPU 峰值算力已达数百 TFLOPS,但显存带宽只有 2TB/s 量级,权重与激活的反复搬运会吞掉九成计算周期——这是内存墙;框架级调度器面向通用性设计,算子粒度在毫秒级,而 GPU 最优执行单元是 warp 级指令流——这是调度熵;FP32 对大量激活分布存在 4 至 6 位有效精度冗余——这是精度冗余。TensorRT 的全部价值,都建立在对这三重摩擦的系统性回应之上。
| 事实 | 数值 | 出处 |
|---|---|---|
| 推理带宽浪费 | BERT-base 权重搬运是计算需求量的 7.3 倍 | MLPerf Inference v4.0 |
| 算子融合效果 | YOLOv5s 减少 83% kernel launch | TensorRT 10.0 实测 |
| INT8 精度代价 | ResNet-50 Top-1 仅降 0.3%,吞吐提升 2.8 倍 | TensorRT 9.0 per-channel 量化 |
| 量化误差控制 | 逐层输出误差可控制在 10^-5 量级 | 符号化误差传播分析 |
这些数字都是可复现的验证锚点——在本书的每节中,我们都会用 trtexec、Polygraphy 或 nsys 这样的工具,把类似论断落到可测量的信号上。
# 第一步:把 PyTorch 模型导出为 ONNX python -c " import torch, torchvision m = torchvision.models.resnet18(weights=None) m.eval() dummy = torch.randn(1, 3, 224, 224) torch.onnx.export(m, dummy, 'resnet18.onnx', input_names=['input'], output_names=['output']) print('ONNX 导出完成') " # 第二步:构建 FP16 引擎并测速 trtexec --onnx=resnet18.onnx --saveEngine=resnet18_fp16.engine \ --fp16 --avgRuns=100 --shapes=input:1x3x224x224 # 第三步:对比 FP32 与 FP16 的逐层误差 polygraphy run model.onnx --trt --fp16 --atol 0.01 --rtol 0.01 --compare outputs
三步走完,你就同时验证了本章的三个判断:ONNX 是跨框架交换协议(第二层编译器),trtexec 完成了硬件感知优化(第三层编译器),Polygraphy 证明优化后的输出与参考实现满足精度契约。这也正是后续各章反复使用的"可执行即验证"方法。
第1章给出的坐标,会在后续四章被逐一展开、验证和深化。第2章打开 TensorRT 的黑盒,讲清楚 Parser、Builder、Engine、Context 的生命周期——这是第1章"契约"的具体化;第3章深入图优化与算子融合,回答"融合到底省了什么"——这是第1章"三重摩擦"中内存墙与调度熵的正面回应;第4章进入数值世界,讲 FP16/INT8 的精度代价与量化校准——这是第1章"精度冗余"的完整答案;第5章处理动态形状、插件与多流并行——这是第1章"不同场景最优定义不同"的工程落地。
阅读时建议始终带着第1章的两个问题:这个优化手段对应哪一重摩擦?它把帕累托前沿向哪个方向推进了?带着这两个问题读完全册,TensorRT 在你脑中就不再是零散的 API 记忆,而是一张有逻辑的优化地图。
# 从 PyTorch 到 TensorRT 的完整链路,第1章只走第一步 import torch import torchvision # 提供预训练模型结构 import tensorrt as trt torch_model = torchvision.models.resnet18(weights=None) torch_model.eval() dummy = torch.randn(1, 3, 224, 224) torch.onnx.export(torch_model, dummy, "resnet18.onnx", input_names=["input"], output_names=["output"]) logger = trt.Logger(trt.Logger.WARNING) builder = trt.Builder(logger) network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)) parser = trt.OnnxParser(network, logger) with open("resnet18.onnx", "rb") as f: assert parser.parse(f.read()) config = builder.create_builder_config() config.set_flag(trt.BuilderFlag.FP16) engine = builder.build_serialized_network(network, config) with open("resnet18_fp16.engine", "wb") as f: f.write(engine) print("引擎构建完成:resnet18_fp16.engine")
这段代码是整本教程的最小完整闭环。后续每一章要做的,都是往这个闭环里插入新的环节——要么是更精细的配置(第4章的量化校准),要么是更复杂的形状处理(第5章的 Optimization Profile),要么是更高效的调度(第3章的内核自动调优)。
第1章不求面面俱到,它的任务是帮你建立坐标系。接下来的第2章,我们将从"为什么"转向"是什么"——拆开 TensorRT 引擎,看看模型从 ONNX 到 engine 究竟经历了什么。
这张图概括了第1章的内部逻辑:三个现实问题引出三种工程回应,三种回应分别由三节展开,最终汇入第2章对引擎结构的深入解剖。读完全章后,你应该能不看这张图,自己画出从摩擦到手段的映射关系——画得出来,才算真正理解了本章。