Open MP wer. 2.5 Wykład PR część 3 Rafał Walkowiak Instytut Informatyki Politechniki Poznańskiej Jesień 2014
OpenMP standard specyfikacji przetwarzania współbieżnego uniwersalny (przenośny) model równoległości typu fork-join (rozgałęzienie - połączenie) dla architektur z pamięcią współdzieloną przetwarzanie rozpoczyna się od jednego wątku przetwarzania regiony współbieżne (parallel regions) wymagają powstania nowych wątków wątki łączą się (bariera synchronizacyjna) przy końcu regionu współbieżnego określona pamięć dostępna dla wszystkich wątków (współdzielona) dla systemów SMP (ang. Symmetrical Multi Processor ) systemy z pamięć współdzieloną, danymi lokalnymi lub współdzielonymi procesów implementowany w większości platform obliczeniowych dostarczany w postaci API Open MP 2
Synchronizacja Synchronizacja niezbędna do: zapewnienia integralności (powiązań części) programu równoległego, zapobieżenia potencjalnie niebezpiecznym dostępom do pamięci np. nadpisanie wyniku, brak danej itp. synchronizacji wybranych zdarzeń przetwarzania, globalnej synchronizacji - bariera synchronizacyjna. Open MP 3
Poziomy równoległości w OpenMP wysoki poziom równoległości przetwarzania - program podzielony na segmenty, które mogą być realizowane współbieżnie, niski poziom równoległości przetwarzania - współbieżna realizacja przez różne wątki iteracji pętli (potencjalnie współbieżnie przez różne procesory) współbieżność na poziomie pul zadań Open MP >= 3.0 Open MP 4
Poziomy równoległości OpenMP Początek sekcji równoległej Początek równoległej pętli for i=10 W1 W2 W3 Zadania realizowane przez wątki i=1 synchronizcja synchronizacja Open MP 5
Projektowanie przetwarzania w Open MP program równoległy - jak napisać? Dyrektywy dla kompilatora: #pragma omp nazwa_dyrektywy klauzule Funkcje biblioteki czasu wykonania określenie/poznanie liczby wątków poznanie numeru wątku poznanie liczby wykorzystywanych procesorów funkcje blokady Open MP 6
Projektowanie przetwarzania w OpenMP Sterowanie wykonaniem parallel, for, sections, single, master (dyrektywy) Specyfikacja danych shared, private, reduction Synchronizacja często wbudowana na początku i końcu obszarów kodu podlegającym dyrektywom sterującym, specyfikacja wprost zastosowanie dyrektyw: barrier, critical, atomic, flush, ordered; Open MP 7
Dyrektywy sterujące przetwarzaniem (1) parallel podstawowa dyrektywa kodu równoległego dyrektywa tworząca związany z nią zbiór wątków (team) realizujących współbieżnie region równoległy - blok strukturalny następujący bezpośrednio po dyrektywie; definiująca współbieżnie realizowany fragment kodu; blok strukturalny (jedno wejście, jedno wyjście) for (wewnątrz regionu równoległego) dyrektywa definiująca realizowany z podziałem pracy fragment kodu pętlę - każda iteracja wykonywana raz - potencjalnie równolegle z innymi iteracjami np. realizowanymi przez inne wątki na innych procesorach. sections, section (wewnątrz regionu równoległego) sections definiuje początek zbioru bloków kodu (oznaczanych section) realizowanych każdy jednokrotnie przez jeden z wątków ze zbioru aktywnych wątków (potencjalnie współbieżnie). Open MP 8
Dyrektywy sterujące przetwarzaniem (2) single dyrektywa definiująca blok kodu realizowany przez tylko jeden, dowolny wątek związany z bieżącym regionem II, przy zakończeniu realizacji bloku bariera synchronizacyjna, master dyrektywa definiująca blok kodu realizowany jednokrotnie tylko przez wątek główny, bez bariery synchronizacyjnej, parallel for fragment kodu realizowany współbieżnie będący jednym blokiem for, parallel sections fragment kodu realizowany współbieżnie będący jednym blokiem sections Open MP 9
Dyrektywy sterujące przetwarzaniem (3) #pragma omp parallel s1 s1 s1 s2 s2 s2 s2 s2 s2 { s1(...); for ( int i =1; i<3, i++) s2(...); } //zakładamy, że tworzone są 3 wątki Open MP 10
Dyrektywy sterujące przetwarzaniem (4) #pragma omp parallel sections { s1 s2 s2 #pragma omp section s1(...); #pragma omp section for (i =1; i<3, i++) s2(...); } //Zakładamy, że tworzone są 3 wątki Open MP 11
s1 Dyrektywy sterujące przetwarzaniem (5) start s1 synch s2 synch s1 #pragma omp parallel { //synchronizacja //synchronizacja #pragma omp for for (i =1; i<4, i++) s1(...); #pragma omp single s2(...); } Open MP 12
Szeregowanie pętli for (1) Zakres iteracji pętli (ustalony w run-time, przy wejściu do pętli) Szeregowanie statyczne Zakres iteracji pętli jest podzielony na podzakresy iteracji o jednakowym rozmiarze określonym jako x w schedule(static, x), liczba i wielkość zakresów przydzielanych do każdego wątku z góry ustalona, domyślnie każdy wątek dostaje jeden zakres; bazuje na zakresie pętli wyznaczonym w czasie przetwarzania. Szeregowanie dynamiczne wątki zwracają się do modułu szeregującego w celu uzyskania pierwszego i kolejnego zakresu iteracji do realizacji, specyfikowany rozmiar x w schedule(dynamic, x), domyślnie zakres iteracji równy jednej iteracji. Open MP 13
Szeregowanie pętli for (2) Szeregowanie sterowane wielkość zakresu wyznaczana na bieżąco maleje w zależności od pozostałej do realizacji liczby iteracji schedule(guided) Szeregowanie realizowane w sposób określany w czasie przetwarzania schedule(runtime) decyduje aktualna wartość zmiennej środowiska OMP_SCHEDULE Open MP 14
Synchronizacja w OpenMP (1) Wewnętrzne bariery synchronizacyjne - oczekiwanie aż wszystkie wątki ze zbioru zrealizują kod objęty jedną z dyrektyw: for sections single nowait likwiduje barierę synchronizacyjną (nie zawsze) Open MP 15
Synchronizacja w OpenMP (2) #pragma omp parallel { #pragma omp for nowait for (i=1; i<n; i++) b[i] = (a[i] + a[i-1])/2.0 #pragma omp for } for (i=0; i<m; i++) y[i]=sqrt(z[i]); klauzula nowait zapobiega barierze synchronizacyjnej po zakończeniu dyrektywy for Open MP 16
Dyrektywy synchronizacyjne (1) single - poprzednie slajdy barrier synchronizacja wszystkich wątków z bieżącego zbioru (#pragma parallel), wątki które dotarły w przetwarzaniu do dyrektywy oczekują na pozostałe wątki; po osiągnięciu miejsca przez wszystkie rozpoczynają one współbieżnie przetwarzanie następnego po dyrektywie wyrażenia; Open MP 17
Dyrektywy synchronizacyjne (2) critical etykieta specyfikuje blok, który może być realizowany jednocześnie tylko przez jeden wątek programu, wzajemne wykluczanie dotyczy bloków o tych samych etykietach (lub bez etykiet), dodatkowo flush atomic zapewnia niepodzielność operacji uaktualnienia specyfikowanej lokacji pamięci dotyczy wyrażeń: x++, ++x, x--, --x x operator = wyrażenie operator = {+, *, -, /, &, ^,, <<, >>} wyznaczenie wartości wyrażenie nie jest atomowe więcej wariantów dyrektywy - wersji dostępów w OpenMP 3.1 Open MP 18
flush Dyrektywy synchronizacyjne (3) zapewnia spójny obraz pamięci w ramach wszystkich wątków; dotyczy zmiennych wyspecyfikowanych jako parametry (lub zmiennych współdzielonych widocznych w bieżącym kontekście); w efekcie stan: wszystkie wcześniejsze operacje tego wątku (realizującego flush) odwołujące się do podanych zmiennych się zakończyły, a następne jeszcze nie zaczęły; wymaga, aby kompilator spowodował zapis zmiennych przechowywanych w rejestrach do pamięci, a sprzęt dokonał zapisu zawartości buforów (pamięci podręcznych) do pamięci oraz ponownie załadował wartości z pamięci; bez parametrów - dotyczy wszystkich zmiennych współdzielonych; automatycznie realizowana w ramach barrier, critical we/wy, ordered we/wy, parallel wy, for wy, sections wy, single wy, atomic (zmienna uaktualniana) volatile dyrektywa kompilatora C, C++, działania na pp Open MP 19
Dyrektywy synchronizacyjne (4) ordered określa blok kodu w ramach regionu równoległej pętli który będzie realizowany wg oryginalnej kolejności iteracji pętli, powoduje sekwencyjność przetwarzania oznaczonego bloku kodu, sprawdzanie zakończenia pracy w bloku dla wcześniejszych iteracji, pozwala aby przetwarzanie poza tym regionem biegło współbieżnie, pojawia się w ramach bloków poprzedzonych dyrektywą for lub parallel for z opcją ordered. Open MP 20
Dyrektywy synchronizacyjne (5) #pragma omp parallel shared(x,y) private (x_next, y_next) { #pragma omp critical ( xaxis ) x_next = pobiez_z_kolejki (x); work(x_next); #pragma omp critical ( yaxis ) y_next = pobiez_z_kolejki (y); work(y_next); } dwie sekcje krytyczne do wzajemnego wykluczania dostępu do dwóch niezależnych kolejek x i y zapobiegają pobieraniu z kolejki tego samego zadania przez wiele wątków Open MP 21
Dyrektywy synchronizacyjne (6) #pragma omp parallel { #pragma omp single printf ( Początek pracy1 \n ); work1( ); #pragma omp single printf( Kończenie pracy1 \n ); #pragma omp single nowait printf( Zakończona praca1 i poczatek pracy2 \n ); work2( ); } Pierwszy z wątków docierający do dyrektywy single generuje komunikat. Bariera na końcu dyrektywy single. Bariera usunięta za pomocą klauzuli nowait. Open MP 22
Dyrektywy synchronizacyjne (7) #pragma omp parallel for shared (x, y, index, n) for (i=0; i<n; i++) { } #pragma omp atomic x[index[i]] += work1(i); y[i] += work2(i); przewaga dyrektywy atomic nad critical atomic dotyczy x, nie dotyczy: y i wyznaczenia work1(i), i domyślnie prywatne Open MP 23
Dane w OpenMP (1) Dane są: private - lokalne dane wątków lokalne kopie zmiennych niewidoczne dla innych wątków shared - globalne dane Współdzielone: Zmienne widoczne w momencie osiągnięcia dyrektywy parallel lub parallel for Prywatne: zadeklarowane dyrektywą threadprivate, zmienne zdefiniowane wewnątrz obszaru równoległego są prywatne, zmienna sterująca pętli for z dyrektywą podziału pracy, umieszczone w klauzuli private, firsprivate, lastprivate, reduction Open MP 24
threadprivate Dane w OpenMP (2) dyrektywa pozwalająca określić poza regionem równoległym zmienne jako prywatne dla każdego wątku, wartości z jednego regionu II są zachowane i przechodzą do kolejnego regionu II w odpowiednich wątkach int counter = 0; #pragma omp threadprivate(counter) Open MP 25
Klauzule sterujące współdzieleniem danych (1) private (lista) klauzula dyrektywy zrównoleglającej lub współdzielącej pracę, pozwala na określenie zmiennych jako prywatnych dla każdego z wątków, dla każdego wątku tworzony jest nowy obiekt o typie określonym przez typ zmiennej, wartość początkowa obiektu jest zgodna z rezultatem działania konstruktora obiektu, firstprivate (lista) W efekcie tej dyrektywy wartość początkowa lokalnego obiektu (określanego bloku i zadania) jest zgodna z wartością oryginalnego obiektu (w wątku nadrzędnym) Open MP 26
Klauzule sterujące współdzieleniem danych (2) lastprivate (lista) tworzy listy obiektów prywatnych dla wątków, wartość zmiennej z wątku przetwarzającego ostatnią iterację pętli lub section zostaje skopiowana do zmiennej oryginalnej - wątku master shared (lista) klauzula powoduje współdzielenie miedzy wątkami wyspecyfikowanych zmiennych Open MP 27
Klauzule sterujące współdzieleniem danych (3) reduction(operacja:lista zmiennych) klauzula powoduje realizację operacji redukcji (scalenie) w oparciu o podaną zmienną skalarną (globalną) operacja redukcji ma postać typu : x = x op expr np.: x = x f( ); x binop = expr) np.: x += f( ) Realizacja: Powstaje prywatna kopia dla każdego wątku (zadania każdego wątku 3.1) każdej ze zmiennych z listy reduction. Każda kopia jest inicjowana w sposób zależny i adekwatny od operatora (np. dla min - max(type)) Na końcu regionu ze zdefiniowaną klauzulą reduction, wartość oryginalnego obiektu jest aktualizowana do wyniku będącego połączeniem za pomocą podanego operatora jego wartości początkowej i ostatecznych wartości każdej z prywatnych kopii. Wartość obiektu oryginalnego podlegającego redukcji jest nie zdeterminowana do momentu zakończenia bloku posiadającego klauzulę reduction (w przypadku klauzuli nowait konieczna bariera do zapewnienia poprawności wartości obiektu). Open MP 28
Klauzule sterujące współdzieleniem danych (4) reduction przykład #pragma omp parallel for private (i) reduction (+:a,y) \ reduction ( : am) for (i=0; i<n; i++) { a += b[i]; y = sum(y, c[i]); am = am b[i] == c[i]; } operator redukcji ukryty w wywoływanej funkcji sum() Open MP 29
Klauzule sterujące współdzieleniem danych (5) copyin(lista zmiennych) dyrektywa powoduje zsynchronizowanie wartości zmiennych typu threadprivate do wartości oryginalnej zmiennej - w ramach wątku master realizacja na początku regionu równoległego copyprivate(lista zmiennych) zsynchronizowanie wartości zmiennej prywatnej do wartości obiektu jednego z wątków realizującego blok single klauzula dostępna tylko w ramach dyrektywy single realizacja przy wyjściu z bloku single Open MP 30
Klauzule sterujące współdzieleniem danych (6) default(private) - sterowanie współdzieleniem zmiennych (traktowane jako prywatne), których atrybuty współdzielenia są zdeterminowane nie wprost. default(none) wymaga, aby wszystkie zmienne, do których następuje odwołanie w regionie współbieżnym, a które nie posiadają predefiniowanych atrybutów współdzielenia, uzyskały takie poprzez wylistowanie w ramach klauzul atrybutów współdzielenia danych. Open MP 31
Funkcje biblioteki czasu wykonania (1) funkcje środowiska przetwarzania omp_set_num_threads (int liczba_wątków) określa liczbę wątków powoływanych przy wejściu do regionu równoległego, posiada wyższy priorytet nad OMP_NUM_THREADS (zm. środowiskowa) realizowana w obszarze kodu w którym: omp_in_parallel = 0 Inne sposoby określania liczby wątków: num_threads klauzula dyrektywy parallel OMP_NUM_THREADS zmienna środowiska omp_set_dynamic i OMP_DYNAMIC zezwalają na dynamiczną modyfikację liczby wątków Złożony algorytm określenia liczby wątków w regione II w 3.1. bazuje na ICV Open MP 32
Funkcje biblioteki czasu wykonania (2) omp_get_num_threads pozwala uzyskać liczbę wątków w zbiorze realizującym bieżący region współbieżny; omp_get_max_threads zwraca (także poza regionem równoległym) maksymalną wartość zwracaną przez omp_get_num_threads; omp_get_thread_num zwraca numer wątku (<0,omp_get_num_threads()-1>) w ramach zbioru realizującego region równoległy, wątkowi master zwraca 0; omp_get_num_procs zwraca maksymalną liczbę procesorów, która może zostać przydzielona do programu; Open MP 33
Funkcje biblioteki czasu wykonania (3) omp_in_parallel() zwraca wartość <> 0 jeśli wywołana w ramach regionu realizowanego współbieżnie; omp_set_nested (true/false) - włączenie/ wyłączenie zagnieżdżonej równoległości dla bieżącego wątku (zadania) omp_get_nested() informacja o statusie zagnieżdżonej równoległości dla wątku(zadania) Parametr OpenMP określenia poziomu zagnieżdżania równoległości w 3.1. Open MP 34
Funkcje biblioteki czasu wykonania (4) - funkcje zamków Zamki powodują zawieszenie przetwarzania w przypadku odwołania się procesu do założonego zamka i pozwalają na wznowienie przetwarzania po otwarciu zamka; Typy: omp_lock_t typ standardowy zamek omp_nest_lock_t typ zagnieżdżony zamek Realizacja: 1. system zapewnia dostęp do najbardziej aktualnego stanu zamka 2. inicjalizacja zamka / usuwanie zamka omp_init_lock/omp_destroy_lock omp_init_nest_lock/omp_destroy_nest_lock tworzenie - ustawiana wartość parametru zagnieżdżenia zamka równa 0 3. omp_set_(nest_)lock - zamykanie wątek jest zawieszany do momentu, gdy wskazany zamek zostanie otwarty przez proces, który go zamknął (typ standardowy), gdy zamek został zamknięty wcześniej przez ten sam wątek (typ zagnieżdżony zamka) następuje zwiększenie licznika zagnieżdżenia; Open MP 35
Funkcje biblioteki czasu wykonania (5) - funkcje zamków 4. Otwarcie zamka: omp_unset_(nest_)lock parametrem jest zamek zamknięty przez ten sam wątek, jest on otwarany (typ standardowy zamka) lub licznik zagnieżdżenia jest zmniejszony i zamek jest zwolniony pod warunkiem, że licznik jest równy 0 (typ zagnieżdżony zamka) 5. test i zamknięcie zamka: omp_test_(nest_)lock funkcja działa jak omp_set_(nest_)lock lecz nie wstrzymuje przetwarzania wątków w przypadku braku możliwości zamknięcie zamka (zwraca zero) zwraca nową wartość licznika zagnieżdżenia Open MP 36
Zmienne środowiskowe dla OpenMP OMP_SCHEDULE OMP_NUM_THREADS OMP_DYNAMIC OMP_NESTED Ustawianie: csh: setenv OMP_SCHEDULE dynamic ksh: export OMP_SCHEDULE= guided,4 Open MP 37
Przykładowe błędy np = omp_get_num_threads(); /* błędny kod */ #pragma omp parallel for private(i) schedule(static) for (i=0; i<np; i++) work(i); ---------------------------------------------------------------------- #pragma omp parallel private(i) /* kod poprawny */ { } i = omp_get_thread_num( ); work(i); barrier wewnątrz bloku critical lub single Open MP 38
Gdzie jest błąd? #include <omp.h> #include <stdio.h> #include <stdlib.h> #define VECLEN 100 float a[veclen], b[veclen]; float dotprod () { int i; float sum; #pragma omp for reduction(+:sum) for (i=0; i < VECLEN; i++) { sum = sum + (a[i]*b[i]); } } int main (int argc, char *argv[]) { int i; float sum; for (i=0; i < VECLEN; i++) a[i] = b[i] = 1.0 * i; sum = 0.0; #pragma omp parallel shared(sum) dotprod(); printf("sum = %f\n",sum); } // zakres zmiennej Open MP 39
Lastprivate, firsprivate - przkład void example(float*a, float*b) { #pragma omp parallel for lastprivate(i) for(i=0; i<k; i++ )a[i] = b[i]; -- i master a równe k #pragma omp parallel for firstprivate(i) for(j=i; j<n; j++ )a[j] = 1.0; } Open MP 40
Task parallelism od OpenMP 3.0 Materiał od tej strony do końca pliku nie jest wymagany do zaliczenia przedmotu Pozwala na zrównoleglenie przetwarzania dla problemów o nieregularnej strukturze: nieograniczone pętle algorytmy rekursywne schematy przetwarzania producentkonsument Open MP 41
Model zadaniowy OpenMP Tworzenie zadań Zakres danych Synchronizacja zadań Model wykonania zadań Open MP 42
Zadanie w OpenMP Zadnie to praca której realizacja może się rozpocząć natychmiast po utworzeniu lub po upływie pewnego czasu Zadania składają się z: Kodu do wykonania środowiska danych zainicjowanego w czasie utworzenia zadania wewnętrznych zmiennych sterujących (ICV) Open MP 43
Dyrektywa zadania (task) #pragma omp task [ klauzule ] Blok strukturalny Zakres danych Klauzule z listą dla określania zakresu danych: shared(), private(), firstprivate(dane pobrane przy tworzeniu zadania), default(shared none)... Przy braku klauzuli stosowane zasady ogólne globalne są współdzielone itp., inne typu firstprivate Używać default(none) jeśli pojawiają się wątpliwości co do określoności zakresu Synchronizacja zadań bariera wszystkie zadania utworzone przez wątki bieżącego poziomu równoległości zostaną zakończone przed wyjściem z bariery #pragma omp taskwait - bariera zadań wątku Wątki zostają zawieszone do zakończenia utworzonych zadań (tylko bezpośrednich potomków) Open MP 44
int a ; void foo ( ) { int b, c ; #pragma omp parallel private ( b ) { int d ; #pragma omp task { int e ; a = shared b = firstprivate c = shared d = firstprivate e = private } } } Zakres danych przykład Open MP 45
Model realizacji zadań Zadania realizowane są przez wątki z bieżącej grupy wątków Grupę wątków stanowią wątki będące wynikiem dyrektywy parallel jest to jeden wątek jeśli zagnieżdżono parallel i zagnieżdżona równoległość jest wyłączona lub niewspomagana. Dyrektywa parallel OpenMP 3.0 tworzy zadanie dla każdego wątku. Wątki mogą zawiesić wykonanie zadania i rozpocząć/wznowić inne. Open MP 46
Szeregowanie zadań Zadanie domyślnie jest tied - realizowane w całości przez wątek który rozpoczął jego realizację. Zadania tied mogą powodować trudności w równoważeniu obciążeń. Wprowadzenie klauzuli untied. Zadanie #pragma omp task untied może być wznowione przez dowolny wątek z bieżącego zbioru. Punktów w kodzie dla szeregowania takich zadań może być wiele. Domyślnie szeregowanie zadań odbywa się w ściśle określonych punktach kodu - punktach szeregowania. Uwaga: ostrożnie z task untied w przypadku połączenia z critical, thread_id, threadprivate Open MP 47
Szeregowanie zadań Punkty szeregowania zadań związanych: Po utworzeniu zadania Po ostatniej instrukcji bloku zadania W regionie taskwait W barierze podanej wprost i niewprost Punkty szeregowania dynamicznie dzielą regiony zadań na części wykonywane przez jeden wątek od początku do końca. Różne części regionu zadania są realizowane w kolejności w jakiej występują w kodzie. Open MP 48
Szeregowanie zadań Gdy wątek osiągnie punkt szeregowania może zrealizować jedno z następujących działań: Rozpocząć realizacje dowolnego zadania typu tied - zadania związanego z bieżącym zespołem wątków - ZZzBZW, Wznowić zawieszoną realizację regionu ZZzBZW, regionu do którego wątek jest tied. Rozpocząć realizacje dowolnego zadania typu untied - ZZzBZW, Wznowić zawieszoną realizację regionu zadania untied ZZzBZW. Open MP 49
Szeregowanie zadań - ograniczenia 1. Klauzula if dyrektywy task oceniona na false powoduje zawieszenie realizacji bieżącego zadania i rozpoczęcie realizacji zadania nowo wygenerowanego, zadanie rodzic może być wznowione po zakończeniu realizacji zadania dziecka. Innymi słowy - Blok jest samodzielnym zadaniem pod warunkiem. 2. Uszeregowanie nowych zadań związanych (tied) nie jest realizowane jeśli zbiór regionów zadań aktualnie związanych z wątkiem (realizowanych wcześniej przez niego), które nie są zawieszone (barrier) zawiera zadania. Jeśli takich regionów zadań nie ma to nowe zadania związane mogą być uszeregowane. Nowe związane zadanie może być uszeregowane również w przypadku, gdy jest potomkiem każdego zadania w tym zbiorze zadań. Open MP 50
#define LARGE_NUMBER 10000000 double item[large_number]; extern void process(double); Dyrektywa Task przykład 1 int main() { #pragma omp parallel { #pragma omp single { int i; for (i=0; i<large_number; i++) #pragma omp task process(item[i]); // i jest firstprivate, item jest shared } } } Open MP 51
Dyrektywa Task przykład 2 int fib(int n) { int i, j; if (n<2) return n; else { #pragma omp task shared(i) i=fib(n-1); #pragma omp task shared(j) j=fib(n-2); #pragma omp taskwait return i+j; } } Open MP 52
Przetwarzanie współbieżne elementów połączonych w listę typedef struct node node; struct node { int data; node * next; }; void process(node * p) { /* praca do wykonania */ } void increment_list_items(node * head) { #pragma omp parallel { #pragma omp single { node * p = head; while (p) { #pragma omp task // p jest firstprivate domyślnie process(p); p = p->next; //następny do obliczeń } } } } // ile równoległych zadań? Open MP 53
Szeregowanie zadań - przykład 1 /* tp prywatne dla wątku*/ void work() { #pragma omp parallel { /* praca tutaj */ #pragma omp task //wiele wątków generuje zadania, wiele wątków realizuje zadania { tp++; /* praca tutaj */ #pragma omp task { /* praca ale bez modyfikacji tp */ } var = tp; // zasady szeregowania konieczność kontynuacji pracy nad zadaniem przez //ten wątek, który pracę rozpoczął sprawiają, że tp prywatna dla // wątku (firstprivate) pozostaje bez zmian w ramach zadania //mimo możliwości modyfikacji w wielu zadaniach i przejściu przez punkt //szeregowania; // wątek nie może realizować innych zadań modyfikujących tp }}} Open MP 54
Szeregowanie zadań przykład 2 int tp; #pragma omp threadprivate(tp) int var; void work() { #pragma omp task { /* wiele wyrażeń praca do wykonania*/ #pragma omp task { tp = 1; /* praca */ #pragma omp task { /* kod bez modyfikacji tp */ } var = tp; // jaka wartość tp 1 czy 2? } // zależne od kolejności realizowania tp = 2; // części pracy zagnieżdżonych zadań } } Open MP 55
Dalsze informacje : OPENMP.ORG Open MP 56