Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 人工智能 / Artificial Intelligence

AI 编译器 / AI Compilers

1. AI 编译器全景——为什么模型需要编译器 / The AI Compiler Landscape and Why Models Need Compilers

2. 编译原理速通——面向 ML 工程师的核心概念 / Compiler Fundamentals for Machine Learning Engineers

3. 中间表示基础——理解 IR 层级与 lowering 链路 / Intermediate Representation Levels and Lowering Pipelines

4. 计算图的构建与表示 / Building and Representing Computational Graphs

5. MLIR 架构、方言与渐进式降级 / MLIR Architecture, Dialects, and Progressive Lowering

6. 算子语义、广播、归约与形状推导 / Operator Semantics, Broadcasting, Reduction, and Shape Inference

7. 模型前端格式:ONNX、TFLite、HLO 与 SavedModel / Model Frontend Formats: ONNX, TFLite, HLO, and SavedModel

8. 图优化 Pass——经典优化在 ML 中的应用 / Graph Optimization Passes for Machine Learning

9. 算子融合——编译器最重要的性能优化 / Operator Fusion as a Core Compiler Optimization

10. 内存规划——Buffer 分配与生命周期管理 / Memory Planning, Buffer Allocation, and Lifetime Management

11. Layout 优化——数据排布转换与内存效率 / Layout Optimization for Data Movement and Memory Efficiency

12. 动态 Shape——符号分析与形状处理 / Dynamic Shapes, Symbolic Analysis, and Shape Processing

13. 硬件约束下的操作调度 / Operation Scheduling Under Hardware Constraints

14. 从模板、DSL 到 IR 降级的代码生成架构 / Code Generation Architectures from Templates and DSLs to IR Lowering

15. CPU 后端:SIMD、分块与多线程 / CPU Backends with SIMD, Tiling, and Multithreading

16. CUDA 后端:合并访存与 Tensor Core / CUDA Backends, Memory Coalescing, and Tensor Cores

17. NPU 后端:脉动阵列与端侧 AI 生态 / NPU Backends, Systolic Arrays, and Edge AI Ecosystems

18. Kernel 性能基础:Roofline 与 Occupancy / Kernel Performance Fundamentals with Roofline and Occupancy

19. CUTLASS 与分层 GEMM 模板 / CUTLASS and Hierarchical GEMM Templates

20. TVM Tensor Expression 与计算调度分离 / TVM Tensor Expressions and Compute-Schedule Separation

21. 使用 Triton 编写高性能 GPU Kernel / Triton for High-Performance GPU Kernels in Python

22. 基于成本模型与实测搜索的自动调度 / Automatic Scheduling with Cost Models and Measurement-Based Search

23. XLA 内部机制:HLO、融合与 SPMD / XLA Internals, HLO, Fusion, and SPMD

24. Torch-MLIR:从 PyTorch 算子到 MLIR 方言 / Torch-MLIR from PyTorch Operators to MLIR Dialects

25. torch.compile:Dynamo、AOTAutograd、Inductor 与 Triton / Torch Compile with Dynamo, AOTAutograd, Inductor, and Triton

26. 从 MLIR 经 LLVM 降级到机器码 / Lowering from MLIR Through LLVM to Machine Code

27. 量化——低精度推理的工程实践 / Engineering Low-Precision Inference with Quantization

28. 分布式编译与训练——多设备编排的编译器支持 / Compiler Support for Distributed Training and Multi-Device Orchestration

29. 生产调试——真实问题的编译器视角排查 / Production Debugging from the Compiler Perspective

30. 未来方向——AI 编译器的新挑战与机遇 / Future Challenges and Opportunities for AI Compilers

本页目录

📅 创建时间:2026-06-03 🏷️ 标签:#MLIR #Dialect #方言 #Linalg #SCF #Affine #IREE #ODS #重用力

📚 前置知识:[[02-ir-fundamentals]](IR 基础) 📚 相关知识:[[03-graph-representation]](计算图表示)[[25-mlir-llvm]](MLIR-LLVM 集成)


