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

 


 Mot :   Pseudo :  
 
 Page :   1  2  3
Auteur Sujet :

Challenge/Partage de connaissances : comment optimisez ce code?

n°1311650
skelter
Posté le 22-02-2006 à 16:52:31  profilanswer
 

Reprise du message précédent :
c'est pire, on l'a déja dit faut s'attendre à moins d'optimisations si on parcourir un tableau avec un pointeur
 
et accessoirement faudrais controller les allocations dynamiques

mood
Publicité
Posté le 22-02-2006 à 16:52:31  profilanswer
 

n°1311653
chrisbk
-
Posté le 22-02-2006 à 16:55:27  profilanswer
 

et j'ai horreur des "+ *machin++"

n°1311682
alexIsBack
Posté le 22-02-2006 à 17:19:33  profilanswer
 

skelter a écrit :

c'est pire, on l'a déja dit faut s'attendre à moins d'optimisations si on parcourir un tableau avec un pointeur
 
et accessoirement faudrais controller les allocations dynamiques


 
 
si on déclare un tableau facon

Code :
  1. double window[_NBrows][_NBcolumns];


 
est ce que l'on nottera une différence de vitesse dans la suite du code par rapport à une déclaration de type

Code :
  1. double **window;
  2. window=new double *[_NBrows];
  3. for (int i=0; i<_NBcolumns;++i)
  4.      window[i]=new double [_NBcolumns];

 
 
juste pour savoir, car il doit y avoir une différence au niveau de la répartition des données en mémoire non? => plusieurs vecteurs éparpillés contre un gros bloc avec la première méthode? ca j'avoue que j'ai oublié

Message cité 1 fois
Message édité par alexIsBack le 22-02-2006 à 17:20:19
n°1311688
alexIsBack
Posté le 22-02-2006 à 17:21:47  profilanswer
 

on peut passer des données en double vers des long long facilement?
on y gagnerai un facteur de vitesse de 2?

n°1311689
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:22:08  profilanswer
 

c'est mal. (le tableau de pointeur là)

n°1311692
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:23:27  profilanswer
 

déjà t'es vraiment sûr d'avoir besoin de double ?
y'a un exemple de ton truc qui marche là ? (le binaire, une image source et  traité que je comprennes ce que ton bignou fait)

n°1311695
skelter
Posté le 22-02-2006 à 17:26:58  profilanswer
 

alexIsBack a écrit :

si on déclare un tableau facon

Code :
  1. double window[_NBrows][_NBcolumns];


 
est ce que l'on nottera une différence de vitesse dans la suite du code par rapport à une déclaration de type

Code :
  1. double **window;
  2. window=new double *[_NBrows];
  3. for (int i=0; i<_NBcolumns;++i)
  4.      window[i]=new double [_NBcolumns];

 
 
juste pour savoir, car il doit y avoir une différence au niveau de la répartition des données en mémoire non? => plusieurs vecteurs éparpillés contre un gros bloc avec la première méthode? ca j'avoue que j'ai oublié


 
 
ben ouai si tu suis le raisonennement c'est encore moins cache-friendly puisque ta matrice est fragmentée par lignes et que les données sont toujours chargées en cache par bloc contigues

Message cité 1 fois
Message édité par skelter le 22-02-2006 à 17:27:42
n°1311698
alexIsBack
Posté le 22-02-2006 à 17:32:42  profilanswer
 

skelter a écrit :

ben ouai si tu suis le raisonennement c'est encore moins cache-friendly puisque ta matrice est fragmentée par lignes et que les données sont toujours chargées en cache par bloc contigues


 
oki doki, oui, c'est en effet logique, mais au final,mieux vau une matrice 2D ou un vecteur ligne qui contient la matrice dépliée?
 
car metton que l'on traite comme ici présenté ligne par ligne mais aussi colonne par colonne, faudrai que l'on fasse des sauts de grande taille dans le vecteur pour rejoindre 2 éléments de lignes voisines plutôt que un saut unitaire pour passer au voisin de colonne...

n°1311699
chrisbk
-
Posté le 22-02-2006 à 17:33:07  profilanswer
 

un vecteur ligne qui contient la matrice déplié

n°1311703
alexIsBack
Posté le 22-02-2006 à 17:37:11  profilanswer
 

bjone a écrit :

déjà t'es vraiment sûr d'avoir besoin de double ?
y'a un exemple de ton truc qui marche là ? (le binaire, une image source et  traité que je comprennes ce que ton bignou fait)


 
je viens de faire les tests en FLOAT, ca reste correcte, donc, oui, on peut passer en float !!!
 
