什么是ASC-IR:为昇腾算子定义MLIR方言的完整指南(TableGen实战)

【免费下载链接】pyasc 本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。 【免费下载链接】pyasc 项目地址: https://gitcode.com/cann/pyasc

一句话理解:ASC-IR 是 pyasc 项目基于 MLIR 框架自定义的中间表示(IR)方言,它用标准化的"操作(Op)+ 类型(Type)"体系描述昇腾算子的计算逻辑,再借助 TableGen 工具自动生成 C++ 代码与 Python 绑定,最终把 Python 代码翻译成 Ascend C 算子并在昇腾 AI 处理器上加速运行。

如果你想在昇腾芯片上开发算子,但不想写 C++,pyasc 提供了一个 Python 编程接口——它和 Ascend C 接口一一对应,且遵守 Python 原生语法。而支撑这一切的"幕后英雄",就是本文的主角 ASC-IR(MLIR 方言) 和 TableGen 代码生成技术。

1. ASC-IR 在 pyasc 架构中的位置

先看 pyasc 的整体架构图。中间一层的「扩展 Dialect」正是核心:左侧的 ASC-IR 基于 MLIR 扩展定义了 Ascend C 的类和接口,右侧的 EmitAsc-IR 则负责把 MLIR 转换为 C++ 代码类。

pyasc架构图:扩展Dialect层包含ASC-IR与EmitAsc-IR两个MLIR方言

简单说,整条链路是:

层干什么代表目录
Python 界面提供 Kernel 开发接口,与基础/高阶 API 1:1 对应python/asc/language/
扩展 DialectASC-IR:用 MLIR 描述算子计算图include/ascir/
Ascend C基础 API & 高阶 API由后端代码生成
基础组件毕昇编译器、Runtime、Profiling 工具—

详细模块说明可参考 docs/architecture_introduction.md。

2. 编译全流程:Python 代码如何变成算子

下面的流程图展示了从 @asc.jit 装饰的 Python 代码到最终输出的完整旅程,ASC-IR 正处于承上启下的中心位置:

pyasc核心模块关系图:从Python AST到ASC-IR再到Ascend C代码

流程要点:

  1. 前端:Python AST Visitor 遍历语法树,调用 pybind 接口创建 ASC-IR 节点;
  2. ASC-IR 定义模块:由 Interface、Attribute、Type、Operation 四件套构成(这正是 MLIR 方言的标准结构);
  3. 后端:Translation 执行代码生成,调用 CodeEmitter 输出的封装方法,产出 Ascend C 代码;
  4. 编译运行:毕昇编译器生成二进制,Runtime 加载执行。

💡 想亲眼看看编译产物?设置环境变量 PYASC_DUMP_PATH 即可在编译完成后查看中间生成的 ASC-IR 文件和 Ascend C 代码,详见 docs/architecture_introduction.md 的"编译和运行模块"章节。

3. 方言四件套:一个 .td 文件读懂 ASC-IR

ASC-IR 的方言定义全部集中在 include/ascir/Dialect/ 目录下,用 TableGen(.td 文件)编写。四个构建块分别是:

3.1 Type:类型定义

MLIR 中的"类型"描述了数据的形状和含义。ASC-IR 在 Core/Base.td 中定义了类型基类,例如张量类型 BaseTensorType 携带了 shape 和 elementType 两个参数——这就是 Ascend C 中张量概念的 MLIR 表达。

// 核心思想:用声明式语法定义"张量 = 形状 + 元素类型"
class AscendC_BaseTensorType<string name, string typeMnemonic, ...>
    : AscendC_Type<name, typeMnemonic, [AscendC_BaseTensorTypeInterface, ...]> {
  let parameters = (ins ArrayRefParameter<"int64_t">:$shape,
                        "Type":$elementType);
}

3.2 Operation:操作定义

Op 是 MLIR 的"积木块"。以 Core/Tensor.td 为例,GlobalTensor::GetPhyAddr 方法被定义为一个 Op:

def AscendC_GlobalTensorGetPhyAddrOp
    : APIOp<"global_tensor.get_phy_addr", "GetPhyAddr", [AscMemberFunc]> {
  let summary = "Call `AscendC::GlobalTensor::GetPhyAddr` method";
  let arguments = (ins AscendC_GlobalTensor:$tensor, Optional<UI64>:$offset);
  let results = (outs AnyRankedOrUnrankedMemRef:$result);
}

注意命名约定:APIOp 的第二个参数 "GetPhyAddr" 对应 Ascend C 的真实 C++ 方法名,这正是"Python 接口与 Ascend C 一一对应"的底层保证。按 API 分类,Op 定义分布在 Basic/(42 个 .td,覆盖向量、标量、数据搬运等基础 API)和 Adv/(9 个 .td,覆盖 Matmul、Softmax 等高阶 API)。

3.3 Interface 与 Attribute

接口(Interface)让不同 Op 共享统一的方法契约,如 Interfaces.td 中的张量接口;属性(Attribute)则承载 Op 的附加配置参数。

3.4 Pass:方言的"加工流水线"

Op 生成后还有一系列 Pass 做图变换,全部在 Transforms/Passes.td 中声明,例如:

Pass作用
ascendc-insert-sync插入核内同步操作
ascendc-hoist-ub-allocation把张量分配提升到函数根部
ascendc-detect-kernel-type检测 kernel 是纯 Vector 还是混合模式

对应的实现代码在 lib/Dialect/Asc/Transforms/,每个 Pass 一个 .cpp 文件,一一对应。

4. TableGen 实战:.td 如何变成 C++ 和 Python

.td 文件本身不可执行,pyasc 自研了一套 TableGen 后端放在 lib/TableGen/,构建时自动运行并产出多种代码:

生成器产物
GenAPITypes.cpp / GenAPITypedefs.cppAPI 类型 C++ 定义
GenOpEmitDecls.cpp / GenOpEmitDefs.cppOp 到 C++ 代码的发射规则(Emit 声明与实现)
GenPybindDefs.cppPython 绑定——让前端 AST Visitor 能通过 pybind 创建 IR 节点

这就是"定义一次,三处受益":同一个 def AscendC_GlobalTensorGetPhyAddrOp,既生成了 MLIR 的 Op 类,又生成了发射 C++ 代码的 Emitter 逻辑,还生成了 Python 侧可 import 的接口。

5. 上手路径:从读示例到读测试

🚀 建议新手按以下顺序探索:

  1. 跑一个最小算子:examples/01_add/add.py 与 examples/02_add_framework/add_framework.py,配合 PYASC_DUMP_PATH 查看生成的 ASC-IR;
  2. 对照测试用例理解 Op 语义:如 test/Target/AscendC/matmul.mlir 展示了 Ascend C Op 文本化后的 IR 长什么样;
  3. 深入方言定义:通读 include/ascir/Dialect/Asc/IR/Core/ 的 6 个 .td 文件;
  4. 进阶到代码生成:浏览 lib/Target/AscendC/ 下按 API 分类的 Emitter 实现(Core/GlobalTensor.cpp 等)。

6. 小结

  • ASC-IR = MLIR 方言:用 Op/Type/Interface/Attribute 四件套把 Ascend C 世界映射到 IR 世界;
  • TableGen 是杠杆:一份 .td 定义,同时驱动 C++ 后端和 Python 前端代码生成,保证接口严格 1:1 对应;
  • 学习路线:跑示例 → dump 中间产物 → 读 .td 定义 → 读 Pass 与 Emitter,即可完整掌握昇腾算子的编译原理。

掌握了 ASC-IR 方言的定义方式,你就有资格参与 pyasc 的贡献了——编写规范见 CONTRIBUTING.md。

【免费下载链接】pyasc 本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。 【免费下载链接】pyasc 项目地址: https://gitcode.com/cann/pyasc

更多推荐