3. 推理引擎核心概念
在自动驾驶场景中,推理引擎并不是一个“把模型跑起来”的黑盒,而是一条由多个阶段串联而成的流水线。理解这条流水线上每个环节的职责与代价,是后续做性能分析和调优的前提。本章围绕模型加载、图优化、算子融合、内存管理、执行调度、批处理与流式推理七个核心术语展开,帮助建立统一的性能语言。
一、核心原理:推理引擎的七段流水线
一个典型的自动驾驶推理引擎,从磁盘上的模型文件到最终输出检测框或轨迹,需要经历七个关键阶段。它们并非严格串行,但逻辑上层层递进:
- 模型加载:将 ONNX、TensorRT、TorchScript 等格式的模型反序列化为内存中的计算图,并完成权重解析与设备绑定。
- 图优化:在计算图层面对节点进行常量折叠、死代码消除、布局转换等操作,减少冗余计算。
- 算子融合:把多个细粒度算子合并为一个内核,减少内核启动次数与中间张量读写。
- 内存管理:为输入、输出和中间张量分配显存或内存,并通过内存池、复用策略降低分配开销。
- 执行调度:决定算子在哪个流、哪个设备、以什么顺序执行,并处理依赖关系。
- 批处理:将多个请求合并为一个批次,提高硬件利用率,但会引入延迟。
- 流式推理:在连续输入场景下,以流水线方式重叠数据搬运与计算,降低端到端时延。
这七个概念共同决定了推理引擎的吞吐、延迟和资源占用。下面这张图展示了它们之间的数据流与依赖关系。
二、方法流程:一次推理请求的完整生命周期
以自动驾驶感知模型为例,一次推理请求从进入引擎到返回结果,通常遵循以下流程:
- 加载与初始化:引擎读取模型文件,构建计算图,完成图优化与算子融合,并预分配内存池。
- 输入准备:将相机图像或激光点云拷贝到设备内存,按模型要求做归一化、resize、layout 转换。
- 调度执行:调度器根据依赖关系将算子分配到 CUDA 流或 CPU 线程池,启动内核。
- 批处理决策:若当前有多个请求,引擎按策略合并为 batch;若为单帧实时场景,则可能选择 batch=1 以降低延迟。
- 流式重叠:在连续帧场景下,第 N 帧的计算与第 N+1 帧的数据搬运重叠,隐藏传输时间。
- 输出后处理:NMS、解码、坐标变换等操作在 CPU 或 GPU 上完成,最终返回结构化结果。
关键认知:模型加载和图优化属于“一次性成本”,而内存管理、执行调度、批处理和流式推理属于“每次推理的持续成本”。调优时,前者关注启动时间,后者关注稳态性能。
三、案例场景:批处理与流式推理的取舍
假设某自动驾驶域控制器上运行一个 BEV 感知模型,单帧推理耗时 30 ms。若采用 batch=1 的流式推理,端到端延迟约为 35 ms,满足 30 FPS 的实时要求;若将 4 帧合并为 batch=4,吞吐可提升到约 90 FPS,但单帧延迟会增加到 80 ms 以上,可能影响控制环路的稳定性。
因此,在自动驾驶场景中,流式推理通常优先于大 batch,因为延迟直接关系到安全。但在离线数据回放、模型评测等场景中,批处理可以显著提高吞吐,降低评测成本。
# 典型推理引擎配置片段(示意)
engine:
model: bev_detection.onnx
precision: fp16
graph_opt:
constant_folding: true
dead_code_elimination: true
fusion:
conv_bn_relu: true
attention_fusion: true
memory:
pool_size_mb: 512
reuse_tensors: true
scheduling:
streams: 2
priority: high
batch:
max_batch_size: 4
mode: dynamic
streaming:
enabled: true
overlap_preprocess: true
四、常见误区与复盘
| 误区 | 表现 | 正确理解 |
|---|---|---|
| 认为算子融合越多越好 | 融合后内核寄存器压力过大,反而降低占用率 | 融合需权衡寄存器、共享内存与并行度,并非越多越好 |
| 忽略内存池的预热 | 首次推理延迟远高于稳态,出现卡顿 | 应在初始化阶段完成内存池预热和 CUDA 上下文绑定 |
| 盲目增大 batch | 吞吐上升但延迟超标,控制环路抖动 | 实时场景优先保证延迟,batch 应动态可调 |
| 把流式推理等同于多线程 | 线程竞争导致调度开销反而增加 | 流式推理依赖流与事件机制,强调数据搬运与计算重叠 |
调优建议:先用 profiling 工具定位瓶颈属于加载、图优化、内存还是调度阶段,再针对性调整。不要在没有数据支撑的情况下同时修改多个参数,否则无法归因。