Получение максимального значения в векторе __m128i с SSE?
Я только начал использовать SSE, и я смущен, как получить максимальное целочисленное значение (max
) __m128i
. Например:
__m128i t = _mm_setr_ps(0,1,2,3);
// max(t) = 3;
Поиск вокруг привел меня к инструкции MAXPS
, но я не могу найти, как использовать это с "xmmintrin.h"
.
Кроме того, есть ли какая-либо документация для "xmmintrin.h"
, которую вы рекомендовали бы, а не просмотр самого файла заголовка?
Ответы
Ответ 1
Если вам нужно выполнять горизонтальные операции над векторами, особенно если он находится внутри внутреннего цикла, то обычно это знак того, что вы приближаетесь к реализации SIMD неправильно. SIMD любит работать с элементами по векторам - "вертикально", если хотите, а не по горизонтали.
Что касается документации, есть очень полезная ссылка на intel.com, которая содержит все коды операций и внутренности для всего, начиная с MMX через различные вкусов SSE вплоть до AVX и AVX-512.
Ответ 2
В случае, если кто-то заботится, и поскольку intrinsics, кажется, способ идти в эти дни, это решение с точки зрения внутренних свойств.
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]);
}
Ответ 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
Ответ 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 имеет встроенные отображения макросов и макросов
http://msdn.microsoft.com/en-us/library/t467de55.aspx