5.1.3 : Fonctions CMake
Nous allons faire un développement très similaire à la partie précédente, mais en améliorant le procédé.
Écrivons le fichier multiplePerfTestFunction.cmake :
La première fonction devra compiler et lancer les tests de performances et devra définir toutes les macros dont le
main_generic.cpp a besoin :
L'ensemble des macro à définir est :
- INCLUDE_FUNCTION_NAME : le textbfheader à utiliser
- FUNCTION_NAME : le nom de la fonction à utiliser
- FUNCTION_STR_NAME_DEF : le nom de la fonction à utiliser sous forme textuelle
- RATIO_NB_NAN : la proportion de nombres exotiques à initialiser dans les tenseurs
- VALUE_DEF : la valeurs que l'on veut insérer dans les tenseurs
Nous devons nous contenter d'appeler correctement la fonction
phoenix_compileAndRunExample qui fera le travail pour nous.
Commençons par definir la fonction :
1
2
3
4
5
6
7
8
9
10
11
|
function(generic_compileAndRunExampleFunc functionName optimsiationMode valueType optimisationFlag valueNbNan defNanValue vectorizeOption configPerformance)
|
Et prennons tout de suite en compte les paramètres supplémentaires à notre fonction qui seront les sources à compiler :
1
|
set(PROGRAM_SRC ${ARGN})
|
Transformons les flags d'optimisation (-O0, -O1, -O2, -O3, -Ofast) en suffixes (O0, O1, O2, O3, Ofast) pour nommer nos executables :
1
2
|
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}")
|
Si on passe un type de valeur, on le concatenne au nom du programme :
1
2
3
|
if(NOT valueType STREQUAL "")
set(baseProgramName "${baseProgramName}_${valueType}")
endif()
|
Si on passe une proportion de valeur, on définit la macro correspondante :
1
2
3
4
5
6
7
|
if(valueNbNan STREQUAL "")
set(DEFINE_RATIO_NB_NAN "")
else()
string(REPLACE "." "" nameValueNbNan ${valueNbNan})
set(baseProgramName "${baseProgramName}_${nameValueNbNan}")
set(DEFINE_RATIO_NB_NAN "-DRATIO_NB_NAN=${valueNbNan}")
endif()
|
On créé ensuite le nom du programme de test :
1
|
set(targetName "${baseProgramName}_${nameOptimisationFlag}")
|
Si on passe une définition de valeur, on ajoute la macro correspondante :
1
2
3
4
5
|
if(defNanValue STREQUAL "")
set(DEFINE_NAN_VALUE "")
else()
set(DEFINE_NAN_VALUE "-DVALUE_DEF=${defNanValue}"")
endif()
|
On définit ensuite les macros relatives aux fonctions en prennant garde à les échaper pour passer la phase de mise en forme de
CMake :
1
2
3
4
5
6
7
8
9
|
if(vectorizeOption STREQUAL "" OR vectorizeOption STREQUAL "${DENORM_DAZ_OPTION}")
set(functionTestName "function_base")
else()
set(functionTestName "function_vectorize")
endif()
set(FUNCTION_INCLUDE_DEF "-DINCLUDE_FUNCTION_NAME="${functionTestName}.h"")
set(FUNCTION_NAME_DEF "-DFUNCTION_NAME=${functionTestName}")
set(FUNCTION_STR_NAME_DEF "-DKERNEL_STR_FUNCTION_NAME="${functionTestName}"")
set(COMPUTE_FUNCTION_DEF "-DCOMPUTE_FUNCTION_DEF=${functionName}")
|
On appelle la fonction
phoenix_compileAndRunExample :
1
2
3
4
|
set(FUNTION_OPTIONS "${FUNCTION_INCLUDE_DEF} ${FUNCTION_NAME_DEF} ${FUNCTION_STR_NAME_DEF} ${COMPUTE_FUNCTION_DEF}")
phoenix_compileAndRunExample(${targetName}
"${optimisationFlag} ${DEFINE_RATIO_NB_NAN} ${vectorizeOption} ${FUNTION_OPTIONS} ${DEFINE_NAN_VALUE}"
"${configPerformance}" ${PROGRAM_SRC})
|
Et on finalise la fonction :
1
|
endfunction(generic_compileAndRunExampleFunc)
|
Ensuite, la deuxième fonction doit compiler et lancer un ensemble de tests de référence (donc sans valeurs exotiques) :
1
2
3
4
5
6
7
8
|
function(multiplePerfTestFunction baseComparisonPlotName functionName optimsiationMode vectorizeOption configPerformance)
|
Nous prennons également tout de suite en compte les paramètres supplémentaires à notre fonction qui seront les sources à compiler :
1
|
set(PROGRAM_SRC ${ARGN})
|
On définie une list qui contient les options d'optimisations pertinentes suivant le mode vectorisé ou non. Il est en effet inutile de compiler en
-O0 tout en vectorisant :
1
2
3
4
5
|
if(vectorizeOption STREQUAL "")
set(listOptimisationFlag -O0 -O1 -O2 -O3 -Ofast)
else()
set(listOptimisationFlag -O2 -O3 -Ofast)
endif()
|
Ensuite, on parcours, la liste que nous venons de créer :
1
2
|
set(listTargetPerf)
foreach(optimisationFlag ${listOptimisationFlag})
|
Nous transformons les flags d'optimisation (-O0, -O1, -O2, -O3, -Ofast) en suffixes (O0, O1, O2, O3, Ofast) pour nommer nos executables :
1
2
|
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}_${nameOptimisationFlag}")
|
Nous appellons notre fonction précédente qui se chargera du reste :
1
2
|
generic_compileAndRunExampleFunc(${functionName} ${optimsiationMode} "" "${optimisationFlag}"
"" "" "${vectorizeOption}" "${configPerformance}" ${PROGRAM_SRC})
|
Nous ajoutons tous kes programmes créés pour pouvoir automatiser la création des graphes qui seront fait dans cette fonction :
1
|
list(APPEND listTargetPerf ${baseProgramName})
|
Fin du
foreach
1
|
endforeach(optimisationFlag)
|
On appelle la fonction pour faire les graphes de performance :
1
|
phoenix_plotPerf("${baseComparisonPlotName}" ${listTargetPerf})
|
Et on finalise la fonction :
1
|
endfunction(multiplePerfTestFunction)
|
Enfin, la troisième fonction doit compiler et lancer un ensemble de tests avec des valeurs exotiques :
1
2
3
4
5
6
7
8
9
10
11
|
function(multiplePerfTestFunctionValue baseComparisonPlotName functionName optimsiationMode valueType optimisationFlag defNanValue vectorizeOption configPerformance)
|
Nous prennons toujours en compte les paramètres supplémentaires à notre fonction qui seront les sources à compiler :
1
2
3
4
|
set(PROGRAM_SRC ${ARGN})
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}_${valueType}")
set(comparisonProgramName "${functionName}_${optimsiationMode}_${nameOptimisationFlag}")
|
Créons une liste de proportions de nombres exotiques que nous voulons traiter :
1
|
set(listRatioNbNan 0.01 0.1 0.25 0.5 0.75 0.9 1)
|
Dans ce cas nous allons itérer sur les différentes proportions de nombres exotiques que nous voulons traiter :
1
2
|
set(listTargetPerf)
foreach(valueNbNan ${listRatioNbNan})
|
On transforme les valeurs entre 0 et 1 par des chaînes de caractères en supprimant le point :
1
|
string(REPLACE "." "" nameValueNbNan ${valueNbNan})
|
On créer le nom du programme et on appelle la première fonction que l'on a déveoppée :
1
2
3
4
5
6
7
|
set(tmpTargetName ${baseProgramName}_${nameValueNbNan}_${nameOptimisationFlag})
generic_compileAndRunExampleFunc(${functionName} ${optimsiationMode} "${valueType}" "${optimisationFlag}"
"${valueNbNan}" "${defNanValue}" "${vectorizeOption}"
"${configPerformance}" ${PROGRAM_SRC})
list(APPEND listTargetPerf ${tmpTargetName})
endforeach(valueNbNan)
|
On appelle la fonction pour faire les graphes de performance :
1
2
|
phoenix_plotPerf("${baseComparisonPlotName}" ${comparisonProgramName}
${listTargetPerf})
|
Et on finalise la fonction :
1
|
endfunction(multiplePerfTestFunctionValue)
|
Il nous reste à faire une fonction qui créée tous les tests de performance pour une fonction données
1
2
3
4
5
6
7
8
9
10
|
function(allTestFunction stdFunctionName CONFIG_FUNCTION VECTORIZED_OPTION NAN_DEF INF_DEF DENORM_DEF MIN_TO_DENORM_DEF)
|
Voici les deux sources de base pour tous les tests de performances de cette partie :
1
2
3
|
set(FUNCTION_BASE_SRC function_base.cpp main_function.cpp)
set(FUNCTION_VECTORIZE_SRC function_vectorize.cpp main_function.cpp)
|
Créons les tests de références :
1
2
3
|
multiplePerfTestFunction("${stdFunctionName}Base" ${stdFunctionName} base "" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunction("${stdFunctionName}Vectorize" ${stdFunctionName} vectorize "${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
|
Nous pouvons également ajouter des graphes (mais il faut faire attention au nom des programmes que l'on compoare) :
1
2
3
4
|
phoenix_plotPerf("cmp${stdFunctionName}Safe03" ${stdFunctionName}_base_O3 ${stdFunctionName}_vectorize_O3)
phoenix_plotPerf("cmp${stdFunctionName}Safe0fast" ${stdFunctionName}_base_Ofast ${stdFunctionName}_vectorize_Ofast)
|
Testons avec des
NaN :
1
2
3
4
5
6
|
multiplePerfTestFunctionValue("${stdFunctionName}BaseNanOfast" ${stdFunctionName} base nan -Ofast "${NAN_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeNanOfast" ${stdFunctionName} vectorize nan -Ofast "${NAN_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
|
Testons avec des
Inf :
1
2
3
4
5
6
|
multiplePerfTestFunctionValue("${stdFunctionName}BaseInfOfast" ${stdFunctionName} base inf -Ofast "${INF_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeInfOfast" ${stdFunctionName} vectorize inf -Ofast "${INF_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
|
Testons avec des nombres dénormalisés :
1
2
3
4
5
6
|
multiplePerfTestFunctionValue("${stdFunctionName}BaseDenormOfast" ${stdFunctionName} base denorm -Ofast "${DENORM_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeDenormOfast" ${stdFunctionName} vectorize denorm -Ofast "${DENORM_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
|
Essayons de régler le problème avec des nombres dénormalisés :
1
2
3
4
5
6
|
multiplePerfTestFunctionValue("${stdFunctionName}BaseDenormDazOfast" ${stdFunctionName} base denormDaz -Ofast "${DENORM_DEF}"
"${DENORM_DAZ_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeDenormDazOfast" ${stdFunctionName} vectorize denormDaz -Ofast "${DENORM_DEF}"
"${VECTORIZED_OPTION} ${DENORM_DAZ_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
|
Voyons ce qu'il se passe lorsque le calcul produit des nombres dénormalisés :
1
2
3
4
5
6
|
multiplePerfTestFunctionValue("${stdFunctionName}BaseMakeDenormOfast" ${stdFunctionName} base make_denorm -Ofast "${MIN_TO_DENORM_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeMakeDenormOfast" ${stdFunctionName} vectorize make_denorm -Ofast "${MIN_TO_DENORM_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
endfunction(allTestFunction)
|
Le fichier
multiplePerfTestFunction.cmake complet :
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
function(generic_compileAndRunExampleFunc functionName optimsiationMode valueType optimisationFlag valueNbNan defNanValue vectorizeOption configPerformance)
set(PROGRAM_SRC ${ARGN})
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}")
if(NOT valueType STREQUAL "")
set(baseProgramName "${baseProgramName}_${valueType}")
endif()
if(valueNbNan STREQUAL "")
set(DEFINE_RATIO_NB_NAN "")
else()
string(REPLACE "." "" nameValueNbNan ${valueNbNan})
set(baseProgramName "${baseProgramName}_${nameValueNbNan}")
set(DEFINE_RATIO_NB_NAN "-DRATIO_NB_NAN=${valueNbNan}")
endif()
set(targetName "${baseProgramName}_${nameOptimisationFlag}")
if(defNanValue STREQUAL "")
set(DEFINE_NAN_VALUE "")
else()
set(DEFINE_NAN_VALUE "-DVALUE_DEF=${defNanValue}"")
endif()
if(vectorizeOption STREQUAL "" OR vectorizeOption STREQUAL "${DENORM_DAZ_OPTION}")
set(functionTestName "function_base")
else()
set(functionTestName "function_vectorize")
endif()
set(FUNCTION_INCLUDE_DEF "-DINCLUDE_FUNCTION_NAME="${functionTestName}.h"")
set(FUNCTION_NAME_DEF "-DFUNCTION_NAME=${functionTestName}")
set(FUNCTION_STR_NAME_DEF "-DKERNEL_STR_FUNCTION_NAME="${functionTestName}"")
set(COMPUTE_FUNCTION_DEF "-DCOMPUTE_FUNCTION_DEF=${functionName}")
set(FUNTION_OPTIONS "${FUNCTION_INCLUDE_DEF} ${FUNCTION_NAME_DEF} ${FUNCTION_STR_NAME_DEF} ${COMPUTE_FUNCTION_DEF}")
phoenix_compileAndRunExample(${targetName}
"${optimisationFlag} ${DEFINE_RATIO_NB_NAN} ${vectorizeOption} ${FUNTION_OPTIONS} ${DEFINE_NAN_VALUE}"
"${configPerformance}" ${PROGRAM_SRC})
endfunction(generic_compileAndRunExampleFunc)
function(multiplePerfTestFunction baseComparisonPlotName functionName optimsiationMode vectorizeOption configPerformance)
set(PROGRAM_SRC ${ARGN})
if(vectorizeOption STREQUAL "")
set(listOptimisationFlag -O0 -O1 -O2 -O3 -Ofast)
else()
set(listOptimisationFlag -O2 -O3 -Ofast)
endif()
set(listTargetPerf)
foreach(optimisationFlag ${listOptimisationFlag})
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}_${nameOptimisationFlag}")
generic_compileAndRunExampleFunc(${functionName} ${optimsiationMode} "" "${optimisationFlag}"
"" "" "${vectorizeOption}" "${configPerformance}" ${PROGRAM_SRC})
list(APPEND listTargetPerf ${baseProgramName})
endforeach(optimisationFlag)
phoenix_plotPerf("${baseComparisonPlotName}" ${listTargetPerf})
endfunction(multiplePerfTestFunction)
function(multiplePerfTestFunctionValue baseComparisonPlotName functionName optimsiationMode valueType optimisationFlag defNanValue vectorizeOption configPerformance)
set(PROGRAM_SRC ${ARGN})
string(REPLACE "-" "" nameOptimisationFlag ${optimisationFlag})
set(baseProgramName "${functionName}_${optimsiationMode}_${valueType}")
set(comparisonProgramName "${functionName}_${optimsiationMode}_${nameOptimisationFlag}")
set(listRatioNbNan 0.01 0.1 0.25 0.5 0.75 0.9 1)
set(listTargetPerf)
foreach(valueNbNan ${listRatioNbNan})
string(REPLACE "." "" nameValueNbNan ${valueNbNan})
set(tmpTargetName ${baseProgramName}_${nameValueNbNan}_${nameOptimisationFlag})
generic_compileAndRunExampleFunc(${functionName} ${optimsiationMode} "${valueType}" "${optimisationFlag}"
"${valueNbNan}" "${defNanValue}" "${vectorizeOption}"
"${configPerformance}" ${PROGRAM_SRC})
list(APPEND listTargetPerf ${tmpTargetName})
endforeach(valueNbNan)
phoenix_plotPerf("${baseComparisonPlotName}" ${comparisonProgramName}
${listTargetPerf})
endfunction(multiplePerfTestFunctionValue)
function(allTestFunction stdFunctionName CONFIG_FUNCTION VECTORIZED_OPTION NAN_DEF INF_DEF DENORM_DEF MIN_TO_DENORM_DEF)
set(FUNCTION_BASE_SRC function_base.cpp main_function.cpp)
set(FUNCTION_VECTORIZE_SRC function_vectorize.cpp main_function.cpp)
multiplePerfTestFunction("${stdFunctionName}Base" ${stdFunctionName} base "" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunction("${stdFunctionName}Vectorize" ${stdFunctionName} vectorize "${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
phoenix_plotPerf("cmp${stdFunctionName}Safe03" ${stdFunctionName}_base_O3 ${stdFunctionName}_vectorize_O3)
phoenix_plotPerf("cmp${stdFunctionName}Safe0fast" ${stdFunctionName}_base_Ofast ${stdFunctionName}_vectorize_Ofast)
multiplePerfTestFunctionValue("${stdFunctionName}BaseNanOfast" ${stdFunctionName} base nan -Ofast "${NAN_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeNanOfast" ${stdFunctionName} vectorize nan -Ofast "${NAN_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}BaseInfOfast" ${stdFunctionName} base inf -Ofast "${INF_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeInfOfast" ${stdFunctionName} vectorize inf -Ofast "${INF_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}BaseDenormOfast" ${stdFunctionName} base denorm -Ofast "${DENORM_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeDenormOfast" ${stdFunctionName} vectorize denorm -Ofast "${DENORM_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}BaseDenormDazOfast" ${stdFunctionName} base denormDaz -Ofast "${DENORM_DEF}"
"${DENORM_DAZ_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeDenormDazOfast" ${stdFunctionName} vectorize denormDaz -Ofast "${DENORM_DEF}"
"${VECTORIZED_OPTION} ${DENORM_DAZ_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}BaseMakeDenormOfast" ${stdFunctionName} base make_denorm -Ofast "${MIN_TO_DENORM_DEF}"
"" "${CONFIG_FUNCTION}" ${FUNCTION_BASE_SRC})
multiplePerfTestFunctionValue("${stdFunctionName}VectorizeMakeDenormOfast" ${stdFunctionName} vectorize make_denorm -Ofast "${MIN_TO_DENORM_DEF}"
"${VECTORIZED_OPTION}" "${CONFIG_FUNCTION}" ${FUNCTION_VECTORIZE_SRC})
endfunction(allTestFunction)
|
Vous pouvez le télécharger
ici.