Conseils et techniques d'optimisation C/C++

Conseils et techniques d'optimisation C/C++ - C++ - Programmation

Marsh Posté le 19-08-2006 à 13:13:50    

Développeur attentif en C/C++, je commence à avoir une petite expérience dans le développement avec ce langage, cependant, perfectionniste j'aimerais par ce topic lancé une collecte centralisée de toutes les petites astuces d'optimisation du code à proprement parlé (sans parlé de l'optimisation par l'algorithme,  etc)
 
Par exemple :
 
 - L'initialisation des variables d'une fonction/méthode est-elle utile (au delà de la sécurité qu'elle peut procurer) ou un gaspillage de temps ?

Code :
  1. void do_something(void)
  2. {
  3.   int a = 0;
  4.   char *b = (char*) NULL;
  5.   ...
  6.   // vaut-il mieux :
  7.   int c; // = 0;
  8.   c = func();
  9.   // ou
  10.   int d = func();
  11. }


 
 - L'allocation dynamique d'un tableau d'objet simple (int/double/char ...) est-elle plus rapide en faisant un malloc, calloc, ou un new ?

Code :
  1. void my_alloc(int N)
  2. {
  3.   int *a = (int*) malloc((N) * sizeof(int));
  4.   char *b = (char*) calloc(N, sizeof(char));
  5.   double *c = new double[N];
  6.   ...
  7.   if (a) { free(a); a = (int*) NULL; }
  8.   if (b) { free(b); b = (char*) NULL; }
  9.   delete[] c; c = (double*) NULL;
  10. }


 
 - Les boucles for sont-elles moins rentables que les boucles whiles ?

Code :
  1. void my_boucle(int nb)
  2. {
  3.   // cas particulier
  4.   int i = MAX_VALUE;
  5.   for ( ; i--; ) {
  6.      // parcours insignifiant, juste compteur de boucle
  7.   }
  8.   // cas plus classique
  9.   int i = START_VALUE;
  10.   for ( ; i < MAX_VALUE; i++) {
  11.     // parcours ordonné, i peut avoir un sens (index de tableau, ...)
  12.     // peut être adapté pour ressembler à la première manière naturellement plus rentable,
  13.     // mais au prix de calcul arithmétique à chaque tour de boucle ^^
  14.   }
  15.   while (i < MAX_VALUE) {
  16.     ...
  17.     i++;
  18.   }
  19.   ...
  20. }


 
 - Doit-on préféré les switchs au if ?

Code :
  1. void my_conditions(int value)
  2. {
  3.   if (value == 1) {
  4.   }
  5.   else if (value == 8) {
  6.   }
  7.   else if (value == 56) {
  8.   }
  9.   else {
  10.   }
  11.   switch(value) {
  12.   case 1 :
  13.  
  14.     break;
  15.   case 8 :
  16.  
  17.     break;
  18.   case 56 :
  19.  
  20.     break;
  21.   default :
  22.     break;
  23.   }
  24.   ...
  25. }


 
 - Comment utilisé à bon escient l'attribut const ? [ char * / const char * / const char const * ]

Code :
  1. // inutile, pour exemple
  2. const int func1(const int value)
  3. {
  4. }
  5. // utilisation d'une chaîne de caractère juste en lecture
  6. void func2(const char *value)
  7. {
  8. }
  9. // pas forcément très clair pour moi ;)
  10. // pointeur constant sur valeur constante ?
  11. void func3(const char const *value)
  12. {
  13. }


 
 - Pour un objet (instance d'une classe) doit-on préféré un passage en paramètre par valeur, pointeur ou référence ?

Code :
  1. class my_obj
  2. {
  3.   ...
  4. };
  5. // passage par valeur
  6. void func1(my_obj o)
  7. {
  8. }
  9. // passage par pointeur (en lecture/écriture)
  10. void func2(my_obj *po)
  11. {
  12. }
  13. // passage par pointeur (en lecture)
  14. void func2(const my_obj *po)
  15. {
  16. }
  17. // passage par référence (en lecture/écriture)
  18. void func2(my_obj &po)
  19. {
  20. }
  21. // passage par référence (en lecture)
  22. void func2(const my_obj &po)
  23. {
  24. }


 
Voilà déjà quelques sujets, je vais arrêter là pour par trop surcharger mais je souhaiterais que ce topic devienne un sujet ouvert à toutes les solutions pour l'optimisation de code C/C++.

Message cité 2 fois
Message édité par Eriandel le 19-08-2006 à 16:02:39
Reply

Marsh Posté le 19-08-2006 à 13:13:50   

Reply

Marsh Posté le 19-08-2006 à 15:44:02    

Je répond avec ma "petite" expérience de programmeur alors s'il venait aux experts l'envie de me casser ben pas grave au moins je comblerai mes lacunes.
 

Eriandel a écrit :

- L'initialisation des variables d'une fonction/méthode est-elle utile (au delà de la sécurité qu'elle peut procurer) ou un gaspillage de temps ?


C'est une sécurité. La perte de performance est minime. Il vaut mieux initialiser un pointeur à NULL avant de l'utiliser que le laisser à une valeur indéfinie : on détectera plus facilement un problème d'initialisation du pointeur. En effet un pointeur nul est moins dangereux qu'un pointeur non initialisé.

Eriandel a écrit :

- L'allocation dynamique d'un tableau d'objet simple (int/double/char ...) est-elle plus rapide en faisant un malloc, calloc, ou un new ?


Pas d'opinion. Il me semble que new sur un type simple fait un simple malloc.

Eriandel a écrit :

- Les boucles for sont-elles moins rentables que les boucles whiles ?


Ca dépend de "rentable". Elles ont surtout des usages différents:
for devrait être réservé pour un parcours indicé. La boucle while et do-while pour les autres usages de boucles. Une mauvaise pratique est d'utiliser for pour faire un peu tout et n'importe quoi.
Ici le gain est avant tout la lisibilité. Heu au passage, faut laisser tomber les variables i, j, etc dans tes boucles car trop peu évocateur. A la place préfère des variables du type PersonIndex. Cela s'avère être un choix judicieux quand les boucles sont imbriquées.
Exemple à ne pas faire : ca = tab[i][j] alors que ChiffreAffaires = Ventes[IndexVendeur][JourDeLaSemaine] est nettement plus explicite.

Eriandel a écrit :

- Comment utilisé à bon escient l'attribut const ? [ char * / const char * / const char const * ]


J'ai vu la dernière écriture uniquement dans des ouvrages jamais dans du code.
L'utilisation du const revet une signification logique. Il s'applique à des variables, pointeurs et méthodes de classes.

Eriandel a écrit :

const int func1(const int value)


Un const sur un type simple est rare, surtout pour un retour de fonction (pas cohérent d'un point de vue logique "pourquoi le code de retour doit il rester constant ?" ). Le const devant value est légitime mais encore une fois, je le vois rarement dans du code.

Eriandel a écrit :

void func2(const char *value)


Le const ici permet de protéger (relativement bien) la variable contre un accès en écriture. M'enfin en cassant le const, tu peux quand même faire une bêtise...
 
A utiliser pour les paramètres d'entrée.

Eriandel a écrit :

void func3(const char const *value)


Le pointeur et la chaîne sont constants. On ne peut ni changer la valeur du pointeur (comme dans l'exemple précédent) ni la chaîne C référencée par le pointeur.

Eriandel a écrit :

- Pour un objet (instance d'une classe) doit-on préféré un passage en paramètre par valeur, pointeur ou référence


Les usages sont différents. Je fais une analogie avec les associations dans le modèle logique (terminologie UML)
 
par valeur : la méthode manipule une copie de l'objet pas l'objet lui-même. Une copie d'un objet peut être un processus couteux voir impossible (désactiver le constructeur de copie et l'opérateur d'affectation en les déclarant private). Cela n'a pas d'incidence pour les type symple c'est pourquoi tu ne verras pas (enfin j'espère) ce genre d'écriture : const long & lValue.
 
par référence : l'objet passé en paramètre ne peut être NULL. L'objet peut être modifié (si tel n'était pas le but, corriger en préfixant d'un const pour prévenir les bêtises) -> cardinalité '1'.
 
par pointeur : l'objet passé en paramètre peut être NULL ET CELA A UNE SIGNIFICATION DETERMINEE -> cardinalité '0..1'.
 
Concernant l'usage de const : il s'agit d'un artifice de programmation pour faire prendre en compte des contraintes conceptuelles par le compilateur. Accessoirement c'est aussi moyen propre de documenter le code. Par exemple en ajoutant un const devant un paramètre, je dis "regardez ce paramètre : vous ne devez pas la modifier". A la fin d'une méthode, cela dit "Cette méthode n'est pas censée changer l'état interne de la classe".
 
 
Voici deux ouvrages qui m'ont bien aidé pour répondre, en mon temps, à ces questions:
"Effective C++" de Scott Meyers (et son second opus More Effective C++).
"Tout sur le code (VO Code Complete)".

Message cité 1 fois
Message édité par slash33 le 19-08-2006 à 16:08:21
Reply

Marsh Posté le 19-08-2006 à 16:22:37    

Toute expérience, aussi petite soit-elle, mérite d'être partagée ! :)
 
Je partage toutes les remarques que tu as pu mettre.
En fait je viens juste de terminé un développement C++ dans lequel j'ai appliqué toutes ces notions, et je remets en cause les principes utilisés pour voir s'il y avait mieux à faire, point de vue solidité/lisibilité du code et performances.
 
D'ailleurs je te remercie pour les référénces sitées, que je ne connaissait même pas (la honte ^^)
 
Et j'ai trouvé deux trois références sur le web donnant un petit aperçu des conseils/techniques que je cherche à voir fusionner dans ce topic ^^
 
// Optimisation du code par des techniques simples mais apparement efficaces
http://www.custard.org/~andrew/optimize.php
 
// L'utilisation de la technique de décalage de bit peut parfois rendre bien des services (gestion des flags notament)
http://www.custard.org/~andrew/programming/bitwise/
 
// COnseils techniques plus complet
http://www.eventhelix.com/Realtime [...] PPCode.htm
 
Malhereusement toutes ces pages sont sous copyright, j'en ferait certainement une traduction
 

Reply

Marsh Posté le 19-08-2006 à 16:27:52    

Citation :

- L'allocation dynamique d'un tableau d'objet simple (int/double/char ...) est-elle plus rapide en faisant un malloc, calloc, ou un new ?


 
n'utilise jamais calloc ou malloc en C++ ! ca ne fais pas la meme chose, mais pour la simple allocation new est au moins aussi rapide que malloc
 

Citation :

- Les boucles for sont-elles moins rentables que les boucles whiles ?


 
non, il y a aucune raison
 

Citation :

- Doit-on préféré les switchs au if ?


 
oui
 

Citation :

- Comment utilisé à bon escient l'attribut const ? [ char * / const char * / const char const * ]


 
tout les const sont utiles, meme pour func1 (certain pensent que c'est inutile de specifier const des parametres en valeur mais ca n'a rien à voir), pour func3 c'est bien un pointeur constant sur un char constant
utilises const au maximun, plus  il y a de const et plus ton compilateur peut optimiser
 

Citation :

- Pour un objet (instance d'une classe) doit-on préféré un passage en paramètre par valeur, pointeur ou référence ?


 
reference (constante si possible)

Reply

Marsh Posté le 19-08-2006 à 16:47:57    

const char const* c'est une erreur, je suppose que vous parlez tous de char const* const
 

Reply

Marsh Posté le 19-08-2006 à 16:49:31    

90% des considérations sont "futiles".
 
ce que tu dois utiliser, c'est l'écriture la plus concise exprimant ta volonté.
 
par exemple entre le "if/else if" et le "switch()/case", le "switch()" décrit mieux une volonté alors que le "if/else if" décrit plus une implémentation possible via une multitude d'instruction minimalistes du langage.
 
après c'est au cas pas cas où un "if/else" sera plus concis qu'un "switch/case" - ou pas.
 
pareil, pour passer un objet consistant en taille, la référence est plus une déclaration d'intention, alors que le pointeur est un plus une implémentation possible de la même intention.
 
plus le code que tu fais se rapproche d'une possible implémentation que d'une intention, moins le compilateur aura des opportunitées pour choisir une implémentation optimale.
 
enfin c'est mon avis a 2 balles :D


Message édité par bjone le 19-08-2006 à 16:50:01
Reply

Marsh Posté le 19-08-2006 à 16:49:37    

Citation :

tout les const sont utiles, meme pour func1 (certain pensent que c'est inutile de specifier const des parametres en valeur mais ca n'a rien à voir)


 
Pourrais-tu être plus précis sur les cas d'emploi/utilité du const dans une fonction du type

Code :
  1. const int func1(const int value)
  2. {
  3. }


Si je ne m'abuse, le const  sur le int value en paramètre indique que l'entier value qui sera copié dans le tas sera constant, mais vu qu'il s'agit d'une copie quel peut en être l'intérêt ?  
Celui du retour aurait un sens plus logique.
 

Citation :

pour func3 c'est bien un pointeur constant sur un char constant


 
C'est une notion que je ne parviens pas à bien saisir
 
const char* indique que le pointeur ne pourra être modifié (sauf si on utilise un abus de c++)
const char const * voudrait dire quoi ? que l'on ne peut modifier ni le pointeur, ni le contenu (du tableau ou seulement du premier élément ?)
 

Reply

Marsh Posté le 19-08-2006 à 16:58:17    

Eriandel a écrit :

Citation :

tout les const sont utiles, meme pour func1 (certain pensent que c'est inutile de specifier const des parametres en valeur mais ca n'a rien à voir)


 
Pourrais-tu être plus précis sur les cas d'emploi/utilité du const dans une fonction du type

Code :
  1. const int func1(const int value)
  2. {
  3. }


Si je ne m'abuse, le const  sur le int value en paramètre indique que l'entier value qui sera copié dans le tas sera constant, mais vu qu'il s'agit d'une copie quel peut en être l'intérêt ?  
Celui du retour aurait un sens plus logique.
 

Citation :

pour func3 c'est bien un pointeur constant sur un char constant


 
C'est une notion que je ne parviens pas à bien saisir
 
const char* indique que le pointeur ne pourra être modifié (sauf si on utilise un abus de c++)
const char const * voudrait dire quoi ? que l'on ne peut modifier ni le pointeur, ni le contenu (du tableau ou seulement du premier élément ?)


 
entre deux prototypes où des fonctions sont dans un autre module objet:
 
void func1(const int value);
void func2(int value);
 
a la compilation d'un module objet employant ces fonctions, le compilateur saura qu'au retour de func1, 'value' n'aura pas été altéré et n'aura pas a être sauvegardé a l'appel et restauré au retour dans certaines situations (style un passage par un registre).
 
donc en plus de "sécurité" intrinsèque a la fonction envers le code du programmeur lors de la compilation, ça peut servir de déclaration d'intention permettant au compilo de trouver des optimisations.
 

Reply

Marsh Posté le 19-08-2006 à 16:58:39    

Citation :

const char const* c'est une erreur, je suppose que vous parlez tous de char const* const


 
Non, je viens de trouver une réponse à cette question :
 

Code :
  1. char *p              = "Hello";  // non-const pointer, non-const data
  2. const char *p        = "Hello";  // non-const pointer, const data
  3. char * const p       = "Hello";  // const pointer, non-const data
  4. const char * const p = "Hello";  // const pointer, const data


Bien que je ne voit pas comment le compilo peut programmer un tel comportement  :D

Reply

Marsh Posté le 19-08-2006 à 17:04:28    

Eriandel a écrit :

Citation :

const char const* c'est une erreur, je suppose que vous parlez tous de char const* const


 
Non, je viens de trouver une réponse à cette question :
 

Code :
  1. char *p              = "Hello";  // non-const pointer, non-const data
  2. const char *p        = "Hello";  // non-const pointer, const data
  3. char * const p       = "Hello";  // const pointer, non-const data
  4. const char * const p = "Hello";  // const pointer, const data




 
Et à quel opus se rapporte const char const* ?

Reply

Marsh Posté le 19-08-2006 à 17:04:28   

Reply

Marsh Posté le 19-08-2006 à 17:10:47    

Citation :

entre deux prototypes où des fonctions sont dans un autre module objet:
 
void func1(const int value);
void func2(int value);
 
a la compilation d'un module objet employant ces fonctions, le compilateur saura qu'au retour de func1, 'value' n'aura pas été altéré et n'aura pas a être sauvegardé a l'appel et restauré au retour dans certaines situations (style un passage par un registre).
 
donc en plus de "sécurité" intrinsèque a la fonction envers le code du programmeur lors de la compilation, ça peut servir de déclaration d'intention permettant au compilo de trouver des optimisations.


 
Très interressant !
 
Durant mon développement, j'ai utilisé de manières outrancières les const, sur tous les types, cependant j'ai constaté un comportement très bizarre qui m'a fait abandonné avec beaucoup d'amertume cette accoutumance :
 
Soit :

Code :
  1. class A {
  2.   meth1(const int);
  3.   meth1(const char*);
  4.   meth1(const A& );
  5. };


 
Si une compilation réussie avec l'utilisation d'une seule de ces méthodes dans un programme tel que :

Code :
  1. void func1(void)
  2. {
  3.   A my_obj;
  4.   int test_value = 0;
  5.   char *str_test = strdup("c'est en forgeant que l'on devient forgeron." );
  6.   my_obj.meth1(test_value);
  7.   my_obj.meth1(str_test);
  8. }


Là j'obtiens carrément une erreur à la compilation m'inquant une ambiguïté dans mes prototypes de méthodes de la classe A !! (remarque je réfère ça à la première solution)
 
Je suppose que c'est due à la taille des objets passé en paramètre (4 octets chacun)
Pourquoi ne s'interresse t-il pas au type !
Une des faiblesse du C (et une force) pas de typage réelement fort.


Message édité par Eriandel le 19-08-2006 à 17:15:59
Reply

Marsh Posté le 19-08-2006 à 17:18:58    

Citation :

Et à quel opus se rapporte const char const* ?


 
J'ai trouver cela dans une référence que m'a conseillé slash33 (merci encore) : "Effective C++"
 
Extrait :
 

Citation :


Item 21:  Use const whenever possible. ¤ Item E21, P1
 
The wonderful thing about const is that it allows you to specify a certain semantic constraint — a particular object should not be modified — and compilers will enforce that constraint. It allows you to communicate to both compilers and other programmers that a value should remain invariant. Whenever that is true, you should be sure to say so explicitly, because that way you enlist your compilers' aid in making sure the constraint isn't violated. ¤ Item E21, P2
 
The const keyword is remarkably versatile. Outside of classes, you can use it for global or namespace constants (see Items 1 and 47) and for static objects (local to a file or a block). Inside classes, you can use it for both static and nonstatic data members (see also Item 12). ¤ Item E21, P3
 
For pointers, you can specify whether the pointer itself is const, the data it points to is const, both, or neither: ¤ Item E21, P4

Code :
  1. char *p              = "Hello";          // non-const pointer,
  2.                                                // non-const data5
  3.       const char *p        = "Hello";          // non-const pointer,
  4.                                                // const data
  5.       char * const p       = "Hello";          // const pointer,
  6.                                                // non-const data
  7.       const char * const p = "Hello";          // const pointer,
  8.                                                // const data


This syntax isn't quite as capricious as it looks. Basically, you mentally draw a vertical line through the asterisk of a pointer declaration, and if the word const appears to the left of the line, what's pointed to is constant; if the word const appears to the right of the line, the pointer itself is constant; if const appears on both sides of the line, both are constant.

Reply

Marsh Posté le 19-08-2006 à 17:35:46    

Eriandel a écrit :


J'ai trouver cela dans une référence que m'a conseillé slash33 (merci encore) : "Effective C++"


 
non mais ce qu'il veut dire c'est que const char == char const, tu t'était trompé en ecrivant char const char *

Reply

Marsh Posté le 19-08-2006 à 17:38:38    

Je ne vois toujours pas apparaitre const char const* :-(
bon, j'arrête de jouer aux devinettes, sinon on va pas en finir.
dans const char const*, le 2ème const se rapporte à ce qui le précède : char
le 1er const se rapporte à ce qui le suit immédiatement -- puisque rien ne le précède -- c'est à dire : char.
Bref.

Reply

Marsh Posté le 19-08-2006 à 17:39:48    

Oups je crois que j'avais mal lu toutes mes excuses

Reply

Marsh Posté le 19-08-2006 à 17:39:57    

Citation :

Là j'obtiens carrément une erreur à la compilation m'inquant une ambiguïté dans mes prototypes de méthodes de la classe A !! (remarque je réfère ça à la première solution)
 
Je suppose que c'est due à la taille des objets passé en paramètre (4 octets chacun)


 
pas du tout, rassure toi le C++ est assez strict et le typage est bien plus fort qu'en C, tu pourrais donner le messages d'erreur du compilateur ?

Reply

Marsh Posté le 19-08-2006 à 17:45:59    

Citation :

Error: Overloading ambiguity between "A::meth1(const int)" and "A::meth1(const char*)"


Voilà typiquement l'erreur obtenue. J'ai due la réinterprétée car je n'ai pas de quoi reproduire l'erreur ^^ .

Reply

Marsh Posté le 19-08-2006 à 18:00:17    

bizarre :??:

Reply

Marsh Posté le 19-08-2006 à 18:00:44    

skoi comme compilo ? vc6 par hasard ? :D

Reply

Marsh Posté le 19-08-2006 à 18:04:31    

slash33 a écrit :

Un const sur un type simple est rare, surtout pour un retour de fonction (pas cohérent d'un point de vue logique "pourquoi le code de retour doit il rester constant ?" ).


Pour empécher l'appel imbriqué d'une fonction non const sur l'objet renvoyé. C'est une stratégie qui est employé notament pour implémenter operator++(int).
 

slash33 a écrit :

Le const devant value est légitime mais encore une fois, je le vois rarement dans du code.


et pour cause, le compilateur n'en profite pas vraiment, puisqu'il utilise souvent d'autres heuristiques pour s'assurer qu'un objet n'est pas modifié.

Reply

Marsh Posté le 19-08-2006 à 18:05:25    

Non, il s'agit du "fameux" compilateur SPARC Solaris Sun08 CC 5.8 !
Remarque j'obtenais la même erreur sous le compilateur HP-UX 11.11 aCC
 
Je devrait tester sous g++, ce que j'aimerais faire mais j'ai, comme qui dirait, un petit problème ^^
 
http://forum.hardware.fr/hardwaref [...] 2174-1.htm
 

Reply

Marsh Posté le 19-08-2006 à 23:07:26    

Enfin, bon , ca reste du branlage de mouche. Uen fois compilé en -O3, tu fais pas la difference entre aucune de ces choses.
 
L'optimsiation c'ets pas trop trop ça hein [:dawa]

Reply

Marsh Posté le 24-02-2007 à 16:02:43    

Salut tout le monde!
A propos de l'optimisation des boucles...
Regardez leur traduction en assembleur par votre compilateur...  :lol:  
On voit tout de suite que c'est optimisable.  :whistle:  
On peut gagner quelques octets d'instruction à chaque tour...  :whistle:

Reply

Marsh Posté le 24-02-2007 à 17:38:58    

Je vais ajouter quelques points sur l'optimisation mais en terme d'optimisation en vitesse.
 
Le plus important bien connaitre les particularité du compilateur et du processeur (ex: le compilateur proprio d'ARM donne de bien meilleur résutat que GCC pour les processeurs ARM); dans cette lignée, savoir comment avoir le code assembleur généré de son code C++.
La documentation du fondeur donne quelques fois quelques pistes pour écrire un code C optimisé.
 
Connaitre le nombre de registre du processeur peut-etre important, par exemple pour savoir le nombre de paramètre limite avant que le compilateur n'empile tous les paramètres dans la pile.
 
Quelques mots clés :
# inline :

Citation :

Une fonction inline(en ligne) est une fonction dont le code est inséré directement dans le flux de code de la fonction appelante. Comme les macro #define, les fonctions inline améliorent la vitesse d'exécution en éliminant l'en-tête d'appel et (surtout!) en permettant au compilateur d'optimiser  à traversl'appel ("intégration procédurale" ).


La fonction inline n'est pas toujours insérée dans le code par le compilateur !!! Il y a certain compilateur qui permettent le mot clé __forceinline
 
# pure :

Citation :

Une fonction est pure si elle retourne toujours la même valeur pour les mêmes paramètres. C'est un composant de la transparence référentielle


Tous les compilateurs ne supportent pas ce mot clé. La fonction doit etre sans effet de bord (ie: la valeur de retour ne dépend seulement que des paramètres)
 
Ainsi ce code :
pure int f(x) {.......}
int z = f(x)*f(x)
sera optimisé par le compilateur comme :
int y = f(x);
int z = y*y

Reply

Marsh Posté le 24-02-2007 à 23:07:22    

patemino a écrit :

Salut tout le monde!
A propos de l'optimisation des boucles...
Regardez leur traduction en assembleur par votre compilateur...  :lol:  
On voit tout de suite que c'est optimisable.  :whistle:  
On peut gagner quelques octets d'instruction à chaque tour...  :whistle:


 
Et ? quel est le gain ? quel est le gain en PRODUCTIVITE , en MAINTENANCE ?

Reply

Marsh Posté le 24-02-2007 à 23:08:48    

Olivier51 a écrit :


Guère de compilateurs supportent ce mot clé. La fonction doit etre sans effet de bord (ie: la valeur de retour ne dépend seulement que des paramètres)


 
[:aloy] et c'est bein dommage :/

Reply

Marsh Posté le 24-02-2007 à 23:39:23    

Joel F a écrit :

Et ? quel est le gain ? quel est le gain en PRODUCTIVITE , en MAINTENANCE ?


Holaaa doucement c'est pas la peine de crier...  :non: Zen !
C'est juste une plaisanterie...

Code :
  1. compteur = 0;
  2. while ( compteur < 10)
  3.         ++compteur;


se traduit généralement en :

Code :
  1. xor ax,ax
  2. debut:
  3.         cmp ax,10
  4.         jae fin
  5.         inc ax
  6.         jmp debut
  7. fin:


Alors qu'on pourrait simplement écrire :

Code :
  1. mov cx, 10
  2. debut:
  3.         loop debut
  4. fin:


Ce qui est drôle c'est que la version avec LOOP est plus rapide que la version DEC/JNE (ou autres JUMP selon conditions) sauf sur P4.

 

De toute façon, la seule optimisation qui se tient est, à mon goût, au niveau algorithmique. Le reste ressemble plus à du chipotage qu'autre chose.
Et pour ce qui est de préférer les switch aux if multi-imbriqués... Je n'appellerais pas cela de l'optimisation mais plutôt prendre des bonnes habitudes de programmation. Mais le inlining reste intéressant pour les "petites" fonctions.

Message cité 1 fois
Message édité par patemino le 24-02-2007 à 23:53:02
Reply

Marsh Posté le 24-02-2007 à 23:52:58    

Olivier51 a écrit :


# pure :

Citation :

Une fonction est pure si elle retourne toujours la même valeur pour les mêmes paramètres. C'est un composant de la transparence référentielle




D'où est issue cette définition ? En tout cas, ce n'est pas la définition que donne GCC pour __attribute__(( pure )).

Reply

Marsh Posté le 25-02-2007 à 00:35:58    

Eriandel a écrit :

Citation :

tout les const sont utiles, meme pour func1 (certain pensent que c'est inutile de specifier const des parametres en valeur mais ca n'a rien à voir)


 
Pourrais-tu être plus précis sur les cas d'emploi/utilité du const dans une fonction du type

Code :
  1. const int func1(const int value)
  2. {
  3. }


Si je ne m'abuse, le const  sur le int value en paramètre indique que l'entier value qui sera copié dans le tas sera constant, mais vu qu'il s'agit d'une copie quel peut en être l'intérêt ?  

t'abuses :o

Reply

Marsh Posté le 25-02-2007 à 11:53:14    

++fab a écrit :

D'où est issue cette définition ? En tout cas, ce n'est pas la définition que donne GCC pour __attribute__(( pure )).


 
c'est la définition fonctionelle de la chose [:spamafote]

Reply

Marsh Posté le 25-02-2007 à 12:34:36    

Joel F a écrit :

c'est la définition fonctionelle de la chose [:spamafote]


 
Selon GCC, une fonction pure a le droit d'avoir comme entrée autre chose que ses paramètres (variables globales, etc. )
Une fonction const -selon GCC- correspond à la définition de pure quotée précedemment.

Reply

Marsh Posté le 25-02-2007 à 12:46:56    

++fab a écrit :

Selon GCC, une fonction pure a le droit d'avoir comme entrée autre chose que ses paramètres (variables globales, etc. )
Une fonction const -selon GCC- correspond à la définition de pure quotée précedemment.


 
bah GCC et les gens du fonctionelle ont juste pas les mêmes normes :/ Ce qui ets fort regrettable ici.

Reply

Marsh Posté le 25-02-2007 à 15:21:25    

++fab a écrit :

D'où est issue cette définition ? En tout cas, ce n'est pas la définition que donne GCC pour __attribute__(( pure )).


Wikipedia (http://fr.wikipedia.org/wiki/Fonction_pure)
J'avais d'autres definitions mais elles étaient en anglais et semblables ...

Reply

Marsh Posté le 25-02-2007 à 15:30:26    

On parle bien de potentiellement impure pour les fonctions à effet de bord.
Cela signifie donc qu'il existe des fonctions à effet de bord qui sont pourtant pures.


Message édité par patemino le 25-02-2007 à 15:31:00
Reply

Marsh Posté le 26-02-2007 à 06:16:05    

Si on ne considère pas un couple code + compilateur précis, tout celà revient à se tirer joyeusement sur la nouille.
 
Ensuite
1) on profile.
2) on désassemble les hotspots repérés.
3) on ajuste le code.
4) goto 1)
pour éviter de perdre trop de temps.
 
Si vos yeux aussi font grève à force de lire ce que pond objdump - attention publicité ehontée - il y a embroider, http://ompf.org/stuff/embroider/

Reply

Marsh Posté le 26-02-2007 à 10:51:12    

Excellent programme. Une idée sur les modifs à faire pour porter ça sur d'autres archs ?

Reply

Marsh Posté le 26-02-2007 à 11:05:29    

Taz a écrit :

Excellent programme. Une idée sur les modifs à faire pour porter ça sur d'autres archs ?


Normalement pas grand chose, même si je dois avouer que le parsage est fait un peu à l'arrache, voir program_t:: parse_op. Je ne me suis pas trop foulé vu que dépendre du format exact que peut produire un autre programme est tjs, hmm, risqué.
 
Ensuite il faut categoriser les operations pour reconnaitre les branches (saut et appels), ce qui est du ressort de operation_t::get_operation_type.
 
Le reste doit fonctionner, si tant est que le 'demanglage' des fonctions reste raisonnable.
 
Tout patch est le bienvenue :)
 
edit: saleté de smileys


Message édité par tbp le 26-02-2007 à 11:06:25
Reply

Marsh Posté le 02-03-2007 à 08:43:15    

Bonjour, toute petite suggestion: choisir des couleurs différentes pour les lignes sur la gauche (voire des styles de pointillés pour l'impression).

Reply

Marsh Posté le 02-03-2007 à 17:31:14    

- L'initialisation des variables d'une fonction/méthode est-elle utile (au delà de la sécurité qu'elle peut procurer) ou un gaspillage de temps ?
oui et ce n'est certainement pas un gaspillage de temps
 
 - L'allocation dynamique d'un tableau d'objet simple (int/double/char ...) est-elle plus rapide en faisant un malloc, calloc, ou un new ?
non
 
 - Les boucles for sont-elles moins rentables que les boucles whiles ?
non
 
 - Doit-on préféré les switchs au if ?
oui
 
 - Comment utilisé à bon escient l'attribut const ? [ char * / const char * / const char const * ]
char* -> pointeur modifiable sur des données modifiables
const char * -> pointeur modifiable sur des données constantes
const char const * -> à ne pas utiliser même si ton compilateur l'accepte
char* const -> pointeur constant sur des données modifiables
const char* const -> pointeur constant sur des données constantes
 
 - Pour un objet (instance d'une classe) doit-on préféré un passage en paramètre par valeur, pointeur ou référence ?
si les trois existent c'est qu'il doit y avoir une raison !
 
Tu dis que tu es perfectionniste ? tu développe en cpp depuis quand déja ? commence par lire ça  
http://casteyde.christian.free.fr/ [...] book1.html
et ça
http://mindview.net/Books/TICPP/ThinkingInCPP2e.html
 
de rien.

Reply

Marsh Posté le 03-03-2007 à 00:31:11    

tithub a écrit :


 - Doit-on préféré les switchs au if ?
oui


 
source :o preuve :o resultats :o car je vois VRAIMENT pas dans quel cas cela est vrai  
(je suis curieux hein, faut prendre la question mal ^^)
 
le premier lien, je troue moche qu'on commence un corus de C++ par du rappel de C et ud ùmelange moche. Un bon cours de C++ ne devrait MEME PAS parler des pointeurs avant d'arriver au polymorphisme et forcer l'utilsiation de string et vector pr ce qui est de gerer les chaines//tableaux dynamiques AMHA.

Message cité 3 fois
Message édité par Joel F le 03-03-2007 à 00:32:36
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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