Est ce plus rapide ?

Est ce plus rapide ? - C - Programmation

Marsh Posté le 18-06-2007 à 11:16:12    

Bonjour,  
 
j'aimerais savoir si :
 

Code :
  1. double cnum=5;
  2. for ( ; ;)
  3.    ma_fonction_bidon(cnum);


 
est plus rapide que :

Code :
  1. for ( ; ;)
  2.    ma_fonction_bidon(5.0);


 
merci  :jap:

Reply

Marsh Posté le 18-06-2007 à 11:16:12   

Reply

Marsh Posté le 18-06-2007 à 11:35:58    

A priori, aucune différence.

 

Maintenant, occultons la question, et admettons qu'il y ait une quelconque différence dans ce genre de micro-optimisation : penses-tu que le gain vaille la peine de se poser la question ?

 

Les seules optimisations valables, sauf cas particuliers (portion de code critique), sont algorithmiques. En dehors de ça, le seul critère important est la maintenabilité du code, c'est-à-dire la possibilité de comprendre et de modifier ce code pour une personne ne le connaissant pas (le concepteur du code inclu, quelques mois plus tard).

Message cité 1 fois
Message édité par Elmoricq le 18-06-2007 à 11:36:33
Reply

Marsh Posté le 18-06-2007 à 11:51:16    

Elmoricq a écrit :

A priori, aucune différence.

 

Maintenant, occultons la question, et admettons qu'il y ait une quelconque différence dans ce genre de micro-optimisation : penses-tu que le gain vaille la peine de se poser la question ?

 

Les seules optimisations valables, sauf cas particuliers (portion de code critique), sont algorithmiques. En dehors de ça, le seul critère important est la maintenabilité du code, c'est-à-dire la possibilité de comprendre et de modifier ce code pour une personne ne le connaissant pas (le concepteur du code inclu, quelques mois plus tard).

 

ok, merci pour ta réponse  :jap: Je sais qu'il n'y a pas grande différence, je voudrai savoir si néanmoins il y en a une.

 


Dans ce site http://www.codeproject.com/cpp/C__ [...] zation.asp, il disent ca :

 


Using Aliases

 

Consider the following example -

 

   void func1( int *data )
    {
        int i;

 

       for(i=0; i<10; i++)
        {
              anyfunc( *data, i);
        }
    }

 

Even though *data may never change, the compiler does not know that anyfunc () did not alter it, and so the program must read it from memory each time it is used - it may be an alias for some other variable that is altered elsewhere. If we know it won't be altered, we could code it like this instead:

 

   void func1( int *data )
    {
        int i;
        int localdata;

 

       localdata = *data;
        for(i=0; i<10; i++)
        {
              anyfunc ( localdata, i);
        }
    }

 

This gives the compiler better opportunity for optimization.


Message édité par in_your_phion le 18-06-2007 à 11:52:07
Reply

Marsh Posté le 18-06-2007 à 11:54:17    

Ca c'est un autre problème ... De toute façon, AVANT de se poser ce genre de question, ecris ton prog en entier et profile le.  
 
"Premature Optimisation is Root of All Evil" :o

Reply

Marsh Posté le 18-06-2007 à 11:56:39    

Si tu es l'auteur de la fonction anyfunc(), utilise plutôt le mot-clef "const", pour justement indiquer que tu ne modifies pas *data. Le compilateur optimisera tout seul, c'est son job.

 

Et si tu n'es pas l'auteur de anyfunc(), tu ne peux que te douter que *data n'est pas modifié, en es-tu sûr ? Et si oui, est-ce à toi d'alourdir ton code pour composer avec les bibliothèques tierses ?

 

Dans les deux cas, cette micro-optimisation est contre-productive.
Et encore une fois, c'est dans l'hypothèse où il y a un quelconque gain mesurable, ce qui n'est pas évident du tout.

Message cité 1 fois
Message édité par Elmoricq le 18-06-2007 à 11:57:27
Reply

Marsh Posté le 18-06-2007 à 11:57:57    

Joel F a écrit :

Ca c'est un autre problème ... De toute façon, AVANT de se poser ce genre de question, ecris ton prog en entier et profile le.  
 
"Premature Optimisation is Root of All Evil" :o


 
oui  ... Je sais bien que c'est mal :o mais je voudrais savoir quand meme, histoire de. Pourquoi c'est un autre problème ?

Reply

Marsh Posté le 18-06-2007 à 11:59:26    

Elmoricq a écrit :

Si tu es l'auteur de la fonction anyfunc(), utilise plutôt le mot-clef "const", pour justement indiquer que tu ne modifies pas *data. Le compilateur optimisera tout seul, c'est son job.

 

Et si tu n'es pas l'auteur de anyfunc(), tu ne peux que te douter que *data n'est pas modifié, en es-tu sûr ? Et si oui, est-ce à toi d'alourdir ton code pour composer avec les bibliothèques tierses ?

 

Dans les deux cas, cette micro-optimisation est contre-productive.
Et encore une fois, c'est dans l'hypothèse où il y a un quelconque gain mesurable, ce qui n'est pas évident du tout.

 

ok  :jap: En admettant que je ne suis pas l'auteur de la fonction et que je sache que cette donnée n'est pas modifée, aucune optimisation possible alors ?


Message édité par in_your_phion le 18-06-2007 à 11:59:36
Reply

Marsh Posté le 18-06-2007 à 12:04:05    

Des micro-optimisations sont possibles, mais comme le dit Joel F, profile d'abord le programme, c'est pas dit que ce soit le meilleur endroit pour optimiser, et c'est pas dit non plus que tu gagnes grand chose...
Et si le gain est négligeable, il vaut mieux privilégier une écriture claire et concise du code, la maintenabilité étant souvent un critère plus pertinent que la vitesse d'exécution (lorsque la différence de temps, sur un code non critique, ne dépasse pas les quelques secondes).

Message cité 1 fois
Message édité par Elmoricq le 18-06-2007 à 12:04:56
Reply

Marsh Posté le 18-06-2007 à 12:10:49    

Elmoricq a écrit :

Des micro-optimisations sont possibles, mais comme le dit Joel F, profile d'abord le programme, c'est pas dit que ce soit le meilleur endroit pour optimiser, et c'est pas dit non plus que tu gagnes grand chose...
Et si le gain est négligeable, il vaut mieux privilégier une écriture claire et concise du code, la maintenabilité étant souvent un critère plus pertinent que la vitesse d'exécution (lorsque la différence de temps, sur un code non critique, ne dépasse pas les quelques secondes).

 

oki oki merci alors :) en fait bon je vais poster l'exo, c'est un calcul de suite

 
Code :
  1. for (i=0;i<10;i++) {
  2.     U_n = U_0 - ma_fonction_bifon(5,U_0);
  3.           if (fabs(U_n-U_0) < DBL_EPS)
  4.               break;
  5.     U_0=U_n;
  6. }
 

enfin c'est un truc qui ressemble, je vois pas quoi optimiser a part ca et la boucle for. On ne connait pas ce que fait la fonction ma_fonction_bidon() mais on sait que 5 est constant.

Message cité 1 fois
Message édité par in_your_phion le 18-06-2007 à 12:11:05
Reply

Marsh Posté le 18-06-2007 à 12:39:02    

y a rien à optimiser. Sauf les noms de variables u0 étant en fait uN-1

Reply

Marsh Posté le 18-06-2007 à 12:39:02   

Reply

Marsh Posté le 18-06-2007 à 12:40:31    

Taz a écrit :

y a rien à optimiser. Sauf les noms de variables u0 étant en fait uN-1

 

:lol:

 

moi aussi je me suis dit la meme chose...et mon optimisation, non ? on peut remplacer la boucle par :

Code :
  1. for (i=11;i--; )


Message édité par in_your_phion le 18-06-2007 à 12:41:16
Reply

Marsh Posté le 18-06-2007 à 12:47:59    

c'est bien beau de parler d'optimisation seulement si tu ne peux pas prouver que ça en est une ça ne vaut rien. Pas la peine de faire un caprice, la moindre des choses pour optimiser c'est de savoir quoi.
 
Soyons sérieux un moment, ce sujet est un classique du genre, la branlette intellectuel du débutant pour optimiser comme les grands. Les grands n'optimisent pas : ils écrivent des algorithmes élégants, faciles à mettre en oeuvre et maintenables. Quand ils ont un souci de performance, ils raisonnent sur la complexité de leur algorithme, utilisent des profilers et des fois même décompilent.
 
Et les problèmes d'aliasing ça existe, maintenant j'attends de voir un projet (je ne parle pas de trucs spécialisés ultra optimisé) qui a obtenu un gain significatif avec ça. Il m'est arrivé de collé un ou deux restrict dans ma vie, ça faisait joli au niveau de l'assembleur, mais même sur 1e6 appels ça ne faisait aucune différence.

Reply

Marsh Posté le 18-06-2007 à 13:03:36    

Taz a écrit :

c'est bien beau de parler d'optimisation seulement si tu ne peux pas prouver que ça en est une ça ne vaut rien. Pas la peine de faire un caprice, la moindre des choses pour optimiser c'est de savoir quoi.

 