MLIR 架构、方言与渐进式降级 / MLIR Architecture, Dialects, and Progressive Lowering ​

┌──────────────────────────────────────────────────────────────────────────────┐
│  🎯 场景:为什么 IREE 能用同一个 IR 编译 PyTorch 和 TensorFlow 模型              │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  你在研究 IREE(一个基于 MLIR 的推理引擎),发现它能同时:                        │
│                                                                              │
│    ✅ 把 TensorFlow 模型 lower 到 Linalg Dialect                              │
│    ✅ 把 PyTorch 模型 lower 到 Linalg Dialect                                 │
│    ✅ 最终 lower 到 LLVM Dialect,运行在 x86、ARM、RISC-V 上                    │
│                                                                              │
│  但 TensorFlow 和 PyTorch 的算子完全不同,                                      │
│  为什么能用同一个中间表示?Dialect 到底是什么?                                  │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14

第1节:MLIR 之前的问题——每个框架维护自己的编译器 ​

1.1 深度学习编译器的碎片化 ​

在 MLIR 出现之前(大约 2019 年之前),每个深度学习框架都维护自己的编译器栈:

┌─────────────────────────────────────────────────────────────────────────────┐
│                         深度学习编译器碎片化时代                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   TensorFlow              PyTorch                    MXNet                   │
│       │                      │                         │                    │
│       ▼                      ▼                         ▼                    │
│   ┌────────┐           ┌────────┐              ┌────────┐                │
│   │ TF/XLA │           │ Torch  │              │  NNVM  │                │
│   │        │           │ Script │              │  /TVM  │                │
│   └────┬───┘           └────┬───┘              └────┬───┘                │
│        │                    │                         │                    │
│        ▼                    ▼                         ▼                    │
│   ┌────────┐           ┌────────┐              ┌────────┐                │
│   │TF/Lite │           │Mobile  │              │   TVM  │                │
│   │Compiler│           │Support │              │Runtime │                │
│   └────────┘           └────────┘              └────────┘                │
│                                                                             │
│   问题:每个框架都要独立实现:                                                  │
│     ❌ 算子 lowering                                 │
│     ❌ 优化通道(pass)                              │
│     ❌ 目标代码生成                                  │
│     ❌ 硬件支持                                      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

1.2 每个框架的问题 ​

框架编译器问题
TensorFlowXLA维护两套编译器(TF/XLA 和 TFLite),代码重复
TensorFlow LiteTFLite只有有限的操作支持,自定义算子困难
PyTorchCaffe2 → ONNX转换路径不统一,精度丢失
MXNetNNVM → TVM影响力小,生态有限
ONNX各框架实现opset 版本混乱,行为不一致
python
"""
具体问题的例子:实现一个 Conv + ReLU 融合

在 TensorFlow/XLA 中:
    需要在 XLA 的 HLO 级别实现融合
    代码位置:tensorflow/compiler/jit/

在 TensorFlow Lite 中:
    需要在 TFLite 的 operator 级别实现
    代码位置:tensorflow/lite/kernels/

在 PyTorch 中:
    需要在 ATen/核心库级别实现
    代码位置:aten/src/ATen/native/

同一个优化逻辑,需要在 3 个不同的地方实现!
而且实现语言也不同(XLA 用 C++, TFLite 用 C++, ATen 用 C++)
但核心逻辑是类似的。
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

第2节:MLIR 的核心洞察——方言作为可扩展的类型化 IR ​

2.1 MLIR 的设计哲学 ​

MLIR(Multi-Level Intermediate Representation)由 Chris Lattner 在 2019 年提出,核心洞察是:

方言(Dialect)作为可扩展的类型化 IR,允许不同抽象级别的表示共存于同一个系统中。

python
"""
MLIR vs 传统 IR 的对比

传统 IR(如 LLVM IR):
    只有一种表示方式
    从高级语言到机器码需要一次"大跳跃"
    所有信息都被 lowered 到同一种形式

MLIR:
    多种方言共存于同一系统
    每个方言代表一个抽象级别
    可以逐步 lower(多级lowering)
    信息可以在高级方言中保留更久
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14

2.2 方言层级架构 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                          MLIR Dialect 层级                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  高层方言(接近算法)                                                          │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Linalg Dialect:线性代数操作(matmul, conv, pooling)                    │   │
│  │  "表示:通用批量矩阵乘法、卷积等计算"                                      │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  SCF Dialect (Structured Control Flow):结构化控制流(if, for, while)  │   │
│  │  "表示:循环嵌套、条件分支"                                              │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  中层方言(接近硬件)                                                          │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Affine Dialect:仿射循环变换(loop tiling, fusion, unrolling)        │   │
│  │  "表示:多面体分析,可优化的循环结构"                                     │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  MemRef Dialect:内存引用(load, store, alloc, dealloc)               │   │
│  │  "表示:内存访问模式"                                                   │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  低层方言(接近硬件/指令)                                                      │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Vector Dialect:向量操作(vector.load, vector.store, vector.contract) │   │
│  │  "表示:SIMD 指令"                                                     │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  LLVM Dialect:LLVM 类型化 SSA                                        │   │
│  │  "表示:LLVM IR 的 MLIR 表示"                                          │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  SPIR-V Dialect:GPU 着色器                                           │   │
│  │  "表示:Vulkan/OpenCL 着色器代码"                                       │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

2.3 为什么方言是可扩展的 ​

MLIR 允许用户定义自己的方言:

python
"""
定义一个新方言的动机

场景:硬件公司有自己的特殊加速器

问题:
    - 加速器有自己的指令集
    - 现有方言无法直接表示
    - 但又希望利用 MLIR 的优化基础设施

解决方案:
    定义一个 CustomHW Dialect
    然后写 Lower 规则到 Linalg 或 LLVM

这样可以:
    1. 利用 MLIR 的通用优化(死代码消除、公共子表达式等)
    2. 在 CustomHW Dialect 级别做硬件特定的优化
    3. 通过 Lower 到已知方言来实现代码生成
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

第3节:主要方言详解 ​

3.1 Linalg Dialect(线性代数) ​

Linalg 是 MLIR 中最常用的高层方言,专门用于表示批量线性代数操作。

python
"""
Linalg Dialect 特点:
1. 面向批量操作:支持 batch matmul, grouped conv 等
2. 迭代空间显式:循环边界在操作参数中
3. 融合友好:容易识别可融合的操作
4. 硬件无关:可以 lower 到 CPU/GPU/NPU

示例:Linalg Matmul
    linalg.matmul ins(%A, %B : memref<?x?xf32>, memref<?x?xf32>)
               outs(%C : memref<?x?xf32>)
"""
1
2
3
4
5
6
7
8
9
10
11

Linalg 操作列表:

操作含义数学表示
linalg.matmul矩阵乘法C[i][j] += A[i][k] * B[k][j]
linalg.batch_matmul批量矩阵乘法BMM[b][i][j] += A[b][i][k] * B[b][k][j]
linalg.conv_2d2D 卷积标准 CNN 卷积
linalg.generic通用索引映射任意逐元素操作
linalg.pooling_max最大池化window max
linalg.pooling_sum求和池化window sum

3.2 SCF Dialect(结构化控制流) ​

SCF(Structured Control Flow) 表示高级控制流结构。

python
"""
SCF Dialect 特点:
1. 结构化:if, for, while 都有良好的嵌套结构
2. SSA 形式:使用 SSA 值而非内存
3. 可转换:可以 lower 到 CFG(控制流图)或 Affine

示例:SCF If
    scf.if %cond {
        // then 分支
        %0 = ...
    } else {
        // else 分支
        %1 = ...
    }

示例:SCF For 循环
    scf.for %i = %c0 to %c100 step %c1 {
        %val = memref.load %A[%i] : memref<100xf32>
        ...
    }
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

