算子NPU实现(Ascend C)
自定义PyTorch算子的NPU实现一般采用Ascend C编程语言实现,推荐“工程化方式”实现算子,其开发的NPU算子简称为“Ascend C算子”。
工程化开发是标准的算子开发流程,其简化了NPU适配过程,同时会自动注册Ascend C算子对应的Ascend IR,以保证PyTorch算子能与TorchAir max-autotune模式(Ascend IR)配合工作。
使用TorchAir reduce-overhead模式时,您可以使用任意方式开发算子NPU实现,只需要保证Torch算子能在Eager模式下正常工作。
使用TorchAir max-autotune模式时,需要确保算子NPU实现是以Ascend C算子工程化方式开发的aclnnXxx接口,以Kernel直调方式开发的NPU实现不会生成Ascend IR注册逻辑,没有对应的Ascend IR,无法完成PyTorch算子到Ascend IR的转换。
本章仅提供基于Ascend C工程化开发算子的关键步骤说明,详细的操作请参考《CANN Ascend C算子开发指南》中的“算子实现>工程化算子开发”章节,例如算子原型json文件的参数含义、msOpGen工具的命令说明等。
创建自定义算子工程与原型
- 编写算子的原型定义json文件,用于生成算子开发工程。
例如MyOp算子的原型json文件名为my_op.json,文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
[ { "op": "MyOp", "input_desc": [ { "name": "x", "param_type": "required", "format": ["ND"], "type": ["float"] }, { "name": "y", "param_type": "optional", "format": ["ND"], "type": ["float"] }, { "name": "z", "param_type": "dynamic", "format": ["ND"], "type": ["float"] } ], "attr": [ { "name": "attr1", "param_type": "required", "type": "float" }, { "name": "attr2", "param_type": "required", "type": "int" } ], "output_desc": [ { "name": "out", "param_type": "required", "format": ["ND"], "type": ["float"] } ] } ]
- 使用msOpGen工具生成算子的开发工程。
${INSTALL_DIR}/python/site-packages/bin/msopgen gen -i my_op.json -c ai_core-<soc_version> -f pytorch -lan cpp -out ./MyOp- ${INSTALL_DIR}为CANN软件安装后文件存储路径,请根据实际环境进行替换。
- -i:指定算子原型定义的json文件所在路径,请根据实际情况修改。
- -c:ai_core-<soc_version>代表算子在AI Core上执行,<soc_version>为昇腾AI处理器的型号,请与实际环境保持一致。
- -lan:参数cpp代表算子基于Ascend C编程框架,使用C/C++编程语言开发。
- -out:生成文件所在路径,可配置为绝对路径或者相对路径,并且工具执行用户对路径具有可读写权限。若不配置,则默认生成在执行命令的当前路径。
- 生成的算子核心工程目录结构如下:
MyOp ├── build.sh // 算子包编译脚本 ├── ...... ├── op_host // Host侧实现 │ ├── my_op.cpp // 算子定义、Tiling、InferShape、InferDataType实现文件 │ └── my_op_tiling.h // 算子Tiling定义文件 └── op_kernel // Kernel侧实现 └── my_op.cpp // Kernel代码实现文件
实现Kernel与Tiling
为方便演示,本样例直接使用默认生成的Kernel和Tiling空实现,不影响后续的编译与执行。
实际业务场景下,您可以参考《CANN Ascend C算子开发指南》中的“算子实现>工程化算子开发”章节下“Kernel侧算子实现”和“Host侧Tiling实现”,进行核心代码开发。
实现InferShape与InferDataType(可选)
本步骤为可选操作,仅当需要使用TorchAir max-autotune模式(Ascend IR)提供的能力时,才需要实现InferShape与InferDataType。
前文msOpGen生成的自定义算子工程会在“op_host/my_op.cpp”中生成一份简单但通常合适的默认实现。默认实现假设输出的shape和data type与第一个输入完全相同,与MyOp的定义一致,无需重新实现。
实际业务场景下,您可以参考《CANN Ascend C算子开发指南》中“算子入图(GE图)开发”章节下“开发流程”完成datatype推导与shape推导。