Soyons sérieux un moment, ce sujet est un classique du genre, la branlette intellectuel du débutant pour optimiser comme les grands. Les grands n'optimisent pas : ils écrivent des algorithmes élégants, faciles à mettre en oeuvre et maintenables. Quand ils ont un souci de performance, ils raisonnent sur la complexité de leur algorithme, utilisent des profilers et des fois même décompilent.

 

Et les problèmes d'aliasing ça existe, maintenant j'attends de voir un projet (je ne parle pas de trucs spécialisés ultra optimisé) qui a obtenu un gain significatif avec ça. Il m'est arrivé de collé un ou deux restrict dans ma vie, ça faisait joli au niveau de l'assembleur, mais même sur 1e6 appels ça ne faisait aucune différence.

 

ok ok peace man, je suis avec toi  :love:  :love:  C'est un exercice. Et je ne vois pas la solution, est-ce vrai que c'est un grand classique du genre ? Je ne vois vraiment pas quoi apporter....


Message édité par in_your_phion le 18-06-2007 à 13:04:26
Reply

Marsh Posté le 18-06-2007 à 13:24:53    

Il faut savoir que le pc passe moins de 10% de son temps dans plus de 90% du code.
 
Comprenant ca, on peut tres vite en deduire que 90% du programme voir plus ne necessite aucune optimisation, voir meme au contraire. Ce code doit etre fait pouyr etre facile a comprendre, facile a debugguer, a maintenir, et evolutif, souple, bien documenté. Ceci est largement plus important qu'une quelquonque optimisation.
 
Le reste du code (de 0% a 10%) doit tout d'abors etre pensé. Un optimisation algorhytmique est en effet plus souhaitable que tout autre chose. Admettons que ton algorhytme est de complexité a*n² . Ce type d'optimisation permet de jouer sur a. Disont que au mieux, tu doubles la vitesse de ton code. Iol faut garder a l'esprit que pour que ca soit interressant, n doit etre tres grand, sinon ce code n'entre pas dans les portions a optimiser.
 
Supposent que n soit egal a 1000 (grandeur faite pour l'exemple, mais dans la realité, ce genre de probleme ne devrait aps se poser avec un truc qui travaille sur 1000 elements). a*n² vaut donc a*1 000 000. Avec l'optimisation supposée ci dessus, on se retrouve avec a*500 000. Il y a certe gain, mais supposnt plutot un refonte de l'algorhytme en b*n*log(n) par exemple.
 
On a alors une complexité de b*3000. Memem si b est 10 fois plus grand que a, le travauil qui reste a faire est donc de a*15 000. Rien a voir !

Reply

Marsh Posté le 18-06-2007 à 13:35:42    

in_your_phion a écrit :

oki oki merci alors :) en fait bon je vais poster l'exo, c'est un calcul de suite
 

Code :
  1. for (i=0;i<10;i++) {
  2.     U_n = U_0 - ma_fonction_bifon(5,U_0);
  3.           if (fabs(U_n-U_0) < DBL_EPS)
  4.               break;
  5.     U_0=U_n;
  6. }


 
enfin c'est un truc qui ressemble, je vois pas quoi optimiser a part ca et la boucle for. On ne connait pas ce que fait la fonction ma_fonction_bidon() mais on sait que 5 est constant.


 

Code :
  1. int i = 0;
  2. do{
  3.     U_n = U_0 - ma_fonction_bifon(5,U_0);
  4.     U_0=U_n;
  5.     i++;
  6. }while(fabs(U_n-U_0) >= DBL_EPS && i<10);


 
Un seul test, un seul branchement, et 30 cycles gagnés par cycle sur un P4 c'est y pas beau ?
Je veraait bien une macro pour fabs, ca evitera aussi un brachement et un/des acces memoire.
 
dans le delire vous devriez chercher du coté des D-loop : http://www.onversity.com/cgi-bin/p [...] Z&P=522#10

Message cité 2 fois
Message édité par deadalnix le 18-06-2007 à 13:36:55
Reply

Marsh Posté le 18-06-2007 à 13:43:55    

deadalnix a écrit :

Code :
  1. int i = 0;
  2. do{
  3.     U_n = U_0 - ma_fonction_bifon(5,U_0);
  4.     U_0=U_n;
  5.     i++;
  6. }while(fabs(U_n-U_0) >= DBL_EPS && i<10);


 
Un seul test, un seul branchement, et 30 cycles gagnés par cycle sur un P4 c'est y pas beau ?
Je veraait bien une macro pour fabs, ca evitera aussi un brachement et un/des acces memoire.
 
dans le delire vous devriez chercher du coté des D-loop : http://www.onversity.com/cgi-bin/p [...] Z&P=522#10


 
ok merci pour ta réponse :) je vais regarder les D-loop. Quand tu dis "30 cycles gagnés par cycle sur un P4", ca veut dire qu'on gagne vraiment du temps ou c'est juste ironique  :o  ?

Reply

Marsh Posté le 18-06-2007 à 13:54:24    

En fait ca va etre difficiel de tout expliquer si tu n'as pas de notion de pipeline processeur mais pour faire simple :
 
Un processeur commence a executer une instruction avant d'avoir terminé l'instruction precedente, ce qui lui permet de traiter 1 instruction par cycle. Mais il existe des instructions, typiquement les branchement, qui modifient l'instruction suivante. L'instruction suivante ne peu etre determiné qu'une fois que le brachement est completement executé.
 
Le P4 a un pipeline de 30 etages, c'est a dire que les instructions sont "decoupées" en 30 etpaes elementaires. Quand une instruction a passé la premiere etape, elle pase dans la suivante, eta ainsi de suite.
 
Cela permet d'avoir des blmoc tres simple dans le processeur et de monter en frequence (d'ou le fait que le P4 monte a 4Ghz). Mais ceci a un cout important : des qu'un instruction modifie le cours normal des operations, il faut attendre 30 cycles pour executer l'instruction suivante.
 
Intel a en fait fait une grosse erreur en faisant le P4, ils pensaient que multiplier les etages permettrait de monter suffisement en frequence pour combler ce probleme. Mais ca n'est pas du tout une bonne idee. AMD a vu bien plus juste avec un pipeline de 12 etages.
 
Tu ne gagnera donc que 12cycle sur un athlon. ce type d'optimisation est donc tres lié a l'architecture du processeur, mais se traduit toujours par une amelioration des perfs.
 
cela dit, la boucle se fait au pire 10 fois dans ton exemple, et fanchement ca vaut aps le coup de chercher a optiser a l'instruction pres.

Reply

Marsh Posté le 18-06-2007 à 14:34:26    

deadalnix a écrit :

Code :
  1. int i = 0;
  2. do{
  3.     U_n = U_0 - ma_fonction_bifon(5,U_0);
  4.     U_0=U_n;
  5.     i++;
  6. }while(fabs(U_n-U_0) >= DBL_EPS && i<10);


 
Un seul test, un seul branchement, et 30 cycles gagnés par cycle sur un P4 c'est y pas beau ?


ouais en SSE99 t'as une instruction fabssubstraceandlessthan10

Reply

Marsh Posté le 18-06-2007 à 15:55:40    

:P dans tous les cas il faudra soustraire, et comparer i a 10 a chaque boucle.
 
Sauf que dans un cas, il y a un brachement, et dans l'autre deux. Sachant qu'un brachement coute facilement une rupture de pipeline . . .
 
Et puis, si tu avais tout lu, je disait que ca n'etait interessant que pour l'exercice etant donné que la boucle ne se fait que dix fois . . .

Reply

Marsh Posté le 19-06-2007 à 09:39:03    

deadalnix a écrit :

En fait ca va etre difficiel de tout expliquer si tu n'as pas de notion de pipeline processeur mais pour faire simple :
 
Un processeur commence a executer une instruction avant d'avoir terminé l'instruction precedente, ce qui lui permet de traiter 1 instruction par cycle. Mais il existe des instructions, typiquement les branchement, qui modifient l'instruction suivante. L'instruction suivante ne peu etre determiné qu'une fois que le brachement est completement executé.
 
Le P4 a un pipeline de 30 etages, c'est a dire que les instructions sont "decoupées" en 30 etpaes elementaires. Quand une instruction a passé la premiere etape, elle pase dans la suivante, eta ainsi de suite.
 
Cela permet d'avoir des blmoc tres simple dans le processeur et de monter en frequence (d'ou le fait que le P4 monte a 4Ghz). Mais ceci a un cout important : des qu'un instruction modifie le cours normal des operations, il faut attendre 30 cycles pour executer l'instruction suivante.
 
Intel a en fait fait une grosse erreur en faisant le P4, ils pensaient que multiplier les etages permettrait de monter suffisement en frequence pour combler ce probleme. Mais ca n'est pas du tout une bonne idee. AMD a vu bien plus juste avec un pipeline de 12 etages.
 
Tu ne gagnera donc que 12cycle sur un athlon. ce type d'optimisation est donc tres lié a l'architecture du processeur, mais se traduit toujours par une amelioration des perfs.
 
cela dit, la boucle se fait au pire 10 fois dans ton exemple, et fanchement ca vaut aps le coup de chercher a optiser a l'instruction pres.


 
ok merci pour ces explications! :) Je pense que pour mon exemple ca ne servira pas des masses effectivement  :lol:  

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed