Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3045 connectés 

  FORUM HardWare.fr
  Programmation
  ASM

  Optimisation en MMX/SSE - Besoin d'aide

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

Optimisation en MMX/SSE - Besoin d'aide

n°500449
Cyberpat92
Posté le 28-08-2003 à 12:48:24  profilanswer
 

Je travaille sur FairUse (logiciel "tout en un" de backup DVD)et j'ai besoin d'optimiser les fonctions de resizing de l'image en les réécrivant en ASM car c'est vraiment très lent en C++ mais je n'ai aucune pratique de ce language.
 
Est-ce que quelqu'un serait intéressé pour s'occuper de cette partie ?
 
Précision : c'est un projet open-source sous licence GPL.


Message édité par Cyberpat92 le 26-03-2004 à 13:06:54
mood
Publicité
Posté le 28-08-2003 à 12:48:24  profilanswer
 

n°500461
Cyberpat92
Posté le 28-08-2003 à 13:09:23  profilanswer
 

Au cas où, voici l'une des fonctions qui font goulot d'étranglement :
 
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])
{
    unsigned loop0, loop1;
 
    for(loop0 = 0; loop0 != n0 + n1 - 1; loop0++) {
        for(loop1 = 0, result[loop0] = 0; loop1 != n0; loop1++) {
            if(loop0 - loop1 < n1) {
                result[loop0] += arg0[loop1] * arg1[loop0 - loop1];
            }
        }
    }
}


Message édité par Cyberpat92 le 28-08-2003 à 13:10:55
n°500464
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-08-2003 à 13:16:23  profilanswer
 

Je m'en serais bien occupé mais j'ai pas trop le temps en ce moment :o
 
[:sisicaivrai] [:sisicaivrai]


---------------
J'ai un string dans l'array (Paris Hilton)
n°500468
Taz
bisounours-codeur
Posté le 28-08-2003 à 13:21:29  profilanswer
 

ben rien qu'au niveau de l'algo, tu peux le faire facilement sur tes boucles, en calculant plus précisément les bornes, puisque finalement tu executes ta boucle interieur tant que  
 
loop1 != n0 && loop0 - loop1 < n1
 
tu te calcules le minimum pour pas te taper 2 tests à chaque fois, et voilà, un test en moins
 

n°500478
Taz
bisounours-codeur
Posté le 28-08-2003 à 13:40:24  profilanswer
 

après ben fais un max de pré-calcul, et si ton CPU à des simd, ça peut etre l'occasion de derouler un peu cette boucle (faire 4 passes d'un coup)

n°500480
ACut
Posté le 28-08-2003 à 13:42:10  profilanswer
 

Compte tenu que:
- loop0 et loop1 sont unsigned
et que
- loop1 est l'incrément de la boucle intérieure
 
le bool (loop0 - loop1 < n1) n'est-il pas dangereux??
 
Edit: ortho!


Message édité par ACut le 28-08-2003 à 13:42:53

---------------
NOUVEAU! Le guide de l'édition en version ebook : http://marcautret.free.fr/autret/150q-ebook/
n°500484
Taz
bisounours-codeur
Posté le 28-08-2003 à 13:51:15  profilanswer
 

aussi, bien vu.

n°500551
bjone
Insert booze to continue
Posté le 28-08-2003 à 14:40:45  profilanswer
 

questions:
 
ta routine est-elle un traitement d'image ? (à priori oui)
dans ce cas, as-tu besoin d'avoir des flottants de type double ?
 
c'est quoi l'algorithme initial ?


Message édité par bjone le 28-08-2003 à 14:41:36
n°500566
Cyberpat92
Posté le 28-08-2003 à 14:53:39  profilanswer
 

Finalement, j'ai simplifié un peu :
 
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])
{
 memcpy(result, arg1, n0 + n1 - 1);
}
 
:whistle:
 
Edit: Finalement je suis revenu en arrière, car la perte de qualité était importante pour un gain de vitesse minime. :heink:


Message édité par Cyberpat92 le 07-09-2003 à 19:20:26
n°509581
Batman2003
Posté le 07-09-2003 à 15:13:02  profilanswer
 

cyberpat92 a écrit :

Finalement, j'ai simplifié un peu :
 
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])
{
 memcpy(result, arg1, n0 + n1 - 1);
}
 
:whistle:  


 
 [:aztechxx]

mood
Publicité
Posté le 07-09-2003 à 15:13:02  profilanswer
 

n°509584
Taz
bisounours-codeur
Posté le 07-09-2003 à 15:14:16  profilanswer
 

