From 348e3b73d8f5e3c1775ff84f0c9e578048ebdb54 Mon Sep 17 00:00:00 2001 From: Denis Monnerat Date: Wed, 8 Oct 2025 10:24:45 +0200 Subject: [PATCH] ajout tp- et cm thread --- README.md | 3 + tp/tp6/README.md | 160 ++++++++++++++++++++++++++++++++++++++ tp/tp6/src/a.out | Bin 0 -> 16112 bytes tp/tp6/src/ex1.c | 27 +++++++ tp/tp6/src/pi.c | 50 ++++++++++++ tp/tp6/src/stack/Makefile | 10 +++ tp/tp6/src/stack/main.c | 21 +++++ tp/tp6/src/stack/stack.c | 32 ++++++++ tp/tp6/src/stack/stack.h | 12 +++ 9 files changed, 315 insertions(+) create mode 100644 tp/tp6/README.md create mode 100755 tp/tp6/src/a.out create mode 100644 tp/tp6/src/ex1.c create mode 100644 tp/tp6/src/pi.c create mode 100644 tp/tp6/src/stack/Makefile create mode 100644 tp/tp6/src/stack/main.c create mode 100644 tp/tp6/src/stack/stack.c create mode 100644 tp/tp6/src/stack/stack.h diff --git a/README.md b/README.md index 1114b06..9cee99c 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,8 @@ Rappels sur la gestion de la [mémoire](cours/memoire.pdf), [td1](td/td1/td1.pdf ### Semaine 5 (29/09 - 03/10) [Tubes, redirections](cours/pipe.pdf), [td5](td/td5/td5.pdf), [tp5](tp/tp5). +#### Semaine 6 (06/10 - 10/10) +[API threads posix](cours/thread.pdf), [tp6](tp/tp6). + diff --git a/tp/tp6/README.md b/tp/tp6/README.md new file mode 100644 index 0000000..3ec9f67 --- /dev/null +++ b/tp/tp6/README.md @@ -0,0 +1,160 @@ +# TP : Threads + +#### Ex1 +```c +#include +#include +#include +#include + +#define NUM_THREADS 16 + +void *thread(void *thread_id) { + int id = *((int *) thread_id); + printf("Hello from thread %d\n", id); + + return NULL; +} + +int main() { + pthread_t threads[NUM_THREADS]; + for (int i = 0; i < NUM_THREADS; i++) + assert( pthread_create(&threads[i], NULL, thread, &i) == 0); + + for (int i = 0; i < NUM_THREADS; i++) + assert( pthread_join(threads[i], NULL) == 0); + + return EXIT_SUCCESS; +} +``` + +1. Est-ce que l’exécution de ce programme est correcte? Vous pouvez vous en assurer en l’exécutant plusieurs fois. +2. Si vous pensez (et avez constaté) que ce n’est pas le cas, expliquez pourquoi. +3. Modifiez le code pour qu’il donne le résultat attendu. + + +#### Ex2 +On veut écrire un programme calculant la somme des entiers +de `1` à `N` à l’aide de `M` threads. Chaque thread calculera la somme +d’un sous-ensemble de ces entiers et la somme globale sera obtenue en +calculant la somme des résultats intermédiaires de chaque thread. + +Les entiers sont répartis uniformément entre les threads comme suit (exemple avec 3 threads) : + +Thread 1 : 1, 4, 7, ... +Thread 2 : 2, 5, 8, ... +Thread 3 : 3, 6, 9, ... + + +Le programme doit lancer `M` threads, attendre qu’ils se terminent, faire la somme des résultats +intermédiaires et afficher le résultat. Les valeurs `N` et `M` seront passées en ligne de commande. + +Il est important que le programme respecte les points suivants : + +- L’implémentation ne doit utiliser aucune variable globale. +- Le travail à effectuer pour chaque thread créé doit être aussi équitable que possible, quelles + que soient les valeurs `N` et `M` choisies par l’utilisateur (ex : N=20, M=8). +- Évitez d’utiliser un tableau pour contenir les valeurs à additionner. +- Réaliser un test de validation automatiquement du résultat obtenu (vous devez connaître le résultat !). + + +Comparez le temps d'éxecution en fonction du nombre de threads. + + + +```c +/* pour "mesurer" le temps */ +static inline double tstamp(void) +{ + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + return tv.tv_sec + tv.tv_nsec * 1.0e-9; +} +``` +#### Ex22 +On reprend l'exercice d'un tp précédent qui calcule une approximation du nombre pi en simulant des lancers de flechettes +sur un disque. + +Un lancer consiste à tirer aléatoirement la position `(x,y)` de la flechette dans le quart supérieur droit du disque `[0,1]x[0,1]`. +On comptabilise le nombre de lancers à l'intérieur du disque (`x^2+y^2 <= 1`). + +Paralléliser le [code](src/pi.c) en créant pour la simulation plusieurs threads (passé à la ligne de commande). + +Remarque : dans le code fournit, on utilise la fonction `rand_r`, et pas `rand`. Cette dernière n'est pas réentrante (état global caché). + +#### Ex3 +On souhaite écrire une petite librairie implantant une pile d'entiers. Sa taille sera statique, et determinée au moment +de sa création. Voici l'interface : + +```c +stack_t * stack_create(int max_size); +``` +crée une pile de taille `max_size` + +```c +int stack_destroy(stack_t *s); +``` + +détruit la pile + +```c +int stack_push(stack_t *s, int val); +``` + +empile la valeur `val` renvoie 1 en cas de succès, 0 sinon. + +```c +int stack_pop(stack_t *s,int *val); +``` + +dépile dans `*val`. renvoie 1 en cas de succès, 0 sinon. + + +( Décider ce que contiendra la structure stack_t définissant un objet de type pile et penser à insérer des assertions dans le code aux endroits nécessaires.) + +1. Testez votre implantation avec une utilisation monothreadé. +2. Testez votre implantation avec ube utilisation multithreadé (une même pile utlisé par plusieurs threads). Cela fonctionne-t-il ? +3. Ajoutez des primitives d'exclusions mutuelles afin de garantir un comportement cohérent et déterministe dans le cas d’une exécution multi-threadée. + + +#### Ex4 (Mutltiplication matrice/vecteur, problème du false sharing) +Le but de l'exercice est de parallèliser le calcul du produit matrice/vecteur. + +Pour rappel, le produit d'une matrice `A[N][P]` par un vecteur `x[P]` donne un vecteur +`y[N]` par : + +```c +for(i=0;i + + nb ThreadsDimensions + + 8000000x88000x80008x8000000 + tempstempstemps + 1 + 2 + 4 + 8 + + + + Que constatez-vous pour la dernière colonne ? + [ chaque processeur utilise un cache de premier niveau (L1) dont les lignes font + 64 octets. Les composantes du vecteur `y` ne sont pas accèder de manière concurrente. Mais il se peut qu'une ligne d'un cache contienne une composante écrite par un autre thread dans un autre cache rendant la ligne ```dirty``` ] + + Modifiez le code pour remédier au problème. + + + diff --git a/tp/tp6/src/a.out b/tp/tp6/src/a.out new file mode 100755 index 0000000000000000000000000000000000000000..b0b356b3da192bc00eec3bbe1c0456f42a74a016 GIT binary patch literal 16112 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 W4%Cgpra#OKq5{ +#include +#include +#include + +#define NUM_THREADS 16 + +void *thread(void *thread_id) +{ + int id = *((int *) thread_id); + printf("Hello from thread %d\n", id); + + return NULL; +} + +int main(int argc, char *argv[]) +{ + pthread_t threads[NUM_THREADS]; + for (int i = 0; i < NUM_THREADS; i++) + assert( pthread_create(&threads[i], NULL, thread, &i) == 0); + + for (int i = 0; i < NUM_THREADS; i++) + assert( pthread_join(threads[i], NULL) == 0); + + return EXIT_SUCCESS; +} + diff --git a/tp/tp6/src/pi.c b/tp/tp6/src/pi.c new file mode 100644 index 0000000..dbc7de5 --- /dev/null +++ b/tp/tp6/src/pi.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +void* nbDansCercleSeq( void* nbLancers ) +{ + long nb = 0; + unsigned int seed; + for( long i = 0; i < (long) nbLancers; i++ ) { + double x = (double) rand_r(&seed) / RAND_MAX; + double y = (double) rand_r(&seed) / RAND_MAX; + if ( x * x + y * y <= 1.0 ) { + nb += 1; + } + } + pthread_exit( (void*) nb ); // <--- on triche ici !!! +} + +double evaluerPi( long nbLancers , long nbThreads ) +{ + long nbTotalDansCercle = 0; + + // TODO + // + return 4.0 * nbTotalDansCercle / nbLancers; +} + + +static inline double tstamp(void) +{ + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + return tv.tv_sec + tv.tv_nsec * 1.0e-9; +} + +int main( int argc , char *argv[] ) +{ + assert( argc >= 3 ); + long nbLancers = strtol(argv [1], NULL, 0); + assert( nbLancers > 0 ); + long nbThreads = strtol(argv [2], NULL, 0); + assert( nbThreads > 0 ); + double t1,t2; + t1 = tstamp(); + double pi = evaluerPi(nbLancers, nbThreads); + t2 = tstamp(); + printf( "pi = %f time = %f\n",pi, t2-t1); + return 0; +} diff --git a/tp/tp6/src/stack/Makefile b/tp/tp6/src/stack/Makefile new file mode 100644 index 0000000..28447ff --- /dev/null +++ b/tp/tp6/src/stack/Makefile @@ -0,0 +1,10 @@ +stack.o : stack.c + gcc -c stack.c + +main.o : main.c stack.h + gcc -c main.c + +main : main.o stack.o + gcc -o main main.o stack.o + +all : main diff --git a/tp/tp6/src/stack/main.c b/tp/tp6/src/stack/main.c new file mode 100644 index 0000000..514a427 --- /dev/null +++ b/tp/tp6/src/stack/main.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include "stack.h" + + + +int main(int argc, char *argv[]) +{ + + int val; + stack_t * s=stack_create(20); + + for(int i=0;i<20; i++) + stack_push(s,i); + + for(int i=0;i<20; i++) + stack_pop(s,&val); + + return 0; +} diff --git a/tp/tp6/src/stack/stack.c b/tp/tp6/src/stack/stack.c new file mode 100644 index 0000000..d1cc620 --- /dev/null +++ b/tp/tp6/src/stack/stack.c @@ -0,0 +1,32 @@ +#include "stack.h" +#include +#include + +struct stack_t { + /* + votre implantation + + */ +}; + +stack_t * stack_create( int max_size) +{ + +} + + +int stack_destroy(stack_t * s) +{ + +} + +int stack_push(stack_t *s,int val) +{ + +} + +int stack_pop(stack_t *s,int * val) +{ + +} + diff --git a/tp/tp6/src/stack/stack.h b/tp/tp6/src/stack/stack.h new file mode 100644 index 0000000..24768ec --- /dev/null +++ b/tp/tp6/src/stack/stack.h @@ -0,0 +1,12 @@ +#ifndef _STACK_INT_H +#define _STACK_INT_H + +typedef struct stack_t stack_t; + +stack_t * stack_create(int max_size); +int stack_destroy(stack_t *s); +int stack_push(stack_t *s, int val); +int stack_pop(stack_t *s,int *val); + + +#endif