This shows you the differences between two versions of the page.
app:laboratoare:03 [2022/10/23 14:46] florin.mihalache |
app:laboratoare:03 [2024/10/22 11:06] (current) alexandru.bala [Tasks (opțional)] |
||
---|---|---|---|
Line 106: | Line 106: | ||
==== 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 îl 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. |
În OpenMP, pentru barieră avem directiva ''#pragma omp barrier'', echivalent cu ''pthread_barrier_t'' din pthreads. | În OpenMP, pentru barieră avem directiva ''#pragma omp barrier'', echivalent cu ''pthread_barrier_t'' din pthreads. | ||
Line 132: | Line 132: | ||
Tipar: ''reduction(operator_operatie:variabila_in_care_se_acumuleaza)'' | Tipar: ''reduction(operator_operatie:variabila_in_care_se_acumuleaza)'' | ||
- | Exemplu de reduction: ''reduction(+:sum)'', unde se însumează elementele unui array în variabila sum | + | Exemplu de reduction: ''reduction(+:sum)'', unde se însumează indecșii unui loop în variabila sum |
Exemplu de folosire de reduction: | Exemplu de folosire de reduction: | ||
Line 167: | Line 167: | ||
==== Ordered ==== | ==== Ordered ==== | ||
- | Directiva ''ORDERED'' este folosit în for-uri cu scopul de a distribui în ordine iterațiile către thread-uri. | + | Directiva ''ORDERED'' este folosită în for-uri cu scopul de a distribui în ordine iterațiile către thread-uri. |
Exemplu: | Exemplu: | ||
Line 202: | Line 202: | ||
* ''COPYIN'' - asignarea unei variabile ''THREADPRIVATE'' este vizibilă tuturor thread-urilor | * ''COPYIN'' - asignarea unei variabile ''THREADPRIVATE'' este vizibilă tuturor thread-urilor | ||
- | ===== Tasks (opțional) ===== | + | ===== Tasks ===== |
- | Task-urile în OpenMP reprezintă un concept prin care putem să avem thread pools pentru paralelizarea de soluții ale căror dimensiune nu o știm (echivalent cu ExecutorService din Java). Un task este executat la un moment dat de către un thread din thread pool. | + | Task-urile în OpenMP reprezintă un concept prin care putem să avem thread pools pentru paralelizarea de soluții ale căror dimensiune nu o știm (echivalent cu ''ExecutorService'' din Java). Un task este executat la un moment dat de către un thread din thread pool. |
- | Pentru crearea unui task se folosește directiva TASK: | + | Pentru crearea unui task se folosește directiva ''TASK'': |
<code c> | <code c> | ||
#pragma omp task [clause1 [[,] clause2, ...]] | #pragma omp task [clause1 [[,] clause2, ...]] | ||
</code> | </code> | ||
- | Pentru sincronizarea task-urilor (în sensul să așteptăm toate rezultatele task-urilor, în stilul barierei), se folosește directiva TASKWAIT (exemplu de folosire în exemplul Fibonacci de mai jos). | + | Pentru sincronizarea task-urilor (în sensul să așteptăm toate rezultatele task-urilor, în stilul barierei), se folosește directiva ''TASKWAIT'' (exemplu de folosire în exemplul Fibonacci de mai jos). |
În privința variabilelor dintr-un task, aici avem trei variante de variabile: | În privința variabilelor dintr-un task, aici avem trei variante de variabile: | ||
- | * shared - toate task-urile au acces la aceeași adresă a unei variabile, o modificare asupra variabilei din partea unui task va fi vizibilă către toate task-urile (uneori putem avea potențial de erori în acest caz). | + | * ''shared'' - toate task-urile au acces la aceeași adresă a unei variabile, o modificare asupra variabilei din partea unui task va fi vizibilă către toate task-urile (uneori putem avea potențial de erori în acest caz). |
- | * firstprivate - fiecare task va avea o copie a unei variabile inițializate cu o valoare înainte de crearea task-ului respectiv. | + | * ''firstprivate'' - fiecare task va avea o copie a unei variabile inițializate cu o valoare înainte de crearea task-ului respectiv. |
- | * private - aici putem să avem variabile care nu sunt inițializate înainte de crearea task-ului și care să fie inițializate în cadrul task-ului. | + | * ''private'' - aici putem să avem variabile care nu sunt inițializate înainte de crearea task-ului și care să fie inițializate în cadrul task-ului. |
<code c> | <code c> | ||
Line 277: | Line 277: | ||
===== Exerciții ===== | ===== Exerciții ===== | ||
- | 1) Paralelizați fișierul ''main.c'' din [[https://github.com/cs-pub-ro/app-labs/tree/master/lab3/skel | schelet]], unde se citește un fișier, unde pe prima linie se află numărul de elemente pentru un array și pe următoarea linie se află array-ul respectiv, se face suma numerelor (aici faceți în trei moduri, separat, cu ''reduction'', cu ''atomic'' și cu ''critical'', unde veți măsura timpii de execuție - hint, folosiți directiva master ca un singur thread să facă măsurătorile), iar la final, cu ajutorul ''sections'', scrieți timpii de execuție în trei fișiere (este deja implementată funcția de scriere în fișier). | + | * Paralelizați fișierul ''main.c'' din [[https://github.com/cs-pub-ro/app-labs/tree/master/lab3/skel | schelet]], unde se citește un fișier, unde pe prima linie se află numărul de elemente pentru un array și pe următoarea linie se află array-ul respectiv, se face suma numerelor (aici faceți în trei moduri, separat, cu ''reduction'', cu ''atomic'' și cu ''critical'', unde veți măsura timpii de execuție - hint, folosiți directiva master ca un singur thread să facă măsurătorile), iar la final, cu ajutorul ''sections'', scrieți timpii de execuție în trei fișiere (este deja implementată funcția de scriere în fișier). |
<note tip>O să aveți nevoie de barieră la citire și înainte de scrierea în fișiere.</note> | <note tip>O să aveți nevoie de barieră la citire și înainte de scrierea în fișiere.</note> | ||
Line 283: | Line 283: | ||
<note>De probă, încercați să puneți ORDERED la for-urile paralelizate, pentru a vedea cum este afectată performanța.</note> | <note>De probă, încercați să puneți ORDERED la for-urile paralelizate, pentru a vedea cum este afectată performanța.</note> | ||
- | 2) **(opțional)** Paralelizați folosind task-uri codul din [[https://github.com/cs-pub-ro/app-labs/blob/master/lab3/skel/tree.c | tree.c]] (folosiți task-uri în funcțiile ''preorder'' și ''height'' - la ultima trebuie să folosiți ''taskwait''). | + | * Paralelizați folosind task-uri codul din [[https://github.com/cs-pub-ro/app-labs/blob/master/lab3/skel/tree.c | tree.c]] (folosiți task-uri în funcțiile ''preorder'' și ''height'' - la ultima trebuie să folosiți ''taskwait''). |
===== Resurse ===== | ===== Resurse ===== | ||
- | [[https://icl.cs.utk.edu/classes/cosc462/2017/ | Cursuri de OpenMP, MPI, CUDA - COSC462]] | + | |
+ | - [[https://stackoverflow.com/questions/18669296/c-openmp-parallel-for-loop-alternatives-to-stdvector | User-defined OpenMP Reduction]] | ||
+ | - [[https://stackoverflow.com/questions/18022133/difference-between-openmp-threadprivate-and-private |Difference between OpenMP threadprivate and private]] | ||
+ | - [[https://learn.microsoft.com/en-us/cpp/parallel/openmp/reference/openmp-clauses?view=msvc-170 | OpenMP Clauses]] |