les paramètres inutiles c'est bien ...

n°509684
Cyberpat92
Posté le 07-09-2003 à 19:19:02  profilanswer
 

BJOne a écrit :

questions:
 
ta routine est-elle un traitement d'image ? (à priori oui)
dans ce cas, as-tu besoin d'avoir des flottants de type double ?
 
c'est quoi l'algorithme initial ?


 
Il s'agit de routines de redimensionnement d'image. Le source complet peut être trouvé sur http://fairuse.free.fr
 
Le problème c'est d'optimiser les fonctione de Resize.cpp

n°509686
Taz
bisounours-codeur
Posté le 07-09-2003 à 19:27:28  profilanswer
 

si tu déroulais un peu toutes ces boucles ça serait mieux (_Resize? et Resize

n°509711
os2
Posté le 07-09-2003 à 21:04:02  profilanswer
 

on a affaire à une fonctione en n^2
 
j'aimerais bien voir le gain en asm, je doute que ça va faire des miracles


---------------
Borland rulez: http://pages.infinit.net/borland
n°509893
slvn
Posté le 08-09-2003 à 00:05:42  profilanswer
 

faut que t utilise le DMA, pour transferer la memoire par packet.

n°509897
chrisbk
-
Posté le 08-09-2003 à 00:15:00  profilanswer
 

cyberpat92 a écrit :

Au cas où, voici l'une des fonctions qui font goulot d'étranglement :
 
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])
{
    unsigned loop0, loop1;
 
    for(loop0 = 0; loop0 != n0 + n1 - 1; loop0++) {
        for(loop1 = 0, result[loop0] = 0; loop1 != n0; loop1++) {
            if(loop0 - loop1 < n1) {
                result[loop0] += arg0[loop1] * arg1[loop0 - loop1];
            }
        }
    }
}
 


 
 
chui un peu perdu dans ton bordel moua....tes indices me laissent reveur
tu gagneras pas grand chose a passer a l'asm.
 

  • Vu que t'indice pas lineraire les MMX et consort te serviront a rien.  
  • de fait, Prefetch non plus
  • seul truc, si result est != des tab initiaux, ecrire dedans au movnt, peut etre que tu soulageras un peu ton cache. T'attends pas a des merveilles non plus, ca sera juste pour dire que t'as optim asm


 
 
 

n°509898
bjone
Insert booze to continue
Posté le 08-09-2003 à 00:44:20  profilanswer
 

j'ai toujours pas compris son algo (j'ai pas chercher trop non plus)
 
je devines que tu as une boucle ligne par ligne, puis pixel par pixel, avec une interpolation linéaire par pixel...
 
mais le truc est tellement mal tourné, et l'utilité des double me laisse perplexe à la base....


Message édité par bjone le 08-09-2003 à 00:44:34
n°509899
bjone
Insert booze to continue
Posté le 08-09-2003 à 00:47:52  profilanswer
 

je pense qu'il y a justement énormément à gagner en asm (ou en mmx/sse), c'est le genre de truc ciblé par le simd.
 
mais vu l'écriture de base, pour qu'il puisse l'optimiser en asm, va y a avoir du boulot (alors que c'est une routine qui semble assez classique)

n°509973
chrisbk
-
Posté le 08-09-2003 à 10:12:31  profilanswer
 

ben pour mmx & cie ca depend de comment il indice son bordel et je dois dire que son fatras dans la declaration de ses boucles me fait perdre le fil....

n°510001
Joel F
Real men use unique_ptr
Posté le 08-09-2003 à 10:46:42  profilanswer
 

ca doit pouvoir se lineariser (quite a calculer des trucs pour rien).
 
D'ailleurs tu boss sur PC (MMX & cie ) ou sur MAC (AltiVec).
Si c sur Mac je dois pouvoir te pondre une version Altivec rapidement.


Message édité par Joel F le 08-09-2003 à 10:47:33
n°510035
Carbon_14
Posté le 08-09-2003 à 11:25:20  profilanswer
 

n0 est l'indice maxi de arg0[], et n1 celui de arg1[] semblerait-il.
Le type double est obligatoire ? Ca correspond à des niveaux ? Ca irait ss dte plus vite en long si "normalisation" préalable  possible.
 