3.3 Affine Dialect(仿射循环优化) ​

Affine 用于表示可以分析优化的循环结构,基于多面体模型(Polyhedral Model)。

python
"""
Affine Dialect 特点:
1. 循环边界是仿射表达式:i < 1024, i < N*M
2. 索引是仿射表达式:A[i, j] where i, j from loops
3. 支持复杂变换:
   - loop tiling
   - loop interchange
   - loop fusion
   - loop unrolling

示例:Affine For
    affine.for %i = 0 to 100 {
        affine.for %j = 0 to 100 {
            %val = affine.load %A[%i, %j] : memref<100x100xf32>
            ...
        }
    }
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

3.4 Vector Dialect(向量操作) ​

Vector 表示 SIMD 和向量操作,是从高层到底层硬件的桥梁。

python
"""
Vector Dialect 特点:
1. 面向硬件向量宽度:vscale * 16 等
2. 支持向量 Load/Store
3. 支持向量点积、矩阵乘法等操作

示例:向量 Load
    vector.load %A[%i, %j], %memref : memref<?x?xf32>, vector<8xf32>

示例:向量点积
    vector.contract {
      indexing_maps = [
        affine_map<(i, j, k) -> (i, k)>,
        affine_map<(i, j, k) -> (k, j)>,
        affine_map<(i, j, k) -> (i, j)>
      ],
      iterator_types = ["parallel", "parallel", "reduction"]
    } %A, %B, %C : vector<4x8xf32>, vector<8x16xf32>, vector<4x16xf32>
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

3.5 LLVM Dialect(LLVM 集成) ​

LLVM 提供和 LLVM IR 的双向转换。

python
"""
LLVM Dialect 特点:
1. 类型映射:
   - MLIR i32 → LLVM i32
   - MLIR memref → LLVM {ptr, offset, shape}
   - MLIR func → LLVM function
2. 支持 Intrinsics 调用
3. 可以 lower 到任何 LLVM 支持的目标

示例:LLVM Add
    %result = llvm.add %a, %b : i64
"""
1
2
3
4
5
6
7
8
9
10
11
12

3.6 方言对比表 ​

方言抽象级别主要用途优化机会
Linalg高层批量线性代数算子融合、tiling
SCF中高层结构化控制流循环重排
Affine中层仿射循环多面体优化
MemRef中层内存引用内存布局、分配优化
Vector中低层SIMD 操作向量化、寄存器分配
LLVM低层LLVM IR指令选择、寄存器分配
SPIR-V低层GPU 着色器SPIR-V 优化

第4节:ODS(Operation Definition Specification) ​

4.1 ODS 简介 ​

ODS 是用 TableGen 定义 MLIR 算子的规范。它提供了:

  1. 简洁的算子定义语法
  2. 自动生成 C++ 代码
  3. 自动生成 ODS 解析器和构建器
  4. 自动生成文档
python
"""
ODS 文件的后缀是 .td(TableGen 定义)

核心概念:
1. Operation:定义一个操作(类似于算子)
2. Operand:操作的输入
3. Result:操作的输出
4. Attribute:操作的属性(常量参数)
5. Region:操作包含的嵌套结构(用于 if/for 等)
"""
1
2
3
4
5
6
7
8
9
10

4.2 ODS 定义示例:通用矩阵乘法 ​

tablegen
// ============================================================
// Linalg Matmul 的 ODS 定义(简化版)
// 完整定义在 llvm-project/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
// ============================================================

