1

我在 gcc 4.4.3 中使用 SSE2。在我的程序中,我需要使用至少 (0 - 7) 个 8 位的 128 位 SIMD 寄存器。请提出一种我可以快速检索 8 位的方法。

我尝试使用_mm_movepi64_pi64or _mm_extract_epi16,这两者在我的程序中都提供了相似的性能。我也在尝试联合方法。union{__m128i a1, int a2[4]}. 虽然,在测试用例中,它给出了很好的结果,但在我的程序中,这种方法并不是很好。

任何想法..(我应该使用上述三种方法中的哪一种?)

4

1 回答 1

1

_mm_movepi64_pi64从 XMM 移动到 MMX 寄存器。这不可能是正确的选择,除非你想在 MMX 寄存器中做更多的 SIMD,并且你的代码用完了 XMM regs。

如果您希望这些位作为数组索引或其他内容,它们必须位于 GP 寄存器中,在这种情况下您需要 SSE4.1 _mm_extract_epi8

如果您需要坚持 SSE2,这应该是获取字节 5 的最快方法xmm0

pextrw eax, xmm0, 2
movzx eax, ah

所以这应该有希望让编译器像这样高效:

(uint8_t)(_mm_extract_epi16(var, n/2) >> ((n%2) * 8))

效率较低的是逐字节移位_mm_bsrli_si128psrldq)将您想要的字节放入 xmm reg 的低字节,然后movd(幸运的是,_mm_extract_epi16(var, 0)发出movd,不是pextrw r32, xmm, 0)。这样,如果您想要的字节是 pextw 将留在结果的高 8 位的奇数字节,您就不必做任何额外的事情。仍然没有简单的方法将它与不是编译时常量的索引一起使用。

将 16B 存储到内存并加载您想要的元素应该是相当不错的。pextract(除非编译器将其优化为指令,否则您可能会通过联合方法得到什么)。编译器将使用堆栈上的 16B 对齐位置。因此,在这种情况下,store->load forwarding 应该可以正常工作,因此延迟会很低。如果您需要将两个单独的元素分成两个单独的整数变量,这可能是最好的选择,也许会击败多个pextrw

于 2015-08-02T02:17:38.287 回答