Bonsoir,
je constate une nette perte de performances selon la manière dont je définis le destructeurs de mes classes de base et je ne comprends pas pourquoi.
J'ai une classe de base Number,
dont hérite une classe générique Real<T> (à terminer) :
Code : 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 #ifndef _NUMBER_HPP #define _NUMBER_HPP /*! * \class Number * \brief This is the base class for all real numbers (including integers). * \warning This class is not abstract so as to maintain good performance. */ class Number { protected: /*! * \fn Number() * \brief default constructor * \warning this constructor MUST NOT be public */ Number(){;}; }; //////////////////////////////////////////////////////////////////////////////// #endif /* _NUMBER_HPP */
Cette dernière classe sert à représenter les nombres réels (float,double,int,...) et utilise des méthodes en ligne pour rester proches des performances initiales des opérations élémentaires (+,-,*,/,...) sur les types numériques (float,double,int) :
Code : 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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 #ifndef _REAL_HPP #define _REAL_HPP #include "Number.hpp" /*! * \class Real */ template<typename T> class Real : public Number { protected: /*! \brief value of the real number */ T _value; protected: /*! \brief default construction */ Real(); /*! \brief copy construction */ Real(T const&); public: /*! \brief assignement of a real number */ T const& operator=(T const&); /*! \brief computation of the absolute value */ double abs()const; public: /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator==(Real<TT>const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator==(TT const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator==(Real<TT>const&,TT const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<=(Real<TT>const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<=(TT const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<=(Real<TT>const&,TT const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>=(Real<TT>const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>=(TT const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>=(Real<TT>const&,TT const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<(Real<TT>const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<(TT const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator<(Real<TT>const&,TT const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>(Real<TT>const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>(TT const&,Real<TT>const&); /*! \brief comparison of two real numbers */ template<typename TT> friend bool operator>(Real<TT>const&,TT const&); public: /*! \brief addition of two real numbers */ template<typename TT> friend TT operator+(Real<TT>const&,Real<TT>const&); /*! \brief addition of two real numbers */ template<typename TT> friend TT operator+(Real<TT>const&,TT const&); /*! \brief addition of two real numbers */ template<typename TT> friend TT operator+(TT const&,Real<TT>const&); /*! \brief substraction of two real numbers */ template<typename TT> friend TT operator-(Real<TT>const&,Real<TT>const&); /*! \brief substraction of two real numbers */ template<typename TT> friend TT operator-(Real<TT>const&,TT const&); /*! \brief substraction of two real numbers */ template<typename TT> friend TT operator-(TT const&,Real<TT>const&); /*! \brief multiplication of two real numbers */ template<typename TT> friend TT operator*(Real<TT>const&,Real<TT>const&); /*! \brief multiplication of two real numbers */ template<typename TT> friend TT operator*(TT const&,Real<TT>const&); /*! \brief multiplication of two real numbers */ template<typename TT> friend TT operator*(Real<TT>const&,TT const&); /*! \brief division of two real numbers */ template<typename TT> friend TT operator/(Real<TT>const&,Real<TT>const&); /*! \brief division of two real numbers */ template<typename TT> friend TT operator/(TT const&,Real<TT>const&); /*! \brief division of two real numbers */ template<typename TT> friend TT operator/(Real<TT>const&,TT const&); }; //////////////////////////////////////////////////////////////////////////////// #include "Real.tcc" #endif /* _REAL_HPP */
De la classe Real<double> hérite une classe DoubleReal représentant les flottants à précision double :
Code : 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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 #ifndef _REAL_TCC #define _REAL_TCC template<typename T> inline Real<T>::Real() {} /*! * \fn Real(T const&) * \param value of a real number * \brief construction by value */ template<typename T> inline Real<T>::Real(T const& value) :Number(),_value(value) {} //////////////////////////////////////////////////////////////////////////////// /*! * \fn inline T& operator=(T const&) * \param value of a real number * \brief assignement of a value */ template<typename T> inline T const& Real<T>::operator=(T const& value) { return _value=value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief addition of two real numbers */ template<typename TT> inline TT operator+(Real<TT>const& left,Real<TT>const& right) { return left._value+right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief addition of two real numbers */ template<typename TT> inline TT operator+(Real<TT>const& left,TT const& right) { return left._value+right; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief addition of two real numbers */ template<typename TT> inline TT operator+(TT const& left,Real<TT>const& right) { return left+right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief substraction of two real numbers */ template<typename TT> inline TT operator-(Real<TT>const& left,Real<TT>const& right) { return left._value-right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief substraction of two real numbers */ template<typename TT> inline TT operator-(Real<TT>const& left,TT const& right) { return left._value-right; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief substraction of two real numbers */ template<typename TT> inline TT operator-(TT const& left,Real<TT>const& right) { return left-right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief multiplication of two real numbers */ template<typename TT> inline TT operator*(Real<TT>const& left,Real<TT>const& right) { return left._value*right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief multiplication of two real numbers */ template<typename TT> inline TT operator*(TT const& left,Real<TT>const& right) { return left*right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief multiplication of two real numbers */ template<typename TT> inline TT operator*(Real<TT>const& left,TT const& right) { return left._value*right; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief division of two real numbers */ template<typename TT> inline TT operator/(Real<TT>const& left,Real<TT>const& right) { return left._value/right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief division of two real numbers */ template<typename TT> inline TT operator/(TT const& left,Real<TT>const& right) { return left/right._value; } //////////////////////////////////////////////////////////////////////////////// /*! * \param left operand * \param right operand * \brief division of two real numbers */ template<typename TT> inline TT operator/(Real<TT>const& left,TT const& right) { return left._value/right; } //////////////////////////////////////////////////////////////////////////////// #endif /* _REAL_TCC */
Le fichier DoubleReal.tcc est aussi vide que DoubleReal.hpp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #ifndef _DOUBLEREAL_HPP #define _DOUBLEREAL_HPP #include "Real.hpp" /*! * \class DoubleReal */ class DoubleReal : public Real<double> { public: DoubleReal(double const&); }; //////////////////////////////////////////////////////////////////////////////// #include "DoubleReal.tcc" #endif /* _DOUBLEREAL_HPP */
Lorsque je mesure le temps mis pour faire plusieurs sommes de doubles, par exemple avec le code
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 #ifndef _DOUBLEREAL_TCC #define _DOUBLEREAL_TCC inline DoubleReal::DoubleReal(double const& value) :Real<double>(value) {} #endif /* _DOUBLEREAL_TCC */
j'obtiens 4 secondes de calcul (g++ -O3).
Code : 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 #include <cstdlib> #include <iostream> #include "Dataset.hpp" #include "KMeans.hpp" #include "Profiler.hpp" #include "DoubleReal.hpp" /* * */ int main() { double a = 1.0;double b = 2.0; unsigned int m=100000; unsigned int n=100000; Profiler prf; // classe permettant de mesurer le temps CPU double tmps = prf.cputime(); for (size_t i=0;i<m;++i) { for (size_t j=0;j<n;++j) a=a+b+b; } tmps = prf.cputime()-tmps; std::cout<<"elapsed CPU time : "<<tmps<<std::endl; return (EXIT_SUCCESS); }
Si je remplace la ligne
par la ligne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 double a = 1.0;double b = 2.0;
je mesure le même temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 DoubleReal a = 1.0;DoubleReal = 2.0;
La mauvaise nouvelle est que je n'ai pas déclaré de destructeur dans les classes Number et Real<T>. J'imagine que par défaut ils sont privés et non virtuels alors qu'ils devraient être publics et virtuels ou protégés et non virtuels si j'en crois l'article de la faq.
Saut que si je déclare ces destructeurs autrement, je perds énormément en performances. Par exemple, pour la classe Number, si j'ajoute
mon temps de calcul passe de 4 secondes à 54 secondes!!!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 ~Number(){;};
C'est d'ailleurs pour cela que mes constructeurs sont déclarés protégés dans les classes Number et Real<T>... mais j'aurais préféré faire des classes abstraites.
Quelqu'un sait-il comment contourner le problème?
Partager