Introduction à OpenMP Daniel Etiemble de@lri.fr Références Dieter an Mey, «Parallel programming in OpenMP», Aachen university of Technology Muller et al, «Introduction to OpenMP», High Performance Computing Center, Stuttgart, www.hlrs.de www.openmp.org 2 1
OpenMP Modèle pour la programmation parallèle Parallélisme en mémoire partagée Parallélisation incrémentale Fondé sur le compilateur Extension aux langages de programmation existants (C/C++, Fortran) Directives Quelques procédures de bibliothèques Supporte le parallélisme de données 3 Modèle d exécution OpenMP Modèle fork-join d exécution parallèle L exécution commence avec un seul processus (thread maître) Début d une construction parallèle : le thread maître crée un ensemble de threads Fin d une construction parallèle. Les threads de l ensemble se synchronise : barrière implicite Seul le thread maître continue à s exécuter Partie séquentielle Partie parallèle Partie séquentielle Partie parallèle Partie séquentielle 4 2
Région parallèle OpenMP Bloc de code à exécuter par plusieurs threads en parallèle. Chaque thread exécute le même code Fortran!$OMP PARALLEL [clause[[,]clause] ] Bloc!$OMP END PARALLEL C/C++ #pragma omp parallel [clause[clause] ] Bloc structuré Clause private (list) shared (list) 5 Construction parallèle OpenMP C/C++ #pragma omp parallel Bloc structuré /*omp end parallel*/ Fortran!$OMP PARALLEL Bloc!$OMP END PARALLEL 6 3
Clauses sur la portée des variables private (liste) Les variables de la liste appartiennent à chaque thread d un ensemble (privées) shared (liste) Les variables de la liste sont partagées par tous les threads de l ensemble Par défaut, les variables sont partagées, mais Les variables locales (pile) des sous programmes appelés sont privées Les variables automatiques d un bloc sont privées La variable de contrôle de boucle du DO (fortran) et for (C) est privée 7 Fonctions de bibliothèque Fonction omp_get_num_threads Fournit le nombre de threads dans l ensemble exécutant la région parallèle dans laquelle elle est appelée C/C++ int omp_get_num_threads(void); Fortran integer function omp_get_num_threads() Fonction omp_get_thread_number Fournit le numéro de thread à l intérieur de l ensemble, compris entre 0 et omp_get_num_threads()-1. Le thread maître a le numéro 0. C/C++ int omp_get_thread_num(void); Fortran integer function omp_get_thread_num() 8 4
Partage du travail et synchronisation Quel thread exécute une instruction ou une opération? Et quand? Constructions de partage de travail Constructions maître et synchronisation 9 Les constructions de partage du travail Divisent l exécution de la partie de code concernée entre les différents threads de l ensemble Doivent être incluses dynamiquement dans une région parallèle Ne doivent pas créer de nouveaux threads Pas de barrière implicite à l entrée Les directives Les sections Do (Fortran) For (C/C++) 10 5
Les directives de section (C/C++) #pragma omp parallel { #pragma omp sections { a= ; b= ; #pragma omp section c= ; d= ; #pragma omp section e= ; f= ; #pragma omp section g= ; h= ; /*omp end sections*/ /*omp end parallel*/ a= c= e= g= b= d= f= h= 11 Directive for (C/C++) #pragma omp parallel private(f) { f=7; #pragma omp for for (i=0;i<20;i++) a[i]=b[i]+f*(i+5); /*omp end parallel*/ f=7 f=7 f=7 f=7 i=0,4 i=5,9 i=10,14 i=15,19 a[i)=b[i] + a[i)=b[i] + a[i)=b[i] + a[i)=b[i] + 12 6
Directive for La clause peut être l une des suivantes private (liste) reduction (operator : liste) Réalise une réduction sur les variables qui apparaissent dans la liste avec l opérateur «operator» En C/C++, les opérateurs sont : +, *, -, &, ^,, &&, A la fin de la réduction, la variable partagée reflète le résultat de la combinaison de la valeur initiale de la variable partagée avec la valeur finale de chacune des copies privées en utilisant l opérateur spécifié schedule (type [,chunk]) Spécifie comment les itérations de la boucle sont divisées parmi les threads nowait (C/C++ sur #pragma omp for) Barrière implicite à la fin du for, sauf si nowait est spécifié Si nowait est spécifié, les threads ne se synchronisent pas à la fin de la boucle 13 Synchronisation Barrière implicite Début et fin des constructions parallèles Fin de toutes les autres constructions La synchronisation implicite peut être supprimée par «nowait» Explicite Critical Le code considéré est exécuté par tous les threads, mais seulement par un threadàla fois C/C++ #pragma omp critical [(name)]» Bloc structuré Fortran!$OMP CRITICAL [(name)]» Bloc!$OMP END CRITICAL [(name)] 14 7
Section critique : un exemple (C/C++) mx=0; #pragma omp parallel private (pmax) { pmax = 0; #pragma omp for private ( r ) for (i=0;i<20;i++) { r= travail(i); pmax =(r>pmax? r : pmax); /*end for*/ /*omp end for*/ #pragma omp critical mx=(pmax>mx? pmax : mx); /*omp end critical*/ /*omp end parallel*/ mx=0 pmax=0 pmax=0 pmax=0 pmax=0 i=0,4 i=5,9 i=10,14 i=15,19 r= r= r= r= pmax= pmax= pmax= pmax= mx= mx= mx= mx= 15 Directive combinée parallel for Raccourci pour spécifier une région parallèle qui contient une seule directive do/for C/C++ #pragma omp parallel for [clause [clause] ] Boucle for Fortran!$ OMP PARALLEL DO [clause [[,]clause] ] Boucle do!$ OMP END PARALLEL DO Cette directive a toutes les clauses de la directive parallèle et de la directive do/for sauf «nowait» 16 8
PI open MP : approche SPMD #include <omp.h> static long etapes = 100000; double pas; #define NB_THREADS 2 void main () { int i; double x, pi, sum[nb_threads]; pas = 1.0/(double) etapes; omp_set_num_threads(nb_threads) #pragma omp parallel { double x; int id; id = omp_get_thread_num(); for (i=id, sum[id]=0.0;i< etapes; i=i+nb_threads){ x = ((double)i+0.5)*pas; sum[id] += 4.0/(1.0+x*x); for(i=0, pi=0.0;i<nb_threads;i++) pi += sum[i] * pas; Programmes SPMD : Chaque thread exécute le même code avec l identificateur de thread spécifiant le travail spécifique du thread. 17 Program PI OpenMP: Work sharing construct #include <omp.h> static long etapes = 100000; double pas; #define NB_THREADS 2 void main () { int i; double x, pi, sum[nb_threads]; pas = 1.0/(double) etapes; omp_set_num_threads(nb_threads) #pragma omp parallel { double x; int id; id = omp_get_thread_num(); sum[id] = 0; #pragma omp for for (i=0;i< etapes; i++){ x = ((double)i+0.5)*pas; sum[id] += 4.0/(1.0+x*x); for(i=0, pi=0.0;i<nb_threads;i++) pi += sum[i] * pas; 18 9
Programme PI OpenMP: clause privée et section critique #include <omp.h> static long etapes = 100000; double pas; #define NB_THREADS 2 void main () { int i; double x, sum, pi=0.0; pas = 1.0/(double) etapes; omp_set_num_threads(nb_threads) #pragma omp parallel private (x, sum) { id = omp_get_thread_num(); for (i=id,sum=0.0;i< etapes;i=i+nb_threads){ x = ((double)i+0.5)*pas; sum += 4.0/(1.0+x*x); #pragma omp critical pi += sum 19 Programme PI OpenMP : For parallèle + réduction #include <omp.h> static long etapes = 100000; double pas; #define NB_THREADS 2 void main () { int i; double x, pi, sum = 0.0; pas = 1.0/(double) etapes; omp_set_num_threads(nb_threads) #pragma omp parallel for reduction(+:sum) private(x) for (i=1;i<= etapes; i++){ x = ((double)i-0.5)*pas; sum = sum + 4.0/(1.0+x*x); pi = pas * sum; OpenMP ajoute 2 à 4 lignes de code 20 10