非对齐场景【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit本节介绍非32字节对齐数据的更多处理方式包括数据搬入、计算和搬出的处理。用户在实际算子开发中可以参考如下方案介绍和算子样例灵活地处理非对齐场景。数据搬运和Vector计算的对齐要求[!NOTE]说明 进行数据搬运和Vector计算时对于搬运的数据长度和操作数的起始地址有如下的对齐要求使用DataCopy接口进行数据搬运搬运的数据长度和操作数的起始地址UB上必须保证32字节对齐。通常情况下进行Vector计算时操作数的起始地址必须保证32字节对齐。具体对齐要求需要查阅对应的API参考进行确认。下文描述中的Global指Global Memory上的tensorLocal指Local Memory上的tensor。下面是一些非对齐搬运和计算的例子。非对齐搬入当需要从Global拷贝11个half数值到Local时为保证搬运的数据长度32字节对齐使用DataCopy拷贝16个half32B数据到Local上Local[11]~Local[15]被写成无效数据-1。图1非对齐搬入![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/非对齐搬入.png 非对齐搬入?utm_sourcegitcode_repo_files)非对齐搬出当需要从Local拷贝11个half数值到Global时为保证搬运的数据长度32字节对齐使用DataCopy拷贝16个half32B数据到Global上Global[11]~Global[15]被写成无效数据-1。图2非对齐搬出![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/非对齐搬出.png 非对齐搬出?utm_sourcegitcode_repo_files)矢量计算起始地址非32字节对齐的错误示例矢量计算时需要保证起始地址32字节对齐如下的示例中从Local1[7]即LocalTensor的第8个数开始计算起始地址不满足32字节对齐是错误示例。图3矢量计算起始地址非32字节对齐的错误示例![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/矢量计算起始地址非32字节对齐的错误示例.png 矢量计算起始地址非32字节对齐的错误示例?utm_sourcegitcode_repo_files)非对齐处理方案DataCopyPad接口提供非对齐搬运的功能如果基于该接口支持的产品开发算子参见产品支持情况则可以直接使用该接口解决非对齐场景下的搬运问题。使用DataCopyPad的完整示例请参考DataCopyPad样例。部分型号不支持DataCopyPad接口可以参考如下的搬运方案处理。首先使用DataCopy对齐数据搬运接口进行数据搬运由于搬入时搬运的数据长度必须保证32字节对齐数据长度非对齐的情况下从Global逐行搬运Tensor数据到Local中Local中每行都存在冗余随机数据。搬入后进行矢量计算时对冗余数据的处理方式有以下几种冗余数据参与计算。一般用于elewise计算场景冗余数据即使参与计算也不影响最终结果如下图所示图5冗余数据参与计算![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/冗余数据参与计算.png 冗余数据参与计算?utm_sourcegitcode_repo_files)通过mask参数掩掉冗余数据。一般用于轴归约计算等场景。如下图所示为只对前4个half数据进行ReduceMin计算可以通过设置mask参数的方法掩掉冗余数据图6使用mask掩掉脏数据![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/使用mask掩掉脏数据.png 使用mask掩掉脏数据?utm_sourcegitcode_repo_files)示例片段如下uint64_t Mask[2] {((uint64_t)1 4) - 1, 0}; // 仅前4位元素参与运算 AscendC::ReduceMinhalf(output, input, workLocal, Mask, 1, 8);通过Duplicate逐行清零。计算前针对每一行数据调用基础API Duplicate对冗余数据位置填充0值通过设置mask值控制仅后5个元素位置有效将冗余数据填充为0如下图所示图7通过Duplicate逐行清零![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/通过Duplicate逐行清零.png 通过Duplicate逐行清零?utm_sourcegitcode_repo_files)示例片段如下uint64_t mask[2] {0b1111100000000000, 0}; // 控制16个元素中后5个元素有效 for (int32_t i 0; i 16; i) { AscendC::Duplicatehalf(input[i*16], static_casthalf(0), mask, 1, 1, 1); }通过Pad一次性清零。计算前针对多行数据可以采用高阶API Pad接口对冗余数据一次性清零。图8通过Pad一次性清零![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/通过Pad一次性清零.png 通过Pad一次性清零?utm_sourcegitcode_repo_files)示例片段如下AscendC::PadParams padParams {0, 10, 0}; AscendC::Pad(outputLocal, inputLocal, padParams, tiling);最后使用DataCopy对齐数据搬运接口进行数据搬出。由于搬出时搬运的数据长度和操作数的起始地址UB上必须保证32字节对齐搬出时可以选择去除冗余数据或者带着冗余数据搬出的方式有以下几种使用UnPad接口去除冗余数据后搬出。待搬出的有效数据总长度满足32字节对齐时可使用高阶API UnPad接口去除冗余数据并完整搬出。如下图所示图9使用UnPad接口去除冗余数据后搬出![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/使用UnPad接口去除冗余数据后搬出.png 使用UnPad接口去除冗余数据后搬出?utm_sourcegitcode_repo_files)示例片段如下AscendC::UnPadParams unPadParams {0, 10}; AscendC::UnPadhalf(outputLocal, inputLocal, unPadParams, tiling); ... AscendC::DataCopy(dstGlobal, outputLocal, 96);使用GatherMask收集有效数据后搬出。待搬出的有效数据总长度大于等于32字节时可使用GatherMask重新收集有效数据保证搬出的有效数据起始地址和数据长度32字节对齐。如下图所示图10使用GatherMask收集有效数据后搬出。![](https://raw.gitcode.com/cann/asc-devkit/raw/258f0725972f41f1a23d1fcda692fd94f2d443ce/docs/zh/guide/figures/使用GatherMask收集有效数据后搬出.png 使用GatherMask收集有效数据后搬出?utm_sourcegitcode_repo_files)示例片段如下AscendC::LocalTensoruint16_t bufPattern tmpPattern.Getuint16_t(); AscendC::Duplicateuint16_t(bufPattern, 0, 16); // 使用用户自定义模式配置数据收集的掩码选择3-18索引位置上的数据 bufPattern.SetValue(0, 0b1111111111111000); // uint16_t类型 bufPattern.SetValue(1, 0b0000000000000111); uint32_t mask 32; uint64_t rsvdCnt 0; AscendC::GatherMask(tailLocal, outputLocal, bufPattern, true, mask, {1, 1, 8, 8}, rsvdCnt); ... AscendC::DataCopy(dstGlobal, outputLocal, 16); AscendC::DataCopy(dstGlobal[3], tailLocal, 16); // 覆盖Global上索引3-18位置上的数据【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考