User Tools

Site Tools


in204:tds:sujets:td9:part1

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
in204:tds:sujets:td9:part1 [2021/11/06 11:24]
bmonsuez [Question n°2]
in204:tds:sujets:td9:part1 [2022/11/18 10:49] (current)
Line 6: Line 6:
  
 [[http://​en.cppreference.com/​w/​cpp/​thread/​thread|std::​thread]] [[http://​en.cppreference.com/​w/​cpp/​thread/​thread|std::​thread]]
- 
- 
-====== Partie n°1 ====== 
- 
-Nous souhaitons mesurer le temps de calcul d'une fonction. Pour ce faire, nous souhaitons créer une fonction : 
-- qui va prendre en argument la fonction que nous souhaitons exécuter, 
-- les arguments que nous devons passer à cette fonction, 
-- qui va lancer un chronomètre,​ 
-- qui va lancer la fonction 
-- qui va récupérer le résultat de la fonction, 
-- qui va estimer le temps passé par le temps de la fonction, 
-- qui va retourner à la fois le  résultat de la fonction mais aussi le temps passé par la fonction. 
  
 ===== Question n°1 ===== ===== Question n°1 =====
  
-Pour simplifier la conception, écrivez dans un premier la fonction qui appelle la fonction factorielle qui suit: +Créer ​un processus léger ​qui est associé à une fonction ​simple.
-et qui va exécuter cette fonction+
  
 <code cpp> <code cpp>
-int factorial(int n)+#​include<​iostream>​ 
 +#​include<​thread>​ 
 + 
 +void simple_method()
 { {
-    return n <1 ? 1 : (n * factorial(n - 1));+ int i 5; 
 + int x = 10; 
 + int result = i * x; 
 + std::cout << "This code calculated the value " 
 + << result << " from thread ID: "  
 + << std::​this_thread:​:get_id() << "​\n"​;
 } }
-</​code>​ 
  
-La fonction aura le squelette suivant: + 
-<​code>​ +int main()
-int estimate_time(int n)+
 { {
-    // Code pour lancer le chronomètre + std::​thread simpleThread(&​simple_method);​ 
-    int result = factorial(n); + std::cout << "Main thread is executing and waiting\n"; 
-    // Code pour calculer le temps écoulé et affiché celui-ci+ simpleThread.join(); 
-    return ​result;+ std::cout << "​Alternate thread has terminated.\n"; 
 + return ​0;
 } }
 +
 </​code>​ </​code>​
  
-===== Question n°2 =====+Exécuter le code et analyser la sortie. Commenter celle-ci, notamment au regard de la documentation de la classe [[http://​en.cppreference.com/​w/​cpp/​thread/​thread|std::​thread]].
  
-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. ​+<hidden Correction>
  
-Il faudra penser ​à utiliser ​un modèle (template) de fonctions.+Un objet ''​std::​thread''​ correspondant ​à un processus léger est créé et est associé au code la méthode ''​simple_method''​. Ce processus démarre immédiatement et lance le calcul. L'​exécution du code principal se poursuit et le message ''​Main thread is executing and waiting''​ est affiché. La ligne suivant attend que l'​exécution du processus léger associé à l'​objet ''​std::​thread''​ termine. Une fois que ce processus a terminé, l'​exécution du processus principal continue, affiche le message ''​Alternate thread has terminated''​ et rend la main.
  
-<​hidden ​Correction>+</hidden>
  
-Il suffit de modifier la fonction antérieure comme un fonction qui prend deux paramètres de types: 
-  - le type correspondant à la fonction, 
-  - le type correspondant au paramètre de la fonction. 
  
-Et le tour est joué. Ceci donne le code suivant ​:+===== Question n°2 ===== 
 + 
 +Ecrire un programme qui lance les deux calculs suivants en parallèle, ​le premier dans un processus léger secondaire, ​le premier dans le processus léger principal ​:
  
 <code cpp> <code cpp>
-template<​class Function, class T> +void worker_process(int numberOfIterations)
-std::​pair<​std::​chrono::​high_resolution_clock::​duration,​ long double> estimate_function_time(Function function, T argument)+
 { {
- auto starting_time ​std::​chrono::​high_resolution_clock::​now(); + for (int i 1; i < numberOfIterationsi++
- auto result = function(argument); +
- auto elasped_time = std::chrono::​high_resolution_clock::​now() - starting_time+ std::cout << "​Worker Thread" << ​ i << "​\n"​
- return std::​make_pair(elasped_time,​ result);+ }
 } }
 </​code>​ </​code>​
  
-</​hidden>​+et 
 +<code cpp> 
 +void main_process() 
 +
 + for (int i = 1; i < 1000; i++) 
 +
 + std::cout << "​Primary Thread: " << i << "​\n";​ 
 +
 +
 +</code> 
 +  
 +Tester le code. 
 +  
 +<hidden ​Correction>
  
- +Nous pouvons écrire le code suivant qui crée deux processus légers, le premier exécutant la fonction ​''​worker_process''​ avec comme paramètre ''​10000''​ et le second exécutant ​la fonction ​''​main_proc''​.
-===== Question n°3 ===== +
- +
-Nous souhaitons désormais pouvoir prendre une fonction ​pouvant prendre plusieurs arguments ​comme la fonction ​puissance.+
  
 <code cpp> <code cpp>
-template<​class T1, T2>  +int main()
-T1 power(T2 x, int y)+
 { {
-   T1 result = (T1)1.0 + std::​thread worker_proc(&​worker_process,​ 10000); 
-   while(y-- > 0+ std::thread main_proc(&​main_process); 
-       result ​ = result * (T1)x+ worker_proc.join(); 
-   return result;+ main_proc.join();
 } }
 </​code>​ </​code>​
  
-Modifier le code de la fonction pour pouvoir prendre une telle fonction comme paramètre.+L'​exécution commence par la tâche ''​worker_proc''​ et nous devons voir certains messages de la tâche ''​main_proc'',​ nous voyons cependant que les messages ne sont pas très entrelacés,​ ce qui est du au fait que l'on alloue un temps d'​utilisation ​de la console à chacun des deux processus légers.
  
-Estimer le temps nécesaire pour calculer ​par exemple ​: 1.02 ^ 10000000.+Pour mettre un peu d'​entrelacement,​ nous pouvons ajouter un peu de temps entre les affichaches, ​par exemple ​1ns pour le premier processus et 10ns pour le secondCeci nous donne le code suivant:
  
 +<code cpp>
 +#​include<​iostream>​
 +#​include<​thread>​
 +#include <​chrono>​
  
-==== 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. 
  
-Exécuter cette fonction pour les fonctions ​<code>​power</code> et <code>​factorial</code> précédemment définie.+void worker_process(int numberOfIterations) 
 +
 + for (int i = 1; i numberOfIterations;​ i++) 
 +
 + std::​cout ​<< ​"​Worker Thread: " ​<< i << "​\n";​ 
 + std::​this_thread::​sleep_for(10ns);​ 
 +
 +}
  
-==== Question n°4 ==== +void main_process() 
- +
-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 ? + for (int i 1; i < 1000; i++) 
- + { 
-Effectuer la modification. + using namespace std; 
- + std::​cout ​<< ​"​Primary Thread: " ​<< ​i << "​\n";​ 
-Calculer le temps pris désormais par ces fonctions.+ std::​this_thread::​sleep_for(1ns);​ 
 + } 
 +}
  
 +int main()
 +{
 + std::​thread worker_proc(&​worker_process,​ 10000);
 + std::​thread main_proc(&​main_process);​
 + worker_proc.join();​
 + main_proc.join();​
 +}
 +</​code>​
  
 +</​hidden>​
  
  
in204/tds/sujets/td9/part1.1636197862.txt.gz · Last modified: 2021/11/06 11:24 by bmonsuez