昇腾社区首页
中文
注册
如何高效处理Ascend C非对齐数据?优化技巧全解析

如何高效处理Ascend C非对齐数据?优化技巧全解析

昇腾CANNAscend C

发表于 2025/06/27

1 引言

对于Ascend C算子开发者而言,为了更高效地操作变量,通常需要满足相应的数据对齐要求。例如在使用DataCopy接口进行数据传输时,必须确保搬运的数据长度和操作数在UB上的起始地址为32字节对齐;在进行向量计算时,操作数的起始地址也需满足32字节对齐的要求。然而,在大多数场景下,会遇到大量非对齐的数据情况。本文提供了完整的处理方案,帮助开发者更加灵活地应对数据非对齐的情况。

2 数据非对齐的典型场景

首先介绍一些非对齐搬运和计算的实例。下文描述中的Global指Global Memory上的tensor,Local指Local Memory上的tensor。

l   非对齐搬入

当需要从Global拷贝11个half数值到Local时,为保证搬运的数据长度32字节对齐,使用DataCopy拷贝16个half(32B)数据到Local上,Local[11]~Local[15]被设置成无效数据-1。

l   非对齐搬出

当需要从Local拷贝11个half数值到Global时,为保证搬运的数据长度32字节对齐,使用DataCopy拷贝16个half(32B)数据到Global上,Global[11]~Global[15]被设置成无效数据-1。

l   矢量计算起始地址非32字节对齐的错误示例

矢量计算时需要保证起始地址32字节对齐,如下的示例中,从Local1[7],即LocalTensor的第8个数开始计算,起始地址不满足32字节对齐,是错误示例。

3 DataCopyPad接口提供非对齐数据搬运功能

目前,对于Atlas A2 训练系列产品、Atlas 800I A2 推理产品、A200I A2 Box 异构组件、Atlas A3 训练系列产品、Atlas A3 推理系列产品以及Atlas 200I/500 A2 推理产品,DataCopyPad接口提供了非对齐数据搬运的功能,开发者可以使用该接口解决非对齐场景下的数据搬运问题。下面介绍该接口的基本用法,关于DataCopyPad接口的详细介绍,请参考:DataCopyPad API参考,使用DataCopyPad的完整示例,请参考DataCopyPad样例(工程化算子开发)DataCopyPad样例(kernel直调)

使用DataCopyPad接口时,主要关注DataCopyExtParams和DataCopyPadExtParams的参数配置,DataCopyExtParams用于控制搬运的数据块大小、步长间隔等信息,DataCopyPadExtParams用于控制Pad补齐的相关信息。

表1-1 DataCopyExtParams结构体参数定义

参数名称含义
blockCount指定该指令包含的连续传输数据块个数。
blockLen指定该指令每个连续传输数据块长度,该指令支持非对齐搬运,每个连续传输数据块长度单位为Byte。
srcStride源操作数,相邻连续数据块的间隔(前面一个数据块的尾与后面数据块的头的间隔)。 如果源操作数的逻辑位置为VECIN/VECOUT,则单位为dataBlock(32Bytes)。如果源操作数的逻辑位置为GM,则单位为Byte。
dstStride目的操作数,相邻连续数据块间的间隔(前面一个数据块的尾与后面数据块的头的间隔)。 如果目的操作数的逻辑位置为VECIN/VECOUT,则单位为dataBlock(32Bytes),如果目的操作数的逻辑位置为GM,则单位为Byte。


表1-2 DataCopyPadExtParams<T>结构体参数定义

参数名称含义
isPad是否需要填充用户自定义的数据,取值范围:true,false。 true:填充padding value。 false:表示用户不需要指定填充值,会默认填充随机值。
leftPadding连续搬运数据块左侧需要补充的数据范围,单位为元素个数。
rightPadding连续搬运数据块右侧需要补充的数据范围,单位为元素个数。
paddingValue左右两侧需要填充的数据值,需要保证在数据占用字节范围内。


接下来我们通过Global Memory->Local MemoryLocal Memory->Global Memory通路的DataCopyPad接口参数配置示例来进一步了解DataCopyPad接口的使用方法。

对于Global Memory->Local Memory(GM->VECIN/VECOUT)的数据搬运,各参数使用说明如下:

