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

什么是ASC-IR:为昇腾算子定义MLIR方言的完整指南(TableGen实战) 什么是ASC-IR为昇腾算子定义MLIR方言的完整指南TableGen实战【免费下载链接】pyasc本项目为Python用户提供算子编程接口支持在昇腾AI处理器上加速计算接口与Ascend C一一对应并遵守Python原生语法。项目地址: https://gitcode.com/cann/pyasc一句话理解ASC-IR 是 pyasc 项目基于 MLIR 框架自定义的中间表示IR方言它用标准化的操作Op 类型Type体系描述昇腾算子的计算逻辑再借助 TableGen 工具自动生成 C 代码与 Python 绑定最终把 Python 代码翻译成 Ascend C 算子并在昇腾 AI 处理器上加速运行。如果你想在昇腾芯片上开发算子但不想写 Cpyasc 提供了一个 Python 编程接口——它和 Ascend C 接口一一对应且遵守 Python 原生语法。而支撑这一切的幕后英雄就是本文的主角ASC-IRMLIR 方言和TableGen代码生成技术。1. ASC-IR 在 pyasc 架构中的位置先看 pyasc 的整体架构图。中间一层的「扩展 Dialect」正是核心左侧的ASC-IR基于 MLIR 扩展定义了 Ascend C 的类和接口右侧的EmitAsc-IR则负责把 MLIR 转换为 C 代码类。简单说整条链路是层干什么代表目录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 正处于承上启下的中心位置流程要点前端Python AST Visitor 遍历语法树调用 pybind 接口创建 ASC-IR 节点ASC-IR 定义模块由 Interface、Attribute、Type、Operation 四件套构成这正是 MLIR 方言的标准结构后端Translation 执行代码生成调用 CodeEmitter 输出的封装方法产出 Ascend C 代码编译运行毕昇编译器生成二进制Runtime 加载执行。 想亲眼看看编译产物设置环境变量PYASC_DUMP_PATH即可在编译完成后查看中间生成的ASC-IR 文件和 Ascend C 代码详见 docs/architecture_introduction.md 的编译和运行模块章节。3. 方言四件套一个 .td 文件读懂 ASC-IRASC-IR 的方言定义全部集中在 include/ascir/Dialect/ 目录下用 TableGen.td 文件编写。四个构建块分别是3.1 Type类型定义MLIR 中的类型描述了数据的形状和含义。ASC-IR 在 Core/Base.td 中定义了类型基类例如张量类型BaseTensorType携带了shape和elementType两个参数——这就是 Ascend C 中张量概念的 MLIR 表达。// 核心思想用声明式语法定义张量 形状 元素类型 class AscendC_BaseTensorTypestring name, string typeMnemonic, ... : AscendC_Typename, typeMnemonic, [AscendC_BaseTensorTypeInterface, ...] { let parameters (ins ArrayRefParameterint64_t:$shape, Type:$elementType); }3.2 Operation操作定义Op 是 MLIR 的积木块。以 Core/Tensor.td 为例GlobalTensor::GetPhyAddr方法被定义为一个 Opdef AscendC_GlobalTensorGetPhyAddrOp : APIOpglobal_tensor.get_phy_addr, GetPhyAddr, [AscMemberFunc] { let summary Call AscendC::GlobalTensor::GetPhyAddr method; let arguments (ins AscendC_GlobalTensor:$tensor, OptionalUI64:$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. 上手路径从读示例到读测试 建议新手按以下顺序探索跑一个最小算子examples/01_add/add.py 与 examples/02_add_framework/add_framework.py配合PYASC_DUMP_PATH查看生成的 ASC-IR对照测试用例理解 Op 语义如 test/Target/AscendC/matmul.mlir 展示了 Ascend C Op 文本化后的 IR 长什么样深入方言定义通读 include/ascir/Dialect/Asc/IR/Core/ 的 6 个 .td 文件进阶到代码生成浏览 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原生语法。项目地址: https://gitcode.com/cann/pyasc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考