La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Parallel Programming in C with MPI and OpenMP Michael J. Quinn Chapitre 17 Open MP.

Présentations similaires


Présentation au sujet: "Parallel Programming in C with MPI and OpenMP Michael J. Quinn Chapitre 17 Open MP."— Transcription de la présentation:

1 Parallel Programming in C with MPI and OpenMP Michael J. Quinn Chapitre 17 Open MP

2 OpenMP: Interface de programmation (API) pour le calcul parallèle sur architecture à mémoire partagée. Directives pour le compilateur Bibliothèque logicielle Variables de lenvironnement OpenMP fonctionne avec Fortran, C, ou C++

3 Modèle à mémoire partagée Les processeurs interagissent et se synchronisent à laide de variables partagées. Processeur Mémoire Processeur

4 Parallélisme avec Fork et Join Initialement un seul thread est actif (maître) Le maître exécute le code séquentiel. Fork: Le maître crée ou active des threads additionnels afin dexécuter du code en parallèle. Join: À la fin du code parallèle, les threads sont éliminés ou suspendus et le flot de contrôle retourne à lunique thread maître.

5 Parallélisme avec Fork et Join

6 Parallélisation incrémentielle Programme séquentiel: Cas particulier dun programme parallèle à mémoire partagée. Parallélisation incrémentielle: On transforme un programe séquentiel en programme parallèle de façon graduelle. Le parallélisme incrémentiel est un avantage important de la programmation parallèle à mémoire partagée.

7 Boucle for parallèle En C le parallélisme de données est souvent exprimé à laide de boucles for: for (i = first; i < size; i += prime) marked[i] = 1; Avec OpenMP il est facile dindiquer quand une boucle doit être exécuté en parallèle. Le compilateur se charge de transformer le code séquentiel en code parallèle: création des threads affectation des itérations aux threads.

8 Pragmas Pragma: Directive au compilateur C ou C++ Signifie pragmatic information Permet au programmeur de communiquer avec le compilateur Le compilateur est libre dignorer les directives Syntaxe: #pragma omp

9 Parallel for #pragma omp parallel for [clause [[,] clause …] for (i = 0; i < N; i++) a[i] = b[i] + c[i]; Le compilateur doit être en mesure de vérifier si le système dexécution aura linformation nécessaire à lordonnancement des itérations de la boucle. Indépendance des itérations Nombre ditérations

10 Forme canonique dune boucle parallel for

11 Variables privées et partagées Variable partagée : Même adresse mémoire pour tous les threads Variable privée : Différentes adresses mémoire pour différents threads. Un thread ne peut pas accéder à une variable privée appartenant à un autre thread. Par défaut, dans unparallel for, les variables sont partagées sauf lindice de boucle.

12 Variables privées et partagées …}…}

13 Comment le système sait-il combien de threads il faut créer? Variable de lenvironnement: OMP_NUM_THREADS 4 fonctions utiles: omp_get_num_procs omp_set_num_threads omp_get_num_threads omp_get_thread_num

14 Fonction omp_get_num_procs Retourne le nombre de processeurs (physique ou virtuels) disponibles par le programme parallèle. int omp_get_num_procs (void)

15 Fonction omp_set_num_threads Le nombre de threads actifs dans les section de code parallèle sera égal au paramètre de la fonction Peut être appelé à plusieurs endroits dans le programme. void omp_set_num_threads (int t)

16 Fonction omp_get_num_threads Retourne le nombre de threads actifs. int omp_get_num_threads (void)

17 Fonction omp_get_thread_num Retourne le numérodu thread. int omp_get_thread_num(void)

18 Déclarer des variables privées Exemple: Algorithme de Floyd for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] = MIN(a[i][j],a[i][k]+a[k][j]); Nimporte laquelle des deux boucles peut être exécutée en parallèle (exécuter les deux en parallèle nécessite trop de threads) On préfère paralléliser la boucle extérieure pour minimiser le nombre de fork/join Chaque thread doit alors posséder sa propre copie de la variable j

19 Clause private Clause: Composante optionnelle à un pragma Clause Private: indique au compilateur de créer une ou plusieurs variables privées. private ( )

20 Exemple #pragma omp parallel for private(j) for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] = MIN(a[i][j],a[i][k]+a[k][j]);

21 Clause firstprivate Pour créer une variable privée dont la valeur initiale est identique à celle du thread maître avant dentrée dans la boucle. Les variable sont initialisées une seule fois pour chaque thread et non pas à chaque La modification dune valeur est effective aussi pour les autres itérations.

22 lastprivate Clause Définition: Dernière itération séquentielle La dernière itération lorsque la boucle est exécutée séquentiellement. Clause lastprivate : Permet au thread qui termine lexécution de la dernière itération séquentielle de copier une variable privée vers le thread maître.

