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 ;
}