昇腾社区首页
中文
注册
开发者
下载

接口基本信息

Fixpipe是一种执行从L0C到GM或L1数据移动的管道,在数据搬运时,其可以执行下述操作:预量化、预ReLU、int8 通道合并、int4 通道合并、f32通道切分、NZ2ND 转换。处理过程见下图:

图1 处理过程

常规搬运

当通道合并、通道切分、NZ2ND被禁用时,接口被定义为从L0C到L1/OUT的常规数据搬运。 当m(矩阵为m*n)不是16的倍数时,硬件将读取额外的哑数据(哑数据指多读的数据,后续会被丢弃),并在写入目标时丢弃这些哑数据。在给定m和n方向大小的情况下,数据块定义为连续ceil(m/16)个16*16分形块,数据块长度定义为m*16*sizeof(data_type)。源地址和目的地址的计算代码如下:

for(j = 0;j < m;j++)
{
    src_temp_n_addr = Xn + j * sizeof(L0C_element) * 16;
    dst_temp_n_addr = Xd + j * 16 * sizeof(DST_element);
    for(k = 0; k < ceil(n/16); k++)
    {
          src_block_addr = src_temp_n_addr + k * src_stride * sizeof(L0C_element) * 16;
          dst_block_addr = dst_temp_n_addr + k * dst_stride * 32;
    }
} 

int8 通道合并

若转换为s8或u8的目标数据类型,分形矩阵需要通过硬件从16*16转换为16*32。如果通道n是16的偶数倍,则n方向上每2个相邻的16*16分形矩阵将合并为1个16*32分形矩阵。如果n是16的奇数倍,则将通道1到通道(n–16)合并,最后16个通道保持未合并。 例如,目标数据类型为s8,m为32,n为48,它将首先将第2个16*16分形矩阵合并为一个16*32矩阵,然后将剩余的16*16分形矩阵直接移入L1。

int4 通道合并

对于转换为s4或u4的目标数据类型,分形矩阵也通过硬件从16*16转换为16*64,如果输出通道数n(矩阵为m*n)是64的倍数,则n方向上每4个相邻的16*16分形矩阵将合并为1个单个的16*64分形矩阵。 例如,目标数据类型是s4,m是32,n是64,它将首先将第1个16*16分形矩阵合并为一个16*64矩阵,然后将第2个16*16分形矩阵也合并。 在这种情况下,n的配置必须是64的倍数。

f32 通道切分

对于目标类型为f32,分形矩阵可以通过硬件从16*16转换为16*8,如果启用通道切分(channelSplit=1),则每个16*16分形矩阵将被分裂为2个单个16*8分形矩阵。 例如,目标数据类型是F32,m是64,n是32,它将被拆分为16个16*8的分形。 如果启用通道切分,n可以是8的倍数。例如,如果n=24,则上面的示例将仅向OUT输出3列16*8分形。

NZ2ND 转换

当NZ2ND_EN使能时,此接口定义为从L0C到目的地址的带NZ2ND转换的数据搬运。

转换流程如下:
for(i = 0; i < nd_num; i++)
{
       src_temp_nd_addr = Xn + src_nd_stride * i * fractal_size;
       dst_temp_nd_addr = Xd + src_nd_stride * i * sizeof(DST_element);
       for(j = 0; j < m; j++)
       {
              src_temp_n_addr = src_temp_nd_addr + j * sizeof(L0C_element) * 16;
              dst_temp_n_addr = dst_temp_nd_addr + j * dst_D * sizeof(DST_element);
              for(k = 0; k < ceil(n/16); k++)
              {
                     src_block_addr = src_temp_n_addr + k * src_stride * sizeof(L0C_element) * 16;
                     dst_block_addr = dst_temp_n_addr + k * 16 * sizeof(DST_element);
              }
       }
}