2016-06-05 3 views
2

Есть ли инструкция в SSE/SSE2, которая может найти max/min в 4 целых числах 32-бит? Я искал что-то, но нашел только инструкции для 16/8 бит. Спасибо заранее.Найти max среди 32-битных целых чисел

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=max&expand=4465,4463,3278&techs=SSE,SSE2

+3

Вы ищете горизонтальную операцию? Или 4 упакованных максимальных операций параллельно, например 'pmaxsd'? Если вам нужен горизонтальный макс с SSE2, просто сохраните его в памяти и используйте скаляр. С SSE4.1, тогда, возможно, перетасовка, как для горизонтальной суммы, будет самой быстрой. Горизонтальные операции медленны. Если вашему алгоритму нужно много, вы неправильно используете SIMD. См. Раздел [SSE tag wiki] (http://stackoverflow.com/tags/sse/info) для руководств. –

+0

«Вы ищете горизонтальную операцию?» Я ищу операции параллельно. Хорошо, вы предлагаете хранить в памяти и использовать скалярные операции. (в случае горизонтального). Но почему вы предлагаете это делать? В конце концов, нет преимущества от использования SIMD. Вы имеете в виду, что горизонтальная операция выполняется так же быстро, как «хранить в памяти и сравнивать« нормальный »(скалярный) способ? – Gilgamesz

+0

Если у вас ровно 4 цифры, а не 1000 номеров, SIMD не имеет особого значения (если ваши номера являются unsigned 16bit, поэтому вы можете использовать специальный ['PHMINPOSUW'] (http://www.felixcloutier.com/x86/PHMINPOSUW.html)). Горизонтальное означает« внутри одного вектора », в отличие от того, что SIMD (например, добавьте [0] к b [0], a [1] в b [1] и т. д.). Если вам нужно найти горизонтальный максимум из 4 элементов без SSE4.1, то вы, вероятно, не может бить скаляр –

ответ

5

Лучший способ без SSE4.1, по-видимому, иметь 32-битное сравнение, а затем использовать эту маску для смешивания: AND(mask, x) OR ANDN(mask, y).

Agner Fog's vector class library имеет a function for it:

// function max: a > b ? a : b 
static inline Vec4i max(Vec4i const & a, Vec4i const & b) { 
#if INSTRSET >= 5 // SSE4.1 supported 
    return _mm_max_epi32(a,b); 
#else 
    __m128i greater = _mm_cmpgt_epi32(a,b); 
    return selectb(greater,a,b); 
#endif 
} 

У меня есть в основном, непроверенных и пока еще не слившиеся изменения для этой библиотеки on github. Большинство моих изменений значительно улучшают некоторые функции, на которые у меня было время, чтобы посмотреть (целые горизонтальные суммы, квадратичный арифметический сдвиг вправо, умножение на квадрат). (Тестирование/обратная связь приветствуется!)

Но много существующего кода неплохое, поэтому я определенно рекомендую использовать эти классы-оболочки. Они не добавляют накладные расходы при создании с включенными оптимизациями, и они делают синтаксис намного проще. например a+b вместо _mm_add_epi32(a,b).

+0

Возможно, горизонтальные операции - это плохие плоды. Я имею в виду, что они не являются операциями, которые вы обычно хотели бы в критической петле, поэтому их оптимизация не так важна. Были ли вы найдены какие-либо критические функции в VCL, которые нуждаются в оптимизации g? Самая сложная часть VCL, я думаю, это перестановки и смеси. См. Например [this] (http://agner.org/optimize/vectorclass/r ead.php? я = 120). Я считаю, что это самая сложная область для реализации с общим классом. –

+1

@ Zboson: да, оказывается, что все VCL всегда использует 'vpblendvb' (2 uops и нуждается в маске из памяти), даже для компиляции-постоянных смесей. Далее в моем списке нужно исправить шаблоны, чтобы использовать более быстрые 'vpblendd' или' pblendw', когда это возможно.Я также нажал ускорение для 'operator >> (Vec2q)' (эмуляция отсутствующего «psarq»), где я сделал значительно лучше для версии 128b, чем просто изменение переменной-смеси для немедленной замены. –

+0

[Здесь] (https://stackoverflow.com/questions/34122605/how-to-optimize-simd-transpose-function-8x4-4x8/34207876#34207876) - еще один интересный пример. Я понял это правильно, но проблема в том, что мне пришлось попробовать несколько вариантов, прежде чем VCL выпустит идеальный код вместо плохого кода. –

2

Может PMAXSD делает трюк?

Сравнивает накопленные подписанные целые числа dword в операнде-адресате (первый операнд) и исходный операнд (второй операнд) и возвращает максимум для каждого упакованного значения в операнде-адресате.

Однако для этого требуется поддержка SSE 4.1 и/или AVX.

Смежные вопросы