我刚刚开始使用SSE,我很困惑如何获得max
的最大整数值(__m128i
)。例如:
__m128i t = _mm_setr_ps(0,1,2,3);
// max(t) = 3;
四处搜索引导我MAXPS
指示,但似乎无法找到如何将其与"xmmintrin.h"
一起使用。
此外,您是否建议使用"xmmintrin.h"
的文档,而不是查看头文件本身?
答案 0 :(得分:15)
如果有人关心并且因为内在现象似乎是最近的方式,这里是一个内在的解决方案。
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]);
}
答案 1 :(得分:10)
如果你发现自己需要对向量进行水平操作,特别是如果它在内部循环中,那么通常表示你正在以错误的方式接近你的SIMD实现。 SIMD喜欢在矢量上按元素操作 - 如果你愿意,可以“垂直”操作,而不是水平操作。
至于文档,有一个very useful reference on intel.com,其中包含从MMX到各种版本的SSE一直到AVX和AVX-512的所有操作码和内在函数。
答案 2 :(得分:8)
根据this page,没有水平最大值,您需要垂直测试元素:
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
答案 3 :(得分:4)
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记录了内在和宏功能映射