在一个_mm_load_si128上使用两个_mm_loadl_epi64

时间:2015-03-03 10:53:37

标签: c intel sse simd intrinsics

我需要使用16位值(正值)并将它们提升为32位。

使用SIMD(我仅限SSE3),以下是我提出的两个选项:

reg_xmm0 = _mm_loadu_si128((const __m128i *)(Src));
reg_xmm2 = _mm_loadu_si128((const __m128i *)(Src+8));

reg_xmm1 = _mm_unpackhi_epi16(reg_xmm0,_mm_setzero_si128());
reg_xmm0 = _mm_unpacklo_epi16(reg_xmm0,_mm_setzero_si128());
reg_xmm3 = _mm_unpackhi_epi16(reg_xmm2,_mm_setzero_si128());
reg_xmm2 = _mm_unpacklo_epi16(reg_xmm2,_mm_setzero_si128()); 

或者我可以这样做,

reg_xmm0 = _mm_loadl_epi64((const __m128i *)(Src));
reg_xmm1 = _mm_loadl_epi64((const __m128i *)(Src+4));
reg_xmm2 = _mm_loadl_epi64((const __m128i *)(Src+8));
reg_xmm3 = _mm_loadl_epi64((const __m128i *)(Src+12));

reg_xmm0 = _mm_unpacklo_epi16(reg_xmm0,_mm_setzero_si128());
reg_xmm1 = _mm_unpacklo_epi16(reg_xmm1,_mm_setzero_si128());
reg_xmm2 = _mm_unpacklo_epi16(reg_xmm2,_mm_setzero_si128());
reg_xmm3 = _mm_unpacklo_epi16(reg_xmm3,_mm_setzero_si128()); 

我应该去哪个approch?使用第二种方法比第一种方法有任何性能提升。请注意,我已将_mm_loadu_si128替换为两个_mm_loadl_epi64

1 个答案:

答案 0 :(得分:1)

大多数情况下,您需要上下文来说明某些事情是更快还是更慢。延迟,执行端口或uop吞吐量(前端)都是常见的瓶颈。

如果使用1寄存器寻址模式,punpcklo可以与内存操作数微融合,使整个内存解包操作成为单个融合域uop。如果你的循环索引到一个数组,而不是递增指针,那么去加载2x128b然后解压缩,因为punpcklwd xmm0, [rsi + rax]不能微融合。

实际上,抓一点。 punpcklo仍然要求其内存操作数为16字节对齐。但是,如果源数据已对齐,您可以使用相同的地址执行一系列punpcklo / punpckhi对。

如果你的内在函数最终编译为4x负载和4x解压缩,那么至少会比2x负载和4x解包更差。

如果您不限于SSE3,SSE4.1的PMOVZXWD xmm1, xmm2/m64将是完美的,因为它没有128b内存操作数以及相应的对齐要求。