DataCopy(GMToUB多维数据搬运NDDMA)
产品支持情况
- Ascend 950PR/Ascend 950DT:支持
- Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持
- Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持
- Atlas 200I/500 A2 推理产品:不支持
- Atlas 推理系列产品AI Core:不支持
- Atlas 推理系列产品Vector Core:不支持
- Atlas 训练系列产品:不支持
功能说明
头文件路径为:"basic_api/kernel_operator_data_copy_intf.h"。
多维数据搬运接口,相比于基础数据搬运接口,可更加自由配置搬入的维度信息以及对应的Stride。
具体支持的数据通路为(以逻辑位置TPosition表示):
- Global Memory -> Unified Buffer
- GM -> VECIN
函数原型
Global Memory -> Unified Buffer,支持多维度搬运
C++template <typename T, uint8_t dim, const NdDmaConfig& config = kDefaultNdDmaConfig> __aicore__ inline void DataCopy(const LocalTensor<T>& dst, const GlobalTensor<T>& src, const NdDmaParams<T, dim>& params)NDDMA Cache刷新,在使用DataCopy接口进行数据搬运前,需要使用NdDmaDci接口刷新NDDMA Cache缓存保证为最新状态。
C++__aicore__ inline void NdDmaDci()
参数说明
表1 模板参数说明
| 参数名 | 描述 |
|---|---|
| T | 源操作数或者目的操作数的数据类型。 |
| dim | 搬运的数据维度,数据类型为uint8_t,支持的维度为[1, 5]。 |
| config | 搬运配置选项,NdDmaConfig类型,定义如下,具体参数说明请参考表3。struct NdDmaConfig { |
表2 参数说明
| 参数名 | 输入/输出 | 描述 |
|---|---|---|
| dst | 输出 | 目的操作数,类型为LocalTensor。 |
| src | 输入 | 源操作数,类型为GlobalTensor。 |
| params | 输入 | 搬运参数NdDmaParams类型,定义如下,具体参数说明请参考表4。template <typename T, uint8_t dim> NdDmaLoopInfo类型,定义如下,具体参数说明请参考表5。 template <uint8_t dim> |
表3 NdDmaConfig结构体参数定义
| 参数名 | 描述 |
|---|---|
| unsetPad | 表示未在NdDmaConfig中统一设置PaddingSize,固定为0xFFFF,为uint16_t数据类型的常量。当loopLpSize或loopRpSize取该值时,对应的PaddingSize由NdDmaLoopInfo中的同名参数按维度设置。 |
| isNearestValueMode | 表示Padding值填取方式,类型为bool。 true:使能最近值填充方式,即左右Padding值会选取当前维度最左或最右的值进行填充,可参考图1。 false:使能常数填充方式,即所有Padding值填充为固定值NdDmaParams::constantValue。 当数据类型为b64时,参数isNearestValueMode的值应为false。 |
| loopLpSize | 所有维度统一使用的左Padding大小,单位为元素个数。取值范围为[0, 255]或unsetPad,默认值为unsetPad。设置为[0, 255]时,所有维度均使用该值,NdDmaLoopInfo::loopLpSize不生效;设置为unsetPad时,按维度使用NdDmaLoopInfo::loopLpSize。 |
| loopRpSize | 所有维度统一使用的右Padding大小,单位为元素个数。取值范围为[0, 255]或unsetPad,默认值为unsetPad。设置为[0, 255]时,所有维度均使用该值,NdDmaLoopInfo::loopRpSize不生效;设置为unsetPad时,按维度使用NdDmaLoopInfo::loopRpSize。 |
| ascOptimize | 预留参数,暂不支持。 |
表4 NdDmaParams结构体参数定义
| 参数名 | 描述 |
|---|---|
| loopInfo | 每维进行搬运的信息,类型为NdDmaLoopInfo<dim>。 NdDmaLoopInfo结构中数组类型参数的元素个数由模板参数dim决定。dim的取值范围为[1, 5],数组的有效索引范围为[0, dim - 1]。具体参数介绍可参考表5。 |
| constantValue | 数据类型为T的数值,当存在维度左右Padding,且不使能NearestValueMode时,该值将作为Padding值填充。 当数据类型为b64时,参数constantValue的值应为0。 |
表5 NdDmaLoopInfo结构体参数定义
| 参数名 | 描述 |
|---|---|
| loopSrcStride | 表示每个维度内,该源操作数元素与下一个元素间的间隔。 单位为元素个数。数据类型为uint64_t,loopSrcStride需在[0, 240)。 |
| loopDstStride | 表示每个维度内,该目的操作数元素与下一个元素间的间隔。 单位为元素个数。数据类型为uint32_t,loopDstStride需在[0, 220)。 |
| loopSize | 表示每个维度内,处理的元素个数(不包含Padding元素)。 单位为元素个数。数据类型为uint32_t,loopSize需在[1, 220)。 |
| loopLpSize | 表示每个维度内,左侧需要补齐的元素个数。 单位为元素个数。数据类型为uint8_t,loopLpSize不要超出该数据类型的取值范围:[0, 255]。 |
| loopRpSize | 表示每个维度内,右侧需要补齐的元素个数。 单位为元素个数。数据类型为uint8_t,loopRpSize不要超出该数据类型的取值范围:[0, 255]。 |
以下以2维的例子介绍几个典型使用场景。
图1 2D Padding场景
图2 2D Transpose场景
图3 2D BroadCast场景
图4 2D Slice场景
数据类型
源操作数和目的操作数支持的数据类型保持一致。
Ascend 950PR/Ascend 950DT支持的数据类型为:bool、int8_t、uint8_t、int16_t、uint16_t、half、bfloat16_t、int32_t、uint32_t、float、complex32、int64_t、uint64_t、double、complex64。
返回值说明
无
约束说明
一条指令所能获取的所有数据的地址范围宽度不能超过40位(1TB),即:
源操作数的每一次循环的大小为:(loopLpSize + loopSize + loopRpSize -1 ) * loopSrcSize,目的操作数的每一次循环的大小为:(loopLpSize + loopSize + loopRpSize -1 ) * loopDstSize,所有的循环的大小加起来不超过2的40次方位。
当每层循环的dstStride为升序序列,则不同循环间的地址空间不能交织或者重叠。以一个2D Padding场景为例,loopSrcStride、loopDstStride第二个维度的stride值最小是3,数据3不能落在维度1的循环中。

该接口通过NDDMA进行数据搬运,对应的NDDMA Cache大小为32KB,在使用DataCopy接口进行数据搬运前,需要使用NdDmaDci接口刷新缓存,否则多核场景下读写同一块Global Memory地址可能会导致部分核读取数据错误。
调用示例
场景1:2D Padding场景,常数填充方式
C++// xGmShape:[16, 32],搬运8列2行数据,左Padding 15,上Padding 13,右Padding 17,下Padding 3,xLocalShape:[32, 64]。 AscendC::NdDmaLoopInfo<2> loopInfo{{1, 32}, {1, 64}, {32, 16}, {15, 13}, {17, 3}}; AscendC::NdDmaParams<T, 2> params{loopInfo, 0}; // padding的值为0 AscendC::NdDmaDci(); // 刷新cache static constexpr AscendC::NdDmaConfig dmaConfig; // 使用默认参数,也可以不传。 AscendC::DataCopy<T, 2, dmaConfig>(xLocal, xGm, params);场景2:2D Padding场景,最近值填充方式
C++// xGmShape:[28, 15],搬运3列4行数据,左Padding 11,上Padding 3,右Padding 6,下Padding 1,xLocalShape:[32, 32]。 AscendC::NdDmaLoopInfo<2> loopInfo{{1, 15}, {1, 32}, {15, 28}, {11, 3}, {6, 1}}; AscendC::NdDmaParams<T, 2> params{loopInfo, 0}; AscendC::NdDmaDci(); // 刷新cache // isNearestValueMode = true左右Padding值会选取当前维度最左或最右的值进行填充。 static constexpr AscendC::NdDmaConfig dmaConfig = {true}; AscendC::DataCopy<T, 2, dmaConfig>(xLocal, xGm, params);场景3:2D Transpose场景
C++// xGmShape:[16, 64],搬运8列4行数据,xLocalShape:[64, 16]。 AscendC::NdDmaLoopInfo<2> loopInfo{{1, 64}, {16, 1}, {64, 16}, {0, 0}, {0, 0}}; AscendC::NdDmaParams<T, 2> params{loopInfo, 0}; AscendC::NdDmaDci(); // 刷新cache static constexpr AscendC::NdDmaConfig dmaConfig; // 使用默认参数,也可以不传。 AscendC::DataCopy<T, 2, dmaConfig>(xLocal, xGm, params);场景4:2D BroadCast场景
C++// xGmShape:[1, 16],搬运16列1行数据并进行广播,xLocalShape:[3, 16]。 AscendC::NdDmaLoopInfo<2> loopInfo{{1, 0}, {1, 16}, {16, 3}, {0, 0}, {0, 0}}; AscendC::NdDmaParams<T, 2> params{loopInfo, 0}; AscendC::NdDmaDci(); // 刷新cache static constexpr AscendC::NdDmaConfig dmaConfig; // 使用默认参数,也可以不传。 AscendC::DataCopy<T, 2, dmaConfig>(xLocal, xGm, params);场景5:2D Slice场景
C++// xGmShape:[32, 64],将16*10的矩阵截取为一个5*7的矩阵,xLocalShape:[16, 16]。 AscendC::NdDmaLoopInfo<2> loopInfo{{1, 64}, {1, 16}, {16, 16}, {0, 0}, {0, 0}}; AscendC::NdDmaParams<T, 2> params{loopInfo, 0}; AscendC::NdDmaDci(); // 刷新cache static constexpr AscendC::NdDmaConfig dmaConfig; // 使用默认参数,也可以不传。 AscendC::DataCopy<T, 2, dmaConfig>(xLocal, xGm, params);
完整样例请参考:多维数据搬运样例。