我在gcc 4.4.3中使用SSE2。在我的程序中,我需要使用128位SIMD寄存器的至少(0 - 7)8位。请建议一种我可以快速检索8位的方法。
我尝试使用_mm_movepi64_pi64
或_mm_extract_epi16
,两者都在我的程序中提供了相似的性能。我也尝试过工会方法。 union{__m128i a1, int a2[4]}
。虽然,在测试用例中,它给出了很好的结果,但在我的程序中,这种方法并不是很好。
任何想法..(上面提到的三种方法我应该使用?)
答案 0 :(得分:1)
_mm_movepi64_pi64
从XMM移动到MMX寄存器。除非你想在MMX寄存器中做更多的SIMD,并且你的代码用完了XMM regs,否则它无法做出正确的选择。
如果您希望将这些位作为数组索引或其他内容,则它们必须位于GP寄存器中,在这种情况下,您需要SSE4.1 _mm_extract_epi8
。
如果您需要坚持使用SSE2,这应该是获取xmm0
字节5的紧固方式:
pextrw eax, xmm0, 2
movzx eax, ah
所以这应该有希望让编译器像这样高效:
(uint8_t)(_mm_extract_epi16(var, n/2) >> ((n%2) * 8))
效率较低的是逐字节_mm_bsrli_si128
(psrldq
)将您想要的字节放入xmm reg的低字节,然后movd
({{1 }}幸运地发出_mm_extract_epi16(var, 0)
,而不是movd
。这样你就不必做任何额外的事情,如果你想要的字节是一个奇数字节,pextw会留在结果的高8位。仍然没有简单的方法来使用不是编译时常量的索引。
将16B存储到内存并加载所需的元素应该相当不错。 (除非编译器将其优化为pextrw r32, xmm, 0
指令,否则您可能会使用union方法获得的内容)。编译器将在堆栈上使用16B对齐的位置。因此,在这种情况下,存储 - >加载转发应该可以正常工作,因此延迟会很低。如果你需要将两个单独的元素分成两个独立的整数变量,这可能是最好的选择,可能超过多个pextract