2012-05-17 16 views

Respuesta

6

Necesita descomprimir cada vector de valores de 8 bits en dos vectores de valores de 16 bits y luego agregarlos.

__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 } 

donde v es un vector de 16 x 8 valores de bit y vl, vh son los dos vectores sin envasar de valores de 8 x 16 bits.

Tenga en cuenta que supongo que los valores de 8 bits no están firmados, por lo que al desempaquetar en 16 bits, el byte alto se establece en 0 (es decir, sin extensión de signo).

Si desea sumar muchos de estos vectores y obtener un resultado de 32 bits, entonces un truco útil es usar _mm_madd_epi16 con un multiplicador de 1, p.

__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

Disculpe mi ignorancia, pero ¿está seguro de que es correcto? Este vsum = _mm_madd_epi16 (vh, _mm_set1_epi16 (1)); borraría el valor anterior de vsum. – Alexandros

+0

@Alexandros: tienes razón, y veo al menos otro error allí también. Creo que debo haber tenido prisa cuando escribí esta respuesta. Arreglaré el código pronto, pero viajaré a presente. –

+1

Gracias Paul, no tienes prisa. Me has ayudado mucho en el pasado, así que siempre que puedas, arréglenlo. ¡¡Ten un buen viaje!! – Alexandros

0

Si necesita inscribirse extender los vectores de bytes en lugar de cero a extender, utilice pmovsxbw (_mm_cvtepi8_epi16). A diferencia de las instrucciones para desempaquetar hi/lo, solo puede pmovsx desde la mitad baja/trimestre/octava de un registro src.

Puede pmovsx directamente desde la memoria, aunque los intrínsecos lo hacen realmente torpe. Como el procesamiento aleatorio es más limitado que el rendimiento de carga en la mayoría de las CPU, probablemente sea preferible hacer dos cargas + pmovsx que hacer una carga + tres mezclas.

Cuestiones relacionadas