VENDREDI 07 MAI 2010
PSHUFB pour une conversion RGB / Niveaux de gris

Récemment, j'ai découvert l'instruction PSHUFB (Packed Shuffle Bytes) qui se trouve dans le 4ième jeu d'instruction SSE qui s'appelle SSSE3 (Supplemental Streaming SIMD Extension 3). On trouve un petit blabla à ce sujet sur Wikipedia.

Cela faisait déjà quelques années, que de temps en temps, j'essayais de me faire une conversion RGB/Niveaux de gris en xmmx sans y arriver efficacement pour cause d'instructions peu intéressantes pour le faire. Il est possible que je m'y prenais mal aussi. L'instruction PSHUFB permet désormais une conversion d'une image RGB en niveaux de gris 5 pixels par 5 pixels soit au moins 5 fois plus vite qu'en C/C++ traditionnel.

Par rapport aux instructions PSHUFW (SSE) et PSHUFLW / PSHUFHW / PSHUFD (SSE2), l'adressage des octets à remanier se fait différemment.

Pour chacune de ces 4 instructions (PSHUFW / PSHUFLW / PSHUFHW / PSHUFD), il y a 3 opérandes SRC, DST et un octet ORDER. L'octet ORDER permet de coder l'adresse des octets à copier de SRC vers DST. Les adresses, dans l'octet ORDER, sont codées par paire de bits. Par exemple, si la valeur de l'octet ORDER est de 141, 10001101 en binaire, alors les opérations suivantes seront effectuéees :


DST[0] = SRC [1] car les bits n°0 (1) et n°1 (0) de ORDER codent 1
DST[1] = SRC [3] car les bits n°2 (1) et n°3 (1)
de ORDER codent 3
DST[2] = SRC [0] car les bits n°4 (0) et n°5 (0)
de ORDER codent 0
DST[3] = SRC [2] car les bits n°6 (0) et n°7 (1)
de ORDER codent 2

A noter également que l'instruction PSHUFW ne fonctionne que sur les registres MMX 64 bits. Les instructions PSHUFLW et PSHUFHW fonctionnent uniquement sur 8 octets, respectivement le QUAD WORD de poids faible et le QUAD WORD de poids fort. Ces 2 instructions là permettent de faire un simili PSHUFW sur des registres XMMX 128 bits. En fait, les 4 instructions PSHUFW (SSE) et PSHUFLW / PSHUFHW / PSHUFD (SSE2) ne permettent de manipuler que 4 données 16 bits (WORD) ou 32 bits (DOUBLE WORD) à la fois et uniquement à l'intérieur d'un 64 bits (QUAD WORD).

Rien qu'en ça l'instruction PSHUFB est une révolution. On peut directement manipuler les 16 octets d'un registre 128 bits et les redisposer n'importe où dans le registre 128 bits de destination.

Différence appréciable également : ce n'est pas un octet ORDER qui définit la manipulation mais directement un registre 128 bits (le registre source). PSHUFB n'a que 2 opérandes. Ce registre source charge 16 bytes signés, un byte négatif permettant d'affecter à l'octet de destination associé un 0. On remarquera que PSHUFB donne la possibilité de faire l'équivalent d'un PSHUFW pour des registres 128 bits.

Un exemple d'utilisation, en syntaxe Intel :


vector addresses(16)
addresses[ 0] = 4;    // code l'opération DST[ 0] = SRC[ 4]
addresses[ 1] = 12;   // code l'opération DST[ 1] = SRC[12]
addresses[ 2] = -1;   // code l'opération DST[ 2] = 0
...
addresses[15] = 15;   // code l'opération DST[15] = SRC[15]

char * ptr = &addresses[0];
__asm  mov      eax, ptr   ;    
__asm  movdqu  xmm0, [eax] ; // chargement des adresses dans xmm0
__asm  pshufb  xmm1, xmm0  ; // manipulation de xmm1 par xmm0

 

Concernant, la conversion RGB en niveaux de gris, le code commenté est disponible ici. Il s'agit d'un code C/C++/XMMX qui prend un buffer RGB 24 bits, démultiplexe les 3 plans R, G et B (démultiplexation en 16 bits par paresse) et calcule en 16 bits le produit R*Cr + G*Cg + B*Cb ensuite ramené à 8 bits. Les constantes Cr, Cg et Cb sont les coefficients de pondération des 3 composantes. Le code, à valeur de test, fonctionne uniquement sur 5 pixels RGB uniquement et n'est pas optimisé. Il s'agit là de tester l'instruction PSHUFB dans le cadre d'une conversion RGB - niveaux de gris.

Le résultat est le suivant ;


  RGB =   20  30  40  50  60  70  80  90 100 110 120 130 140 150 160 170 (données en entrée)
    R =   20   0  50   0  80   0 110   0 140   0 170   0   0   0   0   0
(données en sortie)
    G =   30   0  60   0  90   0 120   0 150   0   0   0   0   0   0   0 (données en sortie)
    B =   40   0  70   0 100   0 130   0 160   0   0   0   0   0   0   0 (données en sortie)
 grey =   29  59  89 119 149  56   0   0   0   0   0   0   0   0   0   0 (données en sortie)
 

Voilà quelques considérations qui sortent un peu de l'ordinaire ...


PUBLIE PAR FLORIAN A 19:01:11
Enregistré dans la ou les catégories xmmx 
0 commentaires / Poster un commentaire

Ajouter un commentaire

Titre du commentaire (facultatif)

Votre nom (obligatoire)

Votre email (facultatif et non publié)

Votre site web (facultatif)

Votre commentaire (obligatoire)



Changer le code

Taper le code ci-dessus (obligatoire)

Recopier le titre de ce billet (obligatoire)


   


FLORIAN SELLA

Bonjour je suis ingénieur en traitement d'images et j'aime bien dessiner à mes heures perdues. Vous trouverez donc sur ce blog des essais et réflexions sur ces 2 sujets. Bonne visite.


ARCHIVES DU BLOG

maths(1)
xmmx(1)
vision(1)



BLOGS

Blog tout confondu
Blog dessins
Blog traitement d'images
Blog divers


S'ABONNER

Fill RSS