En ayant une variable locale "Resulta" qui cumule les += puis resul[loop0] = Resulta; en fin de for(loop1..) ça ferait ss dte rien gagner (en QuicBasic :whistle: ça m'a fait gagner un peu sur un prog, mais compilo pas optimiseur, antiquité !).
 
EDIT :  
si on regarde
       for(loop1 = 0; loop1 < n0; loop1++)  
       {  
           if(loop0 - loop1 < n1)  
           {  
               result[loop0] += arg0[loop1] * arg1[loop0 - loop1];  
           }  
       }  
 
le test if(loop0 - loop1 < n1) revient à if (loop0 - n1 < loop1) donc loop1 peut déjà partir de (loop0 - n1 + 1) si non nul ce qui évitera le test à chaque tour (juste un au début pour déterminer les bornes et faisabilité).
 
EDIT 2 :
Ca ferait qq chose comme  
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])  
{  
   unsigned loop0, loop1;
   int      ind1, ind2;  
 
   for (loop0 = 0; loop0 < n0 + n1 - 1; loop0 ++)  
   {  
       result[loop0] = 0;
       ind1 = loop0 - n1 + 1;
       ind2 = n0;
       if (ind1 < ind2) // voir si inclusif ou exclusif, pas très réveillé
       {
         for (loop1 = ind1; loop1 < ind2; loop1 ++)  
         {  
           result[loop0] += arg0[loop1] * arg1[loop0 - loop1];  
         }  
       }  
   }  
}
 
EDIT 3 :
Si ind1 ne peut pas être négatif, loop0 - n1 + 1 >=0 donc RAZ des result[i] avec i = 0 à loop0 - n1 puis calcul des suivants avec for (loop0 = n1 - 1; loop0 < n0 + n1 - 1; loop0 ++)  
(à voir ds le détail, c'est mon dernier jour de ma semaine de congés :pt1cable:). Si on ne s'intéresse qu'aux points utiles, ça devrait accélérer le traîtement.
 
void ResizePlane::_FilterConvolve(double arg0[], unsigned n0, double arg1[], unsigned n1, double result[])  
{  
   unsigned loop0, loop1;
   
   if (n1 > 1)
   {
     for (loop0 = 0; loop0 < n1 - 1; loop0 ++)  
     {  
       result[loop0] = 0.0;
     }
   }
   for (loop0 = n1 - 1; loop0 < n0 + n1 - 1; loop0 ++)  
   {  
       result[loop0] = 0.0;
       for (loop1 = loop0 - n1 + 1; loop1 < n0; loop1 ++)  
       {  
         result[loop0] += arg0[loop1] * arg1[loop0 - loop1];  
       }  
   }  
}
A VERIFIER...


Message édité par Carbon_14 le 08-09-2003 à 12:00:34
n°513814
Cyberpat92
Posté le 13-09-2003 à 03:52:24  profilanswer
 

Merci de ces réponses et pistes :)
 
