假设我有 8 个 SSE 寄存器,枚举为 r0、r1、r2、...、r7,并且每个都包含 8 个 16 位整数。我想创建一个新寄存器,其中包含 8 个寄存器中每个寄存器的第 i 个元素,从 r0 开始,到 r7。换句话说,我想获得一个包含以下内容的寄存器:
r0[i],r1[i],r2[i],r3[i],r4[i],r5[i],r6[i],r7[i]
如何使用 SSE(或 AVX)来完成?
谢谢!
请注意,索引 i 不是常数,而是在运行时计算的。
最佳答案
这似乎是一个有趣的挑战。如果您需要在您的算法中执行此操作,那么是时候考虑如何组织事情了,这样您不必必须执行此操作,而不是像这样Paul R 在评论中建议的整个 8x8 转置。
我正在考虑为每个寄存器设置类似 pshufb
的东西
xmmN[N] = old_xmmN[i]; // with other elements zeroed.
您将有一个洗牌掩码表,并使用 table[ (i-N) & 7]
洗牌 xmmN
。或者,在零之前/之后复制洗牌掩码,您可以只使用从 table[i]
开始的 8 个连续掩码。 (因此,您将地址计算到寄存器中一次,并使用递增位移。
然后 POR
将寄存器放在树中。 (实际上,为第一个 POR
选择操作数并将其安排在前两个 PSHUFB
之后,因此合并可以与改组重叠。)
您可能会通过存储到内存然后重新加载来获得更好的吞吐量。 (但可能更糟糕的延迟,因为这会导致存储转发延迟。)
rdi = tmp buffer
switch(i) {
case 0:
movd [rdi], xmm0
movd [rdi+2], xmm1
...
movd [rdi+14], xmm8 // note: writes all the way to [rdi+17]. use pextrw to avoid that.
break;
case 1:
pextrw [rdi], xmm0, 1; // SSE4.1 for memory dest pextrw
pextrw [rdi+2], xmm1, 1
...
break;
case 2:
same, but with imm8 = 2;
break;
...
}
movdqa xmm0, [rdi] ;// ~10 cycle store-forwarding stall
关于c - 从多个寄存器收集特定元素并存储到一个寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26290853/