CANN/asc-devkit:带转置数据加载函数
LoadDataWithTranspose
产品支持情况
功能说明
该接口实现带转置的2D格式数据从A1/B1到A2/B2的加载。
下面通过示例来讲解接口功能和关键参数:下文图中一个N形或者一个Z形代表一个分形。
-
对于uint8_t/int8_t数据类型,每次迭代处理32*32*1B数据,可处理2个分形(一个分形512B),每次迭代中,源操作数中2个连续的16*32分形将被合并为1个32*32的方块矩阵,基于方块矩阵做转置,转置后分裂为2个16*32分形,根据目的操作数分形间隔等参数可以有不同的排布。
如下图示例:
- 共需要处理3072B的数据,每次迭代处理32*32*1B数据,需要3次迭代可以完成,repeatTime = 3;
- srcStride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:32*32*1B),这里的单位实际上是拼接后的方块矩阵的大小;
- dstGap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
- dstFracGap = 0,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为0(单位:512B)。

如下图示例:
- repeatTime和srcStride的解释和上图示例一致。
- dstGap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。
- dstFracGap = 2,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为2(单位:512B)。

-
对于half/bfloat16_t数据类型,每次迭代处理16*16*2B数据,可处理1个分形(一个分形512B),每次迭代中,源操作数中1个16*16分形将被转置。
- 共需要处理1536B的数据,每次迭代处理16*16*2B数据,需要3次迭代可以完成,repeatTime = 3;
- srcStride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1 (单位:16*16*2B);
- dstGap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址无间隔;
- 该场景下,因为其分形即为方块矩阵,每个迭代处理一个分形,不存在迭代内分形的间隔,该参数设置无效。

-
对于float/int32_t/uint32_t数据类型,每次迭代处理16*16*4B数据,可处理2个分形(一个分形512B),每次迭代中,源操作数2个连续的16*8分形将被合并为1个16*16的方块矩阵,基于方块矩阵做转置,转置后分裂为2个16*8分形,根据目的操作数分形间隔等参数可以有不同的排布。
如下图示例:
- 共需要处理3072B的数据,每次迭代处理16*16*4B数据,需要3次迭代可以完成,repeatTime = 3;
- srcStride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:16*16*4B),这里的单位实际上是拼接后的方块矩阵的大小;
- dstGap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
- dstFracGap = 0,表示每个迭代内目的操作数前一个分形结束地址与后一个分形起始地址的间隔为0(单位:512B)。

如下图示例:
- repeatTime和srcStride的解释和上图示例一致。
- dstGap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。
- dstFracGap = 2,表示每个迭代内目的操作数前一个分形结束地址与后一个分形起始地址的间隔为2(单位:512B)。

-
对于int4b_t数据类型,每次迭代处理64*64*0.5B数据,可处理4个分形(一个分形512B),每次迭代中,源操作数中4个连续的16*64分形将被合并为1个64*64的方块矩阵,基于方块矩阵做转置,转置后分裂为4个16*64分形,根据目的操作数分形间隔等参数可以有不同的排布。
int4b_t数据类型需要两个数拼成一个int8_t或uint8_t的数,拼凑的规则如下:

如下图示例:
- 共需要处理6144B的数据,每次迭代处理64*64*0.5B数据,需要3次迭代可以完成,repeatTime = 3;
- srcStride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:64*64*0.5B),这里的单位实际上是拼接后的方块矩阵的大小;
- dstGap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
- dstFracGap = 0,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为0(单位:512B)。

如下图示例:
- repeatTime和srcStride的解释和上图示例一致。
- dstGap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。
- dstFracGap = 2,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为2(单位:512B)。

