产品 |
是否支持 |
|---|---|
Ascend 950PR/Ascend 950DT |
√ |
√ |
|
√ |
|
√ |
|
x |
|
x |
|
x |
该接口实现带转置的2D格式数据从A1/B1到A2/B2的加载。
下面通过示例来讲解接口功能和关键参数:下文图中一个N形或者一个Z形代表一个分形。

如下图示例:



如下图示例:

int4b_t数据类型需要两个数拼成一个int8_t或uint8_t的数,拼凑的规则如下:


如下图示例:

1 2 | template <typename T> __aicore__ inline void LoadDataWithTranspose(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LoadData2dTransposeParams& loadDataParams) |
1 2 3 | // 该函数原型仅支持Ascend 950PR/Ascend 950DT template <typename T> __aicore__ inline void LoadDataWithTranspose(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LoadData2dTransposeParamsV2& loadDataParams) |
参数名 |
描述 |
|---|---|
T |
Ascend 950PR/Ascend 950DT,支持数据类型:int8_t/uint8_t/half/bfloat16_t/float/int32_t/uint32_t。 其中int4b_t数据类型仅在LocalTensor的TPosition为B2时支持。 |
参数名称 |
输入/输出 |
含义 |
|---|---|---|
dst |
输出 |
目的操作数,结果矩阵,类型为LocalTensor。 Ascend 950PR/Ascend 950DT,支持的TPosition为B2。 LocalTensor的起始地址需要保证512字节对齐。 数据类型和src的数据类型保持一致。 |
src |
输入 |
源操作数,类型为LocalTensor。 Ascend 950PR/Ascend 950DT,支持的TPosition为B1。 LocalTensor的起始地址需要保证32字节对齐。 数据类型和dst的数据类型保持一致。 |
loadDataParams |
输入 |
LoadDataWithTranspose相关参数,类型为LoadData2dTransposeParams。 具体定义请参考${INSTALL_DIR}/include/ascendc/basic_api/interface/kernel_struct_mm.h,${INSTALL_DIR}请替换为CANN软件安装后文件存储路径。 参数说明请参考表3。 |
loadDataParams |
输入 |
LoadDataWithTranspose相关参数,类型为LoadData2dTransposeParamsV2。 参数说明请参考表4。 |
参数名称 |
输入/输出 |
含义 |
|---|---|---|
startIndex |
输入 |
方块矩阵ID,搬运起始位置为源操作数中第几个方块矩阵(0 为源操作数中第1个方块矩阵)。取值范围:startIndex∈[0, 65535] 。默认为0。 例如,源操作数中有20个大小为16*8*4B的分形(数据类型为float),startIndex=1表示搬运起始位置为第2个方块矩阵,即将第3和第4个分形从源操作数中转置到目的操作数中(第1、2个分形组成第1个方块矩阵,第3、4个分形组成第2个方块矩阵)。 |
repeatTimes |
输入 |
迭代次数。 对于uint8_t/int8_t数据类型,每次迭代处理32*32*1B数据; 对于half/bfloat16_t数据类型,每次迭代处理16*16*2B数据; 对于float/int32_t/uint32_t数据类型,每次迭代处理16*16*4B数据。 对于int4b_t数据类型,每次迭代处理16*64*0.5B数据。 取值范围:repeatTimes∈[0, 255]。默认为0。 |
srcStride |
输入 |
相邻迭代间,源操作数前一个分形与后一个分形起始地址的间隔。这里的单位实际上是拼接后的方块矩阵的大小。 对于uint8_t/int8_t数据类型,单位是32*32*1B; 对于half/bfloat16_t数据类型,单位是16*16*2B; 对于float/int32_t/uint32_t数据类型,单位是16*16*4B。 对于int4b_t数据类型,每次迭代处理16*64*0.5B数据。 取值范围:srcStride∈[0, 65535]。默认为0。 |
dstGap |
输入 |
相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔,单位:512B。取值范围:dstGap∈[0, 65535]。默认为0。 |
dstFracGap |
输入 |
每个迭代内目的操作数转置前一个分形结束地址与后一个分形起始地址的间隔,单位为512B,仅在数据类型为float/int32_t/uint32_t/uint8_t/int8_t/int4b_t时有效。取值范围:dstFracGap∈[0, 65535]。默认为0。 |
addrMode |
输入 |
控制地址更新方式,默认为false:
|
参数名称 |
输入/输出 |
含义 |
|---|---|---|
startIndex |
输入 |
方块矩阵 ID,搬运起始位置为源操作数中第几个分形。取值范围:startIndex∈[0, 65535] 。默认为0。 |
repeatTimes |
输入 |
迭代次数。 对于int4b_t数据类型,每次迭代处理4个分形,每个分形为16*64*0.5B数据。 对于uint8_t/int8_t数据类型,每次迭代处理2个分形,每个分形处理16*32*1B数据; 对于half/bfloat16_t数据类型,每次迭代处理1个分形,每个分形处理16*16*2B数据; 对于int32_t/uint32_t/float数据类型,每次迭代处理4个分形,每个分形为16*8*4B数据。 取值范围:repeatTimes∈[1, 255]。 |
srcStride |
输入 |
相邻迭代间,源操作数前一个分形与后一个分形起始地址的间隔。单位为单个分形512B。 取值范围:srcStride∈[0, 65535]。默认为0。 |
dstGap |
输入 |
相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔,单位:512B。取值范围:dstGap∈[0, 65535]。默认为0。 |
dstFracGap |
输入 |
每个迭代内目的操作数转置前一个分形结束地址与后一个分形起始地址的间隔,单位为512B,仅在数据类型为float/int32_t/uint32_t/uint8_t/int8_t/int4b_t时有效。 |
srcFracGap |
输入 |
每个迭代内源操作数前一个分形结束地址与后一个分形起始地址的间隔,单位为512B,仅在数据类型为float/int32_t/uint32_t/uint8_t/int8_t/int4b_t时有效。 |
addrMode |
输入 |
控制地址更新方式,默认为false:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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); } |
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);