msopgen生成的CANN自定义算子add的构建过程

举报
黄生 发表于 2026/04/02 15:36:11 2026/04/02
【摘要】 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
)

# 生成算子APInpu_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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。