assembly 使用 neon 转置4x4 int32矩阵

vd8tlhqk  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(118)

如何有效地转置表示为四个int32x4t值的矩阵?我不能使用ld4q_s32st4q_s32

o3imoua4

o3imoua41#

转置通常以递归形式实现:

[A B]' == [A' C']
   [C D]     [B' D']

其中每个A,B,C,D可以被认为是一个方阵(并且对于1x 1矩阵,A’== A)。
不幸的是,使用转置只能在需要并行转置最低2x2矩阵的级别上帮助您-ARM 64指令集缺少转置最高级别的指令,即一次64位,在arm-v7上作为swp d2, d0完成。
反正转置还有另一个迭代公式:它会反复地解压或压缩输入。
在 *octave/matlab语言 * 中,我们将zip运算符定义为1,它取数组a的前N/2个元素,并将它们与数组的最后N/2个元素交织。

zip = @(a) [a(1:end/2);a(end/2+1:end)](:)';
  zip(0:15) %--> 0  8  1  9  2 10  3 11  4 12  5 13  6 14  7 15
  zip(ans)  %--> 0  4  8 12  1  5  9 13  2  6 10 14  3  7 11 15

因此,使用intrinsic的完整代码可能如下所示:

inline int32x4x4_t zip(int32x4x4_t a) {
   return { vzip1q_s32(a.val[0], a.val[2]),
            vzip2q_s32(a.val[0], a.val[2]),
            vzip1q_s32(a.val[1], a.val[3]),
            vzip2q_s32(a.val[1], a.val[3]) };
}

int32x4x4_t transpose(int32x4x4_t a) {
    return zip(zip(a));
}

在某些架构中,如果有8个额外的寄存器备用(4个用于索引,4个用于输出),也可以使用vtbl

uint8x16x4_t transpose_vtbl(uint8x16x4_t a) {
   return {
      vqtbl4q_u8(a, idx0),
      vqtbl4q_u8(a, idx1),
      vqtbl4q_u8(a, idx2),
      vqtbl4q_u8(a, idx3)};
}

在这里,int32x4x4_t input需要与vreinterpretq_u8_s32(input.val[i])进行元素转换,然后返回,idx0的值为0 1 2 3 16 17 18 19 32 33 34 35 48 49 50 51idx1 == idx0 + 4等。
在M1或M2上,VTBL似乎是指令级并行化,与例如相反。中度最近的皮层A75(v8.2),其中vtbl花费3 N +1个时钟周期,没有双发出能力。

相关问题