背景概述
在深度神经网络训练与HPC场景中,图算融合优化可带来显著的性能提升。然而,随着融合算子规模与复杂度不断增长,传统基于DSA的手工算子开发模式面临编程门槛高、开发周期长等瓶颈。算子自动生成技术应运而生,它允许开发者聚焦算法逻辑本身,由编译器自动完成后端优化与代码生成,尤其适用于后端架构复杂、算子形态多样的异构计算场景。
AKG(Auto Kernel Generator)正是面向上述需求设计的AI算子编译器,基于MLIR(Multi-Level Intermediate Representation)构建,分为akg-tvm与akg-mlir两个版本,其中akg-mlir支持CPU、NPU等多种后端。本文以NPU后端为例,系统介绍AKG-MLIR的构建、运行及核心编译流程,帮助开发者快速上手并理解其工作原理。
一、环境构建
1.1 依赖要求
- 编译器:GCC > 11,CMake > 3.24
- 关键依赖库:GMP、MLIR(19.1.7)、Zstd、LLVM-dev、AKG Wheel包、BiSheng Compile工具链
1.2 构建步骤
构建过程可参考官方README文档,构建产物位于build/bin目录下,主要包括两个可执行文件:
akg-opt:负责MLIR方言转换与优化pass执行mindspore-translate:负责将融合算子信息(info文件)转换为MindSpore方言表示
构建过程中如遇问题,可结合具体报错信息定位依赖版本或编译选项配置。
二、运行验证
2.1 运行环境配置
运行前需完成以下环境设置:
- 安装bfloat16支持库,并确认相关相对路径配置正确
- 若出现
undefined symbol: rtSetupArgument错误,需将CANN包下的lib64目录加入LD_LIBRARY_PATH,注意根据实际安装路径修改
2.2 结果验证
运行后,output为AKG-MLIR编译计算结果,expect为NumPy计算结果,二者比对一致即验证编译流程正确。
三、编译流程详解
AKG-MLIR的完整编译流水线如下:
info → MindSpore Dialect → Linalg(Hfusion) → HiVM → .so最终生成的.so文件由kernel launch模块加载执行。以下对各阶段逐一说明。
3.1 输入:融合算子info文件
Fused_Add_fusion_33.info是JSON格式的融合算子描述文件,由MindSpore图算融合模块生成,包含Tensor的shape、数据类型及计算逻辑等信息。
3.2 转换为MindSpore Dialect
MindSpore Dialect是基于MLIR的自定义方言,专注于元算子的表达。
转换命令:
akg/akg-mlir/build/bin/mindspore-translate Fused_Add_fusion_33.info --json-to-mindspore-oms.mlir代码路径:
main() → registerToMindsporeDialectTranslation() // mindspore-translate.cpp → translateToMindsporeDialect() // TranslateRegistration.cpp → MindBuilder类 // TranslateToMindsporeDialect.cpp核心流程包括:
mlirBuilder.convertToMLIR():整体转换入口convertOpNode(builder, opNodes[i]):逐节点转换mindOpFactory()→MindBuilder::convertBinaryOp:算子工厂分发- 通过
SmallVector等数据结构构建函数签名与属性
3.3 转换为Linalg(HFusion)
Linalg是MLIR社区方言,抽象了循环与计算细节,专注于线性代数运算表达;HFusion是Linalg的扩展,补充了Linalg未覆盖的算子表示。
转换命令:
akg/akg-mlir/build/bin/akg-opt ms.mlir --ascend-opt-olinalg.mlir主要优化内容:
- Tensor降维
- 替换为
linalg.elementwise计算 - 提前构建
%0等中间值
代码路径:
main() → registerAKGLinalgPasses() // akg-opt.cpp3.4 转换为HiVM并生成.so
HiVM是基于MLIR的自定义方言,更贴近底层硬件指令表达,便于后续指令转换与代码生成。
转换命令:
# 以Ascend Toolkit 8.2.RC1为例ascend-toolkit/8.2.RC1/bisheng_toolkit/bishengir/bin/bishengir-compile linalg.mlir\-enable-hfusion-compile=true\-enable-hivm-compile=true\-enable-lir-compile=true\-block-dim=40\-enable-auto-multi-buffer=true\-enable-bin-relocation=false\-oxxx.so版本差异说明:
不同版本的BiSheng Compile工具链支持的编译选项可能不同。例如,8.3.RC1版本使用-enable-triton-kernel-compile=true替代了-enable-lir-compile=true。若遇到“不识别命令”的报错,请确认当前使用的BiSheng Compile版本及对应支持的选项。
编译问题定位:
- 使用
--mlir-print-ir-after-all打印所有pass的IR输出,定位报错发生的pass阶段 - 根据定位结果,检查对应pass的代码逻辑或配置参数
四、目录结构
AKG-MLIR项目目录结构如下(以实际仓库为准):
akg-mlir/ ├── build/ # 构建产物目录 │ └── bin/ # 可执行文件(akg-opt, mindspore-translate) ├── src/ # 源码目录 │ ├── dialect/ # 自定义方言定义 │ ├── conversion/ # 方言转换pass │ ├── optimization/ # 优化pass │ └── ... ├── tests/ # 测试用例 └── README.md五、自定义Pass开发
AKG-MLIR支持开发者根据需求扩展自定义pass,开发流程如下:
- 编写TableGen描述文件(.td):使用DSL描述pass的输入输出、依赖关系及参数
- TableGen工具生成C++代码:自动生成pass的骨架代码
- 实现pass逻辑:在生成的C++代码基础上补充具体优化逻辑
- 注册pass:在对应的pass注册入口中注册新pass
TableGen文件使用易理解的DSL描述信息,大幅降低了pass开发门槛。具体开发示例可参考社区Merge Request中的diff内容。
六、总结与展望
AKG-MLIR通过多层IR设计与模块化pass架构,实现了从图算融合算子到高性能kernel的自动化编译流程。其核心优势在于:
- 多方言协同:MindSpore Dialect负责高层语义表达,Linalg/HFusion负责计算抽象,HiVM贴近硬件指令,各层各司其职
- 后端可扩展:通过pass组合适配不同硬件后端,降低新硬件适配成本
- 开发效率提升:开发者聚焦算法逻辑,编译器自动完成调度优化与代码生成
后续规划中,AKG-MLIR将进一步分层解耦编译流程,提升可解释性与可调试性,降低开发者的理解与使用门槛。