This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
td9:part2 [2021/11/06 14:53] bmonsuez created |
td9:part2 [2022/11/18 10:48] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Partie 2 :Mesuré le temps passé par une fonction ====== | + | ====== Partie 2 : Mesurer le temps passé par une fonction ====== |
[[in204:tds:sujets:td9|TD9]] | [[in204:tds:sujets:td9|TD9]] | ||
Line 5: | Line 5: | ||
===== Références===== | ===== Références===== | ||
- | [[http://en.cppreference.com/w/cpp/thread/thread|std::thread]] | + | [[https://en.cppreference.com/w/cpp/chrono/high_resolution_clock|std::chrono::high_resolution_clock]] |
+ | |||
+ | [[https://en.cppreference.com/w/cpp/utility/pair/make_pair|str::make_pair(...)]] | ||
+ | |||
+ | [[https://en.cppreference.com/w/cpp/utility/pair/pair|str::pair<T1, T2>]] | ||
Line 27: | Line 31: | ||
int factorial(int n) | int factorial(int n) | ||
{ | { | ||
- | return n <= 1 ? 1 : (n * factorial(n - 1)); | + | return n == 0 ? 1 : (n * factorial(n - 1)); |
} | } | ||
</code> | </code> | ||
La fonction aura le squelette suivant: | La fonction aura le squelette suivant: | ||
- | <code> | + | <code cpp> |
- | int estimate_time(int n) | + | std::pair<std::chrono::high_resolution_clock::duration, int> estimate_factorial_time(int n) |
{ | { | ||
// Code pour lancer le chronomètre | // Code pour lancer le chronomètre | ||
int result = factorial(n); | int result = factorial(n); | ||
- | // Code pour calculer le temps écoulé et affiché celui-ci. | + | // Code pour calculer le temps écoulé |
- | return result; | + | // Retourner la paire contenant le résultat et le temps passé. |
} | } | ||
</code> | </code> | ||
+ | |||
+ | <hidden Correction> | ||
+ | |||
+ | Ceci est assez simple à réaliser en utilisant les fonctions ''std::chrono::high_resolution_clock::now()'' et ''std::make_pair()''. | ||
+ | |||
+ | <code cpp> | ||
+ | std::pair<std::chrono::high_resolution_clock::duration, long double> estimate_factorial_time(int n) | ||
+ | { | ||
+ | auto starting_time = std::chrono::high_resolution_clock::now(); | ||
+ | auto result = factorial(n); | ||
+ | auto elasped_time = std::chrono::high_resolution_clock::now() - starting_time; | ||
+ | return std::make_pair(elasped_time, result); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
+ | |||
===== Question n°2 ===== | ===== Question n°2 ===== | ||
- | Transformer la fonction précédente <code>estimate_time</code> pour qu'elle prenne en argument une fonction arbitraire à un argument et un résultat. | + | Transformer la fonction précédente <code>estimate_time</code> pour qu'elle prenne en argument une fonction arbitraire qui prend un argument et retourne un résultat qui ne sera pas obligatoirement un résultat de type ''long double''. |
Il faudra penser à utiliser un modèle (template) de fonctions. | Il faudra penser à utiliser un modèle (template) de fonctions. | ||
Line 58: | Line 79: | ||
<code cpp> | <code cpp> | ||
template<class Function, class T> | template<class Function, class T> | ||
- | std::pair<std::chrono::high_resolution_clock::duration, long double> estimate_function_time(Function function, T argument) | + | auto estimate_function_time(Function function, T argument) |
{ | { | ||
auto starting_time = std::chrono::high_resolution_clock::now(); | auto starting_time = std::chrono::high_resolution_clock::now(); | ||
Line 75: | Line 96: | ||
<code cpp> | <code cpp> | ||
- | template<class T1, T2> | + | template<class numericalT> |
- | T1 power(T2 x, int y) | + | numericalT power_by_int(numericalT x, int y) |
{ | { | ||
- | T1 result = (T1)1.0 | + | numericalT result = (numericalT)1.0; |
- | while(y-- > 0) | + | while (y-- > 0) |
- | result = result * (T1)x; | + | result *= x; |
- | return result; | + | return result; |
} | } | ||
</code> | </code> | ||
Line 87: | Line 108: | ||
Modifier le code de la fonction pour pouvoir prendre une telle fonction comme paramètre. | Modifier le code de la fonction pour pouvoir prendre une telle fonction comme paramètre. | ||
- | Estimer le temps nécesaire pour calculer par exemple : 1.02 ^ 10000000. | + | __**Remarque**__: il faut penser à utiliser les **packs de paramètres** que nous avons vu dans la première partie du TD. |
+ | |||
+ | <hidden Correction> | ||
+ | Dans le cas présent, comme nous avons aucun, un ou plusieurs paramètres, chacun des paramètres pouvant avoir un type différent. Dans ce cas, nous pouvons remplacer le paramêtre ''T'' de la fonction ''estimate_function_time'' précédenter par un argument correspondant à un pack de paramètres ''...Args''. Et c'est tout ! | ||
+ | |||
+ | template<class Function, class ... Args> | ||
+ | auto estimate_function_time(Function function, Args... arguments) | ||
+ | { | ||
+ | auto starting_time = std::chrono::high_resolution_clock::now(); | ||
+ | auto result = function(arguments...); | ||
+ | auto elasped_time = std::chrono::high_resolution_clock::now() - starting_time; | ||
+ | return std::make_pair(elasped_time, result); | ||
+ | } | ||
+ | |||
+ | </hidden> | ||
+ | |||
+ | Estimer le temps nécesaire pour calculer par exemple : 1.0002 ^ 10000000. | ||
+ | |||
+ | <hidden Correction> | ||
+ | |||
+ | Le code suivant va permettre d'estimer le temps passé à calculer le résultat : | ||
+ | |||
+ | <code cpp> | ||
+ | auto pw = estimate_function_time(power_by_int<long double>, 1.0002, 1000000); | ||
+ | std::cout << "Computing 1.02^1000000=" << pw.second << " in " << pw_10000000.first.count() << " ticks.\n"; | ||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
==== Question n°5 ==== | ==== Question n°5 ==== | ||
- | Créer une fonction nouvelle qui va appeller la fonction <code>estimate_time</code> pour calculer <code>x</code> fois le temps et retourné le temps moyen pour effectuer un "run" de la fonction. | + | Créer une fonction nouvelle qui va appeller la fonction ''estimate_function_time'' pour calculer ''x'' fois le temps nécessaire pour calculer la fonction et qui retourn le temps moyen pour effectuer un "run" de la fonction. |
- | Exécuter cette fonction pour les fonctions <code>power</code> et <code>factorial</code> précédemment définie. | ||
- | ==== Question n°4 ==== | + | Cette fonction aura l'entête suivante : |
- | Que faut-il faire ajouter pour dire au compilateur que la fonction <code>factorial</code> ou que la fonction <code>power</code> peut-être exécutée au moment de l'exécution ? | + | <code cpp> |
+ | template<class Function, class ... Args> | ||
+ | long long mean_function_time(int number_of_runs, Function function, Args... arguments) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </code> | ||
- | Effectuer la modification. | + | <hidden Correction> |
+ | |||
+ | Il suffit de lancer ''number_of_runs'' fois un appel à ''estimate_function_time'' pour la fonction et les arguments. Ceci donne le code suivant : | ||
+ | |||
+ | <code cpp> | ||
+ | template<class Function, class ... Args> | ||
+ | long long mean_function_time(int number_of_runs, Function function, Args... arguments) | ||
+ | { | ||
+ | long long duration = 0L; | ||
+ | int remaining_runs = number_of_runs; | ||
+ | while (remaining_runs-- > 0) | ||
+ | duration += estimate_function_time(function, arguments...).first.count(); | ||
+ | return duration / (long long)number_of_runs; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
- | Calculer le temps pris désormais par ces fonctions. | ||
+ | [[.td9:part1|Manipuler un nombre variable de paramètres]] | ||
+ | [[.td9:part3|Exécution à la compilation]] | ||