...mais après une nuit blanche de plus sur ce p..... de code, j'ai fini par réaliser que la fonction précédemment citée n'est appelée que 4 fois pour un encodage (à l'initialisation en fait) [:atog]
 
Par contre, le "vrai" goulot d'étranglement est là, et j'ai bien peur que ce soit cuit, car je ne vois pas comment optimiser une multiplication :cry:
 
Au fait, il s'agit d'un développement pour PC. Est-ce que le MMX pourraît apporter quelque chose ?
 
void ResizePlane::_ResizeX(const unsigned char *src, unsigned char *dst)
{
 const unsigned char *ptr;
 int     *filter, total;
 unsigned   loop0, loop1, length;
 
 for(loop0 = 0, filter = _filterX; loop0 != _dstDim.x; loop0++) {
  ptr = src + *filter++;
  length = *filter++;
  //for(loop1 = 0, total = 1 << 15; loop1 != length; loop1++) {
  for(loop1 = 0, total = 0x8000; loop1 != length; loop1++) {
   total += *ptr++ * *filter++; // <== ça c'est très lent
  }
  *dst++ = _clip1[total >> 16];
 }
}
 
void ResizePlane::_ResizeY(const unsigned char *src, unsigned srcStep, unsigned char *dst, unsigned dstStep)
{
 const unsigned char *ptr;
 int     *filter, total;
 unsigned   loop0, loop1, length;
 
 for(loop0 = 0, filter = _filterY; loop0 != _dstDim.y; loop0++, dst += dstStep) {
  ptr = src + *filter++ * srcStep;
  length = *filter++;
  //for(loop1 = 0, total = 1 << 15; loop1 != length; loop1++, ptr += srcStep) {
  for(loop1 = 0, total = 0x8000; loop1 != length; loop1++, ptr += srcStep) {
   total += *ptr * *filter++; // <== ça c'est très lent
  }
  *dst = _clip1[total >> 16];
 }
}
 
EDIT : Pour être tout à fait complet, je rajoute la fonction qui appelle les deux précédemment citées :
 
void ResizePlane::Resize(const unsigned char *src, unsigned char *dst)
{
 unsigned loop0;
 
 if(_empty == false) {
  if(_xFirst) {
   for(loop0 = 0; loop0 != _footprint.dim.y; loop0++) {
    _ResizeX(src + (_footprint.pos.y + loop0) * _srcDim.x, _temp + loop0 * _dstDim.x);
   }
   for(loop0 = 0; loop0 != _dstDim.x; loop0++) {
    _ResizeY(_temp + loop0, _dstDim.x, dst + loop0, _dstDim.x);
   }
  } else {
   for(loop0 = 0; loop0 != _footprint.dim.x; loop0++) {
    _ResizeY(src + _footprint.pos.x + loop0, _srcDim.x, _temp + loop0, _footprint.dim.x);
   }
   for(loop0 = 0; loop0 != _dstDim.y; loop0++) {
    _ResizeX(_temp + loop0 * _footprint.dim.x, dst + loop0 * _dstDim.x);
   }
  }
 }
}


Message édité par Cyberpat92 le 13-09-2003 à 03:55:44
n°513825
Taz
bisounours-codeur
Posté le 13-09-2003 à 08:05:15  profilanswer
 

par contre dérouler les boucles ça te dit rien  :pfff:

n°513836
Joel F
Real men use unique_ptr
Posté le 13-09-2003 à 08:58:13  profilanswer
 

Taz a raison. Déroule de 4 ou 8, ca devrait te faire gagner qqs facteurs de vitesse (2 a 3 typiquement)

n°513905
Cyberpat92
Posté le 13-09-2003 à 12:13:56  profilanswer
 

vu. Je connaissais pas le "déroulage" de boucles, mais effectivement ca parait logique.
 
MErci, je vais essayer ca :)

n°514045
os2
Posté le 13-09-2003 à 17:50:58  profilanswer
 

Joel F a écrit :

ca doit pouvoir se lineariser (quite a calculer des trucs pour rien).
 
D'ailleurs tu boss sur PC (MMX & cie ) ou sur MAC (AltiVec).
Si c sur Mac je dois pouvoir te pondre une version Altivec rapidement.


 
ça serait pas mal de pouvoir comparer la version asm avec alvitec et une autre avec mmx...


---------------
Borland rulez: http://pages.infinit.net/borland
n°514051
Taz
bisounours-codeur
Posté le 13-09-2003 à 18:10:36  profilanswer
 

os2 a écrit :


 
ça serait pas mal de pouvoir comparer la version asm avec alvitec et une autre avec mmx...

le mmx et sse c'est de la blague par rapport à altivec

n°514773
Joel F
Real men use unique_ptr
Posté le 15-09-2003 à 11:01:01  profilanswer
 

Typiquement AltiVec va 2 à 4 fois plus vite que MMX et 2 foi splus vite que SSE2.
 
En outre, AltiVec se programme directement en C (pas d'assembleur), n'a pas besoin de "context switching" comme MMX.
 
Si ca interesse des gens j'ai un papier ou deux de comparaison MMX/AltiVec.
En outre je bosse sur une librairie d'encapsulation d'AltiVec au sein de classe STL like qui devrait pas tarder à etre releaser.

n°514780
Taz
bisounours-codeur
Posté le 15-09-2003 à 11:06:59  profilanswer
 

allez balance

n°514792
Joel F
Real men use unique_ptr
Posté le 15-09-2003 à 11:32:44  profilanswer
 

OK, quelques Liens :
 
Une premiere evaluation :
* http://www.lri.fr/~sebot/publi/tsi.ps
 
Pour comprendre :
* http://www.mackido.com/Hardware/AltiVecVsMMX.html
 
* Pour finir, un exemple d'utilisation d'Altivec dans des conditions "exotiques :
http://wwwlasmea.univ-bpclermont.f [...] jfla03.pdf
 
Je posterais d'autres liens + tard, j'ai pas mes bookmarks de boulot sous la main.

n°514799
chrisbk
-
Posté le 15-09-2003 à 11:42:52  profilanswer
 


 
celui ci je laisserais tomber, il est trop vieux sur certains point. Le switch FP-MMX ne coute plus rien (meme si evidemment en utilisant MMX tu trashe ta pile fpu), au moins sur AMD. (j'imagine qu'ils ont mis le paquet la dessus a cause de leur 3dnow) (enfin, ils disent que ca coute plus)
 
Sur brols un peu recent on peut avoir MMX et calcul flottant en meme tps (3dnow pour l'un, SSE pour l'autre). Par contre je ne qualifierais surement pas ca d'ergonomique...


Message édité par chrisbk le 15-09-2003 à 11:43:21
n°514826
Joel F
Real men use unique_ptr
Posté le 15-09-2003 à 12:18:32  profilanswer
 

Je sais bien, des que je retourne au boulot, je posterais les *bons* liens que j'ai utilisé pour ma biblio de DEA.

n°514832
chrisbk
-
Posté le 15-09-2003 à 12:27:06  profilanswer
 

Joel F a écrit :

Je sais bien, des que je retourne au boulot, je posterais les *bons* liens que j'ai utilisé pour ma biblio de DEA.


 
je disais ca juste pour avoir le dernier mot hein ? [:ddr555]

n°514855
Joel F
Real men use unique_ptr
Posté le 15-09-2003 à 12:51:50  profilanswer
 

:sol:  de tte façon MMX ca suxx des ours :o

n°516852
Cyberpat92
Posté le 18-09-2003 à 02:32:13  profilanswer
 

Bon ben c'est devenu ça :
 
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
 
et effectivement, on gagne quand même un peu. Est-il possible avec MMX de faire plusieurs multiplications durant le même cycle CPU pour gagner du temps de calcul ?

n°516865
chrisbk
-
Posté le 18-09-2003 à 07:58:29  profilanswer
 

cyberpat92 a écrit :

Bon ben c'est devenu ça :
 
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
total += *ptr++ * *filter++;
 
et effectivement, on gagne quand même un peu. Est-il possible avec MMX de faire plusieurs multiplications durant le même cycle CPU pour gagner du temps de calcul ?
 


 
vi si c aussi lineaire pas de pb
 
truc genre :
 

Code :
  1. unsigned int total[2];
  2. _asm
  3. {
  4. movq   mm0,[filter]
  5. pmuld  mm0,[ptr];
  6. movq   mm1,[filter+8]
  7. pmuld  mm1,[ptr+8];
  8. movq   mm2,[filter+16]
  9. pmuld  mm2,[ptr+16];
  10. movq   mm3,[filter+24]
  11. pmuld    mm3,[ptr+24];
  12. paddusd  mm0,mm1;
  13. paddusd  mm0,mm2;
  14. paddusd  mm0,mm3;
  15. add filter,32;
  16. add ptr,32;
  17. movq total,mm0;
  18. }
  19. unsigned int rt = total[0] + total[1];


 
pu sur a 100% des noms des instructions, a verifeir

n°517805
Cyberpat92
Posté le 19-09-2003 à 01:24:28  profilanswer
 

J'comprends pas, j'ai cherché un peu et en fait il existe un pmull et un pmulh et plein d'autres trucs marrants auxquels j'ai rien compris... :cry:

n°517834
chrisbk
-
Posté le 19-09-2003 à 07:35:25  profilanswer
 

cyberpat92 a écrit :

J'comprends pas, j'ai cherché un peu et en fait il existe un pmull et un pmulh et plein d'autres trucs marrants auxquels j'ai rien compris... :cry:  


 
ah ouais c vrai qu'ya deux pmull
ben pmulld alors :O
 
(multiplication d'un nombre sur 32bits par un nombre sur 32bits = un nombre sur 64bits. pmull garde les 32bits du bas, tandis que mulh conservera les 32bits du haut)

n°517841
chrisbk
-
Posté le 19-09-2003 à 08:06:47  profilanswer
 

ca me rapelle que je voulais ecrire un tuto mmx pour le forum fut un tps :D

n°517912
Joel F
Real men use unique_ptr
Posté le 19-09-2003 à 09:24:58  profilanswer
 

Tu sais ou il est ?
ca m'interesse pour faire le portge de ma bibliotheque d'AltiVec vers MMX-SSE 2

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  ASM

  Optimisation en MMX/SSE - Besoin d'aide

 

Sujets relatifs
besoin d'aide pour un echoOuvrire un Flash a une frame specifier a l'aide d'un lien Html
[PHP/MySQL] Probleme de guillemets : A L'AIDE !!Optimisation du traitement des chaînes
[Acces:Pages d'acces au donnée] je debute besoin d'aide[HTML/JS] Besoin d'aide xhtml/css : probleme avec IE
Plus de sujets relatifs à : Optimisation en MMX/SSE - Besoin d'aide


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR