Komputerowe Obliczenia Równoległe: Wstęp do OpenMP i MPI



Podobne dokumenty
Przetwarzanie Równoległe i Rozproszone

Komputerowe Obliczenia Równoległe: Wstęp do OpenMP i MPI

Programowanie systemów z pamięcią wspólną specyfikacja OpenMP. Krzysztof Banaś Obliczenia równoległe 1

Wprowadzenie do OpenMP

Open MP wer Rafał Walkowiak Instytut Informatyki Politechniki Poznańskiej Jesień 2014

Programowanie współbieżne Wstęp do OpenMP. Rafał Skinderowicz

Elementy składowe: Przenośność oprogramowania Model SPMD Szczegółowe wersje (bindings) dla różnych języków programowania

Programowanie maszyn z pamięcią wspólną w standardzie OpenMP ciąg dalszy.

Instrukcje cykliczne (pętle) WHILE...END WHILE

Open MP wer Rafał Walkowiak Instytut Informatyki Politechniki Poznańskiej Wiosna

Programowanie maszyn z pamięcią wspólną w standardzie OpenMP.

Open MP. Rafał Walkowiak Instytut Informatyki Politechniki Poznańskie Jesień 2011

Wprowadzenie do zrównoleglania aplikacji z wykorzystaniem standardu OpenMP

OpenMP. Programowanie aplikacji równoległych i rozproszonych. Wykład 2. Model programowania. Standard OpenMP. Dr inż. Tomasz Olas

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Programowanie współbieżne OpenMP wybrane wydajność. Rafał Skinderowicz

PODSTAWY INFORMATYKI 1 PRACOWNIA NR 6

Informatyka I. Wykład 3. Sterowanie wykonaniem programu. Instrukcje warunkowe Instrukcje pętli. Dr inż. Andrzej Czerepicki

7. Pętle for. Przykłady

Składowane procedury i funkcje

Bloki anonimowe w PL/SQL

PARADYGMATY I JĘZYKI PROGRAMOWANIA. Programowanie współbieżne... (w14)

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

PRZETWARZANIE RÓWNOLEGŁE I ROZPROSZONE. Mnożenie macierzy kwadratowych metodą klasyczną oraz blokową z wykorzystaniem OpenMP.

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Pętle. Programowanie komputerowe

Pętle instrukcje powtórzeo

Równoległość i współbieżność

Równoległość i współbieżność

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

4. Funkcje. Przykłady

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

Podstawy programowania w języku Visual Basic dla Aplikacji (VBA)

Wyklad 11 Języki programowania równoległego

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Lock Manager Deadlock Źródła Jak starczy czasu. Dreadlocks. Konrad Błachnio MIMUW 19 maja 2010

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Pętla for. Matematyka dla ciekawych świata -19- Scilab. for i=1:10... end. for k=4:-1:1... end. k=3 k=4. k=1. k=2

Podstawy programowania. Wykład: 4. Instrukcje sterujące, operatory. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1

DECLARE VARIABLE zmienna1 typ danych; BEGIN

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Liczby losowe i pętla while w języku Python

Java Podstawy. Michał Bereta

15. Funkcje i procedury składowane PL/SQL

Generatory. Michał R. Przybyłek

Pakiety podprogramów Dynamiczny SQL

Podstawy Programowania C++

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Oracle PL/SQL. Paweł Rajba.

Język PL/SQL. Rozdział 2. Kursory

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Podstawy programowania skrót z wykładów:

Wsparcie dla OpenMP w kompilatorze GNU GCC Krzysztof Lamorski Katedra Informatyki, PWSZ Chełm

Bloki anonimowe w PL/SQL

SQL 4 Structured Query Lenguage

Materiały do laboratorium MS ACCESS BASIC

Przetwarzanie wielowątkowe przetwarzanie współbieżne. Krzysztof Banaś Obliczenia równoległe 1

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

