Мулт плюс изместване наляво операции с помощта на MMX инструкции за асемблер

Търся да извърша shl(mult(var1,var2),1) операция, където mult умножава var1 и var2 (и двете са 16-битови цели числа със знак), а shl измества наляво аритметично резултата от умножението. Резултатът трябва да бъде наситен, т.е. int32 max или int32 min, ако възникне препълване или недостатъчност и mult(-32768,-32768)=2147483647.

Трябва да направя тази операция за множество стойности по ефективен начин, за който мисля, че използвам MMX/SSE набор от инструкции. Исках да направя mult(sign_extesion(var1), shl(sign_extension(var2))), но току-що открих, че не съществува версия за насищане на MMX mult(). Знаете ли друг начин да го получите?


person LooPer    schedule 27.07.2011    source източник


Отговори (1)


Мисля, че следното трябва да работи за вас. Има само един потенциален случай на препълване (SHRT_MIN * SHRT_MIN) и той обработва това изрично:

#include <limits.h>
#include <mmintrin.h>

int main(void)
{        
    __m64 v1 = _mm_set_pi16(0, SHRT_MAX, 0, SHRT_MIN);
    __m64 v2 = _mm_set_pi16(0, SHRT_MIN, 0, SHRT_MIN);
    __m64 v = _mm_madd_pi16(v1, v2); // 16 x 16 signed multiply
    v = _mm_slli_pi32(v, 1);         // shift left by 1 bit to get full range
    __m64 vcmp = _mm_cmpeq_pi32(v, _mm_set1_pi32(INT_MIN));
                                     // test for SHRT_MIN * SHRT_MIN overflow
    v = _mm_add_pi32(v, vcmp);       // and correct if needed

    return 0;
}
person Paul R    schedule 27.07.2011
comment
имате ли опит за това колко печалба може да се получи чрез умножения чрез MMX вместо единични? - person LooPer; 28.07.2011
comment
@LooPer: зависи от процесора, но повечето настоящи процесори на Intel имат две целочислени ALU, така че вероятно няма какво да се спечели от двупосочен SIMD като този. Ако можете да преминете към 128-битов SSE, тогава трябва да видите значително увеличение на производителността, при условие че не сте ограничени в честотната лента на паметта. - person Paul R; 28.07.2011