CANN学习资源开源仓的中级算子开发三workspace和属性及tilingkey

举报
黄生 发表于 2026/03/29 13:54:31 2026/03/29
【摘要】 workspace是设备侧Global Memory上的一块内存,分为两部分:系统workspace和用户workspace。给人感觉这个东西好像是提升开发便利,但会降低性能的东西。系统workspace:Ascend C API需要预留的,API在计算过程需要一些作为缓存,大小通过GetLibApiWorkSpaceSize接口获取。用户workspace:算子实现使用到的,算子内部需要通...

workspace是设备侧Global Memory上的一块内存,分为两部分:系统workspace和用户workspace。给人感觉这个东西好像是提升开发便利,但会降低性能的东西。系统workspace:Ascend C API需要预留的,API在计算过程需要一些作为缓存,大小通过GetLibApiWorkSpaceSize接口获取。用户workspace:算子实现使用到的,算子内部需要通过额外的device内存进行数据交换或者缓存的时候才需要分配。

workspace我还没有遇到实用场景。在大多数算子开发时,我们不用workspace,而使用LocalMemory的TBuf进行暂存数据。TBuf主要是用于Vector计算申请的临时空间。TBuf和TQue都通过InitBuffer来初始化内存,不同点:

  • 获取内存,TBuf通过Get(),TQue通过AllocTensor()
  • TBuf分配的内存空间只参与计算,无法执行入队出队操作。TQue的出入队列EnQue和DeQue必须成对出现。
  • TBuf申请的内存无需释放,TQue申请内存AllocTensor和释放内存FreeTensor必须成对出现

Ascend C 算子属性是算子定义阶段即确定、计算过程中保持不变的静态参数,它与动态变化的输入张量相互独立,作用是约束和控制算子的计算行为。必选属性定义了算子要做什么。

  • PyTorch示例:调用Conv2d算子时,必须传入in_channels(输入通道数)、out_channels(输出通道数)、kernel_size(卷积核尺寸)—— 缺少输入通道数,卷积层无法确定权重矩阵形状;缺少输出通道数,卷积计算的核心逻辑便无从展开。
  • Ascend C也一样:如开发ELU 算子(指数线性单元)时,alpha可作为必选属性(否则负数部分的缩放逻辑无法确定);

可选属性是算子的辅助配置,若未显式指定则使用默认值,控制算子“怎么做”。

  • PyTorch示例:Conv2dstride(步长)、padding(填充)、bias(偏置)等属性,默认值分别为 1、0、True,调整输出特征图尺寸、边缘保留策略等细节。
  • Ascend C 对应逻辑:如开发GELU 算子的approximate(近似计算方式)、Clamp算子的 min(设置数值的下限)均可作为可选属性,未指定时使用默认值(如 approximate="none"min=0)。

算子属性在运行过程中不可修改,需在 Host 侧调用算子前确定;与输入张量解耦,不依赖数据的形状/数值,仅控制计算逻辑;

带属性的算子两段式接口,其第一段通常为 aclnn算子名GetWorkspaceSize(输入1/输入2……, 属性1/属性2……, 输出1/输出2……, workspaceSize, executor) 形式。调用时需传入属性值;若无需指定属性,需传入默认属性值,确保参数个数与接口定义一致。

TilingKey是将kernel代码进行区分的方法,类似于C++的Template模板机制,编译时会根据不同tilingkey形成不同二进制算子om文件,优化单次调用kernel的性能。我们采用模板编程的方法来替代传统的TilingKey编程,减少对较长又没有明确含义的TilingKey数值标识的依赖。但是呢,msopgen不会生成这个功能文件,需要自行在op_kernel目录下创建一个模板定义文件,以AddCustomTemplate算子为例,创建名为tiling_key_add_custom_template.h的文件(文件名可自定义,推荐使用tiling_key_+算子名.h的形式)。感觉理解起来有些繁琐,这里简要看一下

//定义一个模板参数包,让编译器根据不同的数据类型和配置,生成多个版本的算子代码。
ASCENDC_TPL_ARGS_DECL(AddTemplateCustom, // 外层包装:算子OpType名称

	//数据类型参数
    ASCENDC_TPL_DATATYPE_DECL(D_T_X, C_DT_FLOAT, C_DT_FLOAT16, ASCENDC_TPL_INPUT(0)),  
	// D_T_X:模板参数名称(在kernel代码里用这个名称)。输入参数x的DataType类型
	// C_DT_FLOAT, C_DT_FLOAT16:允许的数据类型(float32和float16)
	// ASCENDC_TPL_INPUT(0):对应kernel的第0个输入                      

    ASCENDC_TPL_DATATYPE_DECL(D_T_Y, C_DT_FLOAT, C_DT_FLOAT16, ASCENDC_TPL_INPUT(1)),  // 与上面类似

    ASCENDC_TPL_DATATYPE_DECL(D_T_Z, C_DT_FLOAT, C_DT_FLOAT16, ASCENDC_TPL_OUTPUT(0)), // 与上面类似。输出。

	//整数参数:自定义UINT类型
    ASCENDC_TPL_UINT_DECL(TILE_NUM, ASCENDC_TPL_8_BW, ASCENDC_TPL_UI_MIX, 2, 0, 2, 3, 5, 10, 12, 13, 9, 8),
	//TILE_NUM:模板参数名称(表示切分的块数)
    //ASCENDC_TPL_8_BW:用8位存储这个值(取值范围0-255)
    //ASCENDC_TPL_UI_MIX:用Unsigned Int Mix混合模式定义取值范围
    //有2组的数据{0-2}、{3-5}和穷举值10、12、13、9、8,最后结果为{0, 1, 2, 3, 4, 5, 10, 12, 13, 9, 8}

	//布尔参数
    ASCENDC_TPL_BOOL_DECL(IS_SPLIT, 0, 1), 
	// 自定义bool类型的模板参数定义:模板参数为是否切分标志位,取值范围为0和1,1表示切分,0表示不切分

);

再看一个实际运行的例子,在op_kernel目录下创建模板参数和模板参数组合文件,命名为tiling_key_clamp.h。定义输入和输出的模板参数D_T_X、D_T_Y支持 C_DT_INT32, C_DT_FLOAT。并设置输入和输出的模板参数D_T_X、D_T_Y类型相同时才是合法的组合。

#ifndef TILING_KEY_CLAMP_H
#define TILING_KEY_CLAMP_H
#include "ascendc/host_api/tiling/template_argument.h"

ASCENDC_TPL_ARGS_DECL(Clamp, // 算子名
ASCENDC_TPL_DATATYPE_DECL(D_T_X, C_DT_INT32, C_DT_FLOAT, ASCENDC_TPL_INPUT(0)), 
ASCENDC_TPL_DATATYPE_DECL(D_T_Y, C_DT_INT32, C_DT_FLOAT, ASCENDC_TPL_OUTPUT(0)),
);

ASCENDC_TPL_SEL(
    ASCENDC_TPL_ARGS_SEL(
    ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_INT32),
    ASCENDC_TPL_DATATYPE_SEL(D_T_Y, C_DT_INT32),
    ),
    ASCENDC_TPL_ARGS_SEL(
    ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_FLOAT),
    ASCENDC_TPL_DATATYPE_SEL(D_T_Y, C_DT_FLOAT),
    ),
);
#endif  // TILING_KEY_CLAMP_H

至于在tiling函数和核函数里的设置和使用,暂时略过,头疼。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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