w PL/SQL bloki nazwane to: funkcje, procedury, pakiety, wyzwalacze

Model pamięci. Rafał Skinderowicz

Instrukcje sterujące. Programowanie Proceduralne 1

Wstęp do programowania

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Optimizing Programs with Intended Semantics

Współbieżność w środowisku Java

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wstęp do programowania. Różne różności

PODSTAWY BAZ DANYCH 13. PL/SQL

ForPascal Interpreter języka Pascal

Skrypty i funkcje Zapisywane są w m-plikach Wywoływane są przez nazwę m-pliku, w którym są zapisane (bez rozszerzenia) M-pliki mogą zawierać

Kursor jawny. Rozdział 10a Kursory. Deklarowanie kursora (1) Deklarowanie kursora (2)

Kursor. Rozdział 10a Kursory. Otwieranie kursora. Deklarowanie kursora

Metody Metody, parametry, zwracanie wartości

Platformy Programistyczne Podstawy języka Java

Programowanie komputerowe. Zajęcia 2

Programowanie obiektowe

Programowanie wielowątkowe. Jarosław Kuchta

Algorytmy i struktury danych

Programowanie Proceduralne

Układy reprogramowalne i SoC Język VHDL (część 4)

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Instrukcje pętli przykłady. Odgadywanie hasła. 1) Program pyta o hasło i podaje adres, gdy hasło poprawne lub komunikat o błędnym haśle.

Jak ujarzmić hydrę czyli programowanie równoległe w Javie. dr hab. Piotr Bała, prof. UW ICM Uniwersytet Warszawski

ECDL Podstawy programowania Sylabus - wersja 1.0

Programowanie obiektowe w VB cz 2

Cheatsheet PL/SQL Andrzej Klusiewicz 1/9

Stuck in the loop. Sterowanie. Marcin Makowski. 29 października Zak lad Chemii Teoretycznej UJ

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Plan wykładu BAZY DANYCH II WYKŁAD 4. Co to jest kursor? Rodzaje kursorów

Wykład 8. Rekurencja. Iterować jest rzeczą ludzką, wykonywać rekursywnie boską. L. Peter Deutsch

Rekurencja. Przygotowała: Agnieszka Reiter

Algorytm. a programowanie -

Procedury i funkcje składowane

Transkrypt:

Komputerowe Obliczenia Równoległe: Wstęp do OpenMP i MPI Patryk Mach Uniwersytet Jagielloński, Instytut Fizyki im. Mariana Smoluchowskiego

Zadania w OpenMP technika zrównoleglania bardziej złożonch problemów, ale również istotna część terminologii OpenMP. Fragment ze specyfikacji: Task A specyfic instance of executable code and its data environment, generated when a thread encounters a task construct or a parallel construct. (... ) When any thread encounters a parallel construct, the thread creates a team of itself and zero or more additional threads and become the master of new team. A set of implicit tasks, one per thread, is generated. The code for each task is defined by the code inside the parallel construct. Each task is assigned to a different thread in the team and becomes tied; that is, it is always executed by the thread to which it is initially assigned. The task region of the task being executed by the encountering thread is suspended, and each member of the new team executes its implicit task.

(... ) When any thread encounters a task construct, a new explicit task is generated. Execution of explicitly generated tasks is assigned to one of the threads in the current team, subject to the thread s availability to execute work. Thus, execution of the new task could be immediate, or deferred until later. Zadania wykonywane przy udziale jawnej konstrukcji task są najczęściej zagnieżdżone. Omówienie takiej sytuacji wymaga wprowadzenia paru pojęć. Obszar zadania (task region) obszar składający się z kodu wykonywanego w danym zadaniu. Zadanie generujące (generating task) zadanie, którego wykonanie spowodowało wygenerowanie zadania związanego z aktualnym obszarem kodu. (Kod poza obszarem równoległym traktowany jest również jako zadanie).

