通算融合自定义算子工程开发指南
环境准备
-
环境部署
调用算子之前,请先参考环境部署完成基础环境搭建。
-
创建算子工程
CANN开发套件包中提供了自定义算子工程生成工具msOpGen,可基于算子原型定义输出算子工程:包括算子host侧代码实现文件、算子kernel侧实现文件以及工程编译配置文件等,详细说明请参考工程化算子开发。使用msOpGen工具创建算子开发工程的步骤如下:
(1)编写算子的原型定义json文件,用于生成算子开发工程。
json文件的详细配置请参考json文件配置参数说明。例如,AddCustom算子的json文件命名为add_custom.json,文件内容如下:
[ { "op": "AddCustom", "input_desc": [ { "name": "x", "param_type": "required", "format": [ "ND", "ND", "ND" ], "type": [ "fp16", "float", "int32" ] }, { "name": "y", "param_type": "required", "format": [ "ND", "ND", "ND" ], "type": [ "fp16", "float", "int32" ] } ], "output_desc": [ { "name": "z", "param_type": "required", "format": [ "ND", "ND", "ND" ], "type": [ "fp16", "float", "int32" ] } ] } ](2)使用msOpGen工具生成算子的开发工程。
以生成AddCustom的算子工程为例,执行如下命令。下文仅针对关键参数进行解释,详细参数说明请参见算子工程创建msOpGen。
${INSTALL_DIR}/cann/python/site-packages/bin/msopgen gen -i $HOME/experimental/mc2/add_custom.json -c ai_core-<soc_version> -lan cpp -out $HOME/experimental/mc2/add_custom- ${INSTALL_DIR}为CANN软件安装后文件存储路径,请根据实际环境进行替换。
- -i:指定算子原型定义文件add_custom.json所在路径,请根据实际情况修改。
- -c:ai_core-<soc_version>代表算子在AI Core上执行,<soc_version>为昇腾AI处理器的型号。
- -lan:参数cpp代表算子基于Ascend C编程框架,使用C/C++编程语言开发。
- -out:生成文件所在路径,可配置为绝对路径或者相对路径,并且工具执行用户对路径具有可读写权限。若不配置,则默认生成在执行命令的当前路径。
(3)命令执行完后,会在-out指定目录或者默认路径下生成算子工程目录,工程中包含算子实现的模板文件,编译脚本等,以AddCustom算子为例,目录结构如下所示:
AddCustom ├── build.sh // 编译入口脚本 ├── cmake // 算子工程编译所需脚本及公共编译文件存放目录 ├── CMakeLists.txt // 算子工程的CMakeLists.txt ├── CMakePresets.json // 编译配置项 ├── framework // AI框架适配时,算子插件实现文件目录 ├── op_host // host侧实现文件 │ ├── add_custom_tiling.h // 算子tiling定义文件 │ ├── add_custom.cpp // 算子原型注册、shape推导、信息库、tiling实现等内容文件 │ ├── CMakeLists.txt ├── op_kernel // kernel侧实现文件 │ ├── CMakeLists.txt │ ├── add_custom.cpp // 算子代码实现文件 └── scripts // 自定义算子工程打包相关脚本所在目录工程目录中的op_kernel和op_host包含了算子的核心实现文件。op_kernel下存放kernel侧算子实现。op_host下存放host侧代码实现,包括算子原型定义、host侧tiling实现。具体实现可参考通算融合算子编程。工程目录中的CMakePresets.json,用于开发者完成工程编译相关配置,之后即可进行编译部署。
编译部署
-
算子工程编译
(1)完成工程编译相关配置。
修改工程目录下的CMakePresets.json cacheVariables的配置项。CMakePresets.json文件内容如下,需要配置的参数请参考编译配置参数列表,其他参数会在工程创建时自动生成。
{ "version": 1, "cmakeMinimumRequired": { "major": 3, "minor": 19, "patch": 0 }, "configurePresets": [ { "name": "default", "displayName": "Default Config", "description": "Default build using Unix Makefiles generator", "generator": "Unix Makefiles", "binaryDir": "${sourceDir}/build_out", "cacheVariables": { "CMAKE_BUILD_TYPE": { "type": "STRING", "value": "Release" }, "ENABLE_SOURCE_PACKAGE": { "type": "BOOL", "value": "True" }, "ENABLE_BINARY_PACKAGE": { "type": "BOOL", "value": "True" }, "ASCEND_COMPUTE_UNIT": { "type": "STRING", "value": "ascendxxx" }, "ENABLE_TEST": { "type": "BOOL", "value": "True" }, "vendor_name": { "type": "STRING", "value": "customize" }, "ASCEND_PYTHON_EXECUTABLE": { "type": "STRING", "value": "python3" }, "CMAKE_INSTALL_PREFIX": { "type": "PATH", "value": "${sourceDir}/build_out" }, "ENABLE_CROSS_COMPILE": { "type": "BOOL", "value": "False" }, "CMAKE_CROSS_PLATFORM_COMPILER": { "type": "PATH", "value": "/usr/bin/aarch64-linux-gnu-g++" }, "ASCEND_PACK_SHARED_LIBRARY": { "type": "BOOL", "value": "False" } } } ] }(2)在算子工程目录下执行如下命令,进行算子工程编译。
bash $HOME/experimental/mc2/build.sh编译成功后,会在当前目录下创建build_out目录,并在build_out目录下生成自定义算子安装包custom_opp_${target_os}_${target_architecture}.run。
用户如果需要编译过程日志存盘,可以使用环境变量ASCENDC_BUILD_LOG_DIR来控制存储路径。用户设置该选项之后,如果编译过程中无错误产生,则对应的log文件后缀会添加"_success",若编译过程有错误产生,则会在屏幕打印对应的报错信息,以及指示用户log文件的具体路径与文件名,同时,对应log文件后缀会添加“_error”。
# 如希望编译日志存储在/home/build_log/,则可以按照如下设置,默认不打开日志存储 export ASCENDC_BUILD_LOG_DIR=/home/build_log/例如,若提示如下信息,说明编译成功。
Self-extractable archive "custom_opp_euleros_aarch64.run" successfully created. -
算子包部署
(1)自定义算子包安装部署。
在自定义算子包所在路径下,执行如下命令,安装自定义算子包。
./custom_opp_<target os>_<target architecture>.run --install-path=<path>- --install-path:可选参数,用于指定自定义算子包的安装目录。支持指定绝对路径,运行用户需要对指定的安装路径有可读写权限。
下文描述中的<vendor_name>为算子工程编译时CMakePresets.json配置文件中字段“vendor_name”的取值,默认为“customize”。
-
默认安装场景:
不配置--install-path参数,安装成功后会将编译生成的自定义算子相关文件部署到
${INSTALL_PATH}/opp/vendors/<vendor_name>目录。${INSTALL_DIR}请替换为CANN软件安装后文件存储路径。 -
指定目录安装场景:
配置--install-path参数,安装成功后会将编译生成的自定义算子相关文件部署到<path>/vendors/<vendor_name>目录,并在<path>/vendors/<vendor_name>/bin目录下新增set_env.bash,写入当前自定义算子包相关的环境变量。
(2)以默认安装场景为例,可查看部署后的目录结构,如下所示:
├── opp //算子库目录 │ ├── vendors //自定义算子所在目录 │ ├── config.ini │ └── vendor_name1 // 存储对应厂商部署的自定义算子,此名字为编译自定义算子安装包时配置的vendor_name,若未配置,默认值为customize │ ├── framework //自定义算子插件库 │ ├── op_api │ │ ├── include │ │ │ └── aclnn_xx.h //算子调用API声明文件 │ │ └── lib │ │ └── libcust_opapi.so │ ├── op_impl │ │ └── ai_core │ │ └── tbe │ │ ├── config │ │ ├── vendor_name1_impl //自定义算子实现代码文件 │ │ │ └── dynamic │ │ │ ├── xx.cpp │ │ │ └── xx.py │ │ ├── kernel //自定义算子二进制文件 │ │ │ └── ${soc_version} //昇腾AI处理器类型 │ │ │ └── config │ │ └── op_tiling │ │ ├── lib │ │ └── liboptiling.so │ └── op_proto //自定义算子原型库所在目录 │ ├── inc │ │ └── op_proto.h │ └── lib │ ├── vendor_name2 // 存储厂商vendor_name2部署的自定义算子(2)配置自定义算子优先级。
多算子包共存的情况下,若不同的算子包目录下存在相同OpType的自定义算子,则以优先级高的算子包目录下的算子为准。下面介绍如何配置算子包优先级:
- 默认安装场景
当“opp/vendors”目录下存在多个厂商的自定义算子时,您可通过配置“opp/vendors”目录下的“config.ini”文件,配置自定义算子包的优先级。“config.ini”文件的配置示例如下:
load_priority=vendor_name1,vendor_name2,vendor_name3-
load_priority:优先级配置序列的关键字,不允许修改。
-
vendor_name1,vendor_name2,vendor_name3:自定义算子厂商的优先级序列,按照优先级从高到低的顺序进行排列。
-
指定目录安装场景
指定目录安装场景下,如果需要多个自定义算子包同时生效,分别执行各算子包安装路径下的set_env.bash脚本即可。每次脚本执行都会将当前算子包的安装路径追加到ASCEND_CUSTOM_OPP_PATH环境变量的最前面。因此可以按照脚本执行顺序确定优先级:脚本执行顺序越靠后,算子包优先级越高。
比如先执行
source <path>/vendor_name1/bin/set_env.bash,后执行source <path>/vendor_name2/bin/set_env.bash,vendor_name2算子包的优先级高于vendor_name1。ASCEND_CUSTOM_OPP_PATH示例如下:ASCEND_CUSTOM_OPP_PATH=<path>/vendor_name2:<path>/vendor_name1:- 指定目录安装场景下安装的算子包优先级高于默认方式安装的算子包。