我正在使用GCC4.4.3中的SSE2。在我的程序中,我需要使用至少(0-7)8位的128位SIMD寄存器。请建议一种我可以快速检索8位的方法。
我试过使用_mm_movepi64_pi64
或_mm_extract_epi16
,这两种方法在我的程序中都有相似的性能。我也在尝试联合的方法。union{__m128i a1, int a2[4]}
。不过,在测试用例中,它给出了很好的结果,在我的程序中,这种方法不是很好。
有什么想法。。(上面提到的三种方法我应该使用哪一种?)
最佳答案
_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寄存器的低位字节,然后movd
(_mm_extract_epi16(var, 0)
幸运地发出movd
,而不是pextrw r32, xmm, 0
)。这样,如果您想要的字节是奇数字节,而pextw将保留在结果的高位8,就不必做任何额外的事情。对于不是编译时常量的索引,仍然没有简单的方法使用它。将16B存储到内存并加载所需的元素应该相当不错。(除非编译器将其优化为
pextract
指令,否则您可能会得到union方法的结果)。编译器将在堆栈上使用一个16B对齐的位置。因此,在这种情况下,“存储”->“加载转发”应该可以正常工作,因此延迟将很低。如果您需要将两个独立的元素分成两个独立的整数变量,这可能是最好的选择,可能比multiplepextrw