2012-05-08 2 views

Répondre

23

Si vous avez besoin signé 32x32 multiplication entier bits alors l'exemple suivant à software.intel.com semble que cela devrait faire ce que vous voulez:

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 */ 
} 

Vous pouvez avoir deux builds - un pour les anciens processeurs et un pour les processeurs récents, auquel cas vous pouvez faire ce qui suit:

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 
} 
+3

Bonne réponse. Drôle, vous avez fait exactement la même faute de frappe que j'avais une fois dans mon code: Ça devrait être _____SSE4_1_____ (pas de soulignement entre E et 4). Gênant, parce que vous ne le remarquez pas facilement - le programme fonctionne parfaitement tant que le chemin du code alternatif est correct – hirschhornsalz

+1

@drhirsch: merci de corriger cela - en code réel j'ai tendance à utiliser '__MNI__',' __SNI__', etc - principalement pour des raisons historiques, mais il est aussi moins sujet à de simples erreurs comme celles ci-dessus. –

+1

Génial, merci! Maintenant, si seulement il y avait un truc similaire pour remplacer '_mm_insert_epi32' sur un CPU avec SSE2 seulement ... –

7

PMULLD, à partir de SSE 4.1, fait cela.

La description est légèrement trompeuse, elle parle de multiplication signée, mais comme elle ne stocke que les 32bits inférieurs, c'est vraiment une instruction insensible aux signes que vous pouvez utiliser pour les deux, tout comme IMUL.

+0

Merci. Mais existe-t-il un moyen d'utiliser uniquement des instructions SSE 2? – Yury

+2

'_mm_mullo_epi32' si vous préférez utiliser l'intrinsèque plutôt que l'assemblage brut –

+1

@Leviathan Oui, mais vous avez besoin de plusieurs instructions. Selon l'architecture, quatre 'imul' sont probablement plus rapides et plus simples. – hirschhornsalz

Questions connexes