x86 - Multiplicación SSE de 4 enteros de 32 bits.
simd multiplication (2)
¿Cómo multiplicar cuatro enteros de 32 bits por otros 4 enteros? No encontré ninguna instrucción que pueda hacerlo.
Si necesita una multiplicación de enteros de 32x32 bits firmada , el siguiente ejemplo en software.intel.com parece que debería hacer lo que desea:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
__m128i tmp1 = _mm_mul_epu32(a,b); /* mul 2,0*/
__m128i tmp2 = _mm_mul_epu32( _mm_srli_si128(a,4), _mm_srli_si128(b,4)); /* mul 3,1 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
}
Es posible que desee tener dos compilaciones, una para CPU antiguas y otra para CPU recientes, en cuyo caso podría hacer lo siguiente:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
#ifdef __SSE4_1__ // modern CPU - use SSE 4.1
return _mm_mullo_epi32(a, b);
#else // old CPU - use SSE 2
__m128i tmp1 = _mm_mul_epu32(a,b); /* mul 2,0*/
__m128i tmp2 = _mm_mul_epu32( _mm_srli_si128(a,4), _mm_srli_si128(b,4)); /* mul 3,1 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
#endif
}
PMULLD , de SSE 4.1, hace eso.
La descripción es un poco engañosa, habla sobre la multiplicación con signos, pero como solo almacena los 32 bits más bajos, es realmente una instrucción que no tiene en cuenta los signos que puede usar para ambos, al igual que IMUL
.