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 :
que vaut-il mieux utiliser : les enums ou les static ?
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 ; };
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 resprsente l'ordre de dveloppement 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 ; }
Partager