def Linalg_MatmulOp : Linalg_Op<"matmul", [
    // 类型约束:输入必须是 MemRef
    DeclareOpInterfaceMethods<MemoryEffectOpInterface>,
    // 符号属性
    AttrSizedOperandSegments
  ]> {
  
  // 算子名称
  let summary = "Generic matrix multiplication operation";
  
  // 描述
  let description = [{
    Computes matrix multiplication: C = A * B
    where A, B, C are 2D memrefs.
  }];
  
  // 输入操作数
  // A: M x K 矩阵
  // B: K x N 矩阵
  arguments = (ins
    Arg<MemRef, "left-hand side input">:$A,    // MemRef<<?x?xf32>
    Arg<MemRef, "right-hand side input">:$B,   // MemRef<<?x?xf32>
    Arg<MemRef, "result memref">:$C            // MemRef<<?x?xf32>
  );
  
  // 输出结果
  results = (outs);
  
  // regions: matmul 内部没有 regions(简单操作)
  regions = (region SizedRegion<0>:$body);
  
  // 额外参数
  let arguments = (ins
    // 迭代空间维度(可选)
    DefaultValuedAttr<I64Attr, "1">:$num_parallel_loops,
    // 索引映射(可选)
    StrAttr:$indexing_maps
  );
  
  // 自动生成方法
  let hasCanonicalizer = 1;
  let hasFolder = 1;
}

// ============================================================
// 实际的 Linalg 简化表示(MLIR Syntax)
// ============================================================

// 上面定义的算子在 MLIR 文件中这样使用:
// func @matmul(%A: memref<?x?xf32>, %B: memref<?x?xf32>, %C: memref<?x?xf32>) {
//   linalg.matmul ins(%A, %B: memref<?x?xf32>, memref<?x?xf32>)
//                outs(%C: memref<?x?xf32>)
//   return
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

4.3 ODS 定义的流程 ​

python
"""
ODS 定义 → C++ 代码生成的流程

  1. 编写 .td 文件(TableGen 定义)
         │
         ▼
  2. TableGen 处理 .td 文件
         │
         ▼
  3. 生成 C++ 头文件(*.h.inc)
         │   - Op 类声明
         │   - Builder 方法声明
         │   - 访问器声明
         │
         ▼
  4. 生成 C++ 实现(*.inc)
         │   - Op 构造函数实现
         │   - 解析器实现
         │   - 打印器实现
         │
         ▼
  5. 在 C++ 中包含生成的头文件
         │
         ▼
  6. 编译进 MLIR

具体命令:
  $ tablegen file.td -gen-op-decls -o file.h.inc
  $ tablegen file.td -gen-op-defs -o file.inc
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

第5节:Dialect Conversion——方言之间的转换 ​

5.1 Conversion Framework ​

MLIR 提供了 Conversion Framework 来处理方言之间的转换。

python
"""
Dialect Conversion 的核心概念:

1. Pattern-based Rewriting:
   - 用 pattern 描述如何把一个 operation 转换成其他 operations
   - 类似于 LLVM 的 pattern matching

2. Type Conversion:
   - 当 lower 时,类型可能需要转换
   - Conversion Framework 会自动处理

3. Legality:
   - 可以标记某些 operations 是非法的(illegal)
   - 必须被 lower 到其他 operations
   - 框架会自动检查是否所有 illegal operations 都被转换
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

5.2 Conversion 示例:Linalg → Affine ​

