TP ‐ Threads - vbridonneau/CoursSysteme GitHub Wiki

Parallelisme et création de threads

Echauffement

Documentation sur les threads

  1. Quelles sont les fonctions de qu'il faut appeler pour :
    • créer un thread;
    • terminer l'exécution d'un thread.
  2. Cherhcer dans le manuel la documentation de chacune des fonctions que vous avez donné pour la question précedente.

Compilation

Cherchez quelle option doit être passée à gcc afin de compiler un code utilisant la bibliothèque pthread.

Exercices

Exécution parallèle

Le but de cet exercice est de de comprendre le comportement d'un programme multi-thread par rapport à un programme séquentiel. Pour cela, nous allons créer un programme qui lancera deux threads. Chaque thread appelera une fonction incrémentant une variable globale compteur. Puis, à la fin de l'exécution des threads, affiche la valeur du compteur.

  1. Ecrivez la fonction incrementer qui sera appelée à la création des threads pour augmenter la valeur du compteur. Le nombre d'incrémentation devra être passé en paramètre et la fonction ne renverra rien (enfin pas d'information en particulier).
  2. Ecrivez le code de la fonction main afin de créer deux threads puis de les attendre et enfin d'afficher la valeur du compteur. Chaque thread devra appeler la fonction avec un nombre d'incrémentation de 1000.
  3. Complétez le programme avec les bons includes et la variable globale afin que le code soit correcte.
  4. Compilez votre programme et tester le. Quelle valeur est affichée ? Est-ce normale ?

Utilisation des mutexs

Pour pallier ce problème, nous allons protéger l'accès à la variable compteur par un mutex :

  1. Rajoutez une variable globale mutex que vous initialiserez de façon statique.

Il ne nous reste plus qu'à mettre une barrière avant d'incrémenter le compteur :

  1. Utilisez votre mutex pour protéger la mise à jour du compteur.

Découpage de tâche

Dans cette exercice on se propose d'écrire un programme effectuant le découpage d'un calcul très long et d'affecter un thread par morceau issu de ce découpage. Pour ce faire, nous allons créer une fonction calcul dont le but est de calculer le résultat d'une somme d'un tableau contenue dans une variable globale. Le code de base est le suivant :

#define TAILLE  100000 // Taille du tableau
#define NTHREAD 10     // Nombre de threads

int tableau[TAILLE];

void* somme(void *arg);

Notre but étant de découper le calcul de la somme en plusieur threads, nous allons devoir réaliser un découpage du code en plusieurs étapes. Commençons par initialiser le tableau.

  1. Ecrivez une fonction initialiser qui initialise le tableau tableau de telle manière à ce qu'il contienne les entiers consécutifs de 0 à TAILLE - 1.

Nous allons à présent créer une structure afin de procéder au découpage de la tâche à exécuter. Cette structure sert à indiquer à chaque thread les données du tableau qu'il doit traité. L'idée est que ce découpage doit être tel que chaque thread traite des données contigues du tableau et traite le même nombre de case. Elle contient donc :

  • Un indice de départ sous forme de nombre entier.
  • Un nombre de case à traiter sous forme d'entier.
  • Le tableau sous forme de pointeur d'entier.
  1. Codez la structure arg_t afin qu'elle contienne ces informations.

Maintenant que l'on a la structure pour effectuer le découpage, nous allons pouvoir créer la fonction somme.

  1. Ecrivez la fonction somme. On supposera que l'argument passé en paramètre est une varaible de type arg_t.

  2. Ecrivez le reste du programme afin de créer les threads et d'effectuer la somme, puis d'afficher le résultat dans le terminal.

Produit Scalaire

Dans cette partie, on consid`ere deux tableaux de nombres flottants u et v, de taille n. On souhaite calculer la somme $$\sum_{k=0}^{n-1} u[k] * v[k] = u[0] * v[0] + u[1] * v[1] + ... + u[n − 1] * v[n − 1]$$ Afin d’optimiser cette tâche, vous devez implémenter une version parallèle du calcul de cette somme en utilisant des threads.

Le calcul doit être divisé en p tâches indépendantes, chacune étant chargée de calculer une somme partielle de termes consécutifs et de taille similaire. Les sommes partielles sont ensuite combinées pour produire la somme finale. Pour ce faire, dans la fonction que vous êtes en train d'écrire pour chaque thread. Vous devrez mettre à jour la somme globale. Vous devez également penser à protéger l'accès à cette variable.

Pour cet exercice, on pensera à traiter les cas ou p ne divise pas la taille des tableaux u et v.

⚠️ **GitHub.com Fallback** ⚠️