Równocześnie, każde zadanie jest traktowane jako zadanie dziecko (child task) obszaru swojego zadania generującego. Zadanie dziecko nie jest częścią zadania generującego. Mówi się również o zadaniach potomnych (descendant tasks). Punkt rozdzielania zadań miejsce w programie, w którym wykonywanie aktualnego zadania może zostać tymczasowo zawieszone, albo miejsce, w którym zadanie się kończy. W punkcie rozdzielania zadań, wątek wykonujący zadanie może rozpocząć wykonywanie kolejnego zadania. Zadania mogą być określone jako tied albo untied. Zadanie określone jako tied musi być dokończone przez wątek, który rozpoczął jego wykonywanie. Zadania untied mogą być dokończone przez dowolny wątek. W obszarach zadań typu untied punkt rozdziału zadań może wystąpić w dowolnym miejscu. W obszarach zadań typu tied punkt rozdziału zadań może wystąpić jedynie tam, gdzie pojawia się bariera (jawna lub wymuszona), oraz w konstrukcjach taskwait i task.

Wszystkie zadania związane z danym obszarem równoległym muszą być ukończone, nim główny wątek opuści dany obszar równoległy. W punkcie rozdziału zadań wątek rozocząć wykonywanie nowego zadania przypisanego do danego obszaru równoległego. Nowe zadanie może być zarówno typu tied, jak i untied. Wątek może też przejść do kontynuacji zawieszonego zadania typu untied lub przypisanego mu zadania tied.

Konstrukcja task definiuje nowe jawne zadanie. Składnia w Fortranie:!$omp task [klauzula[[,] klauzula]...] blok!$omp end task Składnia w C/C++: #pragma omp task [klauzula[[,] klauzula]...] nowa linia blok Dopuszczalne klauzule: if, untied, default, private, firstprivate, shared.

Klauzula if ma postać if(wyrażenie logiczne). Jeśli wyrażenie ma wartość.false. w Fortranie lub 0 w C/C++, wątek przystępuje do natychmiastowego wykonywania zadania. W przeciwnym wypadku zadanie może zostać odłożone na potem. Zadanie utworzone konstrukcją task jest typu tied, chyba, że pojawi się klauzula untied. Pozostałe klauzule dotyczą rodzaju zmiennych występujących w obszarze zadania. Punkty rozdziału zadań związane bezpośredni z dyrektywą task znajdują się przed pierwszą i za ostatnią instrujcą stowarzyszonego z dyrektywą obszaru zadania.

Konstrukcja taskwait wymusza zakończenie wszystkich zadań dzieci określonych od momentu rozpoczęcia aktywnego zadania. Składnia w Fortranie:!$omp taskwait Składnia w C/C++: #pragma omp taskwait nowa linia Z konstrukcją taskwait związany jest punkt rozdziału zadań.

Przykład: Uwaga na błędy w oryginalnej wersji zawartej w specyfikacji! Chcemy policzyć n-ty wyraz ciągu Fibonacciego zadany rekurencją F n = F n 1 + F n 2, F 0 = 0, F 1 = 1. Istnieją przyzwoite metody rozwiązania tego problemu, ale na potrzeby ilustracji spróbujmy zastosować definicję bezpośrednio.

program fibonacci implicit none interface recursive function fib(n) result(res) implicit none integer:: res, n end function end interface integer :: n, fn n = 40 fn = fib(n) write(*,*) Fibonacci series: write(*,*) n =, n, Fn =, fn end program fibonacci

recursive function fib(n) result(res) implicit none integer :: res, n integer :: i, j if (n.lt. 2) then res = n else i = fib(n-1) j = fib(n-2) res = i+j end if end function

program fibonacci implicit none interface recursive function fib(n) result(res) implicit none integer:: res, n end function end interface integer :: n, fn n = 40!$omp parallel shared(n,fn)!$omp single fn = fib(n)!$omp end single!$omp end parallel write(*,*) Fibonacci series: write(*,*) n =, n, Fn =, fn end program fibonacci

