This shows you the differences between two versions of the page.
app:laboratoare:01 [2022/10/23 14:42] florin.mihalache |
app:laboratoare:01 [2022/10/23 14:46] (current) florin.mihalache |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 1 - Introducere în OpenMP ===== | + | ====== Laboratorul 1 - Introducere în OpenMP ====== |
- | ==== Ce învățăm la APP? ==== | + | ===== Ce învățăm la APP? ===== |
La APP vom învăța cum să analizăm o problemă și o soluție a acesteia (mai precis, un program secvențial) și cum am putea să îmbunătățim soluțiile la problema respectivă (adică cum am putea să eficientizăm prin paralelizare soluțiile problemei). | La APP vom învăța cum să analizăm o problemă și o soluție a acesteia (mai precis, un program secvențial) și cum am putea să îmbunătățim soluțiile la problema respectivă (adică cum am putea să eficientizăm prin paralelizare soluțiile problemei). | ||
În cadrul laboratoarelor de APP vom studia despre programarea paralelă (OpenMP, pthreads), despre programarea distribuită (MPI) și despre analiza performanțelor unui program (profiling). | În cadrul laboratoarelor de APP vom studia despre programarea paralelă (OpenMP, pthreads), despre programarea distribuită (MPI) și despre analiza performanțelor unui program (profiling). | ||
- | ==== Ce este OpenMP? ==== | + | ===== Ce este OpenMP? ===== |
OpenMP reprezintă un API prin care putem paraleliza programe secvențiale scrise în C/C++. Acesta este un API high-level, în sensul că programatorul are o varietate de tool-uri și de opțiuni la dispoziția sa, ele putând fi folosite cu mare ușurință. | OpenMP reprezintă un API prin care putem paraleliza programe secvențiale scrise în C/C++. Acesta este un API high-level, în sensul că programatorul are o varietate de tool-uri și de opțiuni la dispoziția sa, ele putând fi folosite cu mare ușurință. | ||
Line 12: | Line 12: | ||
{{ :app:laboratoare:fork_join.png?700 |}} | {{ :app:laboratoare:fork_join.png?700 |}} | ||
- | ==== Includere și compilare ==== | + | ====== Includere și compilare ====== |
Pentru a putea folosi OpenMP în cod, trebuie inclusă biblioteca omp.h în cod: ''#include <omp.h>''. | Pentru a putea folosi OpenMP în cod, trebuie inclusă biblioteca omp.h în cod: ''#include <omp.h>''. | ||
Line 19: | Line 19: | ||
* SunStudio (pe fep): ''cc -xopenmp helloworld.c -o helloworld'' | * SunStudio (pe fep): ''cc -xopenmp helloworld.c -o helloworld'' | ||
- | ==== Sintaxa OpenMP ==== | + | ===== Sintaxa OpenMP ===== |
Pentru OpenMP, se folosesc directive de compilare de tip pragma pentru a marca blocuri de cod paralelizate și pentru a folosi elemente de sincronizare. | Pentru OpenMP, se folosesc directive de compilare de tip pragma pentru a marca blocuri de cod paralelizate și pentru a folosi elemente de sincronizare. | ||
Line 25: | Line 25: | ||
Exemplu: ''#pragma omp parallel default(shared) private(beta, pi)'' | Exemplu: ''#pragma omp parallel default(shared) private(beta, pi)'' | ||
- | === Paralelizarea secvențelor de cod === | + | ==== Paralelizarea secvențelor de cod ==== |
Pentru ca o bucată de cod să fie executată de mai multe thread-uri, folosim directiva ''#pragma omp parallel'' prin care marcăm faptul că acea zonă de cod este executată în paralel de mai multe thread-uri. | Pentru ca o bucată de cod să fie executată de mai multe thread-uri, folosim directiva ''#pragma omp parallel'' prin care marcăm faptul că acea zonă de cod este executată în paralel de mai multe thread-uri. | ||
Line 75: | Line 75: | ||
</code> | </code> | ||
- | ==== Funcții utile ==== | + | ===== Funcții utile ===== |
Pentru setarea numărului de thread-uri din cadrul programului paralelizat, putem să facem în două moduri: | Pentru setarea numărului de thread-uri din cadrul programului paralelizat, putem să facem în două moduri: | ||
* din linia de comandă: ''export OMP_NUM_THREADS=8'' | * din linia de comandă: ''export OMP_NUM_THREADS=8'' | ||
Line 96: | Line 96: | ||
* numărul de procesoare: ''omp_get_num_procs()'' | * numărul de procesoare: ''omp_get_num_procs()'' | ||
- | ==== Vizibilitatea variabilelor ==== | + | ===== Vizibilitatea variabilelor ===== |
Variabilele în cadrul blocurilor paralele pot fi: | Variabilele în cadrul blocurilor paralele pot fi: | ||
* globale - văzute și partajate de toate thread-urile | * globale - văzute și partajate de toate thread-urile | ||
Line 141: | Line 141: | ||
</code> | </code> | ||
- | ==== Paralelizarea buclelor ==== | + | ===== Paralelizarea buclelor ===== |
În OpenMP putem paraleliza buclele de tip for folosind directiva ''#pragma omp for'' în cadrul unei zone paralele. În acest fel, iterațiile din for sunt împărțite egal thread-urilor, fiecare thread având iterațiile sale din cadrul buclei for. | În OpenMP putem paraleliza buclele de tip for folosind directiva ''#pragma omp for'' în cadrul unei zone paralele. În acest fel, iterațiile din for sunt împărțite egal thread-urilor, fiecare thread având iterațiile sale din cadrul buclei for. | ||
Line 175: | Line 175: | ||
</code> | </code> | ||
- | ==== Elemente de sincronizare ==== | + | ===== Elemente de sincronizare ===== |
În OpenMP avem la dispoziție elemente de sincronizare, prin care putem să ne asigurăm faptul că soluția paralelizată funcționează corect, fără probleme în ceea ce privește rezultatele incorecte sau deadlocks. | În OpenMP avem la dispoziție elemente de sincronizare, prin care putem să ne asigurăm faptul că soluția paralelizată funcționează corect, fără probleme în ceea ce privește rezultatele incorecte sau deadlocks. | ||
- | === Mutex === | + | ==== Mutex ==== |
Pentru zonele critice, unde avem operații de read-write, folosim directiva #pragma omp critical, care reprezintă un mutex, echivalentul lui ''pthread_mutex_t'' din pthreads, care asigură faptul că un singur thread accesează zona critică la un moment dat, thread-ul deținând lock-ul pe zona critică în momentul respectiv, și că celelalte thread-uri care nu au intrat încă în zona critică așteaptă eliberarea lock-ului de către thread-ul aflat în zona critică în acel moment. | Pentru zonele critice, unde avem operații de read-write, folosim directiva #pragma omp critical, care reprezintă un mutex, echivalentul lui ''pthread_mutex_t'' din pthreads, care asigură faptul că un singur thread accesează zona critică la un moment dat, thread-ul deținând lock-ul pe zona critică în momentul respectiv, și că celelalte thread-uri care nu au intrat încă în zona critică așteaptă eliberarea lock-ului de către thread-ul aflat în zona critică în acel moment. | ||
Line 200: | Line 200: | ||
</code> | </code> | ||
- | === Barieră === | + | ==== Barieră ==== |
Un alt element de sincronizare reprezintă bariera, care asigură faptul că niciun thread gestionat de barieră nu trece mai departe de aceasta decât atunci cand toate thread-urile gestionate de barieră au ajuns la punctul unde se află bariera. | Un alt element de sincronizare reprezintă bariera, care asigură faptul că niciun thread gestionat de barieră nu trece mai departe de aceasta decât atunci cand toate thread-urile gestionate de barieră au ajuns la punctul unde se află bariera. | ||
Line 222: | Line 222: | ||
</code> | </code> | ||
- | ==== Reduction ==== | + | ===== Reduction ===== |
''reduction'' este o directivă folosită pentru operații de tip reduce / fold pe arrays / colecții sau simple însumări / înmulțiri în cadrul unui loop. Mai precis, elementele dintr-un array sau indecșii unui loop sunt "acumulați" într-o singură variabilă, cu ajutorul unei operații, al cărui semn este precizat. | ''reduction'' este o directivă folosită pentru operații de tip reduce / fold pe arrays / colecții sau simple însumări / înmulțiri în cadrul unui loop. Mai precis, elementele dintr-un array sau indecșii unui loop sunt "acumulați" într-o singură variabilă, cu ajutorul unei operații, al cărui semn este precizat. | ||
Line 239: | Line 239: | ||
</code> | </code> | ||
- | ==== Exerciții ==== | + | ===== Exerciții ===== |
- Descărcați [[https://github.com/cs-pub-ro/app-labs/tree/master/lab1/skel | scheletul de laborator]] și [[https://github.com/cs-pub-ro/app-labs/tree/master/lab1/demo | demo-ul pentru laborator]]. Rulați exemplele din demo. | - Descărcați [[https://github.com/cs-pub-ro/app-labs/tree/master/lab1/skel | scheletul de laborator]] și [[https://github.com/cs-pub-ro/app-labs/tree/master/lab1/demo | demo-ul pentru laborator]]. Rulați exemplele din demo. | ||
- Paralelizați însumarea elementelor unui array, încât suma să fie corectă, folosind fișierul ''array_sum.c'' din schelet, unde este implementată suma serială a elementelor dintr-un array. | - Paralelizați însumarea elementelor unui array, încât suma să fie corectă, folosind fișierul ''array_sum.c'' din schelet, unde este implementată suma serială a elementelor dintr-un array. | ||
- | ==== Resurse utile ==== | + | ===== Resurse utile ===== |
* http://jakascorner.com/blog/ | * http://jakascorner.com/blog/ | ||
* https://ppc.cs.aalto.fi/ | * https://ppc.cs.aalto.fi/ |