一句话理解模型部署
模型部署 = 把训练好的 PyTorch 模型"翻译"成能在车端芯片上飞快运行的优化引擎,同时尽可能不掉精度。
在自动驾驶中,模型部署的终极目标是在50ms 以内(甚至 30ms 以内)完成感知→规划的全链路推理,同时满足功耗、散热、成本的工程约束。
🎯 ONNX:开放神经网络交换格式
什么是 ONNX
ONNX(Open Neural Network Exchange)是微软和 Meta 联合推出的中间表示格式,充当不同深度学习框架之间的"通用语言":
ONNX 将模型表示为计算图(Computational Graph):
- 节点:算子(Conv, Relu, Add, MatMul…)
- 边:张量(Tensor)
- 属性:算子参数(kernel size, stride…)
PyTorch → ONNX 导出
import torch
model = torch.load("model.pth").eval()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
model,
dummy_input,
"model.onnx",
opset_version=17,
input_names=["input"],
output_names=["output"],
dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}}
)
关键参数:
| 参数 | 作用 | 建议 |
|---|---|---|
opset_version | ONNX 算子集版本 | 越高支持算子越多,但需目标推理引擎也支持 |
dynamic_axes | 声明动态轴的维度 | 对 batch 维度必须设置 |
input/output_names | 为输入输出命名 | 便于引擎构建时绑定 |
常见导出问题
- 算子不支持:某些 PyTorch 算子无对应 ONNX 算子。可用
register_custom_op_symbolic注册自定义映射或用原生算子改写 - 动态 shape:ONNX 默认所有张量 shape 固定,使用
dynamic_axes声明可变维度 - 控制流:
if/for需展开为静态图,torch.jit.script可处理多数情况
⚙️ TensorRT:NVIDIA 推理优化引擎
核心优化
| 优化技术 | 原理 | 加速效果 |
|---|---|---|
| 层融合(Layer Fusion) | Conv+BN+Relu 等合并为一个大算子 | 30~50% |
| 精度校准(INT8/FP8) | 使用更低精度数据类型 | 50~200% |
| 内存复用 | 分析 tensor 生命周期,复用内存 | 降低显存占用 |
| 内核自动调优 | 为每个算子搜索最优 CUDA kernel | 10~30% |
ONNX → TensorRT Engine
import tensorrt as trt
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("model.onnx", "rb") as f:
parser.parse(f.read())
config = builder.create_builder_config()
config.set_flag(trt.BuilderFlag.FP16)
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30)
serialized_engine = builder.build_serialized_network(network, config)
with open("model.engine", "wb") as f:
f.write(serialized_engine)
部署流水线
🔢 INT8 量化
为什么要量化
| 精度 | 位宽 | 模型体积 | 推理速度 | 相对精度 |
|---|---|---|---|---|
| FP32 | 32 bit | 100% | 1x | 基准 |
| FP16 | 16 bit | 50% | ~2x | 几乎无损 |
| INT8 | 8 bit | 25% | ~4x | 轻微下降 |
| FP8 (E4M3) | 8 bit | 25% | ~4x | 接近 FP16 |
| INT4 | 4 bit | 12.5% | ~6x | 明显下降 |
校准(Calibration)
INT8 量化需要确定每个 tensor 的动态范围:$real_value = scale \times int8_value$。
TensorRT 支持三种方法:
- Entropy (KL 散度):寻找最优阈值 $T^* = \arg\min_T KL(P_{\text{FP32}} || Q_T)$,效果最好,默认推荐
- Percentile:取 99.9% 百分位作为阈值,速度更快
- MinMax:使用激活绝对最大值,对 outlier 敏感
校准数据选择
config.set_flag(trt.BuilderFlag.INT8)
config.int8_calibrator = MyCalibrator(calibration_data)
# 校准数据:从训练集选取 500~1000 张代表性样本
# 覆盖白天/夜晚、城市/高速等场景
# 校准只观察激活分布,不需要标签
INT8 精度评估
在验证集上分别运行 FP32 和 INT8 模型,逐类计算 mAP 差值。对精度下降 > 1% 的类别进行人工分析(通常是小目标或远距离目标),必要时通过 per-layer precision override 对敏感算子保持 FP16。
🚗 VLA 大模型的车端部署
VLA 的独特挑战
视觉-语言-动作(VLA)模型(如 DriveVLM、EMMA)将 LLM/VLM 引入驾驶决策,却带来了巨大的部署挑战:
| 挑战 | 说明 |
|---|---|
| 模型体积大 | 7B ~ 70B 参数,FP16 权重 14GB ~ 140GB |
| 推理延迟高 | 自回归生成每 token 一次 forward,10~100ms/token |
| 显存需求大 | KV cache 随序列长度增长,长上下文需数十 GB |
| 功耗限制 | 车端散热有限,Orin 功耗上限 15~60W |
LLM/VLM 量化
AWQ(Activation-aware Weight Quantization):权重中约 1% 的 salient channels 对量化敏感,按通道保留 FP16、其余 INT4。
GPTQ(Post-Training Quantization):逐层做 Hessian-aware 量化,支持 INT4/INT3/INT2。
model = AutoModelForCausalLM.from_pretrained("drive-vlm-7b")
awq_model = autoawq.quantize(model, quant_config={"bits": 4, "group_size": 128}, calib_data=calib_dataset)
# 14GB → 4GB,100ms/token → 15ms/token
KV Cache 优化与 Continuous Batching
Continuous batching 将多条推理请求动态合并,不同请求可处于 prefill/decode 的不同阶段,吞吐量提升 2~4 倍。其他关键优化:MQA/GQA(25x)、KV Cache 量化 FP8/INT8(~2x)、PagedAttention(显存利用率提升)。
💻 边缘计算硬件
| 芯片 | 算力 (TOPS) | 功耗 | 制程 | 代表车型 |
|---|---|---|---|---|
| NVIDIA Orin | 254 | 15~60W | 8nm | 蔚来 ET7, 理想 L9, 小鹏 G9 |
| Orin NX | 100 | 10~25W | 8nm | 中低算力方案 |
| NVIDIA Thor | 2000 | 200W | 4nm | 2026+ 集中式计算平台 |
| Snapdragon Ride | 360~700 | 5~65W | 4nm | 宝马、通用 |
| Horizon Journey 5 | 128 | ~30W | 12nm | 比亚迪、理想 |
推理延迟预算
🔧 模型压缩
除量化外,部署前常用的模型压缩手段包括:
剪枝(Pruning):移除贡献小的权重或通道。结构化剪枝(按 channel/filter 裁剪)能直接加速推理,非结构化剪枝需稀疏硬件支持。
知识蒸馏(Knowledge Distillation):用大教师模型的 soft label 训练小模型。在 BEV 感知中常用:教师输出 BEV feature → 学生模仿 feature map,而非只模仿最终检测结果。
量化感知训练(Quantization-Aware Training, QAT):在训练过程中模拟量化误差,使权重适应低精度表示。QAT 通常比 PTQ(训练后量化)精度高 1~3%,但需要额外训练步骤和标注数据。
| 方法 | 压缩率 | 精度损失 | 是否需要重训 |
|---|---|---|---|
| 结构化剪枝 | 20~50% | 低~中 | 是 |
| 知识蒸馏 | 2~10x | 低 | 是(训练学生) |
| PTQ (INT8) | 4x | 低 | 否(仅校准) |
| QAT (INT8) | 4x | 极低 | 是(微调) |
部署最佳实践
- 算子选择:避免 ONNX 不支持的算子(如
torch.einsum、自定义 CUDA kernel) - 动态 shape:尽量减少动态维度,或使用 TensorRT optimization profiles
- 多 stream 并行:让预处理和推理在 CUDA stream 上重叠执行
- 线程绑定:推理线程绑定到特定 CPU core,避免调度抖动
🔮 趋势
- 端侧大模型:随着量化(AWQ/GPTQ)和硬件(Thor/Snapdragon)进步,7B 级 VLA 模型有望 2027 年在车端实时推理
- 模型蒸馏:将大 VLA 模型(70B)知识蒸馏到小模型(7B),保留推理能力的同时缩小体积
- 编译器后端:MLIR/LLVM 化的推理引擎(如 Apache TVM)实现跨硬件多端部署
- 安全认证:ISO 26262 ASIL-D 级别的推理引擎认证,确保部署模型的功能安全
📚 延伸阅读
- NVIDIA. “TensorRT Developer Guide.” NVIDIA Docs, 2023.
- Lin, J. et al. “AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration.” MLSys, 2024.
- Frantar, E. et al. “GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers.” ICLR, 2023.
- Kwon, W. et al. “Efficient Memory Management for Large Language Model Serving with PagedAttention.” SOSP, 2023.
- Team, T. L. “LLaMA: Open and Efficient Foundation Language Models.” arXiv, 2023.
- Hu, Y. et al. “TensorRT LLM: A TensorRT-based Framework for Optimizing LLM Inference.” NVIDIA, 2024.