23 Sections critiques double area, pi, x; int i, n;... area = 0.0; for (i = 0; i < n; i++) { x += (i+0.5)/n; area += 4.0/(1.0 + x*x); } pi = area / n; Exemple: Approximation de

24 Condition de concurrence Si on ne fait que paralléliser la boucle... double area, pi, x; int i, n;... area = 0.0; #pragma omp parallel for private(x) for (i = 0; i < n; i++) { x = (i+0.5)/n; area += 4.0/(1.0 + x*x); } pi = area / n;

25 Condition de concurrence... On obtient une condition de concurrence pour modifier la variable area

26 Pragma critical Section critique: portion de code qui ne peut être exécuté que par un seul thread à la fois. On met #pragma omp critical devant le bloc de code C.

27 Exemple double area, pi, x; int i, n;... area = 0.0; #pragma omp parallel for private(x) for (i = 0; i < n; i++) { x = (i+0.5)/n; #pragma omp critical area += 4.0/(1.0 + x*x); } pi = area / n; Correct mais inefficace!

28 Réductions Une réduction est lapplication dune opération associative sur les éléments dun vecteur Les réductions sont si courantes que OpenMP fourni un mécanisme facilitant son application. On peut ajouter une clause de réduction au pragma parallel for On doit spécifier lopération de réduction et la variable sur laquelle sapplique la réduction OpenMP soccupe de stocker les résultats partiels dans des variables privées.

29 Clause Reduction La clause réduction a la syntaxe suivante: reduction ( : ) OpérateurValeur initiale *1 &Tous les bits à 1 |Tous les bits à 0 ^ &&1 ||0 maxMaximum possible minMinimum possible

30 Exemple 1 double area, pi, x; int i, n;... area = 0.0; #pragma omp parallel for private(x) reduction(+:area) for (i = 0; i < n; i++) { x = (i + 0.5)/n; area += 4.0/(1.0 + x*x); } pi = area / n;

31 Exemple 2 #include void reduction1(float *x, int *y, int n) { int i, b, c; float a, d; a = 0.0; b = 0; c = y[0]; d = x[0]; #pragma omp parallel for private(i) shared(x, y, n) \ reduction(+:a) reduction(^:b) \ reduction(min:c) reduction(max:d) for (i=0; iy[i])c=y[i]; d = fmaxf(d,x[i]); }

32 Amélioration de la performance #1 Quelques fois, transformer une boucle for séquentielle en boucle for parallèle peut dégrader les performances Le problème est que la transformation peut ajouter trop de fork et join par rapport au reste du calcul. Quelques fois, inverser deux boucles inbriquées peut aider si: Le parallélisme est dans la boucle interne Après linversion, la boucle extérieure peut être parallélisée Linversion naugmente pas trop les défauts de caches.

33 Exemple for (i=1; i

34 Amélioration de la performance #2 Lorsquune boucle a peu ditérations, le temps supplémentaire des fork/join devient plus grand que le temps que lon veut sauver par le parallélisme La clause if indique au compilateur dutiliser le parallélisme sous certaines conditions #pragma omp parallel for if(n > 5000)

35 Amélioration de la performance #3 Il est possible de choisir de quelle façon les itérations dune boucle for seront affectées aux threads à laide de la clause schedule On parlera dordonnancement des itérations Il y a deux principaux types dordonnancement: Statique: Lordonnancement est déterminé avant lexécution Dynamique: Lordonnancement est faite en cours dexécution

36 Ordonnancement statique ou dynamique Ordonnancement statique Pas de charge de travail supplémentaire La charge de travail peut être mal équilibrée Ordonnancement dynamique Charge de travail supplémentaire Peut équilibrer la charge de travail

37 Segments ( chunks ) Un segment est une suite ditérations contiguës Augmenter la taille des segments réduit la charge supplémentaire de travail Décroitre la taille des segments permet de mieux équilibrer la charge de travail entre les threads.

38 Clause schedule Syntaxe: schedule ( [, ]) Types permis: static : ordonnancement statique dynamic : ordonnancement dynamique guided : La taille des segments décroit graduellement runtime : Le type est choisit à lexécution en fonction de la variable de lenvironnement OMP_SCHEDULE

39 Options schedule(static): La taille des segments est environ n/t schedule(static,C): La taille des segments est C schedule(dynamic): Une itération à la fois schedule(dynamic,C): C itérations à la fois

40 Options (suite) schedule(guided, C): Ordonnancement dynamique, la taille des segments diminue graduellement jusquà C schedule(guided): C=1 schedule(runtime): Dépend de la variable OMP_SCHEDULE; Exemple en Unix: setenv OMP_SCHEDULE static,1 ou export OMP_SCHEDULE=static,1

41 Autres formes de parallélisme Jusquà maintenant, lemphase a été mise sur la parallélisation des boucles for. Parallélisme de données Nous allons voir dautres situations favorables au parallélisme de données:

42 Traitement dune liste de tâches

43 Code séquentiel (1/2) int main (int argc, char *argv[]) { struct job_struct *job_ptr; struct task_struct *task_ptr;... task_ptr = get_next_task (&job_ptr); while (task_ptr != NULL) { complete_task (task_ptr); task_ptr = get_next_task (&job_ptr); }... }

44 Code séquentiel (2/2) struct task_struct* get_next_task( struct job_struct **job_ptr ) { struct task_struct *answer; if (*job_ptr == NULL) answer = NULL; else { answer = (*job_ptr)->task; *job_ptr = (*job_ptr)->next; } return answer; }

45 Stratégie de parallélisation Chaque thread prend la prochaine tâche dans la liste et la complète. Cela est répété jusquà ce quil ny ait plus de tâche. On doit sassurer que deux threads ne prennent pas la même tâche. On doit donc définir une section critique.

46 Le pragma parallel Précède un bloc de code devant être exécuté par tous les threads. #pragma omp parallel Note: Tous les threads exécutent le même code

47 Code parallel (1/2) int main (int argc, char *argv[]) { struct job_struct *job_ptr; struct task_struct *task_ptr;... #pragma omp parallel private(task_ptr) { task_ptr = get_next_task (&job_ptr); while (task_ptr != NULL) { complete_task (task_ptr); task_ptr = get_next_task (&job_ptr); }... }

48 Code parallel (2/2) char *get_next_task(struct job_struct **job_ptr) { struct task_struct *answer; #pragma omp critical { if (*job_ptr == NULL) answer = NULL; else { answer = (*job_ptr)->task; *job_ptr = (*job_ptr)->next; } return answer; }

49

50 Le pragma for Le pragma parallel demande à tous les threads dexécuter tout le code dans le bloc. Si le bloc contient une boucle for que lon voudrait diviser entre les threads alors on peut utiliser le pragmafor #pragma omp for

51 Exemple for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; } for (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i]; } La première boucle for ne peut pas être parallélisée Paralléliser la seconde boucle est inefficace Le pragma « parallel » seul est insuffisant

52 Exemple #pragma omp parallel private(i,j){ for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { printf ("Exiting (%d)\n", i); break; } #pragma omp for for (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i]; } Remarque: Ce programme contient une erreur. Laquelle?

53 Le pragma single Dans certaines situation on veut quun seul thread exécute une certaine instruction Par exemple, un message en sortie Cest le rôle du pragma single Syntaxe: #pragma omp single

54 Exemple #pragma omp parallel private(i,j,low,high) for (i = 0; i < m; i++) { low = a[i]; high = b[i]; if (low > high) { #pragma omp single printf ("Exiting (%d)\n", i); break; } #pragma omp for for (j = low; j < high; j++) c[j] = (c[j] - a[i])/b[i]; }

55 Clause nowait Le compilateur place une barrière de synchronisation à la fin de chaque bloc couvert par un pragma de type single, parallel ou for. La plupart du temps cela est nécessaire On peut enlever la barrière à laide de la clause nowait Exemple: #pragma omp parallel nowait

56 Parallélisme fonctionnel Nous navons vu jusquà maintenant que le parallélisme de données OpenMP permet ausi daffecter différentes portions du code à différents threads

57 Exemple v = alpha(); w = beta(); x = gamma(v, w); y = delta(); printf ("%6.2f\n", epsilon(x,y));

58 Le pragma parallel sections Précède un bloc contenant k blocs devant être exécutés en parallèle par k threads Syntaxe: #pragma omp parallel sections

59 Le pragma section Précède chacun des blocs à lintérieur dun bloc couvert par le pragma parallel sections Peut être omis pour le premier bloc Syntaxe: #pragma omp section

60 Exemple #pragma omp parallel sections { #pragma omp section /* Optionnel */ v = alpha(); #pragma omp section w = beta(); #pragma omp section y = delta(); } x = gamma(v, w); printf ("%6.2f\n", epsilon(x,y));

61 Autre approche Deux blocs: alpha et beta gamma et delta

62 Le pragma sections Apparaît à lintérieur dun bloc de code couvert par le pragma parallel Possède la même signification que le pragma parallel sections Ajoute de la flexibilité à la façon dorganiser le parallélisme

63 Exemple #pragma omp parallel { #pragma omp sections { v = alpha(); #pragma omp section w = beta(); } #pragma omp sections { x = gamma(v, w); #pragma omp section y = delta(); } printf ("%6.2f\n", epsilon(x,y));


Télécharger ppt "Parallel Programming in C with MPI and OpenMP Michael J. Quinn Chapitre 17 Open MP."

Présentations similaires


Annonces Google