哪一个更快?

时间:2011-06-22 13:21:29

标签: c optimization sse simd sse2

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

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

任何想法..(上面提到的三种方法我应该使用?)

1 个答案:

答案 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_si128psrldq)将您想要的字节放入xmm reg的低字节,然后movd({{1 }}幸运地发出_mm_extract_epi16(var, 0),而不是movd。这样你就不必做任何额外的事情,如果你想要的字节是一个奇数字节,pextw会留在结果的高8位。仍然没有简单的方法来使用不是编译时常量的索引。

将16B存储到内存并加载所需的元素应该相当不错。 (除非编译器将其优化为pextrw r32, xmm, 0指令,否则您可能会使用union方法获得的内容)。编译器将在堆栈上使用16B对齐的位置。因此,在这种情况下,存储 - >加载转发应该可以正常工作,因此延迟会很低。如果你需要将两个单独的元素分成两个独立的整数变量,这可能是最好的选择,可能超过多个pextract