Device侧代码与说明
Device侧代码示例如下,并参考本节内容了解主要操作。
// Device侧文件:kernel_aiv.cce #ifdef __CCE_KT_TEST__ #define __aicore__ #else #define __aicore__ [aicore] #endif extern "C" __global__ __aicore__ void add_kernel(__gm__ float* __restrict__ input_1, __gm__ float* __restrict__ input_2, __gm__ float* __restrict__ output) { set_vector_mask(-1, -1); set_mask_norm(); set_atomic_none(); __ubuf__ float* input_1_local_UB = (__ubuf__ float*)get_imm(0); __ubuf__ float* input_2_local_UB = (__ubuf__ float*)get_imm(1024); __ubuf__ float* output_local_UB = (__ubuf__ float*)get_imm(2048); copy_gm_to_ubuf(input_1_local_UB, input_1, 0, 1, 8, 0, 0); copy_gm_to_ubuf(input_2_local_UB, input_2, 0, 1, 8, 0, 0); set_flag(PIPE_MTE2, PIPE_V, EVENT_ID0); wait_flag(PIPE_MTE2, PIPE_V, EVENT_ID0); vadd(output_local_UB, input_1_local_UB, input_2_local_UB, 1, 1, 1, 1, 0, 0, 0); set_flag(PIPE_V, PIPE_MTE3, EVENT_ID0); wait_flag(PIPE_V, PIPE_MTE3, EVENT_ID0); copy_ubuf_to_gm(output, output_local_UB, 0, 1, 8, 0, 0); pipe_barrier(PIPE_ALL); }
函数内首先通过get_imm()接口传入立即数偏移量,初始化三个需要在UB用到tensor首地址。
- 数据搬入。将需要进行加法计算的两个加数tensor,从GM搬到UB上,这里使用了copy_gm_to_ubuf指令,其接口原型为:
void copy_gm_to_ubuf(__ubuf__ void *dst, __gm__ void *src, uint8_t sid, uint16_t nBurst, uint16_t lenBurst, uint16_t srcGap, uint16_t dstGap)
- dst:UB上首地址空间首地址。
- src:GM起始地址。
- sid:预留参数,此处默认为0即可。
- nBurst:示例从GM搬运256B(64个float类型),一次搬完,所以nBurst设置为1。
- lenBurst:一次连续搬运数据长度,单位32Bytes,元素个数为64,64 * sizeof(float) = 256B,计算搬运长度256/32=8。
- srcStride:两次搬运源地址间隙,单位32Bytes,示例中只搬运一块数据,所以不涉及stride,此处设置0。
- dstStride:两次搬运目的地址间隙,单位32Bytes,示例中只搬运一块数据,所以不涉及stride,此处设置0。
由于下一步计算依赖搬运数据的完整性,所以需要插入同步对,前置指令的流水类型改为PIPE_MTE2,等待其完成过后,才能开始PIPE_V的计算。
- 计算。将在ub上的两个加数进行逐元素相加,这里使用vadd指令,其接口原型为:
void vadd(__ubuf__ float *dst, __ubuf__ float *src0, __ubuf__ float *src1, uint8_t repeat, uint8_t dstBlockStride, uint8_t src0BlockStride, uint8_t src1BlockStride, uint8_t dstRepeatStride, uint8_t src0RepeatStride, uint8_t src1RepeatStride)
- dst:计算结果存放UB上的首地址。
- src0:第一个加数在UB上的首地址。
- src1:第二个加数在UB上的首地址。
- repeat:指令迭代次数,本次是256B,共计8个block,1次执行完。
- dstBlockStride:同一次执行,目的操作数不同block间地址步长。单位为32B,示例dst block连续存储,所以dstBlockStride为1,每个dst block的起始地址间隔为1个block(32B)。
- src0BlockStride:同一次执行,源操作数0不同block间地址步长。单位为32B,示例src0 block连续读取参与运算,所以dstBlockStride为1,每个dst block的起始地址间隔为1个block(32B)。
- src1BlockStride:同一次执行,源操作数1不同block间地址步长。单位为32B,示例src1 block连续读取参与运算,所以dstBlockStride为1,每个dst block的起始地址间隔为1个block(32B)。
- dstRepeatStride:相邻两次执行,目的操作数相同block地址步长。单位为32B,此处不涉及,所以设为0。
- src0RepeatStride:相邻两次执行,源操作数0相同block地址步长。单位为32B,此处不涉及,所以设为0。
- src1RepeatStride:相邻两次执行,源操作数1相同block地址步长。单位为32B,此处不涉及,所以设为0
- 数据搬出。将计算完的结果tensor,从UB上搬出到结果GM指定位置,这里使用了copy_ubuf_to_gm指令,接口原型为:
void copy_ubuf_to_gm(__gm__ void *dst, __ubuf__ void *src, uint8_t sid, uint16_t nBurst, uint16_t lenBurst, uint16_t srcGap, uint16_t dstGap)
- dst:GM上输出结果的首地址。
- src:计算结果在UB上的首地址。
- sid:预留参数,此处默认为0即可。
- nBurst:示例从UB搬运256B(128个half类型),一次搬完,所以nBurst设置为1。
- lenBurst:一次连续搬运数据长度,单位32Bytes;元素个数为64,64 * sizeof(float) = 256B,计算搬运长度256/32=8。
- srcStride:两次搬运源地址间隙,单位32Bytes;示例中只搬运一块数据,所以不涉及stride,此处设置0。
- dstStride:两次搬运目的地址间隙,单位32Bytes;示例中只搬运一块数据,所以不涉及stride,此处设置0。
父主题: Vector算子示例