IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

[MMX/SSE] Opération de type MAC non présente


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut [MMX/SSE] Opération de type MAC non présente
    Bonjour tout le monde !
    J'essaie d'implémenter un filtre de type FIR avec les instructions SIMD SSE2 de Intel. Le problème que je rencontre est l'abscence d'une instruction MAC, afin de multiplier ET accumuler tous les entiers (packed 32 bits dans mon cas). Il existe PMADDWD, mais elle n'accumule que partiellement (les deux 32 bits low dans un 64 bits, et les deux autres dans la partie haute), et j'ai besoin de tout additionner...
    Voici le code générique utilisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for( i = 3; i < width-3; i++ )
        {      
          x16 = px[i]&0x0f;
          x = px[i]>>4;
          Tmp1dBuffer[i] = Src[x-1]*pfilter[4*x16];
          Tmp1dBuffer[i] += Src[x]*pfilter[4*x16 + 1];
          Tmp1dBuffer[i] += Src[x+1]*pfilter[4*x16 + 2];
          Tmp1dBuffer[i] += Src[x+2]*pfilter[4*x16 + 3];
        }
    Les coefficients du filtre varient en fonction d'une position (px[i]) calculée à chaque itération.

    Merci d'avance de votre aide !
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  2. #2
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Salut,

    salut peut-être en faisant une multiplication terme à terme (style PMULHW pour multiplier des words) puis ensuite faire la somme des termes d'un même registre via PHADDSW (somme horizontale des termes d'un même registre).

    Ou un truc dans le genre.

    A noter que je ne l'ai jamais utilisé ...

    Flo.

  3. #3
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    OK, comment fais-tu, quand tu as un filtre ?
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  4. #4
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    De quel type sont Src et pfilter ? Et quelles sont leurs intervalles de valeurs (du moins pour le résultat Tmp1dBuffer) ?

    Flo.

  5. #5
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    Aujourd'hui, Src est de type short (16-bits) et pfilter de type char (8-bits). L'intervalle de valeur, en revanche, je ne l'ai pas cherché, mais en prenant les extrèmes, on doit pouvoir s'en sortir...
    Le buffer est déclaré int (32-bits donc), et je pense que c'est bon.
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  6. #6
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    T'es avec quoi comme compilo asm "AT&T" ou "Intel" ? (histoire de lire les opérandes dans le même sens)

    Flo.

  7. #7
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    Je suis avec GCC et avec Visual C++ (ça doit être compatible). Dans ma tête je préfère Intel, et je crois pouvoir écrire sous forme intel avec les deux. Sinon, j'utilise les intrinsèques, et je vérifie que le code généré est le bon (ce qui est très souvent le cas).
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  8. #8
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Bon, alors je te le fais en At&T (GCC)

    A noter que ça fait un bail que j'ai pas écrit en ASM alors doucement sur la critique si mon truc bat de l'aile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    "movq	     (%0)    , %%xmm0	\n" // tu charges 8 bytes de pfilter dans xmm0
    "pxor         %%xmm7 , %%xmm7   \n" // tu nettoie xmm7 à 0
    "punpcklbw    %%xmm7 , %%xmm0   \n" // tu convertis tes 8 bytes en 8 words
     
    "movdqu	     (%1)    , %%xmm1	\n" // tu charges 8 words de Src dans xmm1
     
    "pmulhuw      %%xmm1 , %%xmm0	\n" // multiplication termes à termes de xmm1 et xmm0 => résultat dans xmm0
    				    // xmm0[0] = Src[x-1]*pfilter[4*x16 + 0]
    				    // xmm0[1] = Src[x+0]*pfilter[4*x16 + 1]
    				    // xmm0[2] = Src[x+1]*pfilter[4*x16 + 2]
    				    // xmm0[3] = Src[x+2]*pfilter[4*x16 + 3]
    				    // ... le reste on s'en fout
     
    "phaddsw      %%xmm7 , %%xmm0	\n" // xmm0[0] = xmm0[0] + xmm0[1] = Src[x-1]*pfilter[4*x16 + 0] + Src[x+0]*pfilter[4*x16 + 1];
    				    // xmm0[1] = xmm0[2] + xmm0[3] = Src[x+1]*pfilter[4*x16 + 2] + Src[x+2]*pfilter[4*x16 + 3];
    				    // ... le reste on s'en fout	
     
    "phaddsw      %%xmm7 , %%xmm0	\n" // xmm0[0] = xmm0[0] + xmm0[1] = Src[x-1]*pfilter[4*x16 + 0] + Src[x+0]*pfilter[4*x16 + 1]
    				    // 			           + Src[x+1]*pfilter[4*x16 + 2] + Src[x+2]*pfilter[4*x16 + 3];
    				    // ... le reste on s'en fout
    Au final, je me demande si c'est correct ce que j'ai écrit ... Il doit y avoir mieux pour faire une simple opération comme celle-là.

    PS : Au fait, c'est pas avec toi qu'on avait fait le truc des VHS ? Si c'est le cas je constate avec plaisir que tu t'es mis aux SIMD ... Bienvenu au club

    N'hésite pas à me relancer sur ce bout de code si ça ne te convient pas.

    A noter enfin qu'il faut souvent modifier sa façon de voir les choses en MMX pour utiliser correctement les instructions et écrire un code le plus abouti possible. Interroge-toi si tu ne te colles pas trop à une écriture trop "horizontale".

    Flo.

  9. #9
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    L'opération d'addition horizontale n'apparait que dans SSSE3 !
    Sinon, ok pour le principe...

    A noter enfin qu'il faut souvent sa façon de voir les choses en MMX pour utiliser correctement les instructions et écrire un code le plus abouti possible. Interroge-toi si tu ne te colles pas trop à une écriture trop "horizontale".
    Qu'as-tu voulu dire ?
    Comment as-tu appris à programmer en MMX/SSE ?
    Je le fais un peu à l'arrache de mon côté...

    Et oui, c'est bien moi la VHS .
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  10. #10
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Ben peut-être que, au lieu de regarder ton code comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for( i = 3; i < width-3; i++ )
        {      
          x16 = px[i]&0x0f;
          x = px[i]>>4;
          Tmp1dBuffer[i] = Src[x-1]*pfilter[4*x16];
          Tmp1dBuffer[i] += Src[x]*pfilter[4*x16 + 1];
          Tmp1dBuffer[i] += Src[x+1]*pfilter[4*x16 + 2];
          Tmp1dBuffer[i] += Src[x+2]*pfilter[4*x16 + 3];
        }
    mais plutôt comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    for( i = 3; i < width-3; i += 4 )
        {      
          x16 = px[i]&0x0f;
          x = px[i]>>4;
     
          Tmp1dBuffer[i + 0] = Src[0][x - 1] * pfilter[0][4 * x16 + 0];
          Tmp1dBuffer[i + 1] = Src[1][x - 1] * pfilter[1][4 * x16 + 0];
          Tmp1dBuffer[i + 2] = Src[2][x - 1] * pfilter[2][4 * x16 + 0];
          Tmp1dBuffer[i + 3] = Src[3][x - 1] * pfilter[3][4 * x16 + 0];
     
          Tmp1dBuffer[i + 0] += Src[0][x + 1] * pfilter[0][4 * x16 + 1];
          Tmp1dBuffer[i + 1] += Src[1][x + 1] * pfilter[1][4 * x16 + 1];
          Tmp1dBuffer[i + 2] += Src[2][x + 1] * pfilter[2][4 * x16 + 1];
          Tmp1dBuffer[i + 3] += Src[3][x + 1] * pfilter[3][4 * x16 + 1];
     
          Tmp1dBuffer[i + 0] += Src[0][x + 2] * pfilter[0][4 * x16 + 2];
          Tmp1dBuffer[i + 1] += Src[1][x + 2] * pfilter[1][4 * x16 + 2];
          Tmp1dBuffer[i + 2] += Src[2][x + 2] * pfilter[2][4 * x16 + 2];
          Tmp1dBuffer[i + 3] += Src[3][x + 2] * pfilter[3][4 * x16 + 2];
     
          Tmp1dBuffer[i + 0] += Src[0][x + 3] * pfilter[0][4 * x16 + 3];
          Tmp1dBuffer[i + 1] += Src[1][x + 3] * pfilter[1][4 * x16 + 3];
          Tmp1dBuffer[i + 2] += Src[2][x + 3] * pfilter[2][4 * x16 + 3];
          Tmp1dBuffer[i + 3] += Src[3][x + 3] * pfilter[3][4 * x16 + 3];
        }
    ça serait plus facile à transcrire en MMX (en XMMX tu en fais 4 de plus par boucle).

    Tu peux utiliser tes opérations classiques termes à termes.

    mm0[0] = pfilter[0][4 * x16 + 0]
    mm0[1] = pfilter[1][4 * x16 + 0]
    mm0[2] = pfilter[2][4 * x16 + 0]
    mm0[3] = pfilter[3][4 * x16 + 0]

    mm1[0] = pfilter[0][4 * x16 + 1]
    mm1[1] = pfilter[1][4 * x16 + 1]
    mm1[2] = pfilter[2][4 * x16 + 1]
    mm1[3] = pfilter[3][4 * x16 + 1]

    et etc pour mm2 et mm3

    mm4[0] = Src[0][x - 1]
    mm4[1] = Src[1][x - 1]
    mm4[2] = Src[2][x - 1]
    mm4[3] = Src[3][x - 1]

    mm5[0] = Src[0][x + 0]
    mm5[1] = Src[1][x + 0]
    mm5[2] = Src[2][x + 0]
    mm5[3] = Src[3][x + 0]

    et etc pour mm6 et mm7

    puis
    mm1 = mm0 * mm1
    mm2 = mm2 * mm3
    mm3 = mm3 * mm4
    mm4 = mm4 * mm5
    mm1 = mm1 + mm2
    mm3 = mm3 + mm4
    mm1 = mm1 + mm3

    Flo.

Discussions similaires

  1. [TP] Constantes typées et non typées, variables
    Par poppels dans le forum Turbo Pascal
    Réponses: 3
    Dernier message: 26/10/2005, 23h00
  2. Champ de type oui/non
    Par dl_jarod dans le forum ASP
    Réponses: 4
    Dernier message: 13/10/2005, 16h03
  3. Réponses: 1
    Dernier message: 07/10/2005, 10h44
  4. MMX/SSE
    Par dickymoe dans le forum C++
    Réponses: 10
    Dernier message: 27/09/2005, 14h24
  5. [access][sql] commen inserer un champ du type oui/non
    Par cmoa59 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 28/04/2005, 11h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo