assembly 用SSE求__m128i向量的最大值?

n3h0vuf2  于 2022-12-23  发布在  其他
关注(0)|答案(4)|浏览(130)

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

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

四处搜索使我找到了MAXPS指令,但我似乎找不到如何将其与"xmmintrin.h"一起使用。
另外,除了查看头文件本身之外,您是否推荐"xmmintrin.h"的任何文档?

mwngjboj

mwngjboj1#

如果有人关心的话,因为内部函数似乎是这些天要走的路,这里有一个内部函数方面的解决方案。

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]); 
}
jq6vz3qz

jq6vz3qz2#

如果您发现自己需要对向量进行水平操作,尤其是在内部循环中,那么 * 通常 * 这是您以错误的方式处理SIMD实现的信号。SIMD喜欢对向量进行元素级操作-如果您喜欢,可以选择“垂直”操作,而不是水平操作。
至于文档,有一个very useful reference on intel.com,它包含所有操作码和内部函数,从MMX到SSE的各种风格,一直到AVX和AVX-512。

k10s72fa

k10s72fa3#

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

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

反之,取最小值:

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

kcwpcxri4#

SSE中没有Horizontal Maximum操作码(至少直到我停止跟踪新的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记录了内部函数Map和宏函数Map
http://msdn.microsoft.com/en-us/library/t467de55.aspx

相关问题