如何开发自己的NPU算子?ops-transformer标准算子开发6步全流程详解
【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-transformer
ops-transformer是 CANN 提供的 transformer 类大模型算子库,覆盖 Attention、MoE、MC2 等场景,帮助大模型在 NPU 上加速计算。本文将带你基于 ops-transformer 完整走一遍NPU算子开发的 6 步标准流程:从环境准备、项目结构理解,到编译打包、Kernel 开发,再到调试与性能验证,全程以官方示例算子 AddExample 为实践对象,零基础也能跟着跑通。
第1步:环境准备与源码下载 🛠️
NPU算子开发的前提是搭好一套可用的编译环境,推荐两条路线:
- CANNLab 云开发环境:默认已提供最新版 CANN 包及配套源码,开箱即用;
- 本地 Docker 部署:参考 docs/zh/install/quick_install.md 完成 NPU 驱动与 CANN 包安装。
环境就绪后,下载与你 CANN 版本配套标签的源码(版本不匹配是新手最常见的编译失败原因):
git clone -b 9.0.0 https://gitcode.com/cann/ops-transformer.git💡 说明:
${tag_version}替换为分支标签名。项目版本配套关系见 README 中的"版本配套"章节。
第2步:看懂标准算子项目的 5 大目录 📂
这是 NPU算子开发 中最容易迷路的一步。每个算子工程(以 examples/add_example/ 为例)都遵循统一的分层结构:
| 目录 | 职责 | 类比理解 |
|---|---|---|
| op_kernel/ | AI Core 侧 Kernel 实现(Ascend C) | 算子的"计算大脑" |
| op_host/ | Host 侧信息库、Tiling、InferShape | 算子的"调度中枢" |
| op_graph/ | 图模式构图、类型推导、融合规则 | 算子的"接入图引擎的接口" |
| examples/ | aclnn / geir 调用示例 | 算子的"使用说明" |
| tests/ | UT 单元测试用例 | 算子的"质检报告" |
几个关键文件值得记住:
- add_example_def.cpp:定义算子名称、输入输出、数据类型等基本信息;
- add_example_tiling.cpp:Tiling 实现,把张量划分成多个小块并行计算;
- add_example.h:Kernel 核心计算逻辑,80% 的算子开发工作都发生在这里。
完整目录规范请参考 docs/zh/install/dir_structure.md。
上图为项目中一个真实算子的张量布局示意。开发 NPU 算子前,务必先弄清每个输入/输出张量的 shape 与内存排布——这是写出正确 Kernel 的第一步。
第3步:一键编译算子包 📦
回到项目根目录,通用编译命令格式为:
bash build.sh --pkg --soc=<芯片版本> --ops=<算子名> -j16以 AddExample 为例:
bash build.sh --pkg --soc=ascend910b --ops=add_example -j16SoC 取值映射表(按你的芯片系列选择):
| 产品系列 | --soc取值 |
|---|---|
| Atlas A2 系列(训练/推理) | ascend910b |
| Atlas A3 系列(训练/推理) | ascend910_93 |
| 950 系列 | ascend950 |
看到如下输出即编译成功,run 包会生成在build_out/目录下:
Self-extractable archive "cann-ops-transformer-custom_linux.${arch}.run" successfully created.⚠️ 编译前先确认 CANN 环境变量已配置(如
source /usr/local/Ascend/cann/set_env.sh),否则会因找不到ASCEND_HOME_PATH而失败。
第4步:安装算子包并配置环境变量 ⚙️
NPU算子开发 编译出的 run 包需要安装到 CANN 的 vendor 目录,运行时才能被识别:
./build_out/cann-ops-transformer-*linux*.run export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/opp/vendors/custom_transformer/op_api/lib:${LD_LIBRARY_PATH}安装成功后,算子会落在${ASCEND_HOME_PATH}/opp/vendors路径下。可用grep load_priority ${ASCEND_HOME_PATH}/opp/vendors/config.ini校验是否加载——无输出通常是目录属主或权限问题。
第5步:修改 Kernel,开发你自己的 NPU 算子 🚀
前面四步跑通后,你手里已经有一个可运行的"骨架算子"。现在把它改成你自己的逻辑。
以 AddExample 为例,打开 op_kernel/add_example.h,在Compute函数中把加法替换为乘法:
__aicore__ inline void AddExample<T>::Compute(int32_t progress) { AscendC::LocalTensor<T> xLocal = inputQueueX.DeQue<T>(); AscendC::LocalTensor<T> yLocal = inputQueueY.DeQue<T>(); AscendC::LocalTensor<T> zLocal = outputQueueZ.AllocTensor<T>(); // 在此处将 Add 替换为 Mul AscendC::Mul(zLocal, xLocal, yLocal, tileLength_); outputQueueZ.EnQue<T>(zLocal); inputQueueX.FreeTensor(xLocal); inputQueueY.FreeTensor(yLocal); }Ascend C 开发的核心套路就是DeQue 取输入 → 调用计算 API → EnQue 输出,完整规范与最小交付件说明见 docs/zh/develop/aicore_develop_guide.md。
开发完执行"重编译 → 重装 → 重验证"三连:
bash build.sh --pkg --soc=ascend910b --ops=add_example -j16 ./build_out/cann-ops-transformer-*linux*.run bash build.sh --run_example add_example eager cust --vendor_name=custom输出从加法结果2.000000变成乘法结果1.000000,说明你的 Kernel 修改已生效 ✅
你的算子放哪里?项目专门提供了 experimental/ 目录存放用户自定义算子,按 attention、moe、mc2 等分类建目录即可,这是贡献新算子的标准入口,规范见 CONTRIBUTING.md。
第6步:算子调试、验证与性能采集 🐞
6.1 功能验证
修改 examples/test_aclnn_add_example.cpp 中的输入 shape 与数据(例如从{32,4,4,4}改为{8,8,8,8},并同步调整 host 侧数据长度),重新运行 example 即可验证不同输入下的正确性:
bash build.sh --run_example add_example eager cust --vendor_name=custom6.2 调试打印
算子执行失败或精度异常时,在 Kernel 中使用两类调试接口:
- printf:打印 Scalar 类型数据,如
AscendC::PRINTF("blockLength is %ld\n", blockLength_); - DumpTensor:把指定 Tensor 内容 Dump 到本地文件,如
DumpTensor(zLocal, 0, 128);
无真机环境也可以先仿真调试:开源算子支持 NPU Simulator 仿真工具,详见 docs/zh/debug/npu_sim.md。
6.3 性能采集
功能验证通过后,用msprof op采集算子级性能:
bash build.sh --run_example add_example eager cust --vendor_name=custom cd build && msprof op ./test_aclnn_add_example执行后会打印 Op Name、Task Duration、Block Dim 等基础信息,并给出性能瓶颈提示,完整数据保存在build/OPPROF_*目录中,可进一步分析流水占比、带宽利用率等指标。
常见问题速查 💬
Q1:编译报找不到ASCEND_HOME_PATH怎么办?先sourceCANN 安装目录下的set_env.sh配置环境变量,再重新编译。
Q2:源码用 master 分支编译失败?请改用与 CANN 版本配套的标签分支(如 9.0.0),版本配套关系见 README。
Q3:只想学调用,不想写 Kernel,从哪入手?先看 docs/QUICKSTART.md 的"编译运行"部分跑通 AddExample,再对照 docs/zh/invocation/quick_op_invocation.md 学习算子调用。
Q4:新算子应该放在项目哪个目录?用户自定义算子统一放在 experimental/ 目录,开发调试后按 CONTRIBUTING.md 流程贡献。
写在最后
恭喜你完成了 NPU算子开发 的完整闭环!🎉 回顾 6 步流程:
- 环境准备:CANNLab/Docker + 配套标签源码
- 看懂结构:op_kernel / op_host / op_graph 分层职责
- 编译打包:
build.sh --pkg --soc --ops - 安装配置:run 包 +
LD_LIBRARY_PATH - 开发 Kernel:Ascend C 的 DeQue-计算-EnQue 套路
- 调试验证:example 验证 + 打印调试 + msprof 性能采集
想深入了解更多标准算子的实现细节(Attention、GroupedMatmul、MoE 等),可以按 docs/zh/op_list.md 浏览项目算子清单,每个算子目录内都附有完整的 README 与 docs 文档,是现成的最佳实践素材。
【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-transformer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考