Documente Academic
Documente Profesional
Documente Cultură
3.1
Biblioteca OpenMP
Biblioteca OpenMP este instalat implicit (la instalarea sistemului de operare) att n sistemele
Linux Ubuntu 12.04 (din laboratoarele B125a, B138), ct i n fiecare nod al sistemului HPC Dell
PowerEdge.
Biblioteca OpenMP asigur interfaa (API-Application Program Interface) pentru exprimarea
paralelismului ntr-un limbaj de baz (Fortan, C, C++) folosind thread-uri multiple care comunic prin
variabile partajate. Exist implementri OpenMP att pentru Linux ct i pentru Windows [Gra03],
[OMP08].
OpenMP folosete modelul fork-join de programare paralel: programul este compus dintr-o
succesiune de regiuni secveniale i regiuni paralele; n regiunile paralele thread-urile multiple execut
task-uri create implicit sau explicit care comunic ntre ele prin variabile partajate. Biblioteca OpenMP
permite paralelizarea semi-automat a programelor:
OpenMP admite numai blocuri structurate: un bloc structurat are un singur punct de intrare i un
singur punct de ieire i nu se admit salturi din bloc n afara lui sau din afar n interiorul blocului, cu
excepia funciei exit() (pentru C, C++) sau a instruciunii STOP (pentru Fortran).
n continuare vor fi prezentate cele mai importante directive OpenMP, mpreun cu clauzele
acestora i cu funciile de bibliotec necesare pentru limbajul C.
3.1.1 Crearea regiunilor paralele n OpenMP
Regiunile paralele se creeaz cu directiva #pragma omp parallel. Atunci cnd un thread (n
general thread-ul master) execut directiva parallel, se creaz o regiune paralel compus dintr-un
grup de thread-uri care se execut n paralel; aceast directiv are urmtoarea sintax:
1
Numrul de thread-uri ale regiunii paralele create este controlat de valoarea variabilei de
mediu OMP_NUM_THREADS, poate fi setat prin comanda sh/bash:
$ export OMP_NUM_THREADS=nr_thread-uri
Atunci cnd toate thread-urile ating sfritul regiunii paralele, ele sunt distruse (sau puse n
ateptare) i numai thread-ul master continu execuia regiunii secveniale urmtoare. Se poate
considera c la terminarea unei regiuni paralele exist o bariera de sincronizare implicit.
Variabile folosite n thread-uri pot fi de tip private sau partajat (shared). Dac o variabil este
de tip private, atunci fiecare thread primete o copie local neiniializat a acestei variabile. Dac o
variabil este de tip partajat (shared), atunci exist o singur copie a variabilei i toate thread-urile care
se execut n paralel au acces la acea copie a variabilei. In mod implicit, variabilele globale sunt de tip
shared, iar cele locale sunt de tip private.
Clauza default poate schimba aceasta, specificnd c tipul implicit al variabilelor este partajat
(shared), sau nici un tip (none) nu este implicit, deci trebuie declarat explicit tipul fiecarei variabile.
Tipul variabilelor se poate specifica prin clauza shared (care specific lista variabilor partajate
de toate thread-urile) sau prin clauza private (care specific lista variabilelor locale ale thread-urilor).
Clauza firstprivate conine lista variabilelor private care se iniializeaz cu valorile pe care le au
variabilele cu acelai nume nainte de nceperea regiunii paralele.
Clauza reduction definete o operatie de reducere paralel, pentru care se specific un operator
asociativ i o list de variabile.
Execuia cu 4 thread-uri:
$ ./Hello_OpenMP 4
Hello OpenMP thread
Hello OpenMP thread
Hello OpenMP thread
Hello OpenMP thread
0
1
3
2
!
!
!
!
Directiva #pragma omp single, introdus ntr-o regiune paralel, are ca efect execuia
instruciunii (sau a blocului de instruciuni) care urmeaz de ctre un singur thread. Thread-ul care
ajunge primul la aceast directiv este ctigtorul pentru execuia blocului ei, iar toate celelalte
thread-uri care ajung la ea ateapt pn cnd blocul este executat, dup care o depete i continu
execuia. Directiva single introduce o barier de sincronizare implicit ntre thread-uri dac nu conine
clauza nowait.
#pragma omp parallel ...
{
...
#pragma omp single
{
bloc single
}
}
Directiva #pragma omp master, introdus ntr-o regiune paralel, are ca efect execuia
instruciunii (sau a blocului de instruciuni) care urmeaz doar de ctre thread-ul master, fr barier de
sincronizare ntre thread-uri.
Directiva #pragma omp critical este utilizat pentru serializarea acceselor mai multor threaduri la o variabil partajat. Instruciunea (sau blocul de instruciuni) care urmeaz unei astfel de
directive este o seciune critic i poate fi executat numai de un singur thread la un moment dat:
4
Argumentul acestei directive este opional dac toate seciunile critice dintr-o regiune paralel
sunt independente unele de altele, sau trebuie introdus explicit, cu un anumit nume pentru toate
directivele critical care se refer la controlul accesului la aceeai variabil partajat.
Directiva critical protejeaz, aadar, accesul mai multor thread-uri la o seciune critic (blocul
directivei) i este echivalent cu utilizarea unui mecanism de sincronizare de tip mutex (lock).
are nici un efect deoarece terminarea buclei coincide cu terminarea regiunii paralele care introduce o
bariera de sincronizare implicit.
7
-lgomp
(b)
(c)
(c)
10
n screenshot-ul (a) sunt lansate n execuie 4 thread-uri care sunt atribuite la 4 procesoare, care
sunt ncrcate 100%, restul procesoarele avnd o ncrcare mult mai mic (execuia altor procese, de
sistem sau utilizator). n screenshot-ul (b) sunt lansate 8 thread-uri, atribuite la 8 procesoare care sunt
ncrcate 100%. n screenshot-ul (c) sunt lansate 16 thread-uri, toate cele 16 procesoare ale nodului
hpc.intern sunt ocupate 100%.
Exerciiul E3.2. Studiai programul folosind textul surs Matrix_Mult_OpenMP.c, executai
pentru fiecare mod de partiionare pe staia Linux i pe HPC i comparai rezultatele. n scriptul de
execuie Exec_Matrix_Mult_OpenMP numrul de repetri ale execuiei (parametrul max_rep transmis
la comanda ./Matrix_Mult_Pthread n p mod max_rep) este mai mare pentru n mic: max_rep = 4096 / n.
3.3.
3.4.
11
3.5.
3.6
12
<include <omp.h>
int main(int argc, char **argv){
int i, j, k, n = 1024, p = 2;
float **a, **b, **c, **d, **e;
// Citire parametri n, p, alocarea si initializarea matricelor ...
#pragma omp parallel num_threads(p) shared (a,b,c,d,e,n) \
private (i,j,k)
{
#pragma omp for
for (i = 0; i < n; i++)
for (j = 0; j < n; j++){ c[i][j] = 0;
for (k = 0; k < n; k++)
c[i][j] += a[i][k] * b[k][j]; }
#pragma omp for
for (i = 0; i < n; i++)
for (j = 0; j < n; j++){ e[i][j] = 0;
for (k = 0; k < n; k++)
e[i][j] += d[i][k] * c[k][j]; }
}
}
Acest program conine dou bucle succesive. Fiecare bucl este o bucl imbricat pe 3 niveluri,
cu bucla exterioar paralelizabil, care se distribuie celor p thread-uri prin directiva #pragma omp for
Exit dependene dintre fiecare iteraie din a doua bucl i toate iteraiile din prima bucl, de
aceea este necesar o barier de sincronizare ntre cele dou bucle. n OpenMP, bariera de sincronizare
necesar este introdus automat la sfritul directivei #pragma omp for (dac nu se adaug clauza
nowait).
Exerciiul E3.6. Implementai algoritmul de nmulire succesiv a matricelor folosind
biblioteca OpenMP, n mod asemntor cu inmulirea a dou matrice. Executai programul pe staia
Linux i pe HPC. Generai matricea de valori ale timpului de execuie folosind un script
Exec_Many_Matrix_Mult_OpenMP pentru aceleai valori ale lui p (1, 2, 4, 8, 12, 16) i n = (16, 32,
64, 256, 1024, 4096). Reprezentai graficele performanelor TP (p), S(p), E(p) folosind programul
Grafice.R.
Bibliografie
1. Felicia Ionescu, Calcul paralel, 2014, slide-uri publicate pe site-ul moodle ETTI.
2. OpenMP Architecture Review Board, OpenMP Application Program Interface, 2008
3. B. Barney, OpenMP Programming, Lawrence Livermore National Laboratory, 2013,
https://computing.llnl.gov/tutorials/OpenMP/
13