函数原型
template <typename T>
__aicore__ inline void LoadDataWithTranspose(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LoadData2dTransposeParams& loadDataParams)
// 该函数原型仅支持Ascend 950PR/Ascend 950DT
template <typename T>
__aicore__ inline void LoadDataWithTranspose(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LoadData2dTransposeParamsV2& loadDataParams)
参数说明
表 1 模板参数说明
表 2 参数说明
|
Atlas A2 训练系列产品 / Atlas A2 推理系列产品 ,支持的TPosition为A2/B2。 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 ,支持的TPosition为A2/B2。 Atlas 200I/500 A2 推理产品 ,支持的TPosition为A2/B2。 |
||
|
Atlas A2 训练系列产品 / Atlas A2 推理系列产品 ,支持的TPosition为A1/B1。 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 ,支持的TPosition为A1/B1。 Atlas 200I/500 A2 推理产品 ,支持的TPosition为A1/B1。 |
||
|
LoadDataWithTranspose相关参数,类型为LoadData2dTransposeParams。 具体定义请参考${INSTALL_DIR}/include/ascendc/basic_api/interface/kernel_struct_mm.h,${INSTALL_DIR}请替换为CANN软件安装后文件存储路径。 参数说明请参考表3。 |
||
|
LoadDataWithTranspose相关参数,类型为LoadData2dTransposeParamsV2。 参数说明请参考表4。 |
表 3 LoadData2dTransposeParams结构体内参数说明
表 4 LoadData2dTransposeParamsV2结构体内参数说明
约束说明
- repeat=0表示不执行搬运操作。
- 开发者需要保证目的操作数转置后的分形没有重叠。
- 操作数地址对齐要求请参见通用地址对齐约束。
- 针对以下型号,推荐使用LoadData2dTransposeParamsV2作为参数,该参数具有更精细的搬运粒度。
- Ascend 950PR/Ascend 950DT
调用示例
-
示例1:该示例输入a矩阵为int8_t类型,shape为[40,70],输入b矩阵为int8_t类型,shape为[70,50],输出c的类型为int32_t。a矩阵从A1->A2转置,b矩阵从B1->B2转置,之后进行Mmad计算和Fixpipe计算。完整使用样例请参见LoadData_L12L0样例。
uint16_t m = 40, k = 70, n = 50; uint32_t fractalShape[0] = 16; uint32_t fractalShape[1] = 32 / sizeof(int8_t); uint32_t fractalNum = 2 uint32_t fractalSize = fractalShape[0] * fractalShape[1]; // A矩阵 LoadDataWithTranspose: Nz -> Zz // dstoffset要根据A矩阵在L0上,宽度方向的对齐来求解 // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(k, fractalShape[1]) * fractalSize * fractalNum; uint32_t srcOffset = CeilDivision(k, fractalShape[0] * fractalNum) * fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(k, fractalShape[0] * fractalNum); loadDataParams.srcStride = 1; loadDataParams.dstGap = 0; loadDataParams.dstFracGap = CeilDivision(k, fractalShape[1]) - 1; for (int i = 0; i < CeilDivision(m, fractalShape[1]); ++i) { AscendC::LoadDataWithTranspose(a2Local[i * dstOffset], a1Local[i * srcOffset], loadDataParams); } // B矩阵 LoadDataWithTranspose: Nz -> Zn // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(n, fractalShape[0] * fractalNum) * fractalSize * fractalNum; uint32_t srcOffset = fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(n, fractalShape[1]); loadDataParams.srcStride = CeilDivision(k, fractalShape[0] * fractalNum); loadDataParams.dstGap = 1; loadDataParams.dstFracGap = 0; for (int i = 0; i < CeilDivision(k, fractalShape[0] * fractalNum); ++i) { AscendC::LoadDataWithTranspose(b2Local[i * dstOffset], b1Local[i * srcOffset], loadDataParams); } -
示例2:该示例输入a矩阵为half类型,shape为[40,70],输入b矩阵为half类型,shape为[70,50],输出c的类型为float。a矩阵从A1->A2转置,b矩阵从B1->B2转置,之后进行Mmad计算和Fixpipe计算。完整使用样例请参见LoadData_L12L0样例。
uint16_t m = 40, k = 70, n = 50; uint32_t fractalShape[0] = 16; uint32_t fractalShape[1] = 32 / sizeof(half); uint32_t fractalNum = 1 uint32_t fractalSize = fractalShape[0] * fractalShape[1]; // A矩阵 LoadDataWithTranspose: Nz -> Zz // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(k, fractalShape[1]) * fractalSize * fractalNum; uint32_t srcOffset = CeilDivision(k, fractalShape[0] * fractalNum) * fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(k, fractalShape[0] * fractalNum); loadDataParams.srcStride = 1; loadDataParams.dstGap = 0; loadDataParams.dstFracGap = CeilDivision(k, fractalShape[1]) - 1; for (int i = 0; i < CeilDivision(m, fractalShape[1]); ++i) { AscendC::LoadDataWithTranspose(a2Local[i * dstOffset], a1Local[i * srcOffset], loadDataParams); } // B矩阵 LoadDataWithTranspose: Nz -> Zn // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(n, fractalShape[0] * fractalNum) * fractalSize * fractalNum; uint32_t srcOffset = fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(n, fractalShape[1]); loadDataParams.srcStride = CeilDivision(k, fractalShape[0] * fractalNum); loadDataParams.dstGap = 0; loadDataParams.dstFracGap = 0; for (int i = 0; i < CeilDivision(k, fractalShape[0] * fractalNum); ++i) { AscendC::LoadDataWithTranspose(b2Local[i * dstOffset], b1Local[i * srcOffset], loadDataParams); } -
示例3:该示例输入a矩阵为float类型,shape为[40,70],输入b矩阵为float类型,shape为[70,50],输出c的类型为float。a矩阵从A1->A2转置,b矩阵从B1->B2转置,之后进行Mmad计算和Fixpipe计算。完整使用样例请参见LoadData_L12L0样例。
uint32_t m = 40, k = 70, n = 50; uint32_t fractalShape[0] = 16; uint32_t fractalShape[1] = 32 / sizeof(float); uint32_t fractalNum = 2 uint32_t fractalSize = fractalShape[0] * fractalShape[1]; // A矩阵 LoadDataWithTranspose: Zz -> Zz // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(k, fractalShape[1] * fractalNum) * fractalSize * fractalNum; uint32_t srcOffset = fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(k, fractalShape[1] * fractalNum); loadDataParams.srcStride = CeilDivision(m, fractalShape[1] * fractalNum); loadDataParams.dstGap = 1; loadDataParams.dstFracGap = 0; for (int i = 0; i < CeilDivision(m, fractalShape[1] * fractalNum); ++i) { AscendC::LoadDataWithTranspose(a2Local[i * dstOffset], a1Local[i * srcOffset], loadDataParams); } // B矩阵 LoadDataWithTranspose: Nz -> Zn // CeilDivision计算两个整数相除,结果向上取整 uint32_t dstOffset = CeilDivision(n, fractalShape[0]) * fractalSize * fractalNum; uint32_t srcOffset = CeilDivision(n, fractalShape[1] * fractalNum) * fractalSize * fractalNum; AscendC::LoadData2dTransposeParams loadDataParams; loadDataParams.startIndex = 0; loadDataParams.repeatTimes = CeilDivision(n, fractalShape[1] * fractalNum); loadDataParams.srcStride = 1; loadDataParams.dstGap = 0; loadDataParams.dstFracGap = CeilDivision(n, fractalShape[0]) - 1; for (int i = 0; i < CeilDivision(k, fractalShape[0]); ++i) { AscendC::LoadDataWithTranspose(b2Local[i * dstOffset], b1Local[i * srcOffset], loadDataParams); } -
示例4:该示例使用了LoadData2dTransposeParamsV2结构体作为参数,输入a矩阵为int8_t类型,shape为[128,128],输入数据格式为NZ,输入b矩阵为int8_t类型,shape为[128,256],输入数据格式为NZ,输出c的类型为float。a矩阵从A1->A2不转置,b矩阵从B1->B2转置,示例仅展示接口调用过程,其余计算和搬运不作参考。
uint32 m = 256; uint32 n = 256; uint32 k = 128; pipe = tpipe; TQue<TPosition::B1, 1> qidB1_; TQue<TPosition::B2, 1> qidB2_; uint32 m = 128; pipe->InitBuffer(qidB1_, 1, n * k * sizeof(int8_t)); pipe->InitBuffer(qidB2_, 1, n * k * sizeof(int8_t)); auto rightMatrix = qidB1_.template DeQue<int8_t>(); LocalTensor<int8_t> b2 = qidB2_.AllocTensor<int8_t>(); uint16_t fracNum = 2; uint16_t kStep = CeilDiv(kLength, 16); uint16_t nStep = CeilDiv(nLength, 32); for (uint16_t i = 0; i < nStep; i ++) { LoadData2dTransposeParamsV2 loadDataParams; loadDataParams.startIndex = i * kStep; loadDataParams.repeatTimes = kStep / 2; loadDataParams.srcStride = 2; loadDataParams.dstGap = nStep*2 - 1; LoadDataWithTranspose(b2[1024*i], rightMatrix, loadDataParams); } qidB2_.EnQue(b2); qidB1_.FreeTensor(rightMatrix);
更多推荐



所有评论(0)