recursive function fib(n) result(res) implicit none integer :: res, n integer :: i, j if (n.lt. 2) then res = n else!$omp task shared(i) i = fib(n-1)!$omp end task!$omp task shared(j) j = fib(n-2)!$omp end task!$omp taskwait res = i+j end if end function

Powyższy przykład jest czysto akademicki. W zastosowaniu do ciągu Fibonacciego nie uzyskujemy przyspieszenia wykonywania zadania. Jest to jednak poprawny sposób zrównoleglenia mniej ziarnistych rekurencji. Kolejne przykłady pochodzą od Yuana Lina z Sun Microsystems.

Rozpoczynanie obszaru równoległego z jednym głównym zadaniem: #pragma omp parallel #pragma omp single nowait /* this is the initial root task */ #pragma omp task /* this is first child task */ #pragma omp task /* this is second child task */

Rozważmy: void foo () #pragma omp task A(); #pragma omp task B(); Zadanie generujące jest też zadaniem i może być wykonywane równocześnie: void foo () #pragma omp task A(); B();

Grupa zadań. Przypuśćmy, że chcemy policzyć następujące zadanie: /* Compute f2 (A, f1 (B, C)) */ int foo () int a, b, c, x, y; a = A(); b = B(); c = C(); x = f1(b, c); y = f2(a, x); return y;

Poszukujemy rozwiązania w poniższym stylu, ale konstrukcja _taskgroup_ nie istnieje. /* Compute f2 (A, f1 (B, C)) */ void foo () int a, b, c, x, y; #pragma omp task shared(a) a = A(); #pragma omp _taskgroup_ #pragma omp task shared(b) b = B(); #pragma omp task shared(c) c = C(); x = f1 (b, c); #pragma omp taskwait y = f2 (a, x);

Rozwiązanie: /* Compute f2 (A, f1 (B, C)) */ void foo () int a, b, c, x, y; #pragma omp task shared(a) a = A(); #pragma omp task if (0) shared (b, c, x) #pragma omp task shared(b) b = B(); #pragma omp task shared(c) c = C(); #pragma omp taskwait x = f1 (b, c); #pragma omp taskwait y = f2 (a, x);

Nie warto nadużywać konstrukcji task. Poniższe dwie pętle powinny dawać równoważne rezultaty, ale pierwsza jest szybsza. /* An OpenMP worksharing for loop */ #pragma omp for for (i=0; i<n; i++) foo(i); /* The above loop converted to use tasks */ #pragma omp single nowait for (i=0; i<n; i++) #pragma omp task firstprivate(i) foo(i);

Redukcja w połączonej liście. Przypomnienie: typedef struct item int data; struct item *next; item_t; Liczymy dobre elementy w liście: int count_good (item_t *item) int n = 0; while (item) if (is_good(item)) n ++; item = item->next; return n;

int count_good (item_t *item) int n = 0; #pragma omp parallel #pragma omp single nowait while (item) #pragma omp task firstprivate(item) if (is_good(item)) #pragma omp atomic n ++; item = item->next; return n;

Zamki (locks) w OpenMP z zadaniami związane są zamki, tj. specjalne zmienne oraz operujący na nich układ funkcji bibliotecznych. Zmienne te służą do synchronizacji zadań. Zmienna tworząca zamek może istnieć w 3 stanach: niezainicjalizowanym (uninitialized), zamkniętym (locked) oraz otwartym (unlocked). Zadanie może zmienić stan zamka z otwartego na zamknięty. Takie zadanie staje się właścicielem zamka. Właściciel zamka może, na powrót, zmienić jego stan z zamkniętego na otwarty. Pozostałym zadaniom nie wolno tego robić. OpenMP wprowadza 2 rodzaje zamków: proste (simple) oraz zagnieżdżalne (nestable). Zagnieżdżalny zamek może być zamykany wiele razy przez to samo zadanie można zamykać zamknięty zamek. Prosty zamek musi być otwarty, aby można było go zamknąć.