l   当blockLen+leftPadding+rightPadding满足32字节对齐时isPad为false,左右两侧填充的数据值会默认为随机值;否则为paddingValue。

l   当blockLen+leftPadding+rightPadding不满足32字节对齐时,框架会填充一些假数据dummy,保证填充后的数据(左右填充的数据+blockLen+假数据)为32字节对齐。若leftPadding、rightPadding都为0:dummy会默认填充待搬运数据块的第一个元素值;若leftPadding/rightPadding不为0:isPad为false,左右两侧填充的数据值和dummy值均为随机值;否则为paddingValue

配置示例1:

l   blockLen为64,每个连续传输数据块包含64Bytes;srcStride为1,因为源操作数的逻辑位置为GM,srcStride的单位为Byte,也就是说源操作数相邻数据块之间间隔1Byte;dstStride为1,因为目的操作数的逻辑位置为VECIN/VECOUT,dstStride的单位为dataBlock(32Bytes),也就是说目的操作数相邻数据块之间间隔1个dataBlock。

l   blockLen+leftPadding+rightPadding满足32字节对齐isPad为false,左右两侧填充的数据值会默认为随机值;否则为paddingValue。此处示例中,leftPadding、rightPadding均为0,则不填充。

l   blockLen+leftPadding+rightPadding不满足32字节对齐时,框架会填充一些假数据dummy,保证填充后的数据(左右填充的数据+blockLen+假数据)为32字节对齐。leftPadding/rightPadding不为0:若isPad为false,左右两侧填充的数据值和dummy值均为随机值;否则为paddingValue

l   配置示例2:

−           blockLen为47,每个连续传输数据块包含47Bytes;srcStride为1,表示源操作数相邻数据块之间间隔1Byte;dstStride为1,表示目的操作数相邻数据块之间间隔1个dataBlock。

−           blockLen+leftPadding+rightPadding不满足32字节对齐leftPadding、rightPadding均为0:dummy会默认填充待搬运数据块的第一个元素值

−           blockLen+leftPadding+rightPadding不满足32字节对齐,leftPadding/rightPadding不为0:若isPad为false,左右两侧填充的数据值和dummy值均为随机值;否则为paddingValue

对于Local Memory->Global Memory(VECIN/VECOUT->GM)的数据搬运,不需要开发者自行填充数据,所以无需关注DataCopyPadExtParams,仅需要关注DataCopyExtParams。

当每个连续传输数据块长度blockLen不满足32字节对齐,由于UB要求32字节对齐,框架在搬出时会自动补充一些假数据来保证对齐,但在当搬到GM时会自动将填充的假数据丢弃掉。

下图呈现了该场景下需要传入的DataCopyParams示例和假数据补齐的原理。blockLen为47,每个连续传输数据块包含47Bytes,不满足32字节对齐;srcStride为1,表示源操作数相邻数据块之间间隔1个dataBlock;dstStride为1,表示目的操作数相邻数据块之间间隔1Byte。框架在搬出时会自动补充17Bytes的假数据来保证对齐,搬到GM时再自动将填充的假数据丢弃掉。

4 不支持DataCopyPad接口的产品,如何处理非对齐数据

然而,某些型号(如Atlas 推理系列产品和Atlas 训练系列产品 ),目前仍不支持DataCopyPad接口,需要参考如下方案处理。

由于搬入时搬运的数据长度必须保证32字节对齐。数据长度非对齐的情况下,从Global逐行搬运Tensor数据到Local中,Local中每行都存在冗余数据。

搬入后,进行矢量计算时对冗余数据的处理方式有以下几种:

l   冗余数据参与计算。一般用于elewise计算场景。

l   通过mask参数掩掉冗余数据。一般用于轴归约计算等场景。

l   通过Duplicate逐行清零。计算前,针对每一行数据,调用基础API Duplicate对冗余数据位置填充0值。

l   通过Pad一次性清零。计算前,针对多行数据,可以采用高阶API Pad接口对冗余数据一次性清零。

由于搬出时搬运的数据长度和操作数的起始地址(UB上)必须保证32字节对齐,搬出时可以选择去除冗余数据或者带着冗余数据搬出的方式。

