3. 中间表示基础

在自动驾驶模型从训练框架走向车端芯片的工程链路中,中间表示(Intermediate Representation,IR)是承上启下的关键数据结构。它既不是训练框架里的原始模型对象,也不是最终芯片上的机器码,而是一种经过抽象、规范化和可分析化的程序表达形式。理解 IR,本质上就是理解“模型如何被编译器读懂、改写并落地到不同硬件”。

核心结论:IR 是编译器与深度学习框架之间的“通用语言”。它把模型从框架私有格式中解耦出来,使优化、量化、切分、映射和代码生成可以在统一语义下进行。

一、IR 的核心原理:为什么需要中间表示

深度学习模型在 PyTorch、TensorFlow 等框架中通常以动态图或静态图形式存在,带有大量框架特有的对象、控制流和运行时依赖。如果直接把这种模型交给车端芯片编译器,会面临三个问题:语义不统一、优化空间不透明、硬件映射困难。IR 的作用就是在这三者之间建立一层稳定、可验证、可变换的抽象。

从编译器视角看,IR 需要满足几个基本条件:第一,语义明确,每个节点和边都有确定含义;第二,结构可分析,便于做依赖分析、生命周期分析和内存规划;第三,变换可组合,优化 Pass 可以按顺序叠加而不破坏正确性;第四,目标可降级,能够逐步 lowering 到不同硬件后端。深度学习框架中的 IR 还额外强调张量形状、数据类型、算子属性和设备放置等信息。

可以把 IR 理解为一张“带语义的程序地图”:节点表示计算或数据,边表示依赖关系,属性描述形状、类型、布局和量化参数。编译器在这张地图上做常量折叠、算子融合、死代码消除、内存复用和算子替换,最终生成面向 NPU、GPU 或 DSP 的可执行代码。

二、IR 在编译器与深度学习框架中的作用

在编译器侧,IR 是优化和代码生成的载体。典型流程是:前端把框架模型转换为高层 IR,经过图级优化后逐步降低到低层 IR,再经过算子选择和调度生成目标代码。在深度学习框架侧,IR 承担模型导出、跨框架转换和部署描述的角色,例如 ONNX 就是一种被广泛支持的图 IR 交换格式。

具体作用可以归纳为以下清单:

  • 解耦框架与硬件:同一份 IR 可以面向不同芯片后端生成代码,减少重复适配。
  • 支撑图级优化:常量折叠、算子融合、布局转换、死代码消除都依赖 IR 结构。
  • 承载量化与精度信息:量化 scale、zero point、数据类型可在 IR 中显式表达。
  • 支持静态分析与内存规划:通过张量生命周期分析复用显存或片上内存。
  • 便于验证与调试:IR 可在不同阶段导出,定位精度损失或算子不支持问题。

三、常见 IR 分类:图 IR、张量 IR、算子 IR

按照抽象层次和表达重点,常见 IR 可以分为图 IR、张量 IR 和算子 IR。它们不是互斥关系,而是同一编译流水线中不同阶段的表达形态。

类型表达重点典型内容常见阶段
图 IR计算图结构与依赖关系节点、边、输入输出、控制流、子图模型导入、图优化
张量 IR张量形状、类型、布局与内存shape、dtype、stride、layout、buffer形状推导、内存规划
算子 IR具体算子的语义与属性Conv、MatMul、Add、激活、量化参数算子选择、代码生成

图 IR 更接近“程序结构”,适合做全局优化;张量 IR 更接近“数据布局”,适合做内存和并行分析;算子 IR 更接近“硬件指令”,适合做后端映射。实际工程中,三者往往嵌套存在:图 IR 的节点内部可以携带张量 IR 描述,算子 IR 则作为图节点的具体实现。

四、方法流程:从模型到 IR 的典型链路

以自动驾驶感知模型部署为例,一条典型链路如下:

PyTorch 模型
  → torch.export / ONNX 导出
  → 高层图 IR(节点 + 张量描述)
  → 图优化 Pass(融合、常量折叠、布局转换)
  → 量化 IR(插入 Q/DQ 节点,记录 scale/zero_point)
  → 低层算子 IR(目标算子集)
  → 内存规划与调度
  → 车端芯片可执行代码

在这个过程中,IR 需要保持“可回退”和“可验证”。例如某算子在后端不支持时,可以通过 IR 回退到 CPU 或替换为等价子图;量化精度异常时,可以对比量化前后 IR 的节点差异,定位是哪一层引入的误差。

五、案例与场景:IR 如何解决实际问题

假设一个 BEV 感知模型包含大量卷积、注意力算子和自定义后处理。直接部署到某国产 NPU 时,发现注意力中的 Softmax 不支持动态形状。此时编译器可以在图 IR 层识别该模式,将其替换为“固定形状 + 掩码”的等价子图;在张量 IR 层重新推导 shape 和 stride;在算子 IR 层选择 NPU 支持的 Softmax 变体。整个过程不需要修改原始训练代码,这就是 IR 带来的工程价值。

另一个常见场景是跨平台部署:同一模型需要同时跑在 Orin、地平线征程和黑芝麻芯片上。通过统一的图 IR 作为中间层,各后端只需实现自己的 lowering 和算子库,前端导出和优化流程可以复用,显著降低多平台适配成本。

六、误区与复盘

误区一:把 IR 等同于 ONNX。ONNX 只是图 IR 的一种交换格式,IR 还包括张量 IR、算子 IR 以及编译器内部的多层表示。
误区二:认为 IR 越底层越好。过早降低到算子 IR 会丢失图级优化机会,通常应先在高层 IR 完成融合与量化,再逐步 lowering。
误区三:忽略 IR 的语义完整性。如果 IR 丢失了布局、量化或控制流信息,后端生成结果可能正确性下降或性能劣化。

复盘建议:在部署工程中,应把 IR 当作“可观测的中间产物”来管理。每个优化阶段都导出 IR 快照,配合精度对比和性能剖析,才能快速定位问题。理解图 IR、张量 IR、算子 IR 的分工,是后续学习模型转换、量化、算子融合和跨平台后端适配的基础。

自动驾驶模型部署中的 IR 分层与流转 训练框架模型 PyTorch / TensorFlow 动态图 / 静态图 导出 中间表示 IR 图 IR(Graph IR) 节点 / 边 / 依赖 / 控制流 / 子图 用于:图优化、算子融合、常量折叠 张量 IR(Tensor IR) shape / dtype / stride / layout / buffer 用于:形状推导、内存规划、并行分析 算子 IR(Operator IR) Conv / MatMul / Add / 激活 / 量化参数 用于:算子选择、调度、代码生成 Lowering 硬件后端 NPU / GPU / DSP / CPU 算子库 + 调度器 IR 上的典型优化 Pass 链 常量折叠 算子融合 布局转换 量化插入 内存复用 不支持算子回退 / 精度验证