mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1592 字
4 分钟
AI 驱动的编译优化
2026-03-13

编译器优化依赖启发式规则——“如果函数小于 N 条指令就内联”、“如果循环迭代次数已知就展开”。这些规则是工程师根据经验制定的,但它们无法覆盖所有场景。AI 驱动的编译优化试图用机器学习替代启发式,让编译器从数据中学习最优决策

一、为什么需要 ML for 编译器#

1.1 启发式的局限#

graph TB subgraph "启发式优化" HEUR["工程师制定的规则<br/>if size < threshold → inline"] PROBLEM1["无法覆盖所有场景"] PROBLEM2["需要手动调参"] PROBLEM3["随硬件演进失效"] end subgraph "ML 驱动优化" ML["从数据学习最优决策<br/>模型预测 inline/no-inline"] ADV1["自动适应不同场景"] ADV2["自动调优参数"] ADV3["可随硬件数据更新"] end style PROBLEM1 fill:#ffcdd2,stroke:#c62828 style ADV1 fill:#c8e6c9,stroke:#2e7d32
问题启发式ML
内联决策固定阈值根据上下文动态决策
Pass 排序固定顺序搜索最优序列
寄存器分配固定策略学习最优分配
向量化固定启发式学习最优向量化策略

二、MLGO:强化学习内联#

2.1 问题定义#

# MLGO 的核心思路:用强化学习决定内联/不内联
# 状态:函数调用图的局部特征(调用深度、指令数、循环数)
# 动作:inline / no-inline
# 奖励:二进制大小减少量
import numpy as np
class InlineEnv:
def __init__(self, call_graph):
self.call_graph = call_graph
self.state = self._extract_features(call_graph)
def step(self, action):
# action: 0=no-inline, 1=inline
if action == 1:
self._inline_current_call()
reward = self._compute_size_reduction()
self.state = self._extract_features(self.call_graph)
return self.state, reward, self._is_done()
# 使用 MLGO 训练内联策略
# 1. 采集训练数据
clang -O2 -fpass-plugin=MLInlineAdvisor \
-mllvm -enable-ml-inline-advisor=training \
-mllvm -ml-inline-advisor-model=unused \
-c training_corpus/*.c
# 2. 训练模型
python3 train_inline_model.py --data=training_log/
# 3. 使用训练好的模型编译
clang -O2 -fpass-plugin=MLInlineAdvisor \
-mllvm -enable-ml-inline-advisor=production \
-mllvm -ml-inline-advisor-model=trained_model/ \
-c my_app.cpp

内联决策:给定一个调用点,决定是否内联被调用函数。

传统启发式:
if (callee_size < threshold && caller_size < max_size)
→ inline
MLGO 方法:
提取调用点特征 → 模型预测 → inline / no-inline
特征包括:
- 调用者/被调用者的大小
- 调用频率
- 调用深度
- 函数类型(冷/热)
- 历史内联效果

2.2 强化学习框架#

graph TB STATE["状态:调用点特征<br/>大小、频率、深度..."] ACTION["动作:inline / no-inline"] REWARD["奖励:执行时间减少<br/>二进制大小减少"] STATE --> MODEL["神经网络模型<br/>决策策略"] MODEL --> ACTION ACTION --> ENV["编译+执行环境"] ENV --> REWARD REWARD --> MODEL style MODEL fill:#e1bee7,stroke:#6a1b9a
# MLGO 训练流程(简化)
class InliningEnv:
def __init__(self, llvm_module):
self.module = llvm_module
self.call_sites = extract_call_sites(llvm_module)
def step(self, action):
"""执行内联决策,返回奖励"""
if action == 'inline':
inline_function(self.call_sites[self.current_idx])
# 编译并测量执行时间
binary = compile_module(self.module)
runtime = measure_runtime(binary)
# 奖励:执行时间减少
reward = self.baseline_runtime - runtime
self.current_idx += 1
next_state = self.get_state()
done = self.current_idx >= len(self.call_sites)
return next_state, reward, done
def get_state(self):
"""提取调用点特征"""
site = self.call_sites[self.current_idx]
return [
site.caller_size,
site.callee_size,
site.call_depth,
site.is_hot,
site.caller_instruction_count,
site.callee_instruction_count,
]
# 训练模型
model = PolicyNetwork(input_dim=6, hidden_dim=128, output_dim=2)
agent = PPOAgent(model)
agent.train(InliningEnv(train_modules), episodes=10000)

2.3 MLGO 效果#

优化目标启发式MLGO提升
执行时间基准-3-7%3-7%
二进制大小基准-1-3%1-3%
内联决策准确率~70%~85%15%
Note

MLGO 的关键创新:将内联决策从静态启发式变为动态策略——模型根据每个调用点的上下文做出最优决策,而不是一刀切的阈值。

三、AutoTVM:自动调优#

3.1 问题定义#

张量程序优化:给定一个计算图(如矩阵乘法),找到最优的调度策略(tile 大小、并行度、向量化等)。

搜索空间:
tile_size_x: [1, 2, 4, 8, 16, 32, 64, 128]
tile_size_y: [1, 2, 4, 8, 16, 32, 64, 128]
tile_size_k: [1, 2, 4, 8, 16, 32, 64, 128]
unroll_factor: [1, 2, 4, 8]
vectorize: [true, false]
parallel: [true, false]
总搜索空间:8 × 8 × 8 × 4 × 2 × 2 = 8192 种配置
AutoTVM 目标:在有限时间内找到最优配置

3.2 XGBoost 代价模型#

# AutoTVM 代价模型
class CostModel:
def __init__(self):
self.model = xgboost.XGBRegressor()
self.features = ScheduleFeatureExtractor()
def predict(self, schedule):
"""预测给定调度的执行时间"""
features = self.features.extract(schedule)
return self.model.predict([features])
def update(self, schedule, measured_time):
"""用实际测量结果更新模型"""
features = self.features.extract(schedule)
self.model.fit(
np.array([features]),
np.array([measured_time]),
increment=True
)
# 特征提取
class ScheduleFeatureExtractor:
def extract(self, schedule):
return [
schedule.tile_size_x,
schedule.tile_size_y,
schedule.tile_size_k,
schedule.unroll_factor,
schedule.vectorize,
schedule.parallel,
# 计算特征
schedule.arithmetic_intensity,
schedule.memory_access_count,
schedule.compute_ops,
]

3.3 搜索策略#

# AutoTVM 搜索流程
def auto_tune(task, n_trials=1000):
model = CostModel()
best_config = None
best_time = float('inf')
for i in range(n_trials):
# 1. 模型推荐候选配置
candidates = model.recommend_top_k(task, k=10)
# 2. 实际测量候选配置
for config in candidates:
time = measure_on_device(task, config)
# 3. 更新模型
model.update(config, time)
# 4. 记录最优
if time < best_time:
best_time = time
best_config = config
return best_config, best_time
搜索方法1000 次试验后性能说明
随机搜索~80% 最优简单但效率低
Grid Search~90% 最优系统但搜索空间大
AutoTVM (XGBoost)~95% 最优代价模型引导搜索

四、程序表征学习#

4.1 IR2Vec#

IR2Vec:将 LLVM IR 转换为向量表示
方法 1:Flow-based(基于数据流)
- 每条指令映射为一个向量
- 通过数据流图传播信息
- 最终得到函数级向量
方法 2:Symmetric(基于对称)
- 每条指令的向量 = 操作码向量 + 操作数向量
- 函数向量 = 所有指令向量的聚合
应用:
- 内联决策预测
- 函数相似性检测
- 优化 Pass 选择

4.2 ProGraML#

ProGraML:图神经网络用于程序分析
输入:程序的控制流图 + 数据流图 + 调用图
处理:GNN 在图上传播信息
输出:节点级/图级向量表示
优势:
- 跨语言(任何有 IR 的语言)
- 跨任务(同一个模型可用于多种优化决策)
- 可迁移(在一个程序集训练,迁移到另一个)

4.3 表征方法对比#

方法输入输出优势劣势
IR2VecLLVM IR向量简单、快速信息有限
ProGraML程序图图向量信息丰富计算开销大
code2vecAST向量路径注意力只适合小函数
inst2vecLLVM IR向量指令级丢失结构信息

五、ML 在编译器中的应用全景#

5.1 应用分类#

应用ML 方法效果成熟度
内联决策RL (MLGO)3-7% 加速生产级
寄存器分配RL1-3% 加速实验级
Pass 排序RL/搜索5-10% 加速实验级
张量调度XGBoost (AutoTVM)2-5x 加速生产级
向量化RL5-15% 加速实验级
代码生成Transformer探索阶段研究级
Bug 检测GNN辅助工具实验级

5.2 TVM/MLIR 框架#

# TVM:ML-oriented 编译框架
import tvm
from tvm import relay
# 定义模型
model = relay.nn.conv2d(data, weight, strides=(1,1), padding=(1,1))
# AutoTVM 调优
with tvm.target.Target("cuda"):
best_config = auto_tvm.tune(model, n_trials=1000)
# 编译优化后的模型
lib = tvm.compile(model, target="cuda", config=best_config)
MLIR:多级中间表示框架
- 统一的 IR 框架,支持多种方言
- Affine 方言:循环优化
- Tensor 方言:张量计算
- GPU 方言:GPU 编程
- Linalg 方言:线性代数
优势:
- 不同优化级别可以混合使用
- ML 方法可以在任何方言级别介入
- 可扩展:添加新方言不需要修改框架

六、挑战与未来#

6.1 当前挑战#

挑战说明解决方向
泛化性模型在新程序上表现差更好的表征 + 迁移学习
训练数据需要大量编译+执行数据合成数据 + 模拟器
部署开销模型推理增加编译时间轻量模型 + 预计算
可解释性模型决策难以解释注意力机制 + 可解释 AI
稳定性模型可能给出错误决策安全回退到启发式

6.2 未来方向#

1. LLM for 编译器
- 大语言模型理解代码语义
- 自动生成优化规则
- 代码翻译(语言A → 语言B)
2. 自改进编译器
- 编译器从每次编译中学习
- 持续优化决策策略
- 适应硬件演进
3. 端到端编译
- 从源码直接生成优化后的机器码
- 跳过中间 IR 层级
- Transformer-based 代码生成

六-B、MLGO 强化学习内联深入#

6B.1 MLGO 的特征工程#

MLGO 为每个调用点提取 28 维特征向量,涵盖调用者、被调用者和调用上下文:

# MLGO 的调用点特征(部分)
def extract_call_site_features(caller, callee, call_site):
return {
# 调用者特征
"caller_basic_block_count": caller.num_bbs,
"caller_instruction_count": caller.num_insts,
"caller_users_count": caller.num_users,
# 被调用者特征
"callee_basic_block_count": callee.num_bbs,
"callee_instruction_count": callee.num_insts,
"callee_callsite_count": callee.num_callsites,
"callee_is_local": callee.is_local,
# 调用点特征
"callsite_cost": call_site.cost,
"callsite_is_recursive": call_site.is_recursive,
"callsite_depth": call_site.depth,
"callsite_is_hot": call_site.is_hot,
# 历史特征
"prev_inline_count": call_site.prev_inlines,
"prev_inline_size_increase": call_site.size_increase,
}
特征类别维度示例作用
调用者特征~10基本块数、指令数衡量内联后代码膨胀
被调用者特征~10函数大小、调用深度衡量内联收益
调用点特征~5调用代价、是否递归衡量调用开销
历史特征~3之前内联效果学习内联趋势

6B.2 AutoTVM 自动调优深入#

AutoTVM 的搜索空间由模板定义——开发者用 TVM 的调度原语描述可调参数:

import tvm
from tvm import autotvm
# 定义矩阵乘法的调度模板
@autotvm.template("matmul")
def matmul(M, N, K):
A = tvm.placeholder((M, K), name='A')
B = tvm.placeholder((K, N), name='B')
C = tvm.compute((M, N), lambda i, j: tvm.sum(A[i, k] * B[k, j], axis=k))
s = tvm.create_schedule(C.op)
# 可调参数
cfg = autotvm.get_config()
cfg.define_knob("tile_y", [1, 8, 16, 32, 64]) # y 方向 tile
cfg.define_knob("tile_x", [1, 8, 16, 32, 64]) # x 方向 tile
cfg.define_knob("tile_k", [1, 8, 16, 32]) # k 方向 tile
cfg.define_knob("unroll", [0, 1, 2, 4]) # 展开因子
# 应用调度
y, x = s[C].op.axis
yo, yi = s[C].split(y, factor=cfg["tile_y"].val)
xo, xi = s[C].split(x, factor=cfg["tile_x"].val)
s[C].reorder(yo, xo, yi, xi)
if cfg["unroll"].val > 0:
s[C].unroll(yi)
s[C].unroll(xi)
return s, [A, B, C]

AutoTVM 的搜索策略对比:

策略原理1000 次试验优势劣势
随机搜索随机采样~80% 最优简单效率低
Grid Search系统遍历~90% 最优完备
XGBoost代价模型引导~95% 最优高效模型偏差
GA (遗传算法)进化搜索~93% 最优全局搜索参数敏感

6B.3 程序表征学习深入#

程序表征学习将程序转换为向量,使 ML 模型能理解代码语义:

flowchart TB PROG["程序"] --> IR["LLVM IR / AST / CFG"] IR --> EMBED["嵌入方法"] EMBED --> VEC["向量表示"] VEC --> TASK["下游任务"] EMBED --> IR2VEC["IR2Vec<br/>基于数据流"] EMBED --> PROGRML["ProGraML<br/>图神经网络"] EMBED --> CODE2VEC["code2vec<br/>路径注意力"] TASK --> INLINE["内联决策"] TASK --> SPEEDUP["加速比预测"] TASK --> SIMILAR["代码相似性"] TASK --> BUG["Bug 检测"] style PROG fill:#e3f2fd,stroke:#1565c0 style VEC fill:#e1bee7,stroke:#6a1b9a style TASK fill:#e8f5e9,stroke:#2e7d32

6B.4 TVM 编译栈深入#

TVM 是端到端的 ML 编译框架,AutoTVM 是其核心调优组件:

flowchart TB MODEL["ML 模型<br/>PyTorch/TF/ONNX"] --> FRONT["前端<br/>Relay IR"] FRONT --> OPT_RELAY["Relay 优化<br/>算子融合+常量折叠"] OPT_RELAY --> LOWER["Lowering<br/>Relay -> TensorIR"] LOWER --> AUTOTVM["AutoTVM 调优<br/>搜索最优调度"] AUTOTVM --> TIR_OPT["TensorIR 优化<br/>循环变换+向量化"] TIR_OPT --> CODEGEN["代码生成<br/>CUDA/ROCm/Hexagon"] CODEGEN --> RUNTIME["TVM Runtime<br/>图执行器"] style MODEL fill:#e3f2fd,stroke:#1565c0 style AUTOTVM fill:#fff3e0,stroke:#e65100 style RUNTIME fill:#e8f5e9,stroke:#2e7d32

TVM 的编译层次:

层次IR优化说明
Relay高级图 IR算子融合、死代码消除类似 XLA/ONNX
TensorIR低级张量 IR循环变换、向量化类似 Halide
Target IR目标特定寄存器分配、指令选择类似 LLVM MC
Note

TVM 的 AutoTVM 是目前 ML 编译优化中最成功的生产级应用——它为每个目标硬件自动找到最优的张量调度策略,无需人工调优。在 GPU 上,AutoTVM 优化的模型通常比手写 cuDNN 内核快 10-30%。MLGO 则是 LLVM 中最成功的 ML 应用,已在 Chrome 的 V8 编译管线中使用。

七、总结#

上一章中,WASM 展示了一个新编译目标的完整生态——从指令集设计到运行时沙箱。回到编译优化本身:无论是 AOT 还是 JIT,优化决策都依赖工程师制定的启发式规则。但这些规则无法覆盖所有场景,也难以随硬件演进自动调整。机器学习为这个问题提供了新思路——让编译器从数据中学习最优决策。

方法适用场景效果成熟度
MLGO (RL)内联/寄存器分配3-7%生产级
AutoTVM (XGBoost)张量调度2-5x生产级
ProGraML (GNN)程序分析辅助研究级
LLM代码生成/翻译探索研究级
Tip

AI 驱动的编译优化不是要替代传统编译器——而是增强传统编译器在启发式规则失效的地方。MLGO 已经在 LLVM 生产环境中使用,AutoTVM 在 TVM 中是标配。未来,ML 将成为编译器优化的标准工具,就像 SIMD 和 GPU 已经成为标准硬件加速器一样。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

AI 驱动的编译优化
https://blog.souloss.com/posts/compiler/ai-and-compiler-optimization/
作者
Souloss
发布于
2026-03-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时