2013-07-25 14 views
6

Come moltiplicare due numeri interi a 64 bit da altri 2 numeri interi a 64 bit? Non ho trovato alcuna istruzione che possa farlo.SSE moltiplicazione di 2 interi a 64 bit

+0

Cosa significa "due numeri interi a 64 bit" in questo contesto? Intendi una coppia di numeri interi a 64 bit (numeri complessi) o un singolo intero a 128 bit rappresentato come una coppia di numeri interi a 64 bit? –

+0

Voglio dire un singolo intero di m128i singolo rappresentato come una coppia di numeri interi a 64 bit –

+1

Possibile duplicato di [questa domanda] (http://stackoverflow.com/questions/12200698/is-it-possibile-a-usare-sse-v2 -to-make-a-128-bit-intero-intero), quindi. –

risposta

3

È necessario implementare la propria routine di moltiplicazione a 64 bit utilizzando le operazioni di moltiplicazione a 32 bit. Probabilmente non sarà più efficiente del semplice fare questo con il codice scalare, soprattutto perché ci sarà un sacco di mischiare i vettori per ottenere tutte le operazioni necessarie.

+0

Dalla parte superiore della mia testa, non c'era un 'pmuldqq' o qualcosa in SSE4 aggiunto? – hirschhornsalz

+0

C'è un 'pmuldq' in SSE4 che è un multiplo 32x32 => 64 bit, quindi è possibile utilizzarlo come elemento di base per una moltiplicazione di 64x64 bit. –

+0

Conosci l'algoritmo scalare migliore per questo (supponendo che tu abbia solo hardware a 32 bit)? Questo è quello che farei. Dividerei ogni numero nella sua parte superiore e inferiore a 32 bit e poi fare (a * b) = (al + ah) * (bl * bh) = t1 + t2 + t3 + t4 dove t1 = al * bl, t2 = al * bh, t3 = ah * bl t4 = ah * bh. Ogni termine sarebbe un numero a 64 bit. Quindi t2 e t3 dovrebbero essere nuovamente suddivisi in basso e alto e il numero finale sarebbe (a * b) l = t1 + t2l + t3l, (a * b) h = t4 + t2h + t3h + c, dove c è qualsiasi trasporto da (a * b) l. Sono 4 mults e 7 aggiunge. È da qualche parte su SO? –

4

So che questa è una domanda vecchia ma in realtà stavo cercando esattamente questo. Dato che non ci sono ancora istruzioni per farlo, ho implementato il 64 bit per moltiplicare me stesso con il pmuldq come menzionato da Paul R. Questo è quello che è venuto fuori con

__m128i Multiply64Bit(__m128i a, __m128i b) 
{ 
    auto ax0_ax1_ay0_ay1 = a; 
    auto bx0_bx1_by0_by1 = b; 

    // i means ignored 

    auto ax1_i_ay1_i = _mm_shuffle_epi32(ax0_ax1_ay0_ay1, _MM_SHUFFLE(3, 3, 1, 1)); 
    auto bx1_i_by1_i = _mm_shuffle_epi32(bx0_bx1_by0_by1, _MM_SHUFFLE(3, 3, 1, 1)); 

    auto ax0bx0_ay0by0 = _mm_mul_epi32(ax0_ax1_ay0_ay1, bx0_bx1_by0_by1); 
    auto ax0bx1_ay0by1 = _mm_mul_epi32(ax0_ax1_ay0_ay1, bx1_i_by1_i); 
    auto ax1bx0_ay1by0 = _mm_mul_epi32(ax1_i_ay1_i, bx0_bx1_by0_by1); 

    auto ax0bx1_ay0by1_32 = _mm_slli_epi64(ax0bx1_ay0by1, 32); 
    auto ax1bx0_ay1by0_32 = _mm_slli_epi64(ax1bx0_ay1by0, 32); 

    return _mm_add_epi64(ax0bx0_ay0by0, _mm_add_epi64(ax0bx1_ay0by1_32, ax1bx0_ay1by0_32)); 
} 
+2

Avete fatto qualche benchmarking del codice rispetto all'uso dei registri di uso generale per questo? Sarei interessato ai risultati visto che sto facendo un sacco di 64 moltiplicazioni a 64 bit. – jeteon

+0

Ho appena fatto un benchmarking, è ancora più veloce della moltiplicazione scalare (compilata con cl/O2). Circa 831600000 moltiplicazioni in media. 0,37 secondi sul mio potentissimo i7 5820k. Nel frattempo le stesse moltiplicazioni scalari hanno preso 1,71 su avg. quindi è circa 4 volte più veloce, il che è un po 'strano. Immagino che cl sia davvero bravo nell'ottimizzare le istruzioni superscalari – JukesOnYou

Problemi correlati