使用SSE获取__m128i向量中的最大值?

我刚开始使用SSE,我很困惑如何获得__m128i的最大整数值( max )。 例如:

 __m128i t = _mm_setr_ps(0,1,2,3); // max(t) = 3; 

搜索引导我到MAXPS指令,但我似乎无法找到如何使用"xmmintrin.h"

另外,您是否会建议使用"xmmintrin.h"文档,而不是查看头文件本身?

如果你发现自己需要对向量进行水平操作,特别是如果它在内部循环中,那么通常表明你正在以错误的方式接近你的SIMD实现。 SIMD喜欢在矢量上按元素操作 – 如果你愿意,可以“垂直”操作,而不是水平操作。

至于文档, 在intel.com上有一个非常有用的参考,其中包含从MMX到各种版本的SSE一直到AVX和AVX-512的所有操作码和内在函数。

如果有人关心并且因为内在似乎是现在的方式,这里是一个内在的解决方案。

 int horizontal_max_Vec4i(__m128i x) { __m128i max1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(0,0,3,2)); __m128i max2 = _mm_max_epi32(x,max1); __m128i max3 = _mm_shuffle_epi32(max2, _MM_SHUFFLE(0,0,0,1)); __m128i max4 = _mm_max_epi32(max2,max3); return _mm_cvtsi128_si32(max4); } 

我不知道这是否比这更好:

 int horizontal_max_Vec4i(__m128i x) { int result[4] __attribute__((aligned(16))) = {0}; _mm_store_si128((__m128i *) result, x); return max(max(max(result[0], result[1]), result[2]), result[3]); } 

根据此页面 ,没有水平最大值,您需要垂直测试元素:

 movhlps xmm1,xmm0 ; Move top two floats to lower part of xmm1 maxps xmm0,xmm1 ; Get maximum of the two sets of floats pshufd xmm1,xmm0,$55 ; Move second float to lower part of xmm1 maxps xmm0,xmm1 ; Get minimum of the two remaining floats 

相反,获得最低要求:

 movhlps xmm1,xmm0 minps xmm0,xmm1 pshufd xmm1,xmm0,$55 minps xmm0,xmm1 

SSE中没有水平最大操作码(至少在我停止跟踪新SSE指令之前)。

所以你被困在做一些洗牌。 你最终得到的是……

 movhlps %xmm0, %xmm1 # Move top two floats to lower part of %xmm1 maxps %xmm1, %xmm0 # Get minimum of sets of two floats pshufd $0x55, %xmm0, %xmm1 # Move second float to lower part of %xmm1 maxps %xmm1, %xmm0 # Get minimum of all four floats originally in %xmm0 

http://locklessinc.com/articles/instruction_wishlist/

MSDN记录了内在和宏function映射

http://msdn.microsoft.com/en-us/library/t467de55.aspx