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 14:52]
bmonsuez [Question 2.2]
in204:tds:sujets:td9:part1 [2022/11/18 10:49] (current)
Line 1: Line 1:
-====== ​Partie 1 : Manipuler un ensemble d'​arguments ​======+====== ​Création & Manipulation de Processus léger ​======
  
-===== Question 1 =====+[[in204:​tds:​sujets:​td9|TD9]]
  
-Ecrire une fonction ''​print''​ qui prend un nombre libre d'​entiers en paramètres et qui affiche ces entiers sur la console.+===== Références=====
  
-Pour ce faire, nous vous conseillons d'​autiliser la classe ''​std::initializer_list<​T>''​ comme argument de la fonction.+[[http://​en.cppreference.com/​w/​cpp/​thread/​thread|std::thread]]
  
-Un [[https://​en.cppreference.com/​w/​cpp/​utility/​initializer_list|std::​initializer_list<​T>​]] permet d'​accéder ​à la une liste de valeurs de type ''​T''​ qui est écrit sous la forme suivante :+===== Question n°1 ===== 
 + 
 +Créer un processus léger qui est associé ​à une fonction simple.
  
 <code cpp> <code cpp>
-std::​initializer_list<intlist_of_values = {1, 3, 4, 2 }; +#include<iostream
-</code>+#include<thread>
  
-Cette liste de valeur n'est pas modifiable. Il est seulement possible de la lire en lecture comme un containeur classique. Les fonctions ''​begin()'',​ ''​end()''​ ainsi que ''​size()''​ permettent d'​accéder aux valeurs stockées dans la liste.+void simple_method() 
 +
 + 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";​ 
 +}
  
-<hidden Correction>​ 
  
-<code cpp> +int main()
-void print(std::​initializer_list<​int> arguments)+
 { {
-    auto it = arguments.begin(),​ + std::​thread simpleThread(&​simple_method); 
-        end_it = arguments.end(); + std::cout << ​"Main thread is executing and waiting\n"​
-    if (it != end_it) + simpleThread.join(); 
-    { + std::cout << "Alternate thread has terminated.\n"; 
-        ​std::cout << ​*it+ return 0;
-        ​while ​(++it != end_it+
-            std::cout << "" ​<< *it        +
-    }+
 } }
 +
 </​code>​ </​code>​
  
-</hidden>+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]].
  
-===== Question 2 =====+<hidden Correction>​
  
-Généraliser cette fonction ​à d'autres types que les types entiers+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>​
  
