算子动态库和静态库编译
算子库编译
算子动态库和静态库编译是将算子实现代码及相关文件编译为动态库和静态库的过程。相比自定义算子包编译,动态库和静态库编译能够显著简化集成与部署流程。该过程包括将算子Kernel实现、Host侧Tiling实现、入图适配文件以及自动生成的单算子调用实现代码编译链接成动态库和静态库。
同时会自动生成以下头文件:

算子动态库和静态库编译支持如下型号:
Atlas A3 训练系列产品 /Atlas A3 推理系列产品 Atlas A2 训练系列产品 /Atlas 800I A2 推理产品 /A200I A2 Box 异构组件Atlas 推理系列产品
算子动态库和静态库编译的具体步骤如下:
- 完成工程编译相关配置。除了上文介绍的基础配置,算子动态库和静态库编译需要在工程目录下的CMakePresets.json cacheVariables的配置项中配置ASCEND_PACK_SHARED_LIBRARY为True,默认为False(会生成run包)。
"ASCEND_PACK_SHARED_LIBRARY": { "type": "BOOL", "value": "True" }
- 在算子工程目录下执行如下命令,进行算子工程编译。
./build.sh
编译成功后,会在${CMAKE_INSTALL_PREFIX}/op_api目录生成以下文件:
- 算子原型定义头文件,用于算子入图场景,定义算子的原型。
- 单算子调用aclnn头文件,用于单算子调用场景,提供直接调用算子的接口。
- 动态库libcust_opapi.so,用于动态链接。
- 静态库lib${vendor_name}.a,用于静态链接。
- 安装文件${vendor_name}-config.cmake和${vendor_name}-targets.cmake,方便开发者将多个厂商的算子动态库或静态库集成到一个公共的动态库中,其中${vendor_name}是厂商名,也可以理解成同一个算子工程生成的算子package名称。具体集成方式可以参考算子库集成和使用。
具体目录结构如下:
├── op_api │ ├── include │ ├── aclnn_optype1.h // 单算子调用aclnn头文件 │ └── aclnn_optype2.h │ └── aclnn_optypexxx.h │ └── op_proto.h // 算子原型定义头文件 │ ├── lib │ ├── cmake │ └── ${vendor_name} │ ├──${vendor_name}-config.cmake // 安装文件,定义了项目中的配置选项和变量 │ └──${vendor_name}-targets.cmake // 安装文件,定义静态库和动态库的构建目标${vendor_name}::static和${vendor_name}::shared,便于开发者使用静态库和动态库,自动处理库的依赖关系 │ ├── libcust_opapi.so // 算子动态库 │ └── lib${vendor_name}.a // 算子静态库
算子库集成和使用
- 单算子调用场景
单算子调用场景可以通过如下方式对算子库编译中生成的动态库和静态库进行集成和使用。
完整样例可参考静态库集成和使用样例。- 动态库集成
find_package(${vendor_name} REQUIRED # ${vendor_name}为编译生成的算子package名称 PATHS ${CUST_PKG_PATH} # ${CUST_PKG_PATH}为编译生成的算子package的存放路径 NO_DEFAULT_PATH ) target_link_libraries(op_runner PRIVATE ... ${vendor_name}::shared # 已自动包含相关的target依赖 ... )
- 静态库集成
find_package(${vendor_name} REQUIRED # ${vendor_name}为编译生成的算子package名称 PATHS ${CUST_PKG_PATH} # ${CUST_PKG_PATH}为编译生成的算子package的存放路径 NO_DEFAULT_PATH ) target_link_libraries(op_runner PRIVATE ... ${vendor_name}::static # 已自动包含相关的target依赖 ... )
- 静态库和动态库混合使用场景
find_package(${vendor_name1} REQUIRED # ${vendor_name1}为编译生成的算子package名称 PATHS ${CUST_PKG_PATH_1} # ${CUST_PKG_PATH_1}为编译生成的算子package的存放路径 NO_DEFAULT_PATH ) find_package(${vendor_name2} REQUIRED # ${vendor_name2}为编译生成的算子package名称 PATHS ${CUST_PKG_PATH_2} # ${CUST_PKG_PATH_2}为编译生成的算子package的存放路径 NO_DEFAULT_PATH ) target_link_libraries(op_runner PRIVATE ... ${vendor_name1}::static # 已自动包含相关的静态库target依赖 ${vendor_name2}::shared # 已自动包含相关的动态库target依赖 ... )
- 动态库集成

- 上文中的算子package存放路径默认指算子工程${CMAKE_INSTALL_PREFIX}/op_api目录,开发者可以自行将op_api目录下的文件拷贝到自己的目录下,此时${CUST_PKG_PATH}可以设置为该自定义目录。
- 由于不同算子工程生成的算子动态库名称相同,如果需要将多个动态库进行集成,需要对libcust_opapi.so名称进行修改:编译前,修改op_host目录中的CMakeLists.txt文件,添加如下代码,设置不同的输出文件名,从而可以区分不同动态库。
set_target_properties(cust_opapi PROPERTIES OUTPUT_NAME ${vendor_name} )
编译后,修改生成的op_api目录中的${vendor_name}-targets.cmake文件,将其中的libcust_opapi.so修改为lib${vendor_name}.so。保证动态库名称的一致性。
- 算子入图场景
- 配置ASCEND_CUSTOM_OPP_PATH环境变量,将动态库libcust_opapi.so的绝对路径追加到该环境变量。由GE框架在图编译和执行时根据该环境变量搜索算子动态库并使用。环境变量位置越靠前,算子的优先级越高。
export ASCEND_CUSTOM_OPP_PATH=${CMAKE_INSTALL_PREFIX}/op_api/lib/:${ASCEND_CUSTOM_OPP_PATH}
动态库编译和算子包编译功能同时使用时,前者生成的动态库优先级更高。
如下示例中,path1和path3是算子包编译生成的目录,path2和path4是动态库编译产物的存放目录,则编译产物的优先级为2>4>1>3。
ASCEND_CUSTOM_OPP_PATH=<path1>/vendor_name1:<path2>/op_api/lib/:<path3>/vendor_name3:<path4>/op_api/lib/
- 如果开发者通过Ascend Graph进行图开发,除了配置环境变量的方式也可以采用直接在应用程序的编译文件中链接动态库libcust_opapi.so的方式。Ascend Graph图开发的相关信息请参考《Ascend Graph开发指南》。动态库链接方式的so加载优先级高于环境变量配置方式。
- 配置ASCEND_CUSTOM_OPP_PATH环境变量,将动态库libcust_opapi.so的绝对路径追加到该环境变量。由GE框架在图编译和执行时根据该环境变量搜索算子动态库并使用。环境变量位置越靠前,算子的优先级越高。
父主题: 工程化算子开发