随路转换ND2NZ搬运
产品支持情况
产品 |
是否支持 Global Memory -> Local Memory |
是否支持 Local Memory -> Local Memory |
---|---|---|
√ |
√ |
|
√ |
√ |
|
x |
x |
|
√ |
x |
|
x |
x |
|
x |
x |
|
x |
x |
功能说明
支持在数据搬运时进行ND到NZ格式的转换。
函数原型
- Global Memory -> Local Memory
1 2
template <typename T> __aicore__ inline void DataCopy(const LocalTensor<T>& dst, const GlobalTensor<T>& src, const Nd2NzParams& intriParams)
- Local Memory -> Local Memory
1 2
template <typename T> __aicore__ inline void DataCopy(const LocalTensor<T>& dst, const LocalTensor<T>& src, const Nd2NzParams& intriParams)
参数说明
参数名 |
描述 |
---|---|
T |
源操作数或者目的操作数的数据类型。 |
参数名称 |
输入/输出 |
含义 |
---|---|---|
dst |
输出 |
目的操作数,类型为LocalTensor。 |
src |
输入 |
源操作数,类型为LocalTensor或GlobalTensor。 |
intriParams |
输入 |
搬运参数,类型为Nd2NzParams。 具体定义请参考${INSTALL_DIR}/include/ascendc/basic_api/interface/kernel_struct_data_copy.h,${INSTALL_DIR}请替换为CANN软件安装后文件存储路径。 |
参数名称 |
含义 |
---|---|
ndNum |
传输ND矩阵的数目,取值范围:ndNum∈[0, 4095]。 |
nValue |
ND矩阵的行数,取值范围:nValue∈[0, 16384]。 |
dValue |
ND矩阵的列数,取值范围:dValue∈[0, 65535]。 |
srcNdMatrixStride |
源操作数相邻ND矩阵起始地址间的偏移,取值范围:srcNdMatrixStride∈[0, 65535],单位为元素。 |
srcDValue |
源操作数同一ND矩阵的相邻行起始地址间的偏移,取值范围:srcDValue∈[1, 65535],单位为元素。 |
dstNzC0Stride |
ND转换到NZ格式后,源操作数中的一行会转换为目的操作数的多行。dstNzC0Stride表示,目的NZ矩阵中,来自源操作数同一行的多行数据相邻行起始地址间的偏移,取值范围:dstNzC0Stride∈[1, 16384],单位:C0_SIZE(32B)。 |
dstNzNStride |
目的NZ矩阵中,Z型矩阵相邻行起始地址之间的偏移。取值范围:dstNzNStride∈[1, 16384],单位:C0_SIZE(32B)。 |
dstNzMatrixStride |
目的NZ矩阵中,相邻NZ矩阵起始地址间的偏移,取值范围:dstNzMatrixStride∈[1, 65535],单位为元素。 |
ND2NZ转换示意图如下,样例中参数设置值和解释说明如下:
- ndNum = 2,表示传输ND矩阵的数目为2 (ND矩阵1为A1~A2 + B1~B2,ND矩阵2为C1~C2 + D1~D2)。
- nValue = 2,ND矩阵的行数,也就是矩阵的高度为2。
- dValue = 24,ND矩阵的列数,也就是矩阵的宽度为24个元素。当dValue不满足32B对齐时,在目的操作数中不足的部分会被补齐为0,例如图示中A2所在DataBlock的空白部分会被补齐为0。
- srcNdMatrixStride = 144,表达相邻ND矩阵起始地址间的偏移,即为A1~C1的距离,即为9个DataBlock,9 * 16 = 144个元素。
- srcDValue = 48,表示一行的所含元素个数,即为A1到B1的距离,即为3个DataBlock,3 * 16 = 48个元素
- dstNzC0Stride = 11。ND转换到NZ格式后,源操作数中的一行会转换为目的操作数的多行,例如src中A1和A2为1行,dst中A1和A2被分为2行。多行数据起始地址之间的偏移就是A1和A2在dst中的偏移,偏移为11个DataBlock。
- dstNzNStride = 2,表示src中一个ND矩阵的第x行和第x+1行转换为NZ格式后在dst中的偏移,即A1和B1在dst之间的偏移为2个DataBlock。
- dstNzMatrixStride = 96,表达dst中第x个ND矩阵的起点和第x+1个ND矩阵的起点的偏移,即A1和C1之间的距离,即为6个DataBlock,6 * 16 = 96个元素。
返回值说明
无
约束说明
针对
支持的通路和数据类型
下文的数据通路均通过逻辑位置TPosition来表达,并注明了对应的物理通路。TPosition与物理内存的映射关系见表1。
产品型号 |
数据通路 |
源操作数和目的操作数的数据类型 (两者保持一致) |
---|---|---|
|
int8_t、uint8_t、int16_t、uint16_t、int32_t、uint32_t、half、float |
|
|
int16_t、uint16_t、int32_t、uint32_t、half、float |
|
|
int8_t、uint8_t、int16_t、uint16_t、int32_t、uint32_t、half、bfloat16_t、float |
|
|
int8_t、uint8_t、int16_t、uint16_t、int32_t、uint32_t、half、bfloat16_t、float |
产品型号 |
数据通路 |
源操作数和目的操作数的数据类型 (两者保持一致) |
---|---|---|
VECIN、VECCALC、VECOUT -> TSCM(UB -> L1 Buffer) |
int8_t、uint8_t、int16_t、uint16_t、int32_t、uint32_t、half、bfloat16_t、float |
|
VECIN、VECCALC、VECOUT -> TSCM(UB -> L1 Buffer) |
int8_t、uint8_t、int16_t、uint16_t、int32_t、uint32_t、half、bfloat16_t、float |
调用示例
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include "kernel_operator.h" class KernelDataCopyGm2UbNd2Nz{ public: __aicore__ inline KernelDataCopyGm2UbNd2Nz() {} __aicore__ inline void Init(__gm__ uint8_t* dstGm, __gm__ uint8_t* srcGm) { AscendC::Nd2NzParams intriParamsIn{1, 32, 32, 0, 32, 32, 1, 0}; intriParams = intriParamsIn; srcGlobal.SetGlobalBuffer((__gm__ half *)srcGm); dstGlobal.SetGlobalBuffer((__gm__ half *)dstGm); pipe.InitBuffer(inQueueSrcVecIn, 1, intriParams.nValue * intriParams.dValue * sizeof(half)); pipe.InitBuffer(inQueueSrcVecOut, 1, intriParams.nValue * intriParams.dValue * sizeof(half)); } __aicore__ inline void Process() { CopyIn(); Compute(); CopyOut(); } private: __aicore__ inline void CopyIn() { AscendC::LocalTensor<half> srcLocal = inQueueSrcVecIn.AllocTensor<half>(); AscendC::DataCopy(srcLocal, srcGlobal, intriParams); inQueueSrcVecIn.EnQue(srcLocal); } __aicore__ inline void Compute() { AscendC::LocalTensor<half> srcLocal = inQueueSrcVecIn.DeQue<half>(); AscendC::LocalTensor<half> dstLocal = inQueueSrcVecOut.AllocTensor<half>(); AscendC::DataCopy(dstLocal, srcLocal, intriParams.nValue * intriParams.dValue); inQueueSrcVecOut.EnQue(dstLocal); inQueueSrcVecIn.FreeTensor(srcLocal); } __aicore__ inline void CopyOut() { AscendC::LocalTensor<half> dstLocal = inQueueSrcVecOut.DeQue<half>(); AscendC::DataCopy(dstGlobal, dstLocal, intriParams.nValue * intriParams.dValue); inQueueSrcVecOut.FreeTensor(dstLocal); } private: AscendC::TPipe pipe; AscendC::TQue<AscendC::TPosition::VECIN, 1> inQueueSrcVecIn; AscendC::TQue<AscendC::TPosition::VECOUT, 1> inQueueSrcVecOut; AscendC::GlobalTensor<half> srcGlobal; AscendC::GlobalTensor<half> dstGlobal; AscendC::Nd2NzParams intriParams; }; extern "C" __global__ __aicore__ void kernel_data_copy_nd2nz_ub2out(__gm__ uint8_t* src_gm, __gm__ uint8_t* dst_gm) { KernelDataCopyGm2UbNd2Nz op; op.Init(dst_gm, src_gm); op.Process(); } |
结果示例:
输入数据(srcGlobal): [1 2 3 ... 1024] 输出数据(dstGlobal):[1 2 ... 15 16 33 34 ... 47 48 65 66 ... 79 80 97 98 ... 111 112 ... 1009 1010... 1023 1024]