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

  FORUM HardWare.fr
  Programmation
  C++

  pointeur sur fonction membre / switch case

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

pointeur sur fonction membre / switch case

n°1564838
GrosBocdel
Posté le 24-05-2007 à 19:47:46  profilanswer
 

Bonjour les habitués!
Je me disais : plutot que de faire un switch case, je vais faire un tableau de pointeurs sur fonctions membres, et ça va être plus rapide. Ce n'est pas le cas : le calcul avec switch/case est deux fois plus rapide. Pourquoi? Le problème n'a pas l'air d'exister si tout ça se fait à l'extérieur d'une classe.
 
 

Code :
  1. #include <string>
  2. #include <iostream>
  3. #include <vector>
  4. #include <math.h>
  5. #include <ctime>
  6. #define nb 1e7
  7. class test
  8. {
  9.     public:
  10.     test()
  11.     {
  12.         res=0;
  13.         tableau[0]=&test::f0;
  14.         tableau[1]=&test::f1;
  15.         tableau[2]=&test::f2;
  16.         tableau[3]=&test::f3;
  17.         tableau[4]=&test::f4;
  18.         tableau[5]=&test::f5;
  19.        
  20.         for (int i=0;i<nb;i++)
  21.         {
  22.             liste.push_back(i%5);
  23.         }
  24.     }
  25.    
  26.    
  27.     void calc1()
  28.     {
  29.         float t1=clock();
  30.         res=0;
  31.         for (int i=0;i<liste.size();i++)
  32.         {
  33.             int index=liste[i];
  34.             (this->*tableau[index])();
  35.         }
  36.         float t2=clock();
  37.         std::cout<<"duree1 :"<<t2-t1<<" resultat : "<<res<<std::endl;
  38.     }
  39.    
  40.    
  41.     void calc2()
  42.     {
  43.         float t1=clock();
  44.         res=0;
  45.         for (int i=0;i<liste.size();i++)
  46.         {
  47.             int index=liste[i];
  48.             switch(index)
  49.             {
  50.                 case 0: f0();break;
  51.                 case 1: f1();break;
  52.                 case 2: f2();break;
  53.                 case 3: f3();break;
  54.                 case 4: f4();break;
  55.                 case 5: f5();break;
  56.             }
  57.         }
  58.         float t2=clock();
  59.         std::cout<<"duree2 : "<<t2-t1<<" resultat : "<<res<<std::endl;
  60.     }
  61.        
  62.     private:
  63.     void f0(){res+=0;}
  64.     void f1(){res+=1;}
  65.     void f2(){res+=2;}
  66.     void f3(){res+=3;}
  67.     void f4(){res+=4;}
  68.     void f5(){res+=5;}
  69.     double res;
  70.     typedef void (test::*fp)();
  71.     fp tableau[10];
  72.     std::vector<int> liste;
  73. };
  74. int main()
  75. {
  76.     test calcul;
  77.     calcul.calc1();
  78.     calcul.calc2();
  79.     return(0);
  80. }

mood
Publicité
Posté le 24-05-2007 à 19:47:46  profilanswer
 

n°1564841
0x90
Posté le 24-05-2007 à 19:50:56  profilanswer
 

dans le cas avec le switch tu fait un appel direct à une fonction définie directement dans la classe -> inline.
 
Avec un pointeur sur fonction membre placé dans un vector ça devient beaucoup moins facile pour le compilo de savoir qu'il peut faire cet inline ....


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1564853
GrosBocdel
Posté le 24-05-2007 à 20:08:23  profilanswer
 

0x90 a écrit :

dans le cas avec le switch tu fait un appel direct à une fonction définie directement dans la classe -> inline.
 
Avec un pointeur sur fonction membre placé dans un vector ça devient beaucoup moins facile pour le compilo de savoir qu'il peut faire cet inline ....


 
Et je ne peux rien faire pour l'aider?

n°1564858
0x90
Posté le 24-05-2007 à 20:14:17  profilanswer
 

Garde ton switch tout simplement [:spamafote]


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1564862
GrosBocdel
Posté le 24-05-2007 à 20:18:07  profilanswer
 

0x90 a écrit :

Garde ton switch tout simplement [:spamafote]


 
Oui, c'est ce que je vais faire... J'avais pensé à ça en me disant que je pouvais éviter des pages et des pages de switch.
Tant pis  :)

n°1564868
0x90
Posté le 24-05-2007 à 20:23:04  profilanswer
 

Un tableau fait autant de lignes que le switch en gros normalement ....
 
Si jamais t'es sous GCC, que la portabilité du code t'inquiète pas trop et que tu as des séries de valeurs de switch qui appellent la même fonction tu peut utiliser des range.


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1564945
bjone
Insert booze to continue
Posté le 24-05-2007 à 23:38:05  profilanswer
 

