msopgen生成的CANN自定义算子add的构建过程
【摘要】 msopgen也没个版本号可看,CANN8.5里面带的会比较旧,使用gitcode上的源码项目。本文是CANN学习资源开源仓的中级算子开发一的扩展。算子目录结构custom_op/├── build.sh # 构建脚本├── CMakeLists.txt # 主CMake配置├── CMakePresets.json ...
msopgen也没个版本号可看,CANN8.5里面带的会比较旧,使用gitcode上的源码项目。本文是CANN学习资源开源仓的中级算子开发一的扩展。算子目录结构
custom_op/
├── build.sh # 构建脚本
├── CMakeLists.txt # 主CMake配置
├── CMakePresets.json # CMake预设
├── framework/ # 框架插件
│ └── tf_plugin/ # TensorFlow插件
├── op_host/ # 主机端代码
│ ├── add_custom_template.cpp
│ └── CMakeLists.txt
├── op_kernel/ # 核函数代码
│ ├── add_custom_template.cpp
│ ├── add_custom_template_tiling.h
│ └── CMakeLists.txt
└── build_out/ # 构建输出
编译准备
# build.sh 中的环境变量优先级
1. BASE_LIBS_PATH
2. ASCEND_HOME_PATH
3. ASCEND_AICPU_PATH
最终: ASCEND_HOME_PATH=/usr/local/Ascend/cann-8.5.0
# 使用CANN提供的Python脚本解析CMakePresets.json (兼容旧版本CMake)
opts=$(python3 $ASCEND_HOME_PATH/tools/tikcpp/ascendc_kernel_cmake/fwk_modules/util/preset_parse.py $script_path/CMakePresets.json)
cmake_version=$(cmake --version | grep "cmake version" | awk '{print $3}')
if [ "$cmake_version" \< "3.19.0" ]; then
# 旧版本CMake
cmake -S . -B "$BUILD_DIR" $opts
else
# 新版本CMake(使用预设) 我是新版本3.28.3 对应 CMakePresets.json 中定义的default配置
cmake -S . -B "$BUILD_DIR" --preset=default
fi
其中的关键配置参数:
{
"CMAKE_BUILD_TYPE": "Release",
"ENABLE_SOURCE_PACKAGE": "True",
"ENABLE_BINARY_PACKAGE": "True",
"ASCEND_COMPUTE_UNIT": "ascend910b",
"ENABLE_TEST": "True",
"vendor_name": "customize",
"ASCEND_CANN_PACKAGE_PATH": "/usr/local/Ascend/ascend-toolkit/latest",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build_out"
}
构建命令
cmake --build "$BUILD_DIR" --target binary package -j$(nproc)
输出文件
build_out/
├── custom_opp_ubuntu_x86_64.run # 安装包(424KB)
├── CMakeCache.txt # CMake缓存
├── Makefile # 生成的Makefile
├── cmake_install.cmake # 安装配置
├── CPackConfig.cmake # CPack配置
├── install_manifest.txt # 安装清单
└── 子目录:
├── autogen/ # 自动生成代码
├── framework/ # 框架构建输出
├── op_host/ # 主机端构建输出
├── op_kernel/ # 核函数构建输出
└── scripts/ # 脚本文件
其中自动生成的代码:
build_out/autogen/
├── aclnn_add_custom_template.h # 算子API头文件: 二段式API
├── aclnn_add_custom_template.cpp # 算子API实现
├── op_proto.h # 算子原型头文件
├── op_proto.cc # 算子原型实现(空)
├── group_proto/ # 分组原型(如果有)
├── ascendc_all_ops.make # 构建配置
├── aic-ascend910b-ops-info.ini # 算子信息配置
└── libascend_all_ops.so # 算子库
由CMake命令触发:
npu_op_code_gen(
SRC ${ops_srcs} # 源文件列表
PACKAGE ${package_name} # 包名(customize)
OUT_DIR ${ASCEND_AUTOGEN_PATH} # 输出目录(build_out/autogen)
JOIN_OP_DEF True # 合并算子定义
)
自动生成的原型头文件 (op_proto.h)宏展开分析
REG_OP(AddCustomTemplate)
.INPUT(x, ge::TensorType::ALL())
.INPUT(y, ge::TensorType::ALL())
.OUTPUT(z, ge::TensorType::ALL())
.OP_END_FACTORY_REG(AddCustomTemplate);
宏展开后相当于:
// 1. 定义算子工厂类
class AddCustomTemplateOperatorFactory : public ge::OperatorFactory {
public:
AddCustomTemplateOperatorFactory() {
// 注册输入输出
InputRegister("x", ge::TensorType::ALL());
InputRegister("y", ge::TensorType::ALL());
OutputRegister("z", ge::TensorType::ALL());
}
// 创建算子实例
ge::OperatorPtr CreateOperator() override {
return std::make_shared<AddCustomTemplateOperator>();
}
};
// 2. 注册到全局工厂
static ge::OperatorFactoryRegister g_add_custom_template_factory_register(
"AddCustomTemplate",
std::make_shared<AddCustomTemplateOperatorFactory>());
算子信息配置 (aic-ascend910b-ops-info.ini)
[AddCustomTemplate]
impl_mode=high_performance
op_mode=dynamic
core_type=VectorCore
support_dtype=float32,float16
support_format=ND
构建输出到安装目录的映射 ( tiling库文件、动态编译的源码未列出 )
构建输出 (build_out/) 安装目录 (/root/vendors/customize/)
────────────────────────────────────────────────────────────────────
autogen/aclnn_add_custom_template.h → op_api/include/aclnn_add_custom_template.h
autogen/op_proto.h → op_proto/inc/op_proto.h
编译的库文件 → op_api/lib/libcust_opapi.so
→ op_proto/lib/linux/x86_64/libcust_opsproto_rt2.0.so
核函数二进制 → op_impl/ai_core/tbe/kernel/ascend910b/add_custom_template/
配置文件 → op_impl/ai_core/tbe/kernel/config/ascend910b/
安装目录结构(少tiling呀)
/root/vendors/customize/
├── bin/
│ └── set_env.bash # 环境设置脚本
├── op_api/
│ ├── include/
│ │ └── aclnn_add_custom_template.h # API头文件
│ └── lib/
│ └── libcust_opapi.so # API库
├── op_proto/
│ ├── inc/
│ │ └── op_proto.h # 原型头文件
│ └── lib/
│ └── linux/x86_64/
│ └── libcust_opsproto_rt2.0.so # 原型库
├── op_impl/
│ └── ai_core/tbe/ #下面漏了一个子目录 op_tiling
│ ├── customize_impl/dynamic/ # 动态实现
│ │ ├── add_custom_template.cpp # 核函数源码
│ │ ├── add_custom_template_tiling.h # Tiling头文件
│ │ └── add_custom_template.py # Python接口
│ ├── kernel/
│ │ └── ascend910b/add_custom_template/
│ │ ├── AddCustomTemplate_816f04e052850554f4b3cacb35f8e8c6.json # 配置
│ │ ├── AddCustomTemplate_816f04e052850554f4b3cacb35f8e8c6.o # 二进制
│ │ ├── AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2.json # 配置
│ │ └── AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2.o # 二进制
│ └── config/
│ └── ascend910b/
│ ├── add_custom_template.json # 算子配置
│ └── binary_info_config.json # 二进制信息配置
├── framework/
│ ├── plugin/
│ │ └── npu_supported_ops.json # NPU支持算子列表
│ └── tensorflow/
│ └── libcust_tf_parsers.so # TensorFlow解析器
├── scripts/
│ └── uninstall.sh # 卸载脚本
└── version.info # 版本信息
其中环境设置脚本 (set_env.bash)
#!/bin/bash
# ASCEND_CUSTOM_OPP_PATH 告诉CANN在哪里查找自定义算子
export ASCEND_CUSTOM_OPP_PATH=/root/vendors/customize:${ASCEND_CUSTOM_OPP_PATH}
# LD_LIBRARY_PATH 添加自定义算子的库路径
export LD_LIBRARY_PATH=/root/vendors/customize/op_api/lib/:${LD_LIBRARY_PATH}
构建编译配置部分:主机端代码编译 (op_host/)
# op_host/CMakeLists.txt 关键部分
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} ops_srcs)
npu_op_code_gen(
SRC ${ops_srcs}
PACKAGE ${package_name}
OUT_DIR ${ASCEND_AUTOGEN_PATH}
JOIN_OP_DEF True
)
# 生成算子API库
npu_op_library(cust_opapi ACLNN
${autogen_aclnn_src}
)
# 生成算子原型库
npu_op_library(cust_op_proto GRAPH
${ops_srcs}
${group_proto_src}
${proto_src}
)
# 生成Tiling库
npu_op_library(cust_optiling TILING
${ops_srcs}
${fallback_src}
)
核函数代码编译 (op_kernel/)
# op_kernel/CMakeLists.txt 关键部分
npu_op_kernel_sources(ascendc_kernels
KERNEL_DIR ./
)
npu_op_kernel_library(ascendc_kernels
SRC_BASE ${CMAKE_CURRENT_SOURCE_DIR}/
TILING_LIBRARY cust_optiling
)
库文件打包
# 主CMakeLists.txt中的打包配置
npu_op_package(${package_name}
TYPE RUN
CONFIG
INSTALL_PATH ${CMAKE_BINARY_DIR}/
)
# 添加各个组件到包中
npu_op_package_add(${package_name}
LIBRARY ascendc_kernels
)
npu_op_package_add(${package_name}
LIBRARY
cust_optiling
cust_opapi
cust_op_proto
)
安装包
# 检查安装包类型
file build_out/custom_opp_opp_ubuntu_x86_64.run
# 输出: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked
# 查看安装包内容
./custom_opp_ubuntu_x86_64.run --list
Target directory: makeself-455251-20260331224724
-r-xr----- root/root 164 2026-03-31 22:47 ./help.info
-r-xr----- root/root 13315 2026-03-31 22:47 ./install.sh
-rw-r--r-- root/root 198 2026-03-31 22:47 ./packages/vendors/customize/framework/plugin/npu_supported_ops.json
-rw-r--r-- root/root 14480 2026-03-31 22:47 ./packages/vendors/customize/framework/tensorflow/libcust_tf_parsers.so
-rw-r--r-- root/root 1075 2026-03-31 22:47 ./packages/vendors/customize/op_api/include/aclnn_add_custom_template.h
-rw-r--r-- root/root 14664 2026-03-31 22:47 ./packages/vendors/customize/op_api/lib/libcust_opapi.so
-rw-r--r-- root/root 1271 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/config/ascend910b/aic-ascend910b-ops-info.json
-rw-r--r-- root/root 3514 2026-03-31 22:44 ./packages/vendors/customize/op_impl/ai_core/tbe/customize_impl/dynamic/add_custom_template.cpp
-rw-r--r-- root/root 11078 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/customize_impl/dynamic/add_custom_template.py
-rw-r--r-- root/root 179 2026-03-31 22:44 ./packages/vendors/customize/op_impl/ai_core/tbe/customize_impl/dynamic/add_custom_template_tiling.h
-rw-r--r-- root/root 2123 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/ascend910b/add_custom_template/AddCustomTemplate_816f04e052850554f4b3cacb35f8e8c6.json
-rw-r--r-- root/root 14704 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/ascend910b/add_custom_template/AddCustomTemplate_816f04e052850554f4b3cacb35f8e8c6.o
-rw-r--r-- root/root 2123 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/ascend910b/add_custom_template/AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2.json
-rw-r--r-- root/root 14704 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/ascend910b/add_custom_template/AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2.o
-rw-r--r-- root/root 3213 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/config/ascend910b/add_custom_template.json
-rw-r--r-- root/root 1711 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/kernel/config/ascend910b/binary_info_config.json
-rw-r--r-- root/root 669712 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/op_tiling/lib/linux/x86_64/libcust_opmaster_rt2.0.so
lrwxrwxrwx root/root 0 2026-03-31 22:47 ./packages/vendors/customize/op_impl/ai_core/tbe/op_tiling/liboptiling.so -> lib/linux/x86_64/libcust_opmaster_rt2.0.so
-rw-r--r-- root/root 322 2026-03-31 22:47 ./packages/vendors/customize/op_proto/inc/op_proto.h
-rw-r--r-- root/root 677904 2026-03-31 22:47 ./packages/vendors/customize/op_proto/lib/linux/x86_64/libcust_opsproto_rt2.0.so
-rw-r--r-- root/root 29 2026-03-31 22:47 ./packages/vendors/customize/version.info
-r-xr----- root/root 2489 2026-03-31 22:47 ./uninstall.sh
-r-xr----- root/root 4788 2026-03-31 22:47 ./upgrade.sh
最后看一下安装包里面的/root/vendors/customize/op_impl/ai_core/tbe/customize_impl/dynamic/add_custom_template.py ,它负责算子的动态编译。
算子注册,这个和tbe算子dsl实现好像呀。
@tbe_register.register_operator("AddCustomTemplate", trans_bool_to_s8=False)
@para_check.check_op_params(para_check.REQUIRED_INPUT, para_check.REQUIRED_INPUT,
para_check.REQUIRED_OUTPUT, para_check.KERNEL_NAME)
def add_custom_template(x_in__, y_in__, z_out_, kernel_name="add_custom_template", impl_mode = ""):
- 使用装饰器注册算子
AddCustomTemplate - 参数检查:2个必需输入,1个必需输出,1个内核名称参数
数据类型映射,提供C++类型与字符串类型的双向映射
DTYPE_MAP = {
"float32": ["DT_FLOAT", "float"],
"float16": ["DT_FLOAT16", "half"],
"int8": ["DT_INT8", "int8_t"],
# ... 其他数据类型
}
编译选项生成
def get_dtype_fmt_options(__inputs__, __outputs__):
# 根据输入输出张量的数据类型和格式生成编译选项
options = []
# 生成 -DDTYPE_X=float -DORIG_DTYPE_X=DT_FLOAT -DFORMAT_X=FORMAT_ND 等选项
return options
内核编译
def add_custom_template(...):
# 1. 构建参数
__inputs__, __outputs__, __attrs__ = _build_args(x_in__, y_in__, z_out_)
# 2. 获取编译选项
options = get_dtype_fmt_options(__inputs__, __outputs__)
options += ["-x", "cce"] # 指定编译器
# 3. 设置包含路径
options.append("-I" + os.path.join(asc_path, "..", "ascendc", "act"))
options.append("-I" + os.path.join(PYF_PATH, "..", "ascendc", "common"))
# 4. 获取内核源码路径
src = get_kernel_source(ascendc_src_file, ascendc_src_dir, ascendc_src_dir_ex)
# 5. 编译算子
compile_op(src, origin_func_name, op_info, options, code_channel, '{}', {'valueDepend': {}})
SOC适配
def get_shortsoc_compile_option(compile_option_list: list, shortsoc:str):
# 根据SOC架构获取特定的编译选项
compile_options = []
if shortsoc in compile_option_list:
compile_options.extend(compile_option_list[shortsoc])
if '__ALLSOC__' in compile_option_list:
compile_options.extend(compile_option_list['__ALLSOC__'])
return compile_options
等等,可以自己详细看py代码。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)