l   使用UnPad接口去除冗余数据后搬出。待搬出的有效数据总长度满足32字节对齐时,可使用高阶API UnPad接口去除冗余数据并完整搬出。

l   使用GatherMask收集有效数据后搬出。待搬出的有效数据总长度大于等于32字节时,可使用GatherMask重新收集有效数据,保证搬出的有效数据起始地址和数据长度32字节对齐。

l   带冗余数据搬出。注意多核处理时开启原子加(使用SetAtomicAdd接口),防止数据踩踏。

下面分别对上述几种处理方案做详细说明,相关代码样例请参考样例介绍

l   冗余数据参与计算

如下图所示,对前11个half数据进行Abs计算,冗余数据可以参与计算,不影响最终结果。步骤为:

a.         使用DataCopy从GLobal搬运16个half数据到Local1中,包含冗余数据-11~-15;

b.         直接使用Abs做整块计算,不用计算尾块大小,冗余数据参与计算。

l   使用mask掩掉冗余数据

如下图所示,假设输入数据的shape为16 * 4,将输入数据搬入到UB后每行数据前4个half数据为有效数据,其余为冗余数据。为只对前4个half数据进行ReduceMin计算,可以通过设置mask参数的方法掩掉冗余数据。针对每行数据的处理步骤为:

a.         使用DataCopy从Global搬运16个half数据到Local1中;

b.         对归约计算的目的操作数Local2清零,如使用Duplicate等;

c.         进行归约操作,将ReduceMin的mask模式设置为前4个数据有效,从而掩掉冗余数据。

l   通过Duplicate逐行清零。

如下图所示,对于搬入后的非对齐数据,逐行进行Duplicate清零处理,步骤为:

a.         使用DataCopy从Global搬运16个half数据到Local中;

b.         使用基础API Duplicate,按照如下方式设置mask值,控制仅后5个元素位置有效,将冗余数据填充为0。

uint64_t mask0 = ((uint64_t)1 << 16) - ((uint64_t)1 << 11);  
uint64_t mask[2] = {mask0, 0};

l   通过Pad一次性清零。

如下图所示,假设输入数据的shape为16 * 6,搬入Local后大小为16 * 16,每行都包含冗余数据,逐行清零性能较差,可以使用Pad一次性清零,步骤为:

a.         将16 * 6的数据从GM上逐行搬入UB后,每行有6个有效数据;

b.         使用Pad接口将冗余数据位置填充为0。(对应Pad接口使用场景为:tensor的width已32B对齐,但是有部分冗余数据)。

l   使用UnPad接口去除冗余数据后搬出。

如下图所示,Local内存大小为16*16,每行中只有前6个数为有效数据, 要搬出的有效数据16 * 6满足32B对齐,可以使用UnPad接口去除冗余数据并完整搬出。步骤如下:

a.         使用UnPad高阶API去除冗余值;

b.         使用DataCopy搬运出连续的16 * 6个half数据到Global中。

l   使用GatherMask收集有效数据后搬出。

如下图所示,为搬出19个half数据到Global中,有16-18这3个数据的搬运无法满足对齐要求,使用GatherMask对有效数据进行重新收集,收集3-18这16个数据并搬出。步骤如下:

a.         完整拷贝前16个half(32B)数据到Global中;

b.         使用GatherMask接口,将Local1[3]~[18]的数Gather到Local2中,Local2从对齐地址开始;

c.         从Local2中搬运Gather的数据(32B整数倍)到Global中。

l   带冗余数据搬出

如下图所示,有4个核参与计算,每个核拷贝出4个数,每个核上拷贝的数据长度不满足32字节对齐,采用将冗余数据一起搬出的方式,步骤如下:

a.         将目标Global完整清零,可以通过在host清零或者在kernel侧用UB覆盖的方式处理;

b.         将本核内的Local数据,除了要搬出的4个有效数据,其余冗余部分清零(使用Duplicate接口);

c.         使用原子累加的方式拷贝到Global,原子累加结合冗余数据清零,确保不会出现数据踩踏。

5 更多学习资源

欢迎访问昇腾社区Ascend C信息专区,获取Ascend C更多学习资源:https://www.hiascend.com/ascend-c


本页内容