IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

méta-programmation et chronomètre


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut méta-programmation et chronomètre
    Bonjour,

    je développe des coeurs de calculs (résolution d'équations) et je suis donc très intéressé par la minimisation des temps de calculs. J'ai lu l'article de Laurent Gomila sur la méta-programmation (http://loulou.developpez.com/tutoriels/cpp/metaprog/). Cet article est très clair mais j'ai cependant quelques questions :

    1) tout doit connu par le compilateur. Certes. Mais dans mon cas toutes mes inputs sont lues à partir de fichiers texte (les fichiers d'initialisation). Donc le prétraitement consiste à lire ces fichiers, le traitement à effectuer les calculs et le post traitements à la visualisation graphique des résultats. Mais donc, à la compilation, rien n'est connu par le compilateur car tout est lu à partir de fichiers texte. Comment appliquer la méta-programmation ? Car les exemples donnés par Laurent Gomila dans son article sont donnés pour comprendre ce qu'est la méta-programmation. Il est rare de calculer factorielle(4). En général on fait plutôt factorielle(n) où n est lu à partir d'un fichier texte (donc inconnu à la compilation)

    2) dans son article, Laurent Gomila utilise des struct et des enum. Sur le site suivant http://fr.wikipedia.org/wiki/C_plus_plus il y a un exemple de méta-programmation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template< size_t N >
    struct CalcCompileTime
    {
        static size_t Fact = N * CalcCompileTime< N - 1 > ;
    };
     
    template<0>
    struct CalcCompileTime<0>
    {
        static size_t Fact = 1 ;
    };
    que vaut-il mieux utiliser : les enums ou les static ?

    3) j'ai codé un exemple donné par Laurent Gomila (le cosinus). C'est plus lent que le "simple" cosinus de <cmath> (d'un facteur 10). Où se trouve mon erreur ? Les fichiers sont en pièce jointe

    4) La méta-programmation étant plus rapide que la programmation "normale", j'en déduis donc qu'il vaut mieux utiliser des librairies de calculs comme Boost plutôt que lapack non ?

    Merci pour vos réponses, et je vais continuer à étudier de près cette technique de programmation car elle m'a l'air très intéressante !

    Code main.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    #include <cmath>
    #include <iostream>
     
    using namespace std;
     
    double GetClock ( void );
     
    #define ITERMAX 1000000
     
     
    template <int I> inline double Factorielle()
    {
        return I * Factorielle<I - 1>();
    }
     
    template <> inline double Factorielle<0>()
    {
        return 1.0;
    }
     
    template <int N> inline double Puissance(double x)
    {
        return x * Puissance<N - 1>(x);
    }
     
    template <> inline double Puissance<0>(double x)
    {
        return 1.0;
    }
     
    // Ici aussi, N resprŽsente l'ordre de dŽveloppement
     
    template <int N> inline double Cosinus(double x)
    {
        return Cosinus<N - 1>(x) + (N % 2 ? -1 : 1) * Puissance<2 * N>(x) / Factorielle<2 * N>();
    }
     
    template <> inline double Cosinus<0>(double x)
    {
        return 1.0;
    }
     
    int main(void)
    {
      double x = 3.14159265358979;
      double sum = 0.;
      double start, end;
      double d;
     
      cout<<"version non metaprogrammation"<<endl;
     
      for(int i = 0 ; i < ITERMAX ; i++)
      {
    	start = GetClock();
    	d = cos(x);
    	end = GetClock();
    	sum += end - start;
      }
     
      cout<<"d = "<< d <<endl;
     
      cout<<"chrono = " << sum / ITERMAX << endl;
     
      cout<<"version metaprogrammation"<<endl;
     
      sum = 0.;
     
      for(int i = 0 ; i < ITERMAX ; i++)
      {
    	start = GetClock();
    	d = Cosinus<7>(x);
    	end = GetClock();
    	sum += end - start;
      }
     
      cout<<"d = "<< d <<endl;
     
      cout<<"chrono = " << sum / ITERMAX << endl;
     
      return 0;
    }
    Code chrono.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    /******************************************************************************
     *                                                                            *
     *                           Import Header Files                              *
     *                                                                            *
     ******************************************************************************/
     
    #include<stdlib.h>
    #include<stdio.h>
    #include <time.h>
    #include <sys/time.h>
    #if defined LINUX || defined MAC
    #define UNIX
    #include <unistd.h>
    #endif
     
    #include<string.h>
    #include <errno.h>
     
    /******************************************************************************
     *                                                                            *
     *                             Private Macros                                 *
     *                                                                            *
     ******************************************************************************/
     
    #define CLOCKERROR    \
    do                    \
    {                     \
      fprintf( stderr, "%s:%d : GetClock() failed (%s)\n",__FILE__,__LINE__,strerror( errno ));\
      exit(EXIT_FAILURE); \
    }                     \
    while(0)
     
    /******************************************************************************
     *                                                                            *
     *                      Public Functions Implementation                       *
     *                                                                            *
     ******************************************************************************/
     
    double GetClock ( void )
    {
    /*
      This function returns the time (like clock()), but it returns the absolute
      real time (whereas clock() returns the time compared to the program). It
      returns the time in seconde with a precision until the micro-seconde.
     
      It returns -1 if there was an error
      
      source : http://www.developpez.net/forums/showthread.php?t=324756
     
     */
     
      double d=-1. ;
    #ifndef UNIX
    #ifdef WINDOWS
      struct timeval tval ;
      struct timezone *tz=NULL ;
      timerclear(&tval);
     
      if ( gettimeofday(&tval, tz) ) CLOCKERROR;
     
      d = ((double)(tval.tv_usec)/1000000.0) ;
      d = (double) tval.tv_sec + d ;
    #else /* neither WINDOWS nor UNIX are defined */
      struct timespec cur_time ;
     
      if (clock_gettime(CLOCK_REALTIME, &cur_time)) CLOCKERROR;
     
      d = ((double)(cur_time.tv_nsec)/1000.0) / 1000000.0 ;
      d = (double) cur_time.tv_sec + d ;
    #endif /* end #ifdef WINDOWS */
    #else  /* UNIX is defined */  
      struct timeval tval ;
      struct timezone *tz=NULL ;
      timerclear(&tval);
     
      if ( gettimeofday(&tval, tz) ) CLOCKERROR;
     
      d = ((double)(tval.tv_usec)/1000000.0) ;
      d = (double) tval.tv_sec + d ;
    #endif /* end #ifndef UNIX */
     
      return d ;
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Mais donc, à la compilation, rien n'est connu par le compilateur car tout est lu à partir de fichiers texte. Comment appliquer la méta-programmation ?
    Tu ne peux pas. Comme tu l'as dit toi-même, pour faire de la méta-programmation il faut tout connaître à l'avance (à la compilation) et non seulement à l'exécution.
    Boost ftw

  3. #3
    Membre à l'essai
    Développeur informatique
    Inscrit en
    Février 2009
    Messages
    15
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2009
    Messages : 15
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par salseropom Voir le message
    3) j'ai codé un exemple donné par Laurent Gomila (le cosinus). C'est plus lent que le "simple" cosinus de <cmath> (d'un facteur 10). Où se trouve mon erreur ? Les fichiers sont en pièce jointe
    Tu essaies de comparer deux fonctions identique qui n'ont peut etre pas le meme algorithm et donc pas forcement les memes performance. Le test que tu as realise montre juste la fonction cos de cmath est dix fois plus rapide que ton implementation. Ce n'est pas concluant.
    Si tu veux voir la difference de performance il faut que tu implementes ton propre cosinus (sans template) utilisant le meme algorithm et la tu pourras juger de la performance gagner par ton template.

    PS: desole pour le manque d'accent mais j'ai juste un clavier QWERTY...

  4. #4
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    La méta-programmation, elle est terminée à la compilation. Et le compilo fait autre chose que tes calculs de factorielle ou cosinus à la compilation, tu ne peux pas comparer les temps. Ca sert surtout à calculer des valeurs à la compilation que tu aurais, avant, calculé à l'exécution bien que rien ne dépendait de l'exécution elle-même.

    Si tu veux que ton programme calcule des choses lues dans des fichiers, il faudrait plutôt un méta-compilateur, qui irait remplacer des "balises" dans ton code par les valeurs qu'il irait lire dans les fichiers... Mais bon

    Bref, la méta-programmation pour les calculs ça n'est pas si utilisé que ça. L'astuce c'est après d'utiliser des techniques comme les expressions templates, présentées également dans l'article de Laurent.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Re, merci pour vos éclaicissements. Je vais donc me pencher sur les bibliothèques sitées par Laurent Gomila : la MTL et boost::uBlas

    Merci

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Plop all.

    je me permet de upper un petit peu ce topic car je vais devoir faire des benchs sur le temps de compilation entre du code avec des surcharges "écrites en dur" et du code où les surcharges sont générées à l'aide de boost::pp (donc au moment de la compilation) et je n'ai pas la moinde idée pratique et réaliste pour le faire.

    Car j'ai bien la technique suivante (en pseudo code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    time_t t=time();
    system("make");
    std::cout<<time()-t<<" s"<<std::endl;
    Mais est ce qu'il n'y a pas d'autres moyens, car c'est vraiment de la bidouille ce que je propose .

    Merci.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  7. #7
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    S'il est possible d'utiliser des scripts shell pour le benchmark utilise plutôt la commande Posix "time".
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  8. #8
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Citation Envoyé par seriousme Voir le message
    S'il est possible d'utiliser des scripts shell pour le benchmark utilise plutôt la commande Posix "time".
    Et pourquoi tenter le shell plutôt que time ? Il y a des imprécisions dessus ?
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  9. #9
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    Et pourquoi tenter le shell plutôt que time ? Il y a des imprécisions dessus ?
    Je pense plutôt que seriousme te conseille de passer par le shell plutôt que par un programme C++ pour effectuer ces benchmarks.

  10. #10
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Ca donne plus d'info qu'un simple "time".

    Et de manière plus générale ce type d'opération, le benchmarking, est réalisée via des outils plus souples que C++, tels des langages de scripting shell ou mieux des langages dynamiques comme Python.
    Il n'est en effet pas nécessaire de profiter des performances que peut offrir C++ par rapport aux autres langages en temps normal.
    Cela offre des applications de benchmark plus "métiers", car non polluées par les détails techniques inutiles : les informations de typage statique notamment.

    Après si le benchmark lui-même est soumis à de fortes contraintes de performances, utilise plutôt C++.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  11. #11
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    permet de mesurer le temps exact que prend g++ pour compiler ton programme.

    Tu ne peux pas passer par la métaprogr directement pour ça.

  12. #12
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Si c'est pour voir ce que génèrent tes macros, fais simplement g++ -P -E
    Boost ftw

  13. #13
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    J'utilise ces options pour vérifier que le code que j'écris va bien faire la même chose que le code de base.

    Je souhaitais mesurer l'inffluence de l'utilisation de boost::pp sur le temps de compilation face à du code avec des surcharges en dur.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/01/2010, 10h47
  2. Boucle for en méta-programmation?
    Par Charlemagne dans le forum Langage
    Réponses: 10
    Dernier message: 27/04/2009, 16h48
  3. Méta-programmation en C#
    Par mister3957 dans le forum C#
    Réponses: 2
    Dernier message: 20/09/2008, 11h47
  4. Méta-programmation
    Par nicolas66 dans le forum C++
    Réponses: 19
    Dernier message: 17/03/2006, 18h51
  5. Méta-Programmation - [ structures de données ]
    Par Dam)rpgheaven dans le forum C++
    Réponses: 3
    Dernier message: 03/12/2004, 19h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo