2016-03-11 2 views
3

Je travaille sur SSE et un débutant ici. Je suis en train d'utiliser l'instruction shuffle pour mélanger un vecteur 16 bits comme ci-dessous:Shuffle vecteurs 16 bits SSE

Entrée:

1 2 3 4 5 6 7 8 

Sortie:

1 5 2 6 3 7 4 8 

Comment puis-je atteindre l'objectif désiré? Je suis confus au sujet de la constante étant utilisé ici et je ne vois aucune instruction shuffle 16 bits. L'instruction shuffle n'est disponible que pour les bits 8 et 32 ​​bits.

+1

_ pense « Je ne vois aucune instruction de lecture aléatoire de 16 bits » _ Il y a 'PSHUFHW' /' PSHUFLW', mais je ne peuvent faire ce que vous essayez de fais ici. – Michael

+0

Vous pouvez toujours utiliser un shuffle de plus petite granularité. Si le contrôle shuffle n'est pas une constante de compilation, il peut être fastidieux de transformer un vecteur d'indices de mots en un vecteur d'indices d'octets. AVX512 résout ce problème en fournissant des shuffles de variables transversales complètes avec les granularités byte, word, dword et qword. (vpermb/vpermw/vpermd/vpermq Le guide intrinsèques manque '_mm512_permutexvar_epi16' (nvm, il n'est simplement pas marqué comme un" swizzle ")) Il y a même des shuffles de contrôle de variable à 2 sources, donc vous pouvez avoir un 512b vecteur de sélection octets/mots/dwords/qwords de 2 autres vecteurs 512b! –

+0

Donc, fondamentalement, écrire du code qui doit être mélangé va être génial ... dans peut-être 10 ans quand on peut parfois abandonner la vectorisation pour les processeurs sans AVX512. –

Répondre

4

Tant que vous pouvez supposer SSSE3 vous pouvez utiliser pshufb aka _mm_shuffle_epi8:

#include <stdio.h> 
#include <tmmintrin.h> // SSSE3 

int main() 
{ 
    __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); 
    __m128i v_perm = _mm_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15); 
    __m128i v_out = _mm_shuffle_epi8(v_in, v_perm); // pshufb 
    printf("v_in = %vhd\n", v_in); 
    printf("v_out = %vhd\n", v_out); 
    return 0; 
} 

Compilez et exécutez:

$ gcc -Wall -mssse3 green_goblin.c 
$ ./a.out 
v_in = 1 2 3 4 5 6 7 8 
v_out = 1 5 2 6 3 7 4 8 

Autre solution qui ne repose que sur SSE2:

#include <stdio.h> 
#include <emmintrin.h> // SSE2 

int main() 
{ 
    __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); 
    __m128i v_out = _mm_shuffle_epi32(v_in, _MM_SHUFFLE(3, 1, 2, 0)); // pshufd 
    v_out = _mm_shufflelo_epi16(v_out, _MM_SHUFFLE(3, 1, 2, 0));  // pshuflw 
    v_out = _mm_shufflehi_epi16(v_out, _MM_SHUFFLE(3, 1, 2, 0));  // pshufhw 
    printf("v_in = %vhd\n", v_in); 
    printf("v_out = %vhd\n", v_out); 
    return 0; 
} 

Compilez et exécutez:

$ gcc -Wall -msse2 green_goblin_sse2.c 
$ ./a.out 
v_in = 1 2 3 4 5 6 7 8 
v_out = 1 5 2 6 3 7 4 8 
+2

#! ¤52 # ¤ASDFWERTøøøøåååå! J'étais sur le point de coller exactement ta réponse et tu m'as encore battu! –

+0

Je me demande comment ces constantes peuvent être déterminées? –

+2

@BharatAhuja, c'est facile l'index court utilise l'index des octets 2 * i et 2 * i + 1. Par exemple. l'index court 3 devient l'index 6 et 7. –