算子kernel侧和host侧实现开发完成后,需要对算子工程进行编译,生成自定义算子安装包*.run,详细的编译操作包括:
编译Ascend C算子kernel侧代码实现文件*.cpp,分为源码发布和二进制发布两种方式。
编译Ascend C算子host侧代码实现文件*.cpp、*.h。
- 将原型定义和shape推导实现编译成算子原型定义动态库libcust_opsproto_*.so,并生成算子原型对外接口op_proto.h。
- 将Tiling实现编译成Tiling动态库liboptiling.so等。
- 基于算子原型定义,自动生成单算子API调用代码和头文件aclnn_*.h,并编译生成单算子API调用的动态库libcust_opapi.so。
上述编译过程示意图如下:
图 1 算子工程编译示意图[object Object][object Object]
完成工程编译相关配置。
在算子工程目录下执行如下命令,进行算子工程编译。
./build.sh
编译成功后,会在当前目录下创建build_out目录,并在build_out目录下生成自定义算子安装包custom_opp_<target os>__<target architecture>.run。
用户如果需要编译过程日志存盘,可以使用环境变量ASCENDC_BUILD_LOG_DIR来控制存储路径。用户设置该选项之后,如果编译过程中无错误产生,则对应的log文件后缀会添加"_success",若编译过程有错误产生,则会在屏幕打印对应的报错信息,以及指示用户log文件的具体路径与文件名,同时,对应log文件后缀会添加“_error”。
[object Object]
完成算子代码实现后,如果当前平台架构和运行环境一致则参考上一节的内容进行编译即可,如果需要实现算子包的交叉编译,您可以参考如下流程。
交叉编译工具下载,下表以Ubuntu系列操作系统为例,展示了编译工具下载命令的样例。其他操作系统,请替换为实际的下载命令。
表 3 Ubuntu系列操作系统交叉编译工具下载命令样例
[object Object][object Object]
[object Object]自定义算子工程交叉编译,构建生成自定义算子包。
修改CMakePresets.json中ENABLE_CROSS_COMPILE为True,启用交叉编译。
[object Object]修改CMakePresets.json中CMAKE_CROSS_PLATFORM_COMPILER为安装后的交叉编译工具路径。
[object Object]在算子工程目录下执行如下命令,进行算子工程交叉编译。
./build.sh
编译成功后,会在当前目录下创建build_out目录,并在build_out目录下生成自定义算子安装包custom_opp_<target os>__<target architecture>.run
在算子工程中,如果开发者想对算子kernel侧代码增加一些自定义的编译选项,可以参考如下内容进行编译选项的定制。
修改算子工程op_kernel目录下的CMakeLists.txt,使用add_ops_compile_options来增加编译选项,方法如下:
具体参数的介绍如下:
表 4 具体参数介绍
[object Object][object Object]
[object Object]
[object Object]
Ascend C框架提供的编译选项介绍如下:
--tiling_key,设置该选项后,只编译指定的相关的kernel代码,用于加速编译过程。若不指定TilingKey编译,则默认编译所有的TilingKey。配置多个TilingKey时,TilingKey之间不能有空格。示例如下,其中1、2为tiling_key。
[object Object]--op_relocatable_kernel_binary,设置该选项为true时,会额外编译一份可被重新链接的二进制文件;不配置或设置为false时该选项均不生效。该选项用于自定义Tiling下沉算子启用SuperKernel的场景,配置该选项所生成的二进制文件,可以使算子在SuperKernel编译时直接复用二进制文件,降低编译耗时。
--kernel-template-input,用于,设置该选项后,只编译指定的模板参数组合相关的Kernel代码,用于加速编译过程。若不设置该选项,则默认编译所有的模板参数组合。传入的参数为键值对列表,整体需用双引号或单引号包裹。不同模板参数之间用英文分号(;)分隔,相同模板参数配置多个值时用英文逗号(,)分隔。配置时不能有空格。示例如下:
[object Object]配置模板参数组合时,模板参数名需要与Kernel入口处以及Host侧定义的模板参数名匹配。对于模板参数组合的值,如果存在自定义类型,需要替换为其对应数字值,如果为原生支持数据类型,则与Kernel入口处入参保持一致。示例如下:
[object Object]编译选项示例如下:
[object Object]-DFORCE_TILING_CONST_PROPAGATION,该选项用于静态shape场景Tiling数据的常量化优化。对于复杂算子,该编译选项可以提升算子静态shape执行性能。该编译选项仅支持自定义算子工程,且仅在算子使用BEGIN_TILING_DATA_DEF注册Tiling结构体的情形下生效,对于算子使用标准C++语法定义Tiling结构体的情形下不生效。使用示例如下:
[object Object]该编译选项的原理是,在算子使用BEGIN_TILING_DATA_DEF注册Tiling结构体的场景下,自定义算子工程在定义该Tiling结构体时,会将其成员变量都定义为static constexpr类型常量,即将Tiling结构体变为静态常量类。由于在前端标记了常量,编译器会根据Tiling数据进行更彻底的常量折叠和优化。
该选项对算子写法有约束,以下情形不支持该选项:
算子代码中不允许有用Tiling结构体定义非const对象,也不允许对Tiling对象的成员进行赋值操作。否则会有编译错误。原因是静态常量无法被重新赋值。
算子代码中不允许有reinterpret_cast<OtherType*>(tiling_data)的行为,否则会得到非预期的结果。这是因为Tiling结构体所有成员都是常量,该类型的对象没有实体,size恒为1字节,对tiling_data的reinterpret_cast会产生未定义的行为。
对于算子使用标准C++语法定义Tiling结构体的情形下不生效的原因是,算子定义Tiling结构体为static constexpr时,无法获得Tiling数据,无法给Tiling结构体成员在定义时初始化。