Advertisement
eggggggggor

vector sum parallel omp

Jun 14th, 2024
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.46 KB | None | 0 0
  1. // V teto domaci uloze se Vas budeme snazit presvedcit, ze vykon vasi implementace zavisi do znacne miry na podobe
  2. // vstupnich dat. Pri navrhu efektivnich algoritmu byste se tedy meli rozhodovat i na zaklade datove sady.
  3. //
  4. // Vasim ukolem je doimplementovat 4 ruzne metody na pocitani sumy kazdeho vstupniho vektoru (`data`).
  5. // V kazde metode budete pouzitivat OpenMP, ale pokazde trochu jinym zpusobem. Rychlost vypoctu Vasi implementace
  6. // budeme porovnavat s nasi referencni implementaci. Vychazet muzete z metody `vector_sum_sequential` implementovane
  7. // ve `vector_sum.h`.
  8.  
  9. #include "vector_sum.h"
  10. #include <atomic>
  11. #include <numeric>
  12. #include <random>
  13.  
  14. // typove aliasy pouzite v argumentech jsou definovane ve `vector_sum.h`
  15. void vector_sum_omp_per_vector(const InputVectors& data, OutputVector& solution, size_t min_vector_size) {
  16.     // V teto metode si vyzkousite paralelizaci na urovni vektoru. Naimplementujte paralelni pristup
  17.     // k vypocteni sum jednotlivych vektoru (sumu vektoru data[i] ulozte do solution[i]). V teto
  18.     // funkci zpracovavejte jednotlive vektory sekvencne a paralelizujte nalezeni sumy v jednom
  19.     // konkretnim vektoru. Tento pristup by mel byt zejmena vhodny, pokud mate maly pocet vektoru
  20.     // velke delky.
  21.     for (int i = 0; i < data.size(); ++i) {
  22.         int sum = 0;
  23.         #pragma omp parallel
  24.         {
  25.             int local_sum = 0;
  26.             #pragma omp for
  27.             for (int j = 0; j < data[i].size(); ++j) {
  28.                 local_sum += data[i][j];
  29.             }
  30.             #pragma omp critical
  31.             sum += local_sum;
  32.         };
  33.         solution[i] = sum;
  34.     }
  35. }
  36.  
  37. void vector_sum_omp_static(const InputVectors& data, OutputVector& solution, size_t min_vector_size) {
  38.     // Pokud vektory, ktere zpracovavame nejsou prilis dlouhe, ale naopak jich musime zpracovat
  39.     // velky pocet, muzeme zparalelizovat vnejsi for smycku, ktera prochazi pres jednotlive
  40.     // vektory. Vyuzijte paralelizaci pres #pragma omp parallel for se statickym schedulingem.
  41.     #pragma omp parallel for schedule(static)
  42.     for (int i = 0; i < data.size(); ++i) {
  43.         long sum = 0;
  44.         for (int j = 0; j < data[i].size(); ++j) {
  45.             sum += data[i][j];
  46.         }
  47.         solution[i] = sum;
  48.     }
  49. }
  50.  
  51. void vector_sum_omp_dynamic(const InputVectors& data, OutputVector& solution, size_t min_vector_size) {
  52.     // Na cviceni jsme si ukazali, ze staticky scheduling je nevhodny, pokud praci mezi
  53.     // jednotliva vlakna nedokaze rozdelit rovnomerne. V teto situaci muze byt vhodnym
  54.     // resenim pouziti dynamickeho schedulingu. Ten je rovnez vhodny v situacich, kdy
  55.     // nevime predem, jak dlouho budou jednotlive vypocty trvat. Dani za to je vyssi
  56.     // rezie pri zjistovani indexu 'i', ktery ma vlakno v dane chvili zpracovavat.
  57.     #pragma omp parallel for schedule(dynamic)
  58.     for (int i = 0; i < data.size(); ++i) {
  59.         long sum = 0;
  60.         for (int j = 0; j < data[i].size(); ++j) {
  61.             sum += data[i][j];
  62.         }
  63.         solution[i] = sum;
  64.     }
  65. }
  66.  
  67. void vector_sum_omp_shuffle(const InputVectors& data, OutputVector& solution, size_t min_vector_size) {
  68.     // Dalsi moznosti, jak se vyhnout problemum pri pouziti statickeho schedulingu (tj.,
  69.     // zejmena nevyvazenemu rozdeleni prace) je predzpracovani dat. V teto funkci zkuste
  70.     // data pred zparalelizovanim vnejsi for smycky (se statickym schedulingem) nejprve
  71.     // prohazet. To samozrejme predpoklada, ze cas potrebny na predzpracovani je radove
  72.     // mensi, nez zisk, ktery ziskame nahrazenim dynamickeho schedulingu za staticky.
  73.     //
  74.     // Tip: Abyste se vyhnuli kopirovani vektoru pri "prohazovani" (ktere muze byt velmi
  75.     // drahe!), muzete prohazovat pouze pointery na vektory. Alternativou je vytvorit si
  76.     // nejprve pole nahodne serazenych indexu a ty pak pouzit pro pristup k poli.
  77.     // Uzitecnymi metodami mohou byt metody `std::iota(...)` (ktera Vam vygeneruje posloupnost
  78.     // indexu od 0 do N) a `std::shuffle(...)`, ktera zajisti nahodne prohazeni prvku.
  79.     std::vector<int> randIdxs(data.size());
  80.     std::iota(randIdxs.begin(), randIdxs.end(), 0);
  81.     std::random_device rd;
  82.     std::mt19937 g(rd());
  83.     std::shuffle(randIdxs.begin(), randIdxs.end(), g);
  84.     #pragma omp parallel for schedule(static)
  85.     for (int i = 0; i < data.size(); ++i) {
  86.         long sum = 0;
  87.         for (int j = 0; j < data[i].size(); ++j) {
  88.             sum += data[i][j];
  89.         }
  90.         solution[i] = sum;
  91.     }
  92. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement