SSE: Comment réduire un _m128i._i32 à _m128i._i8

Je suis très nouveau en SSE – codage: Et je veux stocker le résultat de _m128i [4] avec le type int32 dans un _m128i avec le type int8. (Les valeurs de _m128i [j] ._ i32 [k] sont toutes comsockets entre (-127 et + 127)

Je pense que dans le pseudo-code, ceci est le suivant:

result._i8 = { vec1._i8[0], vec1._i8[4], vec1._i8[8], vec1._i8[12], vec2._i8[0], vec2._i8[4], vec2._i8[8], vec2._i8[12], vec3._i8[0], vec3._i8[4], vec3._i8[8], vec3._i8[12], vec4._i8[0], vec4._i8[4], vec4._i8[8], vec4._i8[12]}; 

Le seul moyen que j’ai trouvé est ce mélange désordonné.

  __m128i mmResult, mmResult0_3, mmResult4_7, mmResult8_11, mmResult12_15; //some calculation ... __m128i mmShuffler0_3 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1,12, 8, 4, 0); __m128i mmShuffler4_7 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 12, 8, 4, 0, -1, -1, -1, -1); __m128i mmShuffler8_11 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1); __m128i mmShuffler12_15 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); mmResult0_3 = _mm_shuffle_epi8(mmResult0_3, mmShuffler0_3); mmResult4_7 = _mm_shuffle_epi8(mmResult4_7, mmShuffler4_7); mmResult8_11 = _mm_shuffle_epi8(mmResult8_11, mmShuffler8_11); mmResult12_15 = _mm_shuffle_epi8(mmResult12_15, mmShuffler12_15); mmResult = _mm_or_si128(_mm_or_si128(mmResult0_3, mmResult4_7), _mm_or_si128(mmResult8_11, mmResult12_15)); 

Y a-t-il un moyen de faire cela plus beau? Y a-t-il un moyen de faire cela plus vite?

Vous pouvez simplement utiliser des opérations d’empaquetage pour réduire vos valeurs 32 bits à 8 bits, par exemple en supposant que vous ayez 4 vecteurs d’éléments int 32 bits, v0v3 :

 __m128i v01 = _mm_packs_epi32(v0, v1); // pack v0, v1 to 16 bits __m128i v23 = _mm_packs_epi32(v2, v3); // pack v2, v3 to 16 bits __m128i v0123 = _mm_packs_epi16(v01, v23); // pack v0...v3 to 8 bits 

Exemple:

 #include  #include  int main(void) { __m128i v0 = _mm_setr_epi32(-8, -7, -6, -5); __m128i v1 = _mm_setr_epi32(-4, -3, -2, -1); __m128i v2 = _mm_setr_epi32( 0, 1, 2, 3); __m128i v3 = _mm_setr_epi32( 4, 5, 6, 7); printf("v0 = %vld\n", v0); printf("v1 = %vld\n", v1); printf("v2 = %vld\n", v2); printf("v3 = %vld\n", v3); __m128i v01 = _mm_packs_epi32(v0, v1); // pack v0, v1 to 16 bits __m128i v23 = _mm_packs_epi32(v2, v3); // pack v2, v3 to 16 bits __m128i v0123 = _mm_packs_epi16(v01, v23); // pack v0...v3 to 8 bits printf("v0123 = %vd\n", v01234); return 0; } 

Comstackr et tester:

 $ gcc -Wall pack_32_8.c && ./a.out v0 = -8 -7 -6 -5 v1 = -4 -3 -2 -1 v2 = 0 1 2 3 v3 = 4 5 6 7 v0123 = -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7