2012-05-17 8 views
6

I haben sehr langen Byte-Arrays, die short (oder int) zu einer Ziel-Array vom Typ hinzugefügt werden müssen. Gibt es einen solchen SSE-Befehl? Oder vielleicht ihr Set?SSE-Befehle: Byte + Short

Antwort

6

Sie müssen jeden Vektor der 8-Bit-Werte in zwei Vektoren mit 16-Bit-Werten entpacken und dann hinzufügen.

__m128i v = _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); 
__m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); // vl = { 7, 6, 5, 4, 3, 2, 1, 0 } 
__m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); // vh = { 15, 14, 13, 12, 11, 10, 9, 8 } 

wo v ist ein Vektor von 16 x 8-Bit-Werte und vl, sind die beiden vh entpackten Vektoren von 8 x 16-Bit-Werte.

Beachten Sie, dass ich davon ausgehe, dass die 8-Bit-Werte unsigned sind, so dass beim Entpacken auf 16 Bits das High-Byte auf 0 gesetzt wird (d. H. Keine Vorzeichenerweiterung).

Wenn Sie viele dieser Vektoren summieren und ein 32-Bit-Ergebnis erhalten möchten, dann ist ein nützlicher Trick, _mm_madd_epi16 mit einem Multiplikator von 1, z.

__m128i vsuml = _mm_set1_epi32(0); 
__m128i vsumh = _mm_set1_epi32(0); 
__m128i vsum; 
int sum; 

for (int i = 0; i < N; i += 16) 
{ 
    __m128i v = _mm_load_si128(&x[i]); 
    __m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); 
    __m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); 
    vsuml = _mm_add_epi32(vsuml, _mm_madd_epi16(vl, _mm_set1_epi16(1))); 
    vsumh = _mm_add_epi32(vsumh, _mm_madd_epi16(vh, _mm_set1_epi16(1))); 
} 
// do horizontal sum of 4 partial sums and store in scalar int 
vsum = _mm_add_epi32(vsuml, vsumh); 
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 8)); 
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4)); 
sum = _mm_cvtsi128_si32(vsum); 
+1

Verzeihen Sie meine Ignoranz aber sind Sie sicher, dass das richtig ist? Dies ist vsum = _mm_madd_epi16 (vh, _mm_set1_epi16 (1)); würde den vorherigen Wert von vsum löschen. – Alexandros

+0

@Alexandros: Du hast Recht, und ich sehe mindestens einen weiteren Fehler drin - ich denke, ich muss es eilig gehabt haben, als ich diese Antwort geschrieben habe - ich werde den Code bald reparieren, aber ich reise weiter Geschenk. –

+1

Danke Paul, keine Eile. Sie haben mir in der Vergangenheit sehr geholfen, also reparieren Sie es, wann immer Sie können. Gute Reise!! – Alexandros

0

Wenn Sie Ihre Byte-Vektoren statt auf Vorzeichen erweitern müssen Null erweitern, verwenden pmovsxbw (_mm_cvtepi8_epi16). Im Gegensatz zu den Entpackungs-Hi/Lo-Anweisungen können Sie nur pmovsx aus der unteren Hälfte/Viertel/Achtel eines Src-Registers.

Sie können Pmovsx direkt aus dem Speicher obwohl, obwohl intrinsics machen dies wirklich ungeschickt. Da der Shuffle-Durchsatz bei den meisten CPUs begrenzter ist als der Ladedurchsatz, ist es wahrscheinlich vorzuziehen, zwei Lade- und Pmovsx-Vorgänge durchzuführen, als einen Ladevorgang und drei Shuffle-Vorgänge durchzuführen.