跳转至

AI 编译器与编译优化 复习资料

一、编译器基础概念

1. 编译器定义

编译器是一种计算机程序,用于将高级程序语言(如 C++、Java、Python 等)编写的源代码转换为计算机能够理解和执行的机器语言代码。

2. 编译器基本构成

组成部分 功能
前端(Front-End) 词法和语法分析,检查语法和语义,生成抽象语法树(AST)
优化器(Optimizer) 对中间代码进行优化,使代码更高效
后端(Back-End) 将优化后的中间代码转换为目标平台的机器代码

3. 从编译到装载的程序创建过程

HLL(高级语言)→ 编译器 → 汇编代码 → 汇编器 → 目标代码 → 链接器 → 可执行二进制代码 → 加载器 → 内存中的二进制指令


二、传统编译器

1. 代表:GCC 与 LLVM

核心概念:前端、后端、中间表达(IR)、优化过程

2. IR(Intermediate Representation,中间表示)

  • 用于表示中间代码的数据结构
  • 设计目的:保证编译器的跨平台性能
  • 对不同硬件平台使用相同的 IR 表示
  • 便于支持新语言和新硬件

3. LLVM 架构特点

  • 多语言前端(C→Clang, Go→Gollvm, Rust→rustc, Toy→toyc)统一生成 LLVM IR
  • 中间层(Middle-end)包含 LLVM 优化器,由多个 Pass 组成
  • 后端生成不同硬件架构的机器码(X86、ARM、MIPS、RISC-V 等)

Pass:对源程序的一次完整扫描与优化处理

4. GCC vs LLVM 对比

维度 GCC(传统) LLVM(现代)
架构 前端直连后端 前端 → IR → 后端
多语言支持 每种语言需适配所有后端 每种语言只需生成 IR
多硬件支持 每个硬件需适配所有前端 每个硬件只需处理 IR
复用性

三、AI 编译器

1. 传统编译器 vs AI 编译器对比

对比维度 传统编译器 AI 编译器
输入 高级语言代码 计算图 / 算子
输出 低级语言 低级语言
主要目的 降低编程难度 优化程序性能
次要目的 优化程序性能 降低编程难度

3. 核心区别

IR 表达层级差异

  • AI 编译器:High-level IR,抽象描述深度学习模型中的运算(Convolution、Matmul、Transformer 等),带有图结构
  • 传统编译器:Low-level IR,描述基本指令运算(load、store 等)

优化策略差异

  • AI 编译器:引入领域特定知识,进行 High-level 优化
  • 算子融合(Operator Fusion)
  • 降低计算精度(int8、fp16、bf16),因为深度学习对精度不敏感
  • 传统编译器:一般不执行改变变量类型和精度的优化

四、前端优化(硬件无关)

4.1 中间表示——计算图

  • 基本数据结构:Tensor(N 维数组)
  • Tensor 形状:[2, 3, 4]
  • 元素类型:int、float、string 等
  • 基本运算单元:Operator
  • 每个 Operator 接收 N 个输入 Tensor,输出 M 个输出 Tensor
  • TensorFlow 中有 >400 个基本 operator
  • 数据流图表示
  • 节点 = Operator
  • 边 = Tensor

4.2 算术表达式化简

通过代数等价变换化简计算图:

化简规则 示例
乘零 a × 0 → 0
乘一 a × 1 → a
加零 a + 0 → a
对数展开 log(exp(x)/y) → x - log(y)

还可利用交换律、结合律调整算子执行顺序。

4.3 公共子表达式消除(CSE)

  • 找到程序中等价的计算表达式,复用结果消除冗余计算
  • AI 编译器中基于计算图搜索相同结构的子图

4.4 死代码消除(DCE)

  • 移除对程序执行结果无影响的代码
  • 优点:提高效率、节省资源、减少代码长度
  • 常在其他图优化 Pass 后应用(如删除推理时仅训练相关的子图)

4.5 常量折叠(Constant Folding)

  • 对编译时常量或常量表达式进行计算来简化代码
  • 在编译期计算并化简

BN 折叠(Batch Normalization Folding)

  • 训练时:μ、σ、γ、β 持续更新
  • 推理时:四个值固定,BN 变为线性变换
  • 卷积也是线性变换 → 可合并为单一线性变换

4.6 算子融合(Operator Fusion)

  • 将多个向量化算子的操作合并成一个
  • 好处:减少内核启动开销、减少内存读取、提高计算密度

4.7 布局转换(Layout Transform)

多维数组在内存中的数据布局方式。

常见布局

布局 含义 特点
NCHW Batch, Channel, Height, Width 每个通道数据连续,适合 GPU,PyTorch/MindSpore 默认
NHWC Batch, Height, Width, Channel 每个像素点数据连续,适合 CPU,TensorFlow 默认

相同数据不同布局导致访问特性不同,影响计算性能。

4.8 内存分配优化

  • Inplace Operation(原地操作):内存不再需要且下一操作是 element-wise 时,直接覆盖内存,无需分配新内存
  • 通过对计算图分析,找到 Inplace Operation 和 Memory Sharing 的机会

前端优化总结

前端优化主要通过图的等价变换化简计算图,降低计算复杂度或内存开销,与硬件无关


五、后端优化(硬件相关)

5.1 后端优化关注点

  • 算子节点的内部具体实现
  • 输入、输出、内存循环方式和计算逻辑

5.2 循环优化

循环展开(Loop Unrolling)

  • 减少循环开销,使能后续优化(如指令并行)

循环分块(Loop Tiling / Blocking)

  • 将数据分块存储在 Cache 中,提高访存效率和数据局部性
  • 避免频繁从主存读取数据带来的访问延迟

循环融合(Loop Fusion)

  • 将相邻或紧密间隔的循环融合在一起
  • 减少循环开销,增加计算密度,改善缓存局部性

循环拆分(Loop Split / Distribution)

  • 将一个循环分解成多个循环
  • 便于后续优化或满足特定硬件约束