c'est une contre-optimisation votre truc car le contexte est bidon.
 
bien sûr si chaque fonction fait 0 ou 1 instruction assembleur (j'adore le res+=0), t'y gagne a faire un gros switch dégueulasse avec la seule instruction inlinée, plustôt qu'un call.
mais avec une fonction qui fait pas juste que nopper, le call depuis un tableau sera insignifiant, et passé un certain nombre de cas de switch, le call sera bien plus économique.
 
change tes res+= par des vraies fonctions (avec des boucles des machins et des bidules), et mets 16,20 fonctions tu vas voir le comportement va s'inverser.

n°1564947
0x90
Posté le 24-05-2007 à 23:48:35  profilanswer
 

bjone a écrit :

c'est une contre-optimisation votre truc car le contexte est bidon.
 
bien sûr si chaque fonction fait 0 ou 1 instruction assembleur (j'adore le res+=0), t'y gagne a faire un gros switch dégueulasse avec la seule instruction inlinée, plustôt qu'un call.
mais avec une fonction qui fait pas juste que nopper, le call depuis un tableau sera insignifiant, et passé un certain nombre de cas de switch, le call sera bien plus économique.
 
change tes res+= par des vraies fonctions (avec des boucles des machins et des bidules), et mets 16,20 fonctions tu vas voir le comportement va s'inverser.


 
Je suis pas trop d'accord, y'a de grandes chances que le switch ( à partir d'une certaine taille et si y'a pas de gros trou vers des valeurs importantes ) soit traduit par le compilo par un tableau, dans ce cas tu garde le temps d'accès constant quelque soit le nombre de switch ET la possibilité d'inliner. Je vois pas trop dans quelle situation alors le déréférencement de pointeur de fonction membre + le call peut alors être moins couteux, par contre j'ai vraiment l'impression que le tableau est une "optimisation" faite main de ce que le compilo ferait, en moins bien à cause de la difficulté accrue d'analyse des pointeurs pour le compilo.
 
( Sinon effectivement le contexte de test est bidon tant qu'il n'est pas exactement la chose qui sera exécutée ;) )


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1564969
Taz
bisounours-codeur
Posté le 25-05-2007 à 08:36:47  profilanswer
 

moi je préfère calc1. Je vois l'intérêt de l'inline ici que parce que les méthodes sont minuscules. Sinon, si elle était de taille plus normale, voire virtuelle, ça n'aurait strictement aucun intérêt.
 
Mais ici le problème, c'est bien que t'as 6 fonctions qui font la même chose à une nuance pres. fais un void f(int inc) { res += inc; } et voilà.

n°1565122
bjone
Insert booze to continue
Posté le 25-05-2007 à 12:38:51  profilanswer
 

0x90 a écrit :

Je suis pas trop d'accord, y'a de grandes chances que le switch ( à partir d'une certaine taille et si y'a pas de gros trou vers des valeurs importantes ) soit traduit par le compilo par un tableau, dans ce cas tu garde le temps d'accès constant quelque soit le nombre de switch ET la possibilité d'inliner. Je vois pas trop dans quelle situation alors le déréférencement de pointeur de fonction membre + le call peut alors être moins couteux, par contre j'ai vraiment l'impression que le tableau est une "optimisation" faite main de ce que le compilo ferait, en moins bien à cause de la difficulté accrue d'analyse des pointeurs pour le compilo.
 
( Sinon effectivement le contexte de test est bidon tant qu'il n'est pas exactement la chose qui sera exécutée ;) )


 
 
on est d'accord que si tu gardes des entiers contigus, le compilo peut utiliser une table de jumps avec les fonctions inlinées.
mais à la moindre irrégularité des cas de switch, le compilo doit basculer vers des tests classiques.
bon après si son cas c'est d'avoir que des case contigus, ça peut être bien, mais à vérifier avec la sortie asm.
 
mais bon avec des vrais fonctions qui font plus de 10 cycles d'horloge, le call du tableau sur les fonctions non inlinées sera déjà moins notable.


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

  pointeur sur fonction membre / switch case

 

Sujets relatifs
est-il possible d'utiliser une fonction de son cru ds une requète SQL?Problème entre argument + fonction + variable + espace
[C] fonction pour remplacer du texte dans une stringfonction recherche de plusieurs éléments
Utilisation d'une fonction..Fonction recursive, Help
[debutant] pointeurMAJ les valeurs retournées par une fonction
quel est la fonction fopen en C# ?Probleme de message d'erreur sur une fonction SNMP
Plus de sujets relatifs à : pointeur sur fonction membre / switch case


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