算子kernel侧和host侧实现开发完成后,需要对算子工程进行编译,生成自定义算子安装包*.run,详细的编译操作包括:
{
"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"
}
}
}
]
}
|
参数名称 |
参数描述 |
默认值 |
|---|---|---|
|
CMAKE_BUILD_TYPE |
编译模式选项,可配置为:
|
“Release” |
|
ENABLE_SOURCE_PACKAGE |
是否开启源码编译 |
“True” |
|
ENABLE_BINARY_PACKAGE |
是否开启二进制编译 |
“True” |
|
vendor_name |
标识自定义算子所属厂商的名称。建议开发者自行指定所属厂商名称,避免和其他厂商提供的算子包冲突。 |
“customize” |
|
ASCEND_PACK_SHARED_LIBRARY |
是否开启动态库编译功能。 |
“False” |
|
环境变量 |
配置说明 |
|---|---|
|
CMAKE_CXX_COMPILER_LAUNCHER |
用于配置C++语言编译器(如g++)、毕昇编译器的启动器程序为ccache,配置后即可开启cache缓存编译,加速重复编译并提高构建效率。使用该功能前需要安装ccache。 配置方法如下,在对应的CMakeLists.txt进行设置: set(CMAKE_CXX_COMPILER_LAUNCHER <launcher_program>) 其中<launcher_program>是ccache的安装路径,比如ccache的安装路径为/usr/bin/ccache,示例如下: set(CMAKE_CXX_COMPILER_LAUNCHER /usr/bin/ccache) |
./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/
完成算子代码实现后,如果当前平台架构和运行环境一致则参考上一节的内容进行编译即可,如果需要实现算子包的交叉编译,您可以参考如下流程。
|
当前平台架构 |
运行环境平台架构 |
编译工具下载命令 |
|---|---|---|
|
x86_64 |
aarch64 |
sudo apt-get install -y g++-aarch64-linux-gnu |
|
aarch64 |
x86_64 |
sudo apt-get install g++-x86-64-linux-gnu |
"ENABLE_CROSS_COMPILE": {
"type": "BOOL",
"value": "True"
}"CMAKE_CROSS_PLATFORM_COMPILER": {
"type": "PATH",
"value": "/usr/bin/aarch64-linux-gnu-g++"
}编译成功后,会在当前目录下创建build_out目录,并在build_out目录下生成自定义算子安装包custom_opp_<target os>_<target architecture>.run
在算子工程中,如果开发者想对算子kernel侧代码增加一些自定义的编译选项,可以参考如下内容进行编译选项的定制。
修改算子工程op_kernel目录下的CMakeLists.txt,使用add_ops_compile_options来增加编译选项,方法如下:
add_ops_compile_options(OpType COMPUTE_UNIT soc_version1 soc_version2 ... OPTIONS option1 option2 ...)
具体参数的介绍如下:
|
参数名称 |
可选/必选 |
参数描述 |
|---|---|---|
|
OpType(算子类型) |
必选 |
第一个参数应传入算子类型,如果需要对算子工程中的所有算子生效,需要配置为ALL。 |
|
COMPUTE_UNIT |
可选 |
标识编译选项在哪些AI处理器型号上生效,多个型号之间通过空格间隔。不配置时表示对所有AI处理器型号生效。
说明:
COMPUTE_UNIT具体配置如下:
|
|
OPTIONS |
必选 |
自定义的编译选项。多个编译选项之间通过空格间隔。 |
add_ops_compile_options(AddCustom COMPUTE_UNIT Ascendxxxyy ... OPTIONS -DNEW_MACRO1=xx) add_ops_compile_options(AddCustom COMPUTE_UNIT Ascendxxxyy ... OPTIONS -DNEW_MACRO2=xx) add_ops_compile_options(AddCustom COMPUTE_UNIT Ascendxxxyy ... OPTIONS -DNEW_MACRO3=xx)
--tiling_key=1,2
--kernel-template-input="D_T_X=A1,A2;D_T_Y=B;D_T_Z=C" --kernel-template-input='D_T_X=A1,A2;D_T_Y=B;D_T_Z=C'
配置模板参数组合时,模板参数名需要与Kernel入口处以及Host侧定义的模板参数名匹配。对于模板参数组合的值,如果存在自定义类型,需要替换为其对应数字值,如果为原生支持数据类型,则与Kernel入口处入参保持一致。示例如下:
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 |
// Host侧模板参数定义 #define ADD_TPL_FP16 10 #define ADD_TPL_FP32 20 ASCENDC_TPL_ARGS_DECL(AddCustomTemplateNativeDtype, ASCENDC_TPL_DATATYPE_DECL(D_T_X, C_DT_FLOAT, C_DT_FLOAT16, ASCENDC_TPL_INPUT(0)), ASCENDC_TPL_DTYPE_DECL(D_T_Y, ADD_TPL_FP16, ADD_TPL_FP32), ASCENDC_TPL_DATATYPE_DECL(D_T_Z, C_DT_FLOAT, C_DT_FLOAT16, ASCENDC_TPL_OUTPUT(0)), ASCENDC_TPL_UINT_DECL(TILE_NUM, ASCENDC_TPL_8_BW, ASCENDC_TPL_UI_MIX, 2, 0, 2, 3, 5, 10, 12, 13, 9, 8), ASCENDC_TPL_BOOL_DECL(IS_SPLIT, 0, 1), ); ASCENDC_TPL_SEL( ASCENDC_TPL_ARGS_SEL( ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_FLOAT), ASCENDC_TPL_DTYPE_SEL(D_T_Y, ADD_TPL_FP32), ASCENDC_TPL_DATATYPE_SEL(D_T_Z, C_DT_FLOAT), ASCENDC_TPL_UINT_SEL(TILE_NUM, ASCENDC_TPL_UI_LIST, 1, 8), ASCENDC_TPL_BOOL_SEL(IS_SPLIT, 0, 1), ASCENDC_TPL_DETERMINISTIC_SEL(true), ASCENDC_TPL_KERNEL_TYPE_SEL(ASCENDC_TPL_AIV_ONLY), ), ASCENDC_TPL_ARGS_SEL( ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_FLOAT16), ASCENDC_TPL_DTYPE_SEL(D_T_Y, ADD_TPL_FP16), ASCENDC_TPL_DATATYPE_SEL(D_T_Z, C_DT_FLOAT16), ASCENDC_TPL_UINT_SEL(TILE_NUM, ASCENDC_TPL_UI_LIST, 1, 8), ASCENDC_TPL_BOOL_SEL(IS_SPLIT, 0, 1), ASCENDC_TPL_DETERMINISTIC_SEL(false), ASCENDC_TPL_KERNEL_TYPE_SEL(ASCENDC_TPL_AIV_ONLY), ), ); #endif //kernel入口 if constexpr (std::is_same_v<D_T_X, float> && std::is_same_v<D_T_Z, float>) { KernelAdd<D_T_X, float, D_T_Z> op; op.Init(x, y, z, tiling_data.totalLength, TILE_NUM); op.Process1(); } else if constexpr (std::is_same_v<D_T_X, half> && std::is_same_v<D_T_Z, half>){ KernelAdd<D_T_X, half, D_T_Z> op; op.Init(x, y, z, tiling_data.totalLength, TILE_NUM); |
编译选项示例如下:
--kernel-template-input="D_T_X=10;D_T_Y=half;D_T_Z=10" --kernel-template-input="D_T_X=10,20;D_T_Y=half,float;D_T_Z=10,20"