Open MP wersja 2.5 Rafał Walkowiak Instytut Informatyki Politechniki Poznańskie Jesień 2011
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 2011-11-13 Open MP 2
OpenMP pamięć współdzielona Obliczenia z uŝyciem wielu procesorów: procesor posiada obszar pamięci lokalnej, procesor ma dostęp do pamięci współdzielonej z innymi procesorami; Synchronizacja niezbędna do: zapewnienia integralności (powiązań) 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. 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) bariera stosowana do ponownego zsynchronizowania wątków na końcu przetwarzania bloku współbieŝnego; 2011-11-13 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 koniec koniec 2011-11-13 Open MP 5
Projektowanie przetwarzania w Open MP 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 2011-11-13 Open MP 6
Projektowanie przetwarzania w OpenMP Sterowanie wykonaniem parallel, for, sections, single, master (dyrektywy) Specyfikacja danych shared, private, reduction Synchronizacja wbudowana na początku i końcu obszarów kodu podlegającym dyrektywom sterującym, specyfikacja wprost zastosowanie dyrektyw: barrier, critical, atomic, flush, ordered; 2011-11-13 Open MP 7
Dyrektywy sterujące przetwarzaniem (1) parallel dyrektywa definiująca współbieŝnie realizowany fragment kodu - wszystkie wątki realizują ten kod, dotyczy bloku strukturalnego (jedno wejście, jedno wyjście) następującego bezpośrednio po dyrektywie for 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 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). 2011-11-13 Open MP 8
Dyrektywy sterujące przetwarzaniem (2) single dyrektywa definiująca blok kodu realizowany jednokrotnie przez dowolny wątek, przy zakończeniu realizacji bloku bariera synchronizacyjna, master dyrektywa definiująca blok kodu realizowany jednokrotnie 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 2011-11-13 Open MP 9
Dyrektywy sterujące przetwarzaniem (3) #pragma omp parallel s1 s1 s1 s2 s2 s2 s2 s2 s2 { s1(...); for (i =1; i<3, i++) s2(...); } //zakładamy, Ŝe tworzone są 3 wątki 2011-11-13 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 2011-11-13 Open MP 11
Dyrektywy sterujące przetwarzaniem (5) #pragma omp parallel { #pragma omp for for (i =1; i<4, i++) s1 s1 s1 s1(...); s2 //synchronizacja #pragma omp single s2(...); //synchronizacja 2011-11-13 Open MP 12 }
Szeregowanie pętli for (1) Szeregowanie statyczne pętla jest podzielona na zakresy 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 kolejnego zakresu iteracji do realizacji, specyfikowany rozmiar x w schedule(dynamic, x), domyślnie zakres iteracji równy jednej iteracji. 2011-11-13 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 2011-11-13 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) 2011-11-13 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 2011-11-13 Open MP 16
single Dyrektywy synchronizacyjne (1) specyfikacja bloku realizowanego tylko przez jeden dowolny wątek (pierwszy gotowy do rozpoczęcia przetwarzania), bariera synchronizacyjna po bloku, barrier synchronizacja wszystkich wątków ze zbioru, 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 dla następnego po dyrektywie wyraŝenia; 2011-11-13 Open MP 17
Dyrektywy synchronizacyjne (2) critical etykieta specyfikuje blok, który moŝe być realizowany jednocześnie tylko przez jeden wątek, wzajemne wykluczanie dotyczy bloków o tych samych etykietach 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 18
Dyrektywy synchronizacyjne (3) flush 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); oznacza to Ŝe wszystkie wcześniejsze operacje 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 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 2011-11-13 Open MP 19
Dyrektywy synchronizacyjne (4) ordered określa blok kodu w ramach regionu równoległej pętli który będzie realizowany w kolejności iteracji pętli, powoduje sekwencyjność przetwarzania oznaczonego bloku kodu, pozwalając 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 2011-11-13 Open MP 20
Dyrektywy synchronizacyjne (5) #pragma omp parallel shared(x,y) private (x_next, y_next) { #pragma omp critical ( xaxis ) x_next = dequeue (x); work(x_next); #pragma omp critical ( yaxis ) y_next = dequeue (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 2011-11-13 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. 2011-11-13 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 2011-11-13 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, zmienne statyczne zdefiniowane w regionie równoległym. Prywatne: zadeklarowane threadprivate, zmienne zdefiniowane wewnątrz obszaru równoległego są prywatne, zmienna sterująca pętli for z dyrektywą zrównoleglającą, umieszczone w klauzuli private, firsprivate,lastprivate,reduction 2011-11-13 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 równoległego są zachowane i przechodzą do kolejnego w odpowiednich wątkach int counter = 0; #pragma omp threadprivate(counter) 2011-11-13 Open MP 25
Klauzule sterujące współdzieleniem danych (1) private 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 W efekcie tej dyrektywy wartość początkowa lokalnego obiektu jest zgodna z wartością oryginalnego obiektu 2011-11-13 Open MP 26
Klauzule sterujące współdzieleniem danych (2) lastprivate wartość oryginalnego obiektu po zakończeniu przetwarzania bloku jest równa wartości lokalnego obiektu wątku realizującego ostatnią iterację lub ostatnią sekcję bloku shared klauzula powoduje współdzielenie miedzy wątkami wyspecyfikowanych zmiennych 2011-11-13 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 kaŝdej ze zmiennych z listy reduction. KaŜda kopia jest inicjowana w sposób zaleŝny od operatora. 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). 2011-11-13 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() 2011-11-13 Open MP 29
Klauzule sterujące współdzieleniem danych (5) copyin(lista zmiennych) dyrektywa powoduje zsynchronizowanie wartości zmiennych typu threadprivate do wartości tej 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 2011-11-13 Open MP 30
Klauzule sterujące współdzieleniem danych (6) default(private) - sterowanie współdzieleniem zmiennych, do których następuje odwołanie w regionie współbieŝnym, a 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. 2011-11-13 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 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 2011-11-13 Open MP 32
Funkcje biblioteki czasu wykonania (2) omp_get_num_threads pozwala uzyskać liczbę wątków w zbiorze aktualnie realizującym 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; 2011-11-13 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 omp_get_nested 2011-11-13 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 usunięciu 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; 35
Funkcje biblioteki czasu wykonania (5) - funkcje zamków 4. Otwarcie zamka: omp_unset_(nest_)lock parametrem jest zamek zamknięty przez ten wątek, jest on otwarty (typ standardowy zamka), 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 2011-11-13 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 2011-11-13 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 2011-11-13 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); } 2011-11-13 Open MP 39
Kompilacja Kompilacja program za pomocą gcc: gcc o hello.exe fopenmp hello.c 2011-11-13 Open MP 40
Lastprivate, firsprivate 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+1 #pragma omp parallel for firstprivate(i) for(j=i; j<n; j++ )a[j] = 1.0; } 2011-11-13 Open MP 41
OpenMP 3.0 Task parallelism Pozwala na zrównoleglenie problemów o nieregularnej strukturze: nieograniczone pętle algorytmy rekursywne schematy przetwarzania producentkonsument 2011-11-13 Open MP 42
Model zadaniowy OpenMP Tworzenie zadań Zakres danych Synchronizacja zadań Model wykonania zadań 2011-11-13 Open MP 43
Zadanie w OpenMP Zadnie to praca której realizacja moŝe się rozpocząć natychmiast 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) 2011-11-13 Open MP 44
Dyrektywa zadania (task) #pragma omp task [ klauzule ] Blok strukturalny Zakres danych Klauzule z listą w nawiasie 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) 2011-11-13 Open MP 45
int a ; void foo ( ) { int b, c ; #pragma omp pa r a l l e l pr ivate ( b ) { int d ; #pragma omp task { int e ; a = shared b = firstprivate c = shared d = firstprivate e = private } } } Zakres danych 2011-11-13 Open MP 46
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. 2011-11-13 Open MP 47
Szeregowanie zadań Zadanie domyślnie jest tied - realizowane w całości przez wątek który rozpoczął jego realizację. 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, punkty szeregowania takich zadań mogą być dowolnie umieszczane w kodzie. 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 2011-11-13 Open MP 48
Szeregowanie zadań Punkty szeregowania tied task: 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. 2011-11-13 Open MP 49
Szeregowanie zadań Gdy wątek osiągnie punkt szeregowania moŝe zrealizować jedno następujących działań: Rozpocząć realizacje dowolnego zadania typu tied - zadania związanego z bieŝącym zespołem wątków, Wznowić zawieszoną realizację regionu zadania związanego z bieŝącym zespołem wątków, regionu do którego wątek jest tied. Rozpocząć realizacje dowolnego zadania typu untied - zadania związanego z bieŝącym zespołem wątków, Wznowić zawieszoną realizację regionu zadania untied związanego z bieŝącym zespołem wątków. 2011-11-13 Open MP 50
Szeregowanie zadań - ograniczenia 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. Blok jest samodzielnym zadaniem pod warunkiem. Uszeregowanie nowych zadań związanych 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. 2011-11-13 Open MP 51
#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 } } } 2011-11-13 Open MP 52
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; } } 2011-11-13 Open MP 53
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; } } } } 2011-11-13 Open MP 54
/* tp thread private */ void work() { #pragma omp parallel { /* do work here */ #pragma omp task { tp++; /* do work here */ Szeregowanie zadań - przykład #pragma omp task { /* praca bez modyfikacji tp */ } var = tp; // zasady szeregowania sprawiają, Ŝe tp prywatna dla // wątku 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 55
Szeregowanie zadań przykład 2 int tp; #pragma omp threadprivate(tp) int var; void work() { #pragma omp task { /* praca */ #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; // pracy zagnieŝdŝonych zadań Open MP 56
Brak reduction w openmp 3.0 realizowane innymi dyrektywami #pragma omp task untied if(warunek dla zadania niezwiązanego) Zadania rozwiązaniem zaniem elastycznym lecz nieefektywnym. Dalsze informacje : OPENMP.ORG 2011-11-13 Open MP 57