asc_transto5hd

产品支持情况

产品 是否支持
Atlas A3 训练系列产品/Atlas A3 推理系列产品
Atlas A2 训练系列产品/Atlas A2 推理系列产品

功能说明

数据格式转换,一般用于将NCHW格式转换成NC1HWC0格式。特别的,也可以用于二维矩阵数据块的转置。本接口单次Repeat内可处理512Byte的数据(16个DataBlock),根据数据类型不同,支持不同shape的矩阵转置(比如数据类型为half时,单次Repeat可完成16*16大小的矩阵转置),同时还可以支持多次Repeat操作。

单次repeat内转换规则如下:

  • 当输入数据类型位宽为16位时,每个DataBlock中包含16个数,指令内部会循环16次,每次循环都会分别从指定的16个DataBlock中的对应位置取值,组成一个新的DataBlock单元放入目的地址中。如下图所示,图中的srcList[0]-srcList[15]代表源操作数的16个DataBlock。

  • 当数据类型位宽为32位时,每个DataBlock包含8个数,指令内部会循环8次,每次循环都会分别从指定的16个DataBlock中的对应位置取值,组成2个新的DataBlock放入目的地址中。如下图所示:

-当数据类型位宽为8位时,每个DataBlock包含32个数,指令内部会循环16次,每次循环都会分别从指定的16个DataBlock中的对应位置取值,组成半个DataBlock放入目的地址中,读取和存放是在DataBlock的高半部还是低半部由参数srcHighHalf和dstHighHalf决定。如下图所示:

基于以上的转换规则,使用该接口进行NC1HWC0格式转换或者矩阵转置。NC1HWC0格式转换相对复杂,这里给出其具体的转换方法:

NCHW格式转换成NC1HWC0格式时,如果是数据类型的位宽为32位或者16位,则C0=16;如果数据类型的位宽为8位,则C0=32。下图以C0=16为例进行介绍:

函数原型

__aicore__ inline void asc_transto5hd_b32(ub_addr8_t dst, ub_addr8_t src, uint8_t repeat,
    uint16_t dst_stride, uint16_t src_stride)
__aicore__ inline void asc_transto5hd_b16(ub_addr8_t dst, ub_addr8_t src, uint8_t repeat,
    uint16_t dst_stride, uint16_t src_stride)
__aicore__ inline void asc_transto5hd_b8(ub_addr8_t dst, ub_addr8_t src, uint8_t repeat,
    uint16_t dst_stride, uint16_t src_stride, bool dst_high_half, bool src_high_half)

参数说明

参数名 输入/输出 描述
addr 输出 地址寄存器。
src_array 输入 操作数地址序列。
dst 输出 目的地址寄存器。
src 输入 源地址寄存器。
repeat 输入 重复迭代次数, repeat∈[0,255]。
注意事项:
• 当repeat为1时,目的操作数/源操作数的有效起始位置为dst/src序列输入的起始位置加上dst_stride/src_stride。如果要让目的操作数/源操作数的有效起始位置为dst/src序列输入的起始位置,需要将dst_stride/src_stride置为0。
•当repeat大于1时,第一次repeat中目的操作数/源操作数的有效起始位置为dst/src序列输入的起始位置,第二次会加上dst_stride/src_stride。以此类推。
dst_stride 输入 相邻迭代间,目的操作数相同DataBlock地址Stride,单位:DataBlock。
相邻迭代间相同DataBlock的地址步长参数的详细说明请参考repeatStride
src_stride 输入 相邻迭代间,源操作数相同DataBlock地址Stride,单位:DataBlock。
相邻迭代间相同DataBlock的地址步长参数的详细说明请参考repeatStride
dst_high_half 输入 指定每个dst地址中的数据存储到DataBlock的高半部还是低半部,该配置只配置int8_t/uint8_t的数据类型。
支持的数据类型为bool,有以下两种取值:
• true:表示存储于DataBlock的高半部。
• false:表示存储于DataBlock的低半部。
src_high_half 输入 指定每个src地址中的数据存储到DataBlock的高半部还是低半部,该配置只配置int8_t/uint8_t的数据类型。
支持的数据类型为bool,有以下两种取值:
• true:表示存储于DataBlock的高半部。
•false:表示存储于DataBlock的低半部。

返回值说明

流水类型

PIPE_TYPE_V

约束说明

  • 操作数地址对齐约束请参考通用地址对齐约束
  • 操作数地址重叠约束请参考通用地址重叠约束
  • 进行NCHW格式到NC1HWC0格式的转换时,一般用法是将src/dst中的每个元素配置为每个HW平面的起点。
  • 为了性能更优,数据类型位宽为8位时建议先固定dst_high_half/src_high_half,再HW方向Repeat后,再改变dst_high_half/src_high_half。

调用示例

constexpr uint64_t total_length = 256;    // total_length指参与计算的数据长度
__ubuf__ half src[total_length];
__ubuf__ half dst[total_length];
const uint32_t STEP = 16;
// src_list和dst_list是16个DataBlock地址的数组
__ubuf__ half* src_list[16] = {
    (__ubuf__ half*)(src + 0 * STEP),
    (__ubuf__ half*)(src + 1 * STEP),
    (__ubuf__ half*)(src + 2 * STEP),
    (__ubuf__ half*)(src + 3 * STEP),
    (__ubuf__ half*)(src + 4 * STEP),
    (__ubuf__ half*)(src + 5 * STEP),
    (__ubuf__ half*)(src + 6 * STEP),
    (__ubuf__ half*)(src + 7 * STEP),
    (__ubuf__ half*)(src + 8 * STEP),
    (__ubuf__ half*)(src + 9 * STEP),
    (__ubuf__ half*)(src + 10 * STEP),
    (__ubuf__ half*)(src + 11 * STEP),
    (__ubuf__ half*)(src + 12 * STEP),
    (__ubuf__ half*)(src + 13 * STEP),
    (__ubuf__ half*)(src + 14 * STEP),
    (__ubuf__ half*)(src + 15 * STEP)
};
__ubuf__ half* dst_list[16] = {
    (__ubuf__ half*)(dst + 0 * STEP),
    (__ubuf__ half*)(dst + 1 * STEP),
    (__ubuf__ half*)(dst + 2 * STEP),
    (__ubuf__ half*)(dst + 3 * STEP),
    (__ubuf__ half*)(dst + 4 * STEP),
    (__ubuf__ half*)(dst + 5 * STEP),
    (__ubuf__ half*)(dst + 6 * STEP),
    (__ubuf__ half*)(dst + 7 * STEP),
    (__ubuf__ half*)(dst + 8 * STEP),
    (__ubuf__ half*)(dst + 9 * STEP),
    (__ubuf__ half*)(dst + 10 * STEP),
    (__ubuf__ half*)(dst + 11 * STEP),
    (__ubuf__ half*)(dst + 12 * STEP),
    (__ubuf__ half*)(dst + 13 * STEP),
    (__ubuf__ half*)(dst + 14 * STEP),
    (__ubuf__ half*)(dst + 15 * STEP)
};
const int32_t VA_REG_ARRAY_LEN = 8;
uint8_t repeat = 16;
uint16_t dst_stride = 16;
uint16_t src_stride = 1;

// asc_set_va_reg接口要求前8个和后8个地址序列与地址寄存器分别关联
asc_set_va_reg(VA0, dst_list);
asc_set_va_reg(VA1, dst_list + VA_REG_ARRAY_LEN);
asc_set_va_reg(VA2, src_list);
asc_set_va_reg(VA3, src_list + VA_REG_ARRAY_LEN);

asc_transto5hd_b16(VA0, VA2, repeat, dst_stride, src_stride);