Получить максимальное значение в векторе __m128i с SSE? - PullRequest
12 голосов
/ 26 марта 2012

Я только начал использовать SSE, и меня смущает, как получить максимальное целое значение (max) из __m128i.Например:

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

Поиск вокруг привел меня к MAXPS инструкции, но я не могу найти, как использовать это с "xmmintrin.h".

Кроме того, есть ли какая-либо документация для "xmmintrin.h", которую вы бы порекомендовали, вместо того, чтобы заглядывать в сам файл заголовка?

Ответы [ 4 ]

16 голосов
/ 04 сентября 2013

На случай, если кому-то все равно, и, как кажется, внутренняя часть - это путь, которым стоит идти в эти дни, вот решение с точки зрения внутренних характеристик.

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]); 
}
10 голосов
/ 26 марта 2012

Если вам нужно выполнить горизонтальные операции с векторами, особенно если они находятся во внутреннем цикле, то это обычно - признак того, что вы неправильно подходите к реализации SIMD.SIMD любит поэлементно работать с векторами - "вертикально", если хотите, а не горизонтально.

Что касается документации, на сайте intel.com есть очень полезная ссылка , которая содержит всекоды операций и встроенные функции для всего, начиная от MMX и заканчивая различными версиями SSE, вплоть до AVX и AVX-512.

8 голосов
/ 26 марта 2012

Согласно этой странице , максимальный горизонтальный размер отсутствует, и вам необходимо проверить элементы по вертикали:

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
4 голосов
/ 26 марта 2012

В 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 имеет документированные внутренние и макро-функции.

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

...