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 🏷️ 标签:#torch.compile #Dynamo #Inductor #AOTAutograd #FXGraph #TritonBackend #FullGraph #Dynamism 📚 前置知识:[[/04-ai/01-llm-engineering/07-llm-evolution]](LLM 发展脉络) 📚 相关知识:[[03-graph-representation]](计算图表示) [[11-dynamic-shape]](动态 Shape)


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

┌─────────────────────────────────────────────────────────────────────────────┐
│  场景:torch.compile 第一次调用慢 5 秒,后续 20ms —— 为什么?               │
├─────────────────────────────────────────────────────────────────────────────┤
│  你在生产环境用 torch.compile 部署模型,第一次调用延迟 5 秒,后续只需 20ms。 │
│                                                                             │
│  你觉得这很诡异:                                                            │
│  - 5 秒的延迟是从哪里来的?                                                 │
│  - 是 Dynamo graph capture 慢?还是 Inductor codegen 慢?                   │
│  - 为什么 warmup 后这么快?JIT 编译的产物能被缓存吗?                       │
│                                                                             │
│  你的模型还有 Python control flow(if/else, for 循环),                   │
│  torch.compile 对动态控制流支持如何?                                        │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13

第1节 torch.compile 全景 ​

1.1 PyTorch 2.0 编译栈架构 ​

torch.compile 是 PyTorch 2.0 的核心特性,提供了一个可扩展的编译栈:

┌─────────────────────────────────────────────────────────────────────────────┐
│                       torch.compile Architecture                             │
└─────────────────────────────────────────────────────────────────────────────┘

    ┌──────────────────────────────────────────────────────────────────────┐
    │  User Code (Python)                                                  │
    │  model = MyModel()                                                   │
    │  compiled = torch.compile(model)                                     │
    │  output = compiled(input)                                           │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
    ┌──────────────────────────────────────────────────────────────────────┐
    │  Layer 1: TorchDynamo                                                 │
    │  ┌────────────────────────────────────────────────────────────────┐  │
    │  │  Graph Capture                                                   │  │
    │  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐       │  │
    │  │  │ bytecode │  │  FX     │  │  graph   │  │  graph   │       │  │
    │  │  │ analysis │──▶ break  │──▶ capture │──▶ break   │       │  │
    │  │  │          │  │ detection│ │          │  │ detection │       │  │
    │  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘       │  │
    │  └────────────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
    ┌──────────────────────────────────────────────────────────────────────┐
    │  Layer 2: AOTAutograd                                                 │
    │  ┌────────────────────────────────────────────────────────────────┐  │
    │  │  Forward + Backward Graph                                       │  │
    │  │                                                                  │  │
    │  │  Forward Graph          Backward Graph                           │  │
    │  │  ┌─────────┐           ┌─────────┐                              │  │
    │  │  │ Linear  │──▶ ... ──▶│ Loss    │                              │  │
    │  │  └─────────┘           └────┬────┘                              │  │
    │  │                               │                                   │  │
    │  │                               ▼                                   │  │
    │  │                         ┌─────────┐                              │  │
    │  │                         │GradSum  │                              │  │
    │  │                         └─────────┘                              │  │
    │  └────────────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
    ┌──────────────────────────────────────────────────────────────────────┐
    │  Layer 3: Inductor (Backend)                                          │
    │  ┌────────────────────────────────────────────────────────────────┐  │
    │  │  CPU Backend:                      GPU Backend:                │  │
    │  │  ┌─────────────┐                  ┌─────────────┐               │  │
    │  │  │ C++ CodeGen │                  │Triton Kernel│              │  │
    │  │  │             │                  │  Generation  │              │  │
    │  │  │ GEMM, Conv  │                  │             │              │  │
    │  │  │ Element-wise│                  │ Matmul, Softmax             │  │
    │  │  │ Loops       │                  │ Layernorm   │              │  │
    │  │  └──────┬──────┘                  └──────┬──────┘              │  │
    │  │         │                                 │                     │  │
    │  │         ▼                                 ▼                     │  │
    │  │  ┌─────────────┐                  ┌─────────────┐               │  │
    │  │  │  GCC/Clang  │                  │  Triton JIT │               │  │
    │  │  │  compile    │                  │  compile    │               │  │
    │  │  └─────────────┘                  └─────────────┘               │  │
    │  └────────────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
    ┌──────────────────────────────────────────────────────────────────────┐
    │  Compiled Artifacts (Cached)                                         │
    │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐             │
    │  │  C++ .so     │  │  .ptx        │  │  metadata    │             │
    │  │  (CPU)       │  │  (CUDA)      │  │  (tracing)  │             │
    │  └──────────────┘  └──────────────┘  └──────────────┘             │
    └──────────────────────────────────────────────────────────────────────┘
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
60
61
62
63
64
65
66
67
68
69
70
71

1.2 延迟分解:5 秒去哪了 ​

python
import torch
import time

model = MyModel()
input_tensor = torch.randn(1, 512, 768)

# 第一次调用:包含编译时间
start = time.time()
compiled_model = torch.compile(model, mode="reduce-overhead")
#                            ^^^^^^^^^^^^ 编译模式

# warmup 运行(实际触发编译)
output = compiled_model(input_tensor)  # 首次调用:JIT 编译
torch.cuda.synchronize() if torch.cuda.is_available() else None
first_call_time = time.time() - start
print(f"First call (including compile): {first_call_time:.2f}s")

# 后续调用:纯执行
times = []
for _ in range(100):
    start = time.time()
    output = compiled_model(input_tensor)
    times.append(time.time() - start)
avg_time = sum(times) / len(times)
print(f"Subsequent call (pure execution): {avg_time*1000:.2f}ms")

# 延迟分解分析
"""
5 秒的组成(典型值):

TorchDynamo Graph Capture:     ~0.5s
  - Python bytecode 分析:        ~0.2s
  - FX Graph construction:       ~0.2s
  - Graph break handling:        ~0.1s

AOTAutograd (Backward Capture): ~1.0s
  - Reverse-mode AD:            ~0.8s
  - Graph construction:          ~0.2s

Inductor CodeGen:               ~3.5s
  - Scheduler optimization:      ~0.5s
  - Triton/C++ kernel 生成:     ~2.5s
  - Kernel 编译 (Triton JIT):    ~0.5s

总计:                           ~5.0s
"""
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

第2节 TorchDynamo:Graph Capture 层 ​

2.1 两种 Capture 策略 ​

TorchDynamo 支持两种图捕获策略:

python
import torch
from torch._dynamo import optimize

# 策略1:Symbolic(符号化推理)- nopython=True
# 尝试完整捕获,失败时报错
@torch.compile(backend="inductor", fullgraph=True)
def forward_symbolic(x):
    return model(x)

# 策略2:Tracing(跟踪)- nopython=False(默认)
# 遇到不支持的操作时自动 graph break
@torch.compile(backend="inductor")
def forward_tracing(x):
    return model(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

2.2 Graph Break 详解 ​

Graph Break 是 TorchDynamo 遇到不支持的 Python 特性时自动分割图的机制:

python
# 触发 Graph Break 的情况

# 1. Python built-in 函数(不是 torch 操作)
@torch.compile
def fn1(x):
    result = []              # Python list
    for i in range(10):      # Python range (非 tensor)
        result.append(x * i) # list.append (非 torch)
    return torch.stack(result)  # 这里才回到 torch

# 触发多个 graph break:
# Graph 1: x → x*0 → x*1 → ... → stack
# (每个 iteration 都是独立的 graph)

# 2. 数据依赖的分支
@torch.compile
def fn2(x):
    if x.sum() > 0:          # 数据依赖的 if
        return x * 2
    else:
        return x / 2

# Graph Break: 运行时才知道走哪个分支

# 3. 非 tensor 操作
@torch.compile
def fn3(x):
    print(x.shape)           # Python print (side effect)
    return x.relu()

# 4. 动态索引(数据依赖)
@torch.compile
def fn4(x, idx):
    return x[idx]            # idx 的值运行时才知道
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

2.3 Graph Break 检测和优化 ​

python
import torch
from torch._dynamo import list_graph_breakReasons
from torch._dynamo.config import config

# 检测 graph break
model = MyModel()
optimized_model = torch.compile(model, backend="inductor")

# 运行时会记录 graph break
# 通过环境变量查看
# TORCH_LOGS="dynamo" python train.py

# 在代码中检测
@torch.compile
def monitored_fn(x):
    # 这会有 graph break
    y = x.clone()
    y.add_(1)  # In-place operation
    return y

# 优化建议:减少 graph break
@torch.compile
def optimized_fn(x):
    y = x + 1     # Out-of-place (无 graph break)
    return y
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

2.4 fullgraph=True 强制完整图 ​

python
# fullgraph=True:强制捕获完整图,遇到不支持的操作报错

@torch.compile(fullgraph=True)  # 强制完整图
def simple_forward(x):
    return torch.nn.functional.relu(torch.matmul(x, x.T))

# 正常运行
x = torch.randn(100, 100)
print(simple_forward(x).shape)  # torch.Size([100, 100])

# 遇到不支持的操作会报错
@torch.compile(fullgraph=True)
def problematic_forward(x):
    if x.sum() > 0:  # 数据依赖的分支 - 不支持!
        return x * 2
    return x

try:
    problematic_forward(torch.randn(10))
except torch._dynamo.exc.UserError as e:
    print(f"Error: {e}")
    # UserError: Graph break in user code
    # reason: generic_jump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

2.5 dynamo.config 配置 ​

python
from torch._dynamo import config

# 关键配置项
torch._dynamo.config.configure_mockables = []  # mock 外部库
torch._dynamo.config.replay_record_options = None
torch._dynamo.config.error_on_recompile = False  # recompile 时不报错

# 常用运行时配置
@torch.compile(dynamic=True)  # 启用动态 shape 支持
def dynamic_fn(x):
    return torch.matmul(x, x.T)

# 调试配置
# export TORCH_LOGS="dynamo,graph_break"
# export TORCHDYNAMO_VERBOSE=1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

第3节 AOTAutograd:反向图捕获 ​

3.1 为什么需要 AOTAutograd ​

JIT 编译需要完整的 forward + backward 图,因为 GPU 使用反向模式自动微分,backward 必须在 forward 之前就确定:

python
import torch

model = torch.nn.Linear(256, 10)
optimizer = torch.optim.Adam(model.parameters())

# 动态图模式(Eager)
for data, target in dataloader:
    optimizer.zero_grad()
    output = model(data)
    loss = loss_fn(output, target)
    loss.backward()        # 反向传播在运行时决定
    optimizer.step()

# 编译模式(需要 AOT)
compiled_model = torch.compile(model, backend="inductor")
compiled_optimizer = torch.compile(optimizer.step, backend="inductor")

for data, target in dataloader:
    optimizer.zero_grad()
    output = compiled_model(data)   # forward
    loss = loss_fn(output, target)
    loss.backward()                 # backward
    # 需要捕获 backward 图!
    compiled_optimizer()            # 参数更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

3.2 AOTAutograd 的工作原理 ​

python
# AOTAutograd 的转换过程
"""
原始计算(Eager Mode):

    Forward:                     Backward:
    x ──▶ Linear ──▶ Relu ──▶   grad ←─┬─┐
                               grad ←──┘ │
                                       │
                                       ▼
    grad ──▶ Relu' ←── Linear' ←── grad

AOTAutograd 捕获后的图:

    AOT Forward:                    AOT Backward:
    x ──▶ Linear ──▶ Relu ──▶      grad ──▶ Relu' ──▶ Linear' ──▶ grad

两者被作为一个整体 JIT 编译,
backward kernel 和 forward kernel 一起生成
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

3.3 AOTAutograd 配置 ​

python
# AOTAutograd 相关配置
from torch._inductor import config

# 1. cudagraphs:减少内存分配开销
config.triton.cudagraphs = True  # 启用 CUDA Graphs

# 2. 内存规划
config.memory_planning = True    # 预分配内存

# 3. 组合使用
model = torch.compile(
    model,
    backend="inductor",
    mode="reduce-overhead",
    options={"cudagraphs": True}
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

第4节 Inductor:代码生成层 ​

4.1 Inductor 整体架构 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Inductor Architecture                                │
└─────────────────────────────────────────────────────────────────────────────┘

    ┌──────────────────────────────────────────────────────────────────────┐
    │  FX Graph Input                                                       │
    │  (来自 TorchDynamo + AOTAutograd)                                      │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
    ┌──────────────────────────────────────────────────────────────────────┐
    │  Inductor Scheduler                                                   │
    │  ┌────────────────────────────────────────────────────────────────┐  │
    │  │  1. Decouple:分解依赖关系                                        │  │
    │  │  2. Fusion:合并可融合的操作                                      │  │
    │  │  3. Schedule:确定执行顺序                                       │  │
    │  │  4. Tile:分块以适应缓存                                          │  │
    │  └────────────────────────────────────────────────────────────────┘  │
    └──────────────────────────────────────────────────────────────────────┘
                                    │
                    ┌───────────────┴───────────────┐
                    ▼                               ▼
    ┌──────────────────────────────┐ ┌──────────────────────────────┐
    │  CPU Backend                  │ │  GPU Backend                 │
    │  ┌────────────────────────┐   │ │  ┌────────────────────────┐   │
    │  │  C++ CodeGen           │   │ │  │  Triton KernelGen      │   │
    │  │                        │   │ │  │                        │   │
    │  │  - Loop nests          │   │ │  │  - TritonGPU dialect   │   │
    │  │  - SIMD intrinsics     │   │ │  │  - Tile-level fusion   │   │
    │  │  - OpenMP parallelism  │   │ │  │  - Shared memory opt   │   │
    │  │                        │   │ │  │                        │   │
    │  └───────────┬────────────┘   │ │  └───────────┬────────────┘   │
    │              │                │ │              │                │
    └──────────────┼────────────────┘ └──────────────┼────────────────┘
                   │                               │
                   ▼                               ▼
    ┌──────────────────────────────┐ ┌──────────────────────────────┐
    │  GCC/Clang 编译               │ │  Triton JIT 编译              │
    │  .so 文件                     │ │  PTX/CUBIN                   │
    └──────────────────────────────┘ └──────────────────────────────┘
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

4.2 CPU Backend:C++ CodeGen ​

python
# Inductor 生成的 C++ 代码示例
# 模型: output = (input @ weight).relu()
# 生成代码:

#include <torch/extension.h>
#include <vector>

// GEMM + ReLU kernel
void compiled_kernel(float* output, const float* input, 
                     const float* weight, int M, int N, int K) {
    #pragma omp parallel for collapse(2)
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            float sum = 0.0f;
            for (int k = 0; k < K; k++) {
                sum += input[i * K + k] * weight[j * K + k];  // 注意:weight layout
            }
            output[i * N + j] = sum > 0 ? sum : 0;  // ReLU fused
        }
    }
}

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
    m.def("forward", &compiled_kernel, "Compiled kernel");
}
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

4.3 GPU Backend:Triton KernelGen ​

python
# Inductor 生成的 Triton 代码示例
# 模型: 矩阵乘法 + ReLU

@triton.jit
def triton_kernel(
    # Pointers
    input_ptr, weight_ptr, output_ptr,
    # Strides
    stride_input, stride_weight, stride_output,
    # Shapes
    M, N, K,
    # Block sizes
    BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr, BLOCK_K: tl.constexpr,
    # Other
    GROUP_M: tl.constexpr
):
    # pid 的计算
    pid = tl.program_id(axis=0)
    num_pid_m = tl.cdiv(M, BLOCK_M)
    num_pid_n = tl.cdiv(N, BLOCK_N)
    num_pid_in_group = GROUP_M * num_pid_n
    group_id = pid // num_pid_in_group
    first_pid_m = group_id * GROUP_M
    group_size_m = min(num_pid_m - first_pid_m, GROUP_M)
    pid_m = first_pid_m + (pid % group_size_m)
    pid_n = (pid % num_pid_in_group) // group_size_m
    
    # 加载数据到 shared memory
    offs_m = (pid_m * BLOCK_M + tl.arange(0, BLOCK_M)) % M
    offs_n = (pid_n * BLOCK_N + tl.arange(0, BLOCK_N)) % N
    offs_k = tl.arange(0, BLOCK_K)
    input_ptrs = input_ptr + offs_m[:, None] * stride_input + offs_k[None, :]
    weight_ptrs = weight_ptr + offs_k[:, None] * stride_weight + offs_n[None, :]
    input = tl.load(input_ptrs)
    weight = tl.load(weight_ptrs)
    
    # 计算 matmul
    accumulator = tl.dot(input, weight)
    
    # ReLU activation fused
    accumulator = tl.where(accumulator > 0, accumulator, 0.0)
    
    # 存储结果
    offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
    offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
    output_ptrs = output_ptr + offs_m[:, None] * stride_output + offs_n[None, :]
    tl.store(output_ptrs, accumulator)
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

第5节 CompiledAutograd ​

5.1 什么是 CompiledAutograd ​

CompiledAutograd 把 autograd 引擎本身也 JIT 编译,进一步减少 Python overhead:

python
import torch
from torch._dynamo import compiled_autograd

# 不使用 CompiledAutograd
# backward 仍然有 Python overhead

# 使用 CompiledAutograd
def train_step(model, data, target):
    with compiled_autograd.enable():
        output = model(data)
        loss = loss_fn(output, target)
        loss.backward()  # 这里也被 JIT 编译!
        optimizer.step()
        optimizer.zero_grad()

# 或者用装饰器
@torch.compile(backend="inductor")
def train_step(model, optimizer, data, target):
    output = model(data)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第6节 AOTInductor:离线编译 ​

6.1 什么是 AOTInductor ​

AOTInductor 允许离线编译模型,不依赖 Python 运行时:

python
# AOTInductor 使用流程

# 1. 使用 AOTInductor 导出
import torch
from torch.export import export
from torch._inductor.aot import aot_compile

model = MyModel().eval()
example_inputs = (torch.randn(1, 512, 768),)

# AOT 编译
compiled_model = aot_compile(
    model,
    example_inputs,
    options={
        "aot_inductor.output_path": "/tmp/model.so"
    }
)

# 2. 部署到目标环境(不需要 PyTorch)
import ctypes
lib = ctypes.CDLL("/tmp/model.so")

# 设置输入输出
input_ptr = lib.get_input_ptr(0)
output_ptr = lib.get_output_ptr(0)

# 调用
lib.run()
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

第7节 性能调优 ​

7.1 编译模式选择 ​

模式适用场景编译时间运行性能
default通用中等好
reduce-overhead小 batch、频繁调用较长最优 overhead
max-autotune大 batch、追求极限性能最长最优性能
fwdeductionforward 为主中等forward 快
python
import torch

model = MyModel()

# 模式1:默认
compiled_default = torch.compile(model, mode="default")

# 模式2:减少 Python overhead(适合小 batch)
compiled_reduce_overhead = torch.compile(model, mode="reduce-overhead")

# 模式3:自动搜索最优 kernel 配置(适合大 batch)
compiled_max_autotune = torch.compile(model, mode="max-autotune")

# 模式4:只编译 forward(backward 仍然用 eager)
compiled_fwdeduction = torch.compile(model, mode="fwdeduction")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

7.2 Inductor 配置 ​

python
from torch._inductor import config

# 1. Triton 配置
config.triton.autotune_pointwise = True   # 自动调优 pointwise ops
config.triton.cudagraphs = True            # CUDA Graphs
config.triton.num_autotune_threads = 8    # 并行搜索线程数

# 2. C++ Backend 配置
config.cpp.dynamic_scale = True           # 动态缩放
config.cpp threads = 16                   # C++ 线程数

# 3. 内存优化
config.memory_planning = True              # 内存规划
config.max_autotune = True                # 最大自动调优

# 应用配置
model = torch.compile(model, options={
    "triton.cudagraphs": True,
    "max_autotune": True,
    "inductor.config": config
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

7.3 常见问题诊断 ​

问题原因解决方案
第一次调用太慢JIT 编译使用 torch._dynamo.config 预编译
Graph break 过多动态 control flow简化模型或使用 fullgraph=True
Recompilation 爆炸动态 shape使用 dynamic=True
内存占用过高CUDA graphs禁用或减少 batch size
数值不正确精度问题检查 dtype,使用 torch.float32

升华 ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                    torch.compile 核心原则                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. 三层分离                                                                │
│     TorchDynamo 捕获图 → AOTAutograd 捕获反向图 → Inductor 生成代码          │
│                                                                             │
│  2. 首次调用慢是正常的                                                       │
│     5 秒来自 graph capture + codegen,后续调用才是纯执行                      │
│                                                                             │
│  3. Graph break 是双刃剑                                                    │
│     允许动态 control flow,但会降低编译优化效果                              │
│                                                                             │
│  4. 编译模式选择决定性能                                                     │
│     reduce-overhead(小 batch)、max-autotune(大 batch)                   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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

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

  • 🔴 torch.compile 三层架构:TorchDynamo(捕获)→ AOTAutograd(反向图)→ Inductor(代码生成)
  • 🔴 第一次调用 5 秒的来源:主要是 Inductor 代码生成(Triton/C++ JIT 编译)
  • 🔴 Graph Break 的机制:遇到不支持的 Python 特性时自动分割图,牺牲优化换灵活性
  • 🔴 AOTAutograd 的必要性:JIT 需要完整的 forward + backward 图,eager 的动态 backward 不够
  • 🔴 Inductor 的双 backend:CPU 用 C++/OpenMP,GPU 用 Triton

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

  • ✅ 具体 graph break 原因代码:查看 torch._dynamo.graph_break 源码
  • ✅ Triton kernel 的完整语法:Triton 官方文档
  • ✅ C++ backend 的 SIMD 选项:Inductor 源码 config.cpp.*
  • ✅ max-autotune 的搜索空间:Inductor scheduler 源码
  • ✅ AOTInductor 完整部署流程:PyTorch AOTInductor 教程

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇24. Torch-MLIR:从 PyTorch 算子到 MLIR 方言 / Torch-MLIR from PyTorch Operators to MLIR Dialects
下一篇26. 从 MLIR 经 LLVM 降级到机器码 / Lowering from MLIR Through LLVM to Machine Code

持续记录,持续成长

Copyright © Tidenflow