-Cette fois-ci, nous attaquons les choses un peu plus complexes. En effet, pour cela, vous allez utiliser les [[https://​en.cppreference.com/​w/​cpp/​language/​parameter_pack|packs de paramètres]] des fonctions et des classes templatées. 
  
-Quand nous écrivons :+===== Question n°2 =====
  
-  * ''​template<​class ...Args> f(Args... arguments)'',​ cela signifie que la fonction prend comme arguments ​un ensemble d'​arguments ​qui ont des types différents. La variable ''​arguments''​ fait référence à l'​ensemble des valeurs ayant chacun ​un type différentc'est pour cela que l'on parle de **pack de paramètres**. Attention, il n'est pas possible d'​accéder aux données individuelles présentes ​dans le **pack de paramètres**.+Ecrire ​un programme ​qui lance les deux calculs suivants en parallèle, le premier dans un processus léger secondairele premier ​dans le processus léger principal :
  
-  * l'​opérateur ''​sizeof...(Args)''​ permet d'​obtenir le nombres d'​arguments passés à la fonction ou spécifié comme paramètres de la classe. 
- 
-  * En fait, les packs de paramètres servent à être passés directement à une fonction. Ainsi nous pouvons écrire le code suivant : 
 <code cpp> <code cpp>
-void number_of_args() { std::cout << "no arguments";​ } +void worker_process(int numberOfIterations)
-template<​classT>​ void number_of_args(T) { std::cout << "one argument";​ } +
-template<​classT1,​ class T2> void number_of_args(T1,​ T2) { std::cout << "two arguments";​ } +
- +
-template<​class ...Args>​ +
-void func(Args... arguments)+
 { {
-    return number_of_args(arguments...);+ for (int i = 1; i < numberOfIterations;​ i++) 
 +
 + std::cout << "​Worker Thread: " << ​ i << "​\n"​; 
 + }
 } }
 </​code>​ </​code>​
-va appeller en fonction du nombre d'​arguments l'une des fonctions ''​number_of_args''​. 
- 
-Nous pouvons désormais imaginer une approche récursive pour compter le nombre d'​arguments en implantant le code suivant : 
  
 +et
 <code cpp> <code cpp>
-template<​class ...Args>​ +void main_process()
-int number_of_args(T first_argument,​ Args... arguments)+
 { {
-    return 0; + for (int i = 11000; i++
-+
-template<class T, class ...Args>​ + std::cout << "​Primary Thread: " << i << "​\n"​; 
-int number_of_args(T first_argument,​ Args... arguments+ }
-+
-    ​return 1 + number_of_args(arguments);+
 } }
 </​code>​ </​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''​.
  
-L'​appel de la fonction ''​number_of_args''​ qui suit : 
 <code cpp> <code cpp>
-    ​std::cout << number_of_args(1"​e",​ 2.0, '​c'​<< "​\n"​;+int main() 
 +
 + std::thread worker_proc(&​worker_process10000); 
 + std::​thread main_proc(&​main_process);​ 
 + worker_proc.join(); 
 + main_proc.join(); 
 +}
 </​code>​ </​code>​
  
-retournera ​''​4''​. +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.
-     +
-==== Question 2.1 ====+
  
-Expliquer comment ​le code a été exécuté ?+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 second. Ceci nous donne le code suivant:
  
-<hidden Correction+<code cpp
-le code ''​number_of_args(1,​ "​e",​ 2.0, '​c'​)''​ correspond à appeller la fonction : +#​include<​iostream>​ 
 +#​include<​thread>​ 
 +#include <​chrono>​
  
-''​number_of_args<​int,​ const char*, double, char> number_of_args(1,​ "​e",​ 2.0, '​c'​)''​ avec : 
-   ​* ​ T = int, 
-   * Args.. = const char*, double, char 
  
-Cette fonction appelle récursivement ''​1 + number_of_args("​e",​ 2.0, '​c'​)'',​ soit  
  
-''​number_of_args<​const char*, double, char> number_of_args("​e",​ 2.0, '​c'​)''​ avec : +void worker_process(int numberOfIterations
-   *  T = const char*, +{ 
-   * Args.. ​double, char + for (int i = 1; i < numberOfIterations;​ i++) 
- + { 
-puis ensuite ''​1 + number_of_args(2.0,​ '​c'​)'',​ soit  + std::cout << "Worker Thread: ​" << i << ​"\n"
- + std::​this_thread:​:sleep_for(10ns); 
-''​number_of_args<double, char> number_of_args("e", 2.0, '​c'​)''​ avec : + } 
-   ​* ​ T = double, +}
-   * Args.. = char +
- +
-puis ensuite ''​1 + number_of_args('​c'​)'',​ soit  +
- +
-''​number_of_args<char> number_of_args("e", 2.0, '​c'​)''​ avec : +
-   ​* ​ T = char, +
-   * Args.. =  +
- +
-puis ensuite ''​1 + number_of_args()'',​ soit  +
- +
-''​number_of_args<​char>​ number_of_args()''​ avec : +
-   * Args.. =  +
- +
-qui elle retroune ''​0''​. +
- +
-Ce qui génère bien le résultat ''​4''​. +
- +
-</​hidden>​ +
- +
-==== Question 2.2 ==== +
- +
-En vous inspirant du code précédant,​ proposer une fonction ''​print''​ qui prend un nombre variable de paramètres qui peuvent avoir des types différents et qui imprime cette liste de paramètres sur la console. +
- +
-<hidden Correction>​+
  
-template<​class T> +void main_process()
-void print(T first_argument)+
 { {
-    ​std::cout << ​first_argument;+ for (int i = 1; i < 1000; i++) 
 +
 + using namespace std; 
 + std::cout << ​"​Primary Thread: " << i << "​\n";​ 
 + std::​this_thread::​sleep_for(1ns); 
 + }
 } }
  
-template<​class T, class ...Args>​ +int main()
-void print(T first_argument,​ Args... arguments)+
 { {
-    ​std::cout << first_argument;​ + std::thread worker_proc(&​worker_process,​ 10000); 
-    if (sizeof...(Args) > 0+ std::thread main_proc(&​main_process)
-        std::cout << ", "+ worker_proc.join(); 
-    print(arguments...);+ main_proc.join();
 } }
 +</​code>​
  
 </​hidden>​ </​hidden>​
- 
- 
- 
- 
-[[td9:​part2|Partie suivante: Mesurer le temps passé par une fonction]] 
  
  
in204/tds/sujets/td9/part1.1636210340.txt.gz · Last modified: 2021/11/06 14:52 by bmonsuez