- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
本文是 CANN asc-devkit 算子原型注册与管理(prototype register management)系列中的一篇 API 实战指南,核心讲解 OpAICPUDef 的KernelSo配置接口:它用于指定 AI CPU(AICPU)算子实现文件编译生成的动态库(.so)文件名称,是自定义 AICPU 算子原型定义中把"核函数实现产物"与"算子注册信息"关联起来的关键一环。读完本文,你将掌握KernelSo的签名、参数语义与链式调用方式,并理解它和 AI CPU 算子编译、OP_ADD原型注册流程之间的完整关系。
KernelSo 是什么:一句话定位
在 asc-devkit 的算子原型注册体系中,算子原型通过一个继承自OpDef的 C++ 类承载(详见算子原型定义),而 AI CPU 算子的实现信息由OpAICPUDef描述。OpDef::AICPU() 返回OpAICPUDef引用,开发者在该引用上链式调用Engine、OpkernelLib、KernelSo、FunctionName等接口完成 AICPU 算子配置。
KernelSo的职责非常单一明确:
配置 AICPU 算子实现文件编译生成的动态库文件的名称。
也就是说,开发者编写的 AICPU 算子核函数实现(.aicpu文件或-x aicpu方式编译的.cpp文件)最终会被编译成动态库(.so),KernelSo("...")中的字符串值即用于向框架声明这个动态库的名字,供算子调度与加载时定位使用。它属于"部署前注册信息",与OpkernelLib(固定为CUSTAICPUKernel)、FunctionName(固定为RunCpuKernel)等配置共同构成 AICPU 自定义算子被框架识别、编译和执行所需的完整描述。
函数原型与参数语义
KernelSo的函数原型如下:
OpAICPUDef &KernelSo(const char *value)参数说明
| 参数 | 输入/输出 | 说明 |
|---|---|---|
value | 输入 | AI CPU 算子实现文件编译生成的动态库文件的名称 |
其中value是const char *类型的字符串,应当与编译 AICPU 算子实现文件后产出的动态库文件名保持一致。例如使用bisheng -shared -x aicpu编译出的libxxx.so,其库名通常即对应此处的value。建议在原型定义中显式、准确填写,避免算子注册信息与实际产物名称不一致导致运行时无法定位实现库。
返回值说明
返回类型为OpAICPUDef &,即返回算子定义对象自身的引用,支持继续链式调用其他配置接口,例如:
this->AICPU() .Engine("DNN_VM_AICPU") .OpkernelLib("CUSTAICPUKernel") .KernelSo("libxxx.so") .FunctionName("RunCpuKernel");关于OpAICPUDef的完整说明,请参考 OpAICPUDef。
约束说明
无。KernelSo没有额外使用约束,但需注意其语义强依赖编译产物命名,实际开发中应保证配置值与构建产物一致。
使用场景:AICPU 算子原型注册流程
KernelSo出现在 AICPU 自定义算子原型定义阶段。整体流程如下:
- 编写 AICPU 算子实现:以
.aicpu为后缀(或.cpp+-x aicpu编译选项)定义__global__ __aicpu__修饰的核函数,例如仓库示例 aicpu_tiling.aicpu 中的MyAicpuKernel。AI CPU 编程规范详见 AI CPU编程。 - 编译生成动态库:使用
bisheng或 CMake 将实现文件编译为.so。 - 在 Host 侧原型文件中,通过继承
OpDef的算子类构造函数,调用this->AICPU()获取OpAICPUDef,链式配置Engine、OpkernelLib、KernelSo、FunctionName等。 - 在文件末尾通过
OP_ADD(opType)注册算子类型(见 OP_ADD),编译工具据此识别算子原型并生成 aclnn 接口、图模式原型等相关代码。
一个典型的 AICPU 原型定义骨架如下:
namespace ops { class AddCustom : public OpDef { public: explicit AddCustom(const char* name) : OpDef(name) { // 输入输出、属性定义(Input/Output/Attr) this->Input("x") .ParamType(REQUIRED) .DataType({ge::DT_FLOAT16}) .Format({ge::FORMAT_ND}); this->Output("z") .ParamType(REQUIRED) .DataType({ge::DT_FLOAT16}) .Format({ge::FORMAT_ND}); // AICPU 实现信息:引擎、kernelLib、动态库名称、核函数接口名 this->AICPU() .Engine("DNN_VM_AICPU") .OpkernelLib("CUSTAICPUKernel") .KernelSo("libadd_custom_aicpu.so") .FunctionName("RunCpuKernel"); } }; OP_ADD(AddCustom); } // namespace ops与 KernelSo 配套的 OpAICPUDef 配置项速查
KernelSo是OpAICPUDef提供的众多链式配置接口之一。为了正确填写原型定义,下表汇总了同系列接口的固定取值要求(均可在原型注册与管理目录下找到对应 API 文档):
| 接口 | 功能 | 取值要求 |
|---|---|---|
| Engine | 配置算子调用的引擎 | 固定为DNN_VM_AICPU |
| OpkernelLib | 配置算子调用的 kernelLib | 固定为CUSTAICPUKernel |
| KernelSo | 配置实现文件编译生成的动态库名称 | 与编译产物.so名称一致 |
| FunctionName | 配置核函数(Kernel)接口名称 | 固定为RunCpuKernel |
| UserDefined | 配置是否为用户自定义算子 | 仅支持True,缺省默认为True |
| ComputeCost | 预留参数 | 固定为100 |
| FlagPartial | 预留参数 | 固定为False |
| FlagAsync | 预留参数 | 固定为False |
| ExtendCfgInfo | 额外添加键值对形式的扩展配置 | key+value自定义 |
从这张表可以推断:KernelSo是整个 AICPU 注册信息中唯一需要开发者根据自己工程实际填写"产物名称"的字段,其余多数字段都是框架约定的固定值,因此它也是最容易因拼写或命名不一致而引发问题的配置项。
深度原理:KernelSo 对应的动态库从何而来
KernelSo的取值不是凭空约定,而是与 AI CPU 算子的编译产物一一对应。仓库中的 AI CPU算子编译 文档说明了动态库的生成方式:
与 AI Core 算子只需一个.asc文件即可编译不同,AI CPU 算子需要同时包含.aicpu文件(核函数定义)和.asc文件(通过内核调用符调用核函数)才能编译生成可执行文件。当需要把 AI CPU 算子实现打包为动态库时,使用 bisheng 命令行:
# 编译 test_aicpu.cpp 生成算子动态库 # -lxxx 表示默认链接库 bisheng -shared -x aicpu test_aicpu.cpp -o libtest_aicpu.so -lxxx ...其中:
-shared/--shared:编译生成动态链接库;-x aicpu:指定编译语言为 AICPU,表明编译的是 AI CPU 算子编程语言代码;-o libtest_aicpu.so:指定输出动态库文件名,该名称正是KernelSo("...")中应填写的值。
若单独编译 AI CPU 算子代码生成动态库、静态库,需要手动链接内置链接库(如ascendc_runtime、ascendcl、runtime等)。使用 CMake 时同样可以将.aicpu文件直接打入动态库,例如:
# 将 .cpp 文件置为 AICPU 属性,支持 AI CPU 算子编译 set_source_files_properties( aicpu_kernel.cpp PROPERTIES LANGUAGE AICPU ) add_library(kernel_lib SHARED add_custom_base.cpp aicpu_kernel.cpp # 支持 AI CPU 算子与 AI Core 算子一起打包为动态库 )从上述编译链路可以推断:KernelSo本质上是在算子原型注册信息中登记"运行时按名加载"的库文件标识——框架拿到算子注册信息后,需要根据这个名称在部署目录中找到对应的.so,再结合FunctionName(RunCpuKernel)定位库内核函数入口。因此,动态库名称的拼写、大小写与编译输出必须严格一致,这是KernelSo配置正确的核心要求。
实际工程中的注意事项
结合仓库文档与示例,使用KernelSo时有几点值得留意:
- 产物命名一致性:
KernelSo的值应与bisheng -shared -x aicpu ... -o <name>或 CMakeadd_library(... SHARED)产出的库文件名一致。若使用默认库前缀lib,请确认注册时填写的字符串与最终文件名匹配。 - 与固定字段协同:AICPU 自定义算子的
Engine固定为DNN_VM_AICPU、OpkernelLib固定为CUSTAICPUKernel、FunctionName固定为RunCpuKernel,不要擅自改动这些约定值(见各字段文档的取值要求)。 - 原型注册位置:
KernelSo的调用位于 Host 侧算子原型文件(如op_host/add_custom.cpp)中自定义算子类的构造函数内,通过this->AICPU()进入OpAICPUDef配置链,最终由文件末尾的OP_ADD(AddCustom)完成注册(详见算子原型定义)。 - 可参考仓库样例:04_aicpu 样例 展示了 AICPU 算子(含 Tiling 下沉)从核函数实现到工程组织的完整形态,其中 aicpu_tiling.aicpu 演示了
__global__ __aicpu__核函数的标准写法,可作为编写实现文件、进而配置KernelSo的参照。
总结
OpAICPUDef::KernelSo是 asc-devkit 自定义 AICPU 算子原型注册中的一个小而关键的配置接口:它用一个字符串把"算子原型"和"算子实现编译产出的动态库"绑定起来。掌握它的签名(OpAICPUDef &KernelSo(const char *value))、取值语义(与.so编译产物名称一致)以及在OpAICPUDef链式配置中的位置,再结合Engine、OpkernelLib、FunctionName等固定字段和OP_ADD注册流程,即可完整、正确地完成一个 AICPU 自定义算子的原型定义与注册。
- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
相关推荐
asc-devkit 算子原型注册:OpAICPUDef::Engine 接口详解与 AICPU 算子引擎配置实战
asc devkit 算子原型注册:OpAICPUDef::Engine 接口详解与 AICPU 算子引擎配置实战 本篇技术指南围绕 asc devkit(CA
人工智能深度学习算子库CANNAscendasc-devkit 算子原型注册系列:OpAICPUDef::ExtendCfgInfo 扩展配置接口详解
asc devkit 算子原型注册系列:OpAICPUDef::ExtendCfgInfo 扩展配置接口详解 导读 ExtendCfgInfo 是 asc de
人工智能深度学习算子库CANNAscendasc-devkit 算子原型注册详解:OpAICPUDef::FlagAsync 预留参数的语义与正确用法
asc devkit 算子原型注册详解:OpAICPUDef::FlagAsync 预留参数的语义与正确用法 导读 FlagAsync 是 CANN asc d
人工智能深度学习算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考