W Fortranie prosty zamek jest zmienną integer typu kind=omp_lock_kind, a zamek zagnieżdżalny typu kind=omp_nest_lock_kind. W C/C++ określony jest typ omp_lock_t dla zamka prostego oraz typ omp_nest_lock_t dla zamka zagnieżdżalnego. Wszystkie funkcje operujące na zamkach wymuszają operację flush pracujemy zawsze na aktualnych wartościach zamków; nie ma potrzeby ręcznego wymuszania operacji flush. Zajmiemy się teraz funkcjami pracującymi na zamkach prostych.

Inicjalizacja zamka: W Fortranie: subroutine omp_init_lock (zamek) integer (kind=omp_lock_kind) zamek W C/C++: void omp_init_lock(omp_lock_t *zamek);

Zapewnienie, że zamek będzie w stanie niezainicjalizownym: W Fortranie: subroutine omp_destroy_lock (zamek) integer (kind=omp_lock_kind) zamek W C/C++: void omp_destroy_lock(omp_lock_t *zamek);

Zamykanie zamka: W Fortranie: subroutine omp_set_lock (zamek) integer (kind=omp_lock_kind) zamek W C/C++: void omp_set_lock(omp_lock_t *zamek);

Otwieranie zamka: W Fortranie: subroutine omp_unset_lock (zamek integer (kind=omp_lock_kind) zamek W C/C++: void omp_unset_lock(omp_lock_t *zamek);

Sprawdzanie zamka: W Fortranie: logical function omp_test_lock (zamek) integer (kind=omp_lock_kind) zamek W C/C++: int omp_test_lock(omp_lock_t *zamek); Funkcja omp_test_lock próbuje zamknąć zamek. Jeśli zamek był w stanie otwartym, zamyka go i zwraca wartość odpowiadającą prawdzie. Jeśli zamka nie udało się zamknąć (zamek należy do innego zadania), funkcja zwraca wartość odpowiadającą fałszowi.

Funkcje odpowiadające zamkom zagnieżdżalnym zachowują się niemal tak samo. W nazwach występuje nest_lock zamiast lock. Ponadto, zarówno w Fortranie, jak i w C/C++ funkcja omp_test_nest_lock zwraca zaktualną wartość licznika mówiącego o stopniu zamknięcia zamka, lub zero w przypadku, gdy zamka nie udało się zamknąć. Funkcja omp_set_nest_lock zwiększa wartość licznika o 1, funkcja omp_unset_nest_lock zmniejsza wartość licznika o 1. Funkcje te operują na zmiennych właściwego typu, tj. integer (kind=omp_nest_lock_kind) w Fortranie i omp_nest_lock_t w C/C++.

program zamek use omp_lib integer(omp_lock_kind) :: lck integer :: id call omp_init_lock(lck)!$omp parallel shared(lck) private(id) id = omp_get_thread_num() do while (.not. omp_test_lock(lck))! nie mamy zamka i wykonujemy coś zastępczego call skip(id) end do! mamy zamek i wykonujemy pracę call work(id) call omp_unset_lock(lck)!$omp end parallel call omp_destroy_lock(lck) end program zamek

W OpenMP 2.5 zamki były przypisane do wątków. Wersja 3.0 przypisuje zamki do zadań. W wersji 3.0 poniższy program nie jest poprawny (przykład ze specyfikacji): program lock use omp_lib integer :: x integer(kind=omp_lock_kind) :: lck call omp_init_lock(lck) call omp_set_lock(lck) x = 0!$omp parallel shared(x)!$omp master x = x + 1 call omp_unset_lock(lck)!$omp end master! tutaj jakaś praca!$omp end parallel call omp_destroy_lock(lck) end