ce que fait l'algo là?
si tu n'as pu le compiler, imagine : il balaye chaque ligne de la gauche vers la droite avec un effet filtre passe bas. donc, en gros, sur une image, ca smoothe les arrêtes d'orientation verticales et la réponse est assymétrique entre la gauche et la droite
c'est juste un algo pour tester en fait. mais c'est une bonne base pour apprende à optimiser car il y a plein de données à traiter

mood
Publicité
Posté le 22-02-2006 à 17:37:11  profilanswer
 

n°1311704
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:37:30  profilanswer
 

Code :
  1. for (unsigned int i=0; i<NBloops; ++i)
  2.    for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  3.    {       
  4.    value=0; // initialize la variable pour chaque nouvelle ligne traitée
  5.       for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  6.       {


 
=>
 

Code :
  1. for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  2.    {       
  3.       for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  4.       {
  5.            for (unsigned int i=0; i<NBloops; ++i)
  6.            {
  7.                value=0;


 
?

n°1311705
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:38:45  profilanswer
 

alexIsBack a écrit :

je viens de faire les tests en FLOAT, ca reste correcte, donc, oui, on peut passer en float !!!
 
ce que fait l'algo là?
si tu n'as pu le compiler, imagine : il balaye chaque ligne de la gauche vers la droite avec un effet filtre passe bas. donc, en gros, sur une image, ca smoothe les arrêtes d'orientation verticales et la réponse est assymétrique entre la gauche et la droite
c'est juste un algo pour tester en fait. mais c'est une bonne base pour apprende à optimiser car il y a plein de données à traiter


 
y'a rien à compiler, ton code tel quel il ne peut générér que des blobs artistiques.....
 
edit: en fait non c'est pas compilable si Taz passe et vois ton #include <iostream.h> et le cout atteinable comme ça il va te chier une pendule :D


Message édité par bjone le 22-02-2006 à 17:42:48
n°1311709
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:45:39  profilanswer
 

bjone a écrit :

Code :
  1. for (unsigned int i=0; i<NBloops; ++i)
  2.    for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  3.    {       
  4.    value=0; // initialize la variable pour chaque nouvelle ligne traitée
  5.       for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  6.       {


 
=>
 
?


 
pardon autant pour moi:
 

Code :
  1. for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  2.    {       
  3.            for (unsigned int i=0; i<NBloops; ++i)
  4.            {
  5.                value=0;
  6.                for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  7.                {


 

n°1311710
alexIsBack
Posté le 22-02-2006 à 17:46:23  profilanswer
 

bjone a écrit :

Code :
  1. for (unsigned int i=0; i<NBloops; ++i)
  2.    for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  3.    {       
  4.    value=0; // initialize la variable pour chaque nouvelle ligne traitée
  5.       for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  6.       {


 
=>
 

Code :
  1. for (IDrow=0; IDrow <_NBrows;  ++IDrow)
  2.    {       
  3.       for (IDcolumn=0; IDcolumn<_NBcolumns ; ++IDcolumn)
  4.       {
  5.            for (unsigned int i=0; i<NBloops; ++i)
  6.            {
  7.                value=0;


 
?


 
si tu mets le value=0 avant la 3ième boucle, ca veut dire que le premier pixel de la ligne commence avec value=0 pour lui seul, par contre, les pixels suivants connaitrons grâce à 'value' le résultat du pixel précédent d'ou un effet filtre passe bas (smooth, blur suivant le vocabulaire)
 
ca fait un genre de filtre pixel(i+1)= alpha*pixel(i)+(1-alpha)*nouvelleValeur
 
si tu met le value=0 à chaque tour de boucle...ben ca sert à rien

n°1311711
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:48:11  profilanswer
 

oui j'ai reposté derrière.

n°1311712
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:49:44  profilanswer
 

et mets tes tau/valeur en float.  
 
en fait ça changera rien suivant la config du fpu (en 80x86 sans sse bien sûr).

n°1311715
alexIsBack
Posté le 22-02-2006 à 17:53:44  profilanswer
 

bjone a écrit :

et mets tes tau/valeur en float.  
 
en fait ça changera rien suivant la config du fpu (en 80x86 sans sse bien sûr).


 
 
oui, j'ai tout repassé en float, en effet pas de changement de vitesse (je suis sur un p4)
mais il y a moyen de jouer avec les sse avec les float non, genre gérer 4 floats à la fois par opération? avec les intrinsics

n°1311717
bjone
Insert booze to continue
Posté le 22-02-2006 à 17:56:11  profilanswer
 

oui...
 
mais tu as déplacé le for( NBloops ) ?
 
parceque ça risque de faire une sacrée différence. (enfin j'espère :D)

Message cité 1 fois
Message édité par bjone le 22-02-2006 à 17:56:33
n°1311720
alexIsBack
Posté le 22-02-2006 à 18:00:44  profilanswer
 

bjone a écrit :

oui...
 
mais tu as déplacé le for( NBloops ) ?
 
parceque ça risque de faire une sacrée différence. (enfin j'espère :D)


 
 
le for( NBloops ) ne sert qu'à exécuter plusieurs fois la boucle pour avoir une valeur moyenne du temps d'éxécution, autrement cette boucle n'a pas lieu d'être

n°1311738
bjone
Insert booze to continue
Posté le 22-02-2006 à 18:35:40  profilanswer
 

a bon :D lol je suis déçu.
 
et bien si tu le fais, tu risques quand même de voir une différence :D

n°1311810
Joel F
Real men use unique_ptr
Posté le 22-02-2006 à 20:34:37  profilanswer
 

alexIsBack a écrit :

quelles manips effectue tu donc à la main?


Maintenant plus rien. J'ai encapsulé tout mes codes de manip matrcioielle ALtiVec dans une bibliotheque (cf ma signature)

n°1312046
Sve@r
Posté le 23-02-2006 à 11:15:44  profilanswer
 

alexIsBack a écrit :

Code :
  1. unsigned int IDrow, IDcolumn, NBloops=100;
  2. //appel de la fonction de filtrage 10 fois
  3. for (unsigned int i=0; i<NBloops; ++i)




 
Moi je trouve un gain de x10 en mettant "NBloops=10" pour le faire correspondre au commentaire  :D  :D  :D  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1312170
alexIsBack
Posté le 23-02-2006 à 13:42:41  profilanswer
 

Sve@r a écrit :

Moi je trouve un gain de x10 en mettant "NBloops=10" pour le faire correspondre au commentaire  :D  :D  :D


 
héhé, bien vu, je viens de corriger la bétise ;)

n°1312173
alexIsBack
Posté le 23-02-2006 à 13:43:23  profilanswer
 

là, je viens de transformer la matrice en un seul vecteur et le tout en float, j'ai un gain de 1.5...

n°1312478
bjone
Insert booze to continue
Posté le 23-02-2006 à 17:18:50  profilanswer
 

les lignes sont les mêmes dans ton windowfilter ?

n°1312842
alexIsBack
Posté le 24-02-2006 à 09:46:50  profilanswer
 

dans window fillter peut se trouver n'importe quoi, une constante=>remplacer le tableau par une simple constante, oiu alors une valeur différente pour chaque pixel, ca permet de changer l'effet du filtre localement

n°1312863
skelter
Posté le 24-02-2006 à 10:37:23  profilanswer
 

tu peux montrer ton code actuel ?

n°1312879
alexIsBack
Posté le 24-02-2006 à 11:04:00  profilanswer
 

Code :
  1. #include <iostream.h>
  2. #include <ctime>
  3. unsigned int _NBcolumns=640; // nombre de colonnes des buffers
  4. unsigned int _NBrows=480; // nombre de lignes des buffers
  5. // Entry point
  6. int main(int argc, char *argv[])
  7. {
  8. // buffers d'entrée et de sortie
  9. float outputFrame[_NBcolumns*_NBrows], inputFrame[_NBcolumns*_NBrows], windowfilter[_NBcolumns*_NBrows];
  10. // variables/buffers utilisés dans les boucles:
  11. float value, tau=10.0;
  12. unsigned int IDrow, NBloops=100, index, IDstop;
  13. cout<<"loop started"<<endl;
  14. int startTime=clock();
  15. //appel de la fonction de filtrage 100 fois
  16. for (unsigned int i=0; i<NBloops; ++i)
  17. {
  18.    /* PARTIE A OPTIMISER */
  19.    // boucle appelée pour toute nouvelle image d'entrée (inputFrame) on retyrouve le code suivant :
  20.        IDrow=_NBrows;
  21. while((index=(--IDrow)))
  22. {
  23.  // set init  
  24.  value=0;
  25.  IDstop = _NBrows*(_NBcolumns-1)+IDrow; // calcul de l'index de fin de boucle
  26.  do
  27.  {
  28.   /* temporal effect introduced with RetinaProcessedPicture(Index) in the first line */
  29.   value = outputFrame[index]*tau + inputFrame[index] +  windowfilter[index]* value;
  30.   outputFrame[index] = value;
  31.  }while((index+=_NBrows)<IDstop);
  32. }; 
  33.    /* FIN DE LA PARTIE A OPTIMISER  */
  34. }
  35. int endTime=clock();
  36. cout<<"filtering finished, time elapsed="<<(endTime-startTime)/(NBloops)<<"clocks"<<endl;
  37. return 0;
  38. }


Message édité par alexIsBack le 24-02-2006 à 11:55:51
n°1312897
skelter
Posté le 24-02-2006 à 11:33:27  profilanswer
 

avec quoi tu compiles ? avec g++ ca ne compile pas (variables non déclarées + 4 pages de warnings)
 
index, result et IDstop ne sont pas déclarées, IDColumn et value ne sont pas utilisée ??

Message cité 1 fois
Message édité par skelter le 24-02-2006 à 11:33:55
n°1312900
alexIsBack
Posté le 24-02-2006 à 11:46:12  profilanswer
 

oups, g raté des copier coller, je remodifie

n°1312908
alexIsBack
Posté le 24-02-2006 à 11:59:54  profilanswer
 

skelter a écrit :

avec quoi tu compiles ? avec g++ ca ne compile pas (variables non déclarées + 4 pages de warnings)
 
index, result et IDstop ne sont pas déclarées, IDColumn et value ne sont pas utilisée ??


 
c'est fait

n°1312915
skelter
Posté le 24-02-2006 à 12:11:29  profilanswer
 

pour moi c'est 2x plus rapide avec ta premiere version (g++ -O3 ..., version 3.2.2)
 
#include <iostream.h> -> #include <iostream>
 
et ajoutes 'using namespace std;' au debut du main
 
unsigned int NBcolumns=640;
unsigned int NBrows=480;
->
// ne prefixes jamais par un _, et déclares les dans le main tant qu'a faire (toujours en portée minimale)
const size_t NBcolumns=640;
const size_t NBrows=480;
 
le type de retour de std::clock est std::clock_t
 
et surtout déclares tes variables en portée minimale et seulement dés que tu en as besoin, et utilise 'const' quand tu ne la modifies pas

Message cité 2 fois
Message édité par skelter le 24-02-2006 à 12:13:41
n°1312919
alexIsBack
Posté le 24-02-2006 à 12:17:32  profilanswer
 

skelter a écrit :

pour moi c'est 2x plus rapide avec ta premiere version (g++ -O3 ..., version 3.2.2)
 
#include <iostream.h> -> #include <iostream>
 
et ajoutes 'using namespace std;' au debut du main
 
unsigned int NBcolumns=640;
unsigned int NBrows=480;
->
// ne prefixes jamais par un _, et déclares les dans le main tant qu'a faire (toujours en portée minimale)
const size_t NBcolumns=640;
const size_t NBrows=480;
 
le type de retour de std::clock est std::clock_t
 
et surtout déclares tes variables en portée minimale et seulement dés que tu en as besoin, et utilise 'const' quand tu ne la modifies pas


 
 
2*plus rapide avec la première version? c'est bizarre chez moi, c'ets limite l'inverse... avec g++ O3 sur un pentium 4 prescott
 
on m'a dit que avec les boucles while c'était plus rapide, est ce vrai?
 
en tout cas, quelle est la méthode la plus appropriée : tableau 2D ou vecteur 1D?

n°1312923
chrisbk
-
Posté le 24-02-2006 à 12:24:15  profilanswer
 

alexIsBack a écrit :


on m'a dit que avec les boucles while c'était plus rapide, est ce vrai?


 
ca sent la fumisterie. au pire desassemble, mais franchement ca sent la vieille legende facon "ok, c'est tout crado mais c'est rapide"

n°1312924
skelter
Posté le 24-02-2006 à 12:28:02  profilanswer
 

Citation :

2*plus rapide avec la première version? c'est bizarre chez moi, c'ets limite l'inverse... avec g++ O3 sur un pentium 4 prescott


 
pour c'est logique que le premiere soit plus rapide, apres si c'est l'inverse chez toi je peux pas dire
 
 

Citation :

en tout cas, quelle est la méthode la plus appropriée : tableau 2D ou vecteur 1D


 
dans ce cas je dirais tableau 2D puisque ton calcul dépend de 2 dimensions
 

Citation :

on m'a dit que avec les boucles while c'était plus rapide, est ce vrai?


 
for et while sont deux mots cles pour construire une boucle, sémantiquement un for à toujours sont équivalent en while (et inversement) il n'y a donc aucune raisons (je penses) que le code généré soit différent

n°1312928
alexIsBack
Posté le 24-02-2006 à 12:42:00  profilanswer
 

skelter a écrit :

pour moi c'est 2x plus rapide avec ta premiere version (g++ -O3 ..., version 3.2.2)
 
#include <iostream.h> -> #include <iostream>
 
et ajoutes 'using namespace std;' au debut du main
 
unsigned int NBcolumns=640;
unsigned int NBrows=480;
->
// ne prefixes jamais par un _, et déclares les dans le main tant qu'a faire (toujours en portée minimale)
const size_t NBcolumns=640;
const size_t NBrows=480;
 
le type de retour de std::clock est std::clock_t
 
et surtout déclares tes variables en portée minimale et seulement dés que tu en as besoin, et utilise 'const' quand tu ne la modifies pas


 
 
le fait que ca ralentisse viens je pense du fait que les données de la dernière boucle ne sont pas contigues, (on fait des sauts de _NBrows), y a t il moyen de faire du prefectch pour mettre en cache les futures données avant le prochain tour de boucle?


Message édité par alexIsBack le 24-02-2006 à 12:47:46
n°1312935
skelter
Posté le 24-02-2006 à 12:50:00  profilanswer
 

dans la premiere version il n'y a pas ce probleme
 
essayes aussi avec une bibliothèque de templates pour gérer les matrices et autre (boost::ublas, blitz++ ou celle de joelF)

n°1312957
alexIsBack
Posté le 24-02-2006 à 13:06:48  profilanswer
 

chrisbk a écrit :

ca sent la fumisterie. au pire desassemble, mais franchement ca sent la vieille legende facon "ok, c'est tout crado mais c'est rapide"


 
c'est vrai que je suis assez d'accrd avec toi lol

n°1313022
++fab
victime du syndrome IH
Posté le 24-02-2006 à 14:15:00  profilanswer
 

skelter a écrit :

dans la premiere version il n'y a pas ce probleme
essayes aussi avec une bibliothèque de templates pour gérer les matrices et autre (boost::ublas, blitz++ ou celle de joelF)


 
Si le filtrage peut-etre décrit comme un produit matriciel ... Avec la réutilisation de "value", je ne sais pas ce que ça donne ...
 

n°1313042
skelter
Posté le 24-02-2006 à 14:47:15  profilanswer
 

en effet c'est le gros probleme ca, le calcul de outputFrame[n] dépend de outputFrame[n-1], ceci dit je ne connais pas trop ces bibliotèque et je sais pas si elles permettent de construire ce genre  d'expressions
on peut aussi voir l'algo d'une autre facon (quitte à réorganiser les données ligne->colonne en colonne->ligne) en bouclant sur les colonne ca se résoud en une unique expression vectorielle
 

Code :
  1. /*
  2. c -> indice de la colonne
  3. <matrice>[c] -> vecteur de données correspondant à la colonne
  4. */
  5. outputFrame[0] = outputFrame[0] * tau + inputFrame[0];
  6. for( size_t c = 1; c < NBColumns; c++ )
  7.     outputFrame[c] = outputFrame[c] * tau + inputFrame[c] + windowfilter[c] * outputFrame[c-1];


 

n°1313182
alexIsBack
Posté le 24-02-2006 à 18:18:40  profilanswer
 

oui, on peut écrire cela sous la forme que tu propose bien entendu, mais qu'est ce que ca change si on ajoute la variable temporaire value?
 
est ce que value permet de garder cette donnée temporaire plus proche du processeur ou est ce que l'expresiion  

Code :
  1. outputFrame[c] = outputFrame[c] * tau + inputFrame[c] + windowfilter[c] * outputFrame[c-1];


suffit?

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3

Aller à :
Ajouter une réponse
 

Sujets relatifs
Code asp d'un user controlOu puis-je télécharger le code source d'un portfolio dans ce genre :
Code source GPLcomment appeler du code python dans une page web ?
Impression CODEcode vba pour inserer une ligne dans une macro
communication code php et C via sockets[Résolu]Obtenir le code source.
[C] Partage administratif et droits d'accès[RESOLU] Code couleur sous visual basic
Plus de sujets relatifs à : Challenge/Partage de connaissances : comment optimisez ce code?


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)