Home
avatar

230

总结论文相关Pass序列生成内容

阅读Optimizing LLVM Pass List using Reinforcement Learning论文总结

Sun Y. Optimizing LLVM Pass List using Reinforcement Learning[J]. 2022.

LLVM 编译器中预定义的优化选项 -O3 的局限性:

  1. -O3并非最优解:虽然-O3调用了 LLVM 中预定义的一系列优化 passes,实际使用中包含了200多个 passes(其中很多重复执行),但这并不意味着它是最优的组合。
  2. 存在冗余和边际效益递减:部分 passes 可能是冗余的,重复运行带来的收益有限,存在简化空间。
  3. 可用的 passes 远多于被使用的:LLVM 14.0.0 注册了超过200种 passes,而-O3只使用了其中73种,表明还有大量未被利用的优化手段。
  4. 自定义 pass 的困境:LLVM 支持用户自定义 passes,但现有优化流程极其复杂,新 pass 的插入时机和位置难以确定。
  5. pass 的顺序至关重要:不同 passes 之间可能相互影响,顺序会影响整体优化效果,形成一个组合爆炸的问题。
  6. 搜索空间庞大:即使使用简单的贪心算法,从200个 passes 中搜索一个有效序列也需要几天时间。
  7. 需要智能优化工具:具备对编译环境深入理解和决策能力,更高效地探索优化组合。

Link Time Optimization (LTO)

从 C 到 LLVM IR 不容易:虽然 clang 能将单个 C 文件编译为 LLVM IR,但实际项目往往包含多个 C 文件,处理起来更加复杂。

常规方法繁琐且低效

  • 将每个源文件编译为 bitcode。
  • 对每个 bitcode 文件单独运行优化。
  • 最后将优化后的 bitcode 编译并链接为可执行文件。
  • 这种方法重复创建优化线程,效率低,尤其在文件较多时开销大。

更优的方法是优化前先链接

  • 先将所有 bitcode 文件链接为一个整体。
  • 对合并后的 bitcode 统一执行优化和代码生成。
  • 这样可以简化流程、减少重复操作、提高效率。

LTO 是理想方案

  • Clang 的 Link Time Optimization(LTO)功能支持在链接阶段进行跨模块优化。
  • 更重要的是,它允许在 LLVM IR 层面进行链接,正好满足项目级优化的需求。

传统方法:

image-20250626103751006

image-20250626103912304

缺点: 每次环境中执行一个新的 pass,该 pass 会被追加到 pass 列表中。Clang 被重新调用,重新编译整个程序时间开销大。

改进:

image-20250626104709908

-Xclang -disable-O0-optnone使得生成未优化IR,初期对未经优化的IR进行复制。

定义:

  1. Observation(观测空间):所有可能的 IR bitcode 集合 B
  2. Action(动作空间):所有合法的 LLVM Pass 列表 P
  3. Step(环境步进):opt(bx, p),表示将 pass p 应用到 bitcode bx 上。
  4. Reset(环境重置):对未经优化的IR进行复制。
  5. Reward(奖励函数): image-20250626122122404
  6. Termination(终止条件):可以自定义Step

问题:

Observation: 在使用 预训练模型IR2vec 嵌入简化状态表达的基础上,加入 Pass 动作历史以增强状态信息,且保持状态转移的马尔可夫性。

Action: 实际上并 不是所有 pass 在任何状态下都能安全运行。运行失败类 Pass、构建失败类 Pass优化阶段成功,但在生成可执行文件时报错、执行效率低 Pass。

解决方案:

方案描述优点缺点
1. 预清洗 Pass 列表事先筛除所有可能报错或无效的 pass,仅保留验证过的“安全” pass 列表安全性高,运行稳定可能丢失一些潜在有用的优化策略,限制 agent 表达能力
2. 保留全部 Pass,失败惩罚允许 agent 尝试任意 pass,但如果失败(报错或运行过慢)就给予负奖励提供更大探索空间,符合强化学习探索精神增加训练波动性和不确定性,需要额外的错误处理机制

对比:

策略优点缺点
① 手动清洗 Pass 列表(预筛选)- 缩小动作空间,简化训练- 避免意外错误,提高系统稳定性- 提高训练吞吐率(less crash, faster iter)- 无法利用某些偶尔有效的 pass- 静态分析可能遗漏某些边界情况
② 全部尝试 + 惩罚机制(动态探索)- 能学习哪些 pass 是 “坏” 的- 给高代价 pass 一次被发现的机会- 减少对人工筛选的依赖- 增加训练成本(运行失败/超时)- 需要完善错误处理机制- 惩罚设计不当可能导致训练不稳定

最终策略:

  1. 自动化清洗 Pass 列表(主策略)
  • 对每个 Pass 单独运行一次在一个干净、未优化的程序上;
  • 如果该 pass 会:
    • ❌ 导致优化错误,
    • 🕒 或执行时间超出设定阈值,
    • 就被视为“无效或代价高”,被自动剔除。
  1. Step 函数的健壮实现(应对最坏情况)
  • 每次运行 pass:
    • 记录返回码;
    • 设置超时限制,防止卡死;
  • 若运行失败或超时:
    • 回滚至上一个干净状态;
    • 施加 负奖励惩罚,防止 agent 频繁尝试无效 pass;
  • ❗ 惩罚值需谨慎设定:
    • 惩罚太重 → 数值不稳定,影响训练;
    • 惩罚太轻 → agent 学不会规避坏 pass。

三种Agent:Deep Q Network (DQN)、Proximal Policy Optimization (PPO)、World Model Agent

其中PPO的效果最好(演化)、World Model Agent(使用的时候是推理)

模型评估效果:

image-20250626120431095image-20250626120512404
image-20250626120612865image-20250626120743386
LLVM Pass

喜欢这篇文章嘛,觉得文章不错的话,奖励奖励我!

支付宝打赏支付宝微信打赏 微信