python
"""
Linalg 到 Affine 的转换示例

原始 Linalg IR:
    #accesses = [
      affine_map<(i, j, k) -> (i, k)>,   // A[i, k]
      affine_map<(i, j, k) -> (k, j)>,   // B[k, j]
      affine_map<(i, j, k) -> (i, j)>     // C[i, j]
    ]
    #attr = affine_map<(i, j, k) -> (i, j, k)>
    
    linalg.generic {
      indexing_maps = #accesses,
      iterator_types = ["parallel", "parallel", "reduction"]
    } ins(%A, %B: memref<?x?xf32>, memref<?x?xf32>)
      outs(%C: memref<?x?xf32>) {
      ^bb0(%a: f32, %b: f32, %c: f32):
        %0 = arith.mulf %a, %b : f32
        %1 = arith.addf %c, %0 : f32
        linalg.yield %1 : f32
      }

Lower 后的 Affine IR:
    affine.for %i = 0 to %M {
      affine.for %j = 0 to %N {
        %result = arith.constant 0.0 : f32
        affine.for %k = 0 to %K {
          %a = affine.load %A[%i, %k] : memref<?x?xf32>
          %b = affine.load %B[%k, %j] : memref<?x?xf32>
          %prod = arith.mulf %a, %b : f32
          %result = arith.addf %result, %prod : f32
        }
        affine.store %result, %C[%i, %j] : memref<?x?xf32>
      }
    }
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

第6节:多级 Lowering 实例 ​

6.1 端到端 Lowering 示例 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                     端到端 Lowering:Linalg → LLVM                           │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Level 1: Linalg (高层抽象)                                                  │
│  ═══════════════════════════════════════════════════════════════            │
│  linalg.matmul ins(%A, %B: memref<128x64xf32>, memref<64x32xf32>)          │
│               outs(%C: memref<128x32xf32>)                                 │
│                                                                             │
│  ↓ Lowering using `linalg-to-affine` pass                                   │
│                                                                             │
│  Level 2: Affine (循环层级)                                                  │
│  ═══════════════════════════════════════════════════════════════            │
│  affine.for %i = 0 to 128 {                                                │
│    affine.for %j = 0 to 32 {                                                │
│      %0 = arith.constant 0.0 : f32                                          │
│      affine.for %k = 0 to 64 {                                              │
│        %a = affine.load %A[%i, %k]                                          │
│        %b = affine.load %B[%k, %j]                                          │
│        %0 = arith.addf %0, (%a * %b)                                        │
│      }                                                                      │
│      affine.store %0, %C[%i, %j]                                            │
│    }                                                                        │
│  }                                                                          │
│                                                                             │
│  ↓ Lowering using `affine-to-scf` pass                                      │
│                                                                             │
│  Level 3: SCF (显式循环)                                                     │
│  ═══════════════════════════════════════════════════════════════            │
│  scf.for %i = 0 to 128 {                                                    │
│    scf.for %j = 0 to 32 {                                                   │
│      ...  // 类似 Affine,但没有仿射约束                                      │
│    }                                                                        │
│  }                                                                          │
│                                                                             │
│  ↓ Lowering using `scf-to-cf` pass                                          │
│                                                                             │
│  Level 4: CF + MemRef (控制流 + 内存)                                        │
│  ═══════════════════════════════════════════════════════════════            │
│  llvm.mlir.enter %i.0, ^bb1                                                 │
│  llvm.br ^bb2                                                               │
│  llvm.load %A_ptr                                                            │
│  ...                                                                        │
│                                                                             │
│  ↓ Lowering using `func-to-llvm` + `memref-to-llvm` passes                  │
│                                                                             │
│  Level 5: LLVM Dialect                                                      │
│  ═══════════════════════════════════════════════════════════════            │
│  llvm.call @matmul_f32(%A_ptr, %B_ptr, %C_ptr, %M, %N, %K)                 │
│                                                                             │
│  ↓ Lowering using `llvm-to-llvm` + `llvm-to-asm`                           │
│                                                                             │
│  Level 6: 机器码                                                            │
│  ═══════════════════════════════════════════════════════════════            │
│  vmovups %xmm0, (%rax)        # 加载数据                                    │
│  vfmadd231ps %xmm0, (%rbx)    # fused multiply-add                          │
│  ...                                                                        │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

6.2 每个层级的优化机会 ​

层级可用优化示例
Linalg算子融合、tiling、paddingConv+ReLU 融合成单kernel
Affine循环变换、交换、分块将 j 循环提到 i 循环内
SCF循环展开、预取减少分支开销
MemRef内存布局、分配优化内存池化
Vector向量化、混合宽度利用 SIMD
LLVM指令选择、寄存器分配更好的寄存器分配

第7节:MLIR 在实际项目中的应用 ​

7.1 IREE——端到端推理引擎 ​

IREE(Intermediate Representation Execution Environment) 是 Google 基于 MLIR 的端到端推理引擎。

python
"""
IREE 的架构:

┌─────────────────────────────────────────────────────────────────────────────┐
│                              IREE 架构                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  输入模型                                                                     │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐                       │
│  │TensorFlow│  │ PyTorch │  │   ONNX  │  │  TFLite │                       │
│  │Models   │  │Models   │  │ Models  │  │ Models  │                       │
│  └────┬────┘  └────┬────┘  └────┬────┘  └────┬────┘                       │
│       │            │            │            │                              │
│       ▼            ▼            ▼            ▼                              │
│  ┌─────────────────────────────────────────────────────────────────┐        │
│  │                  IREE Input Dialect                             │        │
│  │           (统一的、面向模型的中间表示)                              │        │
│  └─────────────────────────────────────────────────────────────────┘        │
│                                 │                                           │
│                                 ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────┐        │
│  │                  Linalg Dialect                                 │        │
│  │            (批量线性代数操作)                                     │        │
│  └─────────────────────────────────────────────────────────────────┘        │
│                                 │                                           │
│                                 ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────┐        │
│  │                  Vector + SCF Dialects                          │        │
│  │               (向量化 + 结构化控制流)                              │        │
│  └─────────────────────────────────────────────────────────────────┘        │
│                                 │                                           │
│                                 ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────┐        │
│  │                  LLVM Dialect                                   │        │
│  │               (LLVM 类型的 SSA)                                  │        │
│  └─────────────────────────────────────────────────────────────────┘        │
│                                 │                                           │
│                                 ▼                                           │
│  ┌─────────────────────────────────────────────────────────────────┐        │
│  │                  Runtime                                      │        │
│  │    ┌────────┐  ┌────────┐  ┌────────┐  ┌────────┐             │        │
│  │    │ x86    │  │  ARM   │  │RISC-V  │  │ Vulkan │             │        │
│  │    │ VMApp  │  │ VMApp  │  │ VMApp  │  │ SPIR-V │             │        │
│  │    └────────┘  └────────┘  └────────┘  └────────┘             │        │
│  └─────────────────────────────────────────────────────────────────┘        │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

7.2 IREE 的编译流程 ​

python
"""
IREE 编译 PyTorch 模型的完整流程:

1. PyTorch → IREE Input
   ┌─────────────────────────────────────────────────────────────────────┐
   │  import iree.compiler.torch as iree_torch                          │
   │                                                                       │
   │  # PyTorch 模型                                                      │
   │  model = torchvision.models.resnet18(pretrained=True)               │
   │  model.eval()                                                       │
   │                                                                       │
   │  # 编译到 IREE                                                       │
   │  binary = iree_torch.compile_file(                                  │
   │      "resnet18.pt",                                                 │
   │      output_format="vm-bytecode-fb",                                │
   │      import_args=["--torch-backend-type=vmfb"]                      │
   │  )                                                                  │
   └─────────────────────────────────────────────────────────────────────┘
   
2. IREE Input → Flow Dialect
   - 简化模型结构
   - 提取函数签名
   - 处理动态 shape
   
3. Flow Dialect → Stream Dialect
   - 资源流化
   - 内存规划
   
4. Stream Dialect → HAL Dialect
   - 设备分配
   - 命令缓冲
   
5. HAL Dialect → Executable Dialect
   - 具体化操作
   - 绑定内存
"""

print("IREE 的核心优势:")
print()
print("1. 统一表示:")
print("   PyTorch、TensorFlow、ONNX 模型都可以编译到同一个中间表示")
print()
print("2. 多目标支持:")
print("   - VMFB(虚拟机字节码):通用部署")
print("   - CUDA/ROCm:GPU 支持")
print("   - Vulkan SPIR-V:移动端 GPU")
print("   - LLVM:CPU 后端(x86, ARM, RISC-V)")
print()
print("3. 分层优化:")
print("   - 高层优化(Linalg):算子融合、tiling")
print("   - 中层优化(Affine/Vector):循环优化、向量化")
print("   - 低层优化(LLVM):指令选择、寄存器分配")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

7.3 其他使用 MLIR 的项目 ​

项目用途MLIR 层级
TensorFlow/XLAGoogle 深度学习编译器HLO → LMHLO → LLVM
PyTorch (Torch-MLIR)PyTorch 到 MLIRTorch IR → Linalg
MLIR-AIEAMD AI EnginePython → Linalg → Vector
TOSA标准算子接口Model → TOSA → Linalg
SPIR-V ToolsGPU 着色器Linalg → SPIR-V
FlangFortran 编译器Fortran → HLFIR → MLIR

第8节:为什么 MLIR 重要 ​

8.1 MLIR 解决了什么问题 ​

python
"""
MLIR 之前的编译器架构(以 TensorFlow 为例):

TensorFlow → XLA HLO ──┬──→ CPU (LLVM)
                       │
                       └──→ GPU (CUDA/NVPTX)

TensorFlow → TFLite ───→ FlatBuffer

问题:
1. XLA 和 TFLite 是完全独立的代码库
2. 优化不能共享
3. 新硬件支持需要在两个地方实现

MLIR 之后的架构:

TensorFlow → TF Dialect → XLA HLO ─┬──→ LLVM → CPU
       │                           │
       │                           └──→ NVPTX → CUDA
       │
       └──→ TFLite Dialect → Linalg ──→ LLVM → CPU
                       │
                       └──→ SPIR-V → Vulkan

优势:
1. 共享优化基础设施
2. 可以在不同层级做优化
3. 新硬件支持只需要 lower 到 LLVM
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

8.2 MLIR 的设计原则 ​

原则说明示例
可扩展允许定义新的方言CustomHW Dialect
分层多种抽象层级共存Linalg → Affine → LLVM
SSA + 类型所有值都有类型i32, memref<f32>
Region操作可以嵌套scf.if, scf.for
Pattern Rewriting基于规则的转换linalg-fusion pass
Pass Infrastructure标准化优化管道-convert-linalg-to-affine

升华 ​

┌──────────────────────────────────────────────────────────────────────────────┐
│  📚 MLIR 架构:核心原则                                                       │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  1. **方言是 MLIR 的核心抽象**:每种方言代表一个计算抽象级别                      │
│                                                                              │
│  2. **多级 Lowering 是 MLIR 的核心思想**:逐步从高级表示 lower 到硬件            │
│                                                                              │
│  3. **可扩展性是 MLIR 的灵魂**:可以定义新方言来解决特殊问题                      │
│                                                                              │
│  4. **共享优化基础设施**:不同框架/硬件可以用相同的优化 pass                      │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13

"AI 可查 vs 必须理解"清单 ​

必须理解(不理解就等于不会):

  • 🔴 方言层级的概念:Linalg(高层)、Affine(中层)、LLVM(低层)分别代表什么
  • 🔴 多级 Lowering 的思想:为什么需要逐步 lower,而不是一步到位
  • 🔴 ODS 的基本用途:TableGen 定义算子、自动生成代码的概念
  • 🔴 MLIR 的核心问题:解决了深度学习编译器碎片化的什么问题
  • 🔴 IREE 的架构:输入模型如何 lower 到不同硬件

AI 可查(知道去哪查就行):

  • ✅ 具体方言的语法:MLIR Syntax 细节,用到时查文档
  • ✅ ODS 定义的完整语法:TableGen 语法很复杂,完整参考在 LLVM 文档
  • ✅ 特定 pass 的选项:--linalg-fusion 有哪些参数
  • ✅ 特定硬件的后端细节:不同硬件有不同限制
  • ✅ MLIR C++ API:操作 MLIR 库的细节

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇4. 计算图的构建与表示 / Building and Representing Computational Graphs
下一篇6. 算子语义、广播、归约与形状推导 / Operator Semantics, Broadcasting, Reduction, and Shape Inference

持续记录,持续成长

Copyright © Tidenflow