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

Podobne dokumenty
Wprowadzenie do OpenMP

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

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

Przetwarzanie Równoległe i Rozproszone

Wprowadzenie do zrównoleglania aplikacji z wykorzystaniem standardu OpenMP

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

Programowanie Rozproszone i Równoległe

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

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

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

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

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

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

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

1 Podstawy c++ w pigułce.

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

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

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Wstęp do programowania

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Struktura pliku projektu Console Application

Zajęcia nr 1 Podstawy programowania. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

KURS C/C++ WYKŁAD 2. char znak; znak = a ; Program 2 #include<stdio.h> void main() { char znak; while( (znak = getchar() )!= t ) putchar(znak); }

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

PROE wykład 4 pozostałe operatory, forward declaration, dziedziczenie. dr inż. Jacek Naruniec

Wstęp do programowania. Wykład 1

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

1 Podstawy c++ w pigułce.

Programowanie komputerowe. Zajęcia 1

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

ZASADY PROGRAMOWANIA KOMPUTERÓW

Programowanie komputerowe. Zajęcia 3

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

7. Pętle for. Przykłady

Podstawy Programowania C++

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

Tablice 1 C(3) D(1,-2)

tablica: dane_liczbowe

O superkomputerach. Marek Grabowski

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

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

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 25 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 38

Fortran 90/95 wykład 1

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Wstęp do programowania

3. Instrukcje warunkowe

Wyklad 11 Języki programowania równoległego

Programowanie w C++ Wykład 3. Katarzyna Grzelak. 12 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 35

Programowanie - wykład 4

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Elementy języka C. ACprogramislikeafastdanceonanewlywaxeddancefloorbypeople carrying razors.

Pytania sprawdzające wiedzę z programowania C++

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 5

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

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

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

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

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Podstawy Programowania. Wykład 1

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

ForPascal Interpreter języka Pascal

Programowanie I. O czym będziemy mówili. Plan wykładu nieco dokładniej. Plan wykładu z lotu ptaka. Podstawy programowania w językach. Uwaga!

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

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

Przekazywanie argumentów wskaźniki

Widoki zagnieżdżone, layout. 1. Wprowadzenie Repozytoria danych

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Wstęp do Programowania, laboratorium 02

Podstawy Programowania Podstawowa składnia języka C++

Wstęp do Programowania 2

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Wstęp do programowania

Języki C i C++ Wykład: 2. Wstęp Instrukcje sterujące. dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Technologie cyfrowe semestr letni 2018/2019

Podstawy Programowania

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

C++ wprowadzanie zmiennych

Podstawy Informatyki. Kompilacja. Historia. Metalurgia, I rok. Kompilatory C++ Pierwszy program. Dyrektywy preprocesora. Darmowe:

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Wstęp do informatyki- wykład 5 Instrukcja selekcji if-else Operatory arytmetyczne i logiczne

Pętla for. Wynik działania programu:

Podstawy Informatyki. Metalurgia, I rok. Wykład 6 Krótki kurs C++

Programowanie w języku C++

r. Tablice podstawowe operacje na tablicach

Programowanie obiektowe W3

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Programowanie Proceduralne

C-struktury wykład. Dorota Pylak

Paostwowa Wyższa Szkoła Zawodowa w Płocku Dariusz Wardowski

1 P roste e t ypy p d a d n a ych c - c ąg ą g d a d l a szy 2 T y T py p z ł z o ł żo ż ne e d a d n a ych c : T BLICE

Język C++ zajęcia nr 2

I - Microsoft Visual Studio C++

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Transkrypt:

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

OpenMP (Open Multi Processing) zbiór dyrektyw kompilatora, funkcji bibliotecznych, zmiennych środowiskowych pozwalających na zrównoleglenie programów wykonywanych na komputerach współdzielących pamięć. OpenMP standaryzuje lata doświadczeń w programowaniu z wykorzystaniem współdzielonej pamięci. Implementacje dla Fortranu oraz C/C++ dostarczane przez producentów kompilatorów. Strona internetowa projektu: http://openmp.org można pobrać najnowszą specyfikację.

Dyrektywy OpenMP mają formę odpowiednich komentarzy (Fortran) lub dyrektyw #pragma (C/C++). Kompilator wspierający OpenMP interpretuje je jako odpowiednie instrukcje. Kompilator bez wsparcia OpenMP lub z wyłączonym wsparciem może je łatwo zignorować. Wsparcie OpenMP wymaga zwykle zastosowania odpowiedniej flagi podczas kompilacji, np. ifort -openmp prog.f90 -o prog icc -openmp prog.c -o prog Dla kompilatorów z grupy gcc stosowna flaga ma postać -fopenmp.

Równoległość w OpenMP uzyskuje się w ramach modelu fork join.

Przykład na dobry początek: Podstawowa konstrukcja parallel rozpoczyna obszar równoległy. Do momentu jej napotkania program wykonywany jest seryjnie, po czym tworzony jest zespół wątków wykonujących dalsze zadania. Po wyjściu z obszaru równoległego program wykonywany jest przez jeden wątek. program hello1 write(*,*) 'Jestem w obszarze seryjnym.'!$omp parallel write(*,*) 'Jestem w obszarze rownoleglym.'!$omp end parallel write(*,*) 'Jestem w obszarze seryjnym.' end program hello1

Wersja C++ powyższego programu: #include <iostream> using namespace std; main(){ cout << "Jestem w obszarze seryjnym.\n"; #pragma omp parallel { cout << "Jestem w obszarze rownoleglym.\n"; } } cout << "Jestem w obszarze seryjnym.\n";

Dyrektywy w Fortranie: W formie fixed source wszystkie linijki dyrektyw muszą rozpoczynać się od!$omp, c$omp lub *$omp. Powyższe komentarze muszą rozpoczynać się w 1. kolumnie. W kolumnie 6. pierwszej dyrektywy musi znajdować się spacja lub zero. Kolumna 6. kontynuacji dyrektywy nie może zawierać zera ani spacji. Stosują się przy tym zwykłe zasady dotyczące długości linii, kontynuacji, pozycji w kolumnach itp. Przykład równoważnych dyrektyw: c23456789!$omp parallel do shared(a,b,c) c$omp parallel do c$omp+shared(a,b,c) c$omp paralleldoshared(a,b,c)

W formie free source dyrektywy rozpoczynają się od!$omp. Dyrektywa musi być poprzedzona białymi znakami. Stosują się zwykłe zasady dotyczące kontynuacji linii. Przykład:!23456789!$omp parallel do &!$omp shared(a,b,c)!$omp parallel &!$omp&do shared(a,b,c)

Kompilacja warunkowa chcemy, aby pewne fragmenty kodu były wykonywane jedynie gdy wspierany jest OpenMP. Fortran: Odpowiednie fragmenty kodu umieszczamy w linijkach rozpoczynających się znacznikiem typu komentarza. W notacji fixed source możliwe są znaczniki!$, *$ oraz c$. Znaczniki te wymieniane są na 2 spacje. Po takiej wymianie muszą być spełnione normalne reguły notacji. W notacji free source możliwy jest tylko jeden znacznik!$. C/C++: W implementacjach wspierających OpenMP i preprocesor, zdefiniowane jest makro _OPENMP. Wartość _OPENMP ustalona jest na yyyymm, gdzie yyyy oznacza rok, a mm miesiąc indentyfikujące wspieraną wersję OpenMP.

Przykład: program hello2!$ use omp_lib implicit none!$ integer :: num_threads write(*,*) 'Jestem w obszarze seryjnym'!$omp parallel write (*,*) 'Jestem w obszarze rownoleglym'!$omp single!$ num_threads = omp_get_num_threads()!$ write(*,*) 'liczba watkow: ', num_threads!$omp end single!$omp end parallel write (*,*) 'Jestem w obszarze seryjnym' end program hello2

Podstawowa kwestia do dobrego zrozumienia: model pamięci używany przez OpenMP. Każdy z wątków ma dostęp do wspólnej części pamięci. Każdy z wątków może używać tymaczasowego widoku (temporary view) pamięci pamięci pełniącej rolę typu cache odwoływanie się do zmiennych ze wspólnej pamięci nie musi faktycznie oznaczać zmianu stanu zmiennych wspólnej pamięci. Zmiana ta może odbyć się w ramach tymczasowego widoku. Każdy z wątków dysponuje obszarem pamięci zarezerwowanym dla zmiennych prywatnych dostępnych jedynie dla danego wątku.

Zmienne w ramach OpenMP mogą być deklarowane jako współdzielone (shared) bądź prywatne (private). Zmienne wspołdzielone przechowywane są we wspólnej części pamięci, a ich kopie mogą znajdować się również w tymczasowym widoku pamięci. Operacja synchronizująca tymczasowy widok pamięci danego wątku oraz wspólną pamięć to operacja flush. Operacja flush jest wywoływana automatycznie przez część konstrukcji OpenMP, ale może być też wymuszona dedykowaną dyrektywą flush, gdy zachodzi taka potrzeba.

W chwili, w której rozpoczyna się wykonywanie obszaru równoległego, w prywatnej pamięci każdego z wątków tworzona jest osobna kopia każdej zmiennej zadeklarowanej jako zmienna prywatna w danym obszarze równoległym. Zmiany takiej zmiennej dokonywane przez poszczególne wątki dotyczą jedynie pamięci prywatnej i nie wpływają na wartość danej zmiennej widzianej przez pozostałe wątki. Kopie zmiennych prywatnych mogą być inicjalizowane wartością z obszaru seryjnego, jeśli jest to wyraźnie zaznaczone (klauzula firstprivate).

Składnia konstrukcji parallel w Fortranie:!$omp parallel [klauzula[[,] klauzula]...] blok!$omp end parallel W C/C++: #pragma omp parallel [klauzula[[, ]klauzula]...] blok Dopuszczalne klauzule: if, num_threads, default, private, firstprivate, shared, copyin, reduction. Będzie o nich mowa w dalszej części wykładu.

Klauzula if ma postać if(wyrażenie warunkowe). Jeśli wyrażenie warunkowe ma wartość.false. (Fortran) lub 0 (C/C++), obszar określony strukturą parallel wykonywany jest przez jeden wątek (seryjnie). W przeciwnym wypadku liczba wątków może zostać określona kaluzulą num_threads(liczba watków). Domyślna liczba wątków przechowywana jest przez zmienną środowiskową OMP_NUM_THREADS. W obrębie struktury parallel liczba wątków zwracana jest przez funkcję biblioteczną omp_get_num_threads(). Każdy z wątków w obszarze równoległym (określonym poprzez konstrukcję parallel) numerowany jest począwszy od 0, do n 1, gdzie n jest liczbą wątków. Wątek może uzyskać swój numer wywołująć funkcję omp_get_thread_num(). Reguły określania liczby wątków stają się bardziej skomplikowne w przypadku zagnieżdżonych obszarów równoległych.

Zmienne wymienione w klauzuli shared(lista zmiennych rozdzielana przecinkami) są traktowane jako współdzielone w obszarze zadanym konstrukcją parallel. Domyślnie, większość zmiennych jest współdzielona. Wyjątek stanowią np. indeksy występujące w pętlach do (Fortran) oraz for (C/C++), z którymi związane są odpowiednie dyrektywy OpenMP. Indeksy te traktowane są jako zmienne prywatne. Podobnie prywatne są zmienne wymienione w klauzuli private(lista zmiennych rozdzielana przecinkami).

Przykład: obliczany liczbę π. Wiemy, że 1 dx π = 4 0 1 + x 2. spróbujmy obliczyć tę wartość metodą trapezów.

program pi_integral implicit none integer, parameter :: lp = selected_int_kind(8) integer, parameter :: dp = kind(1.0d0) real(dp) :: pi, x, dx integer(lp) :: num_points, i num_points = 1000 dx = 1.0_dp/real(num_points,dp) pi = 0.0_dp do i = 1, num_points x = (i - 0.5_dp)*dx pi = pi + 4.0_dp/(1.0_dp + x**2 ) end do pi = pi*dx write(*,*) 'wartosc pi: ', pi end program pi_integral

Poniższy kod przedstawia wersję programu pi_integral zrównolegloną wyłącznie przy użyciu konstrukcji parallel. program pi_integral!$ use omp_lib implicit none integer, parameter :: lp = selected_int_kind(8) integer, parameter :: dp = kind(1.0d0) real(dp) :: pi, x, dx integer(lp) :: num_points, i integer(lp) :: num_i, num_f!$ integer(lp) :: thread_num, num_threads, points_per_thread, reszta!$ real(dp), dimension(:), allocatable :: pi_parts num_points = 1000 num_i = 1 num_f = num_points dx = 1.0_dp/real(num_points,dp)

!$omp parallel!$omp single!$ num_threads = omp_get_num_threads()!$omp end single!$omp end parallel!$ allocate(pi_parts (0:num_threads - 1))!$ points_per_thread = num_points«um_threads!$ reszta = mod(num_points, num_threads)!$omp parallel private(thread_num, num_i, num_f, x, pi, i)!$ thread_num = omp_get_thread_num()!$ if (thread_num.lt. reszta) then!$ num_i = thread_num*(points_per_thread+1) + 1!$ num_f = num_i + points_per_thread!$ else!$ num_i = reszta + thread_num*points_per_thread + 1!$ num_f = num_i + points_per_thread - 1!$ endif

pi = 0.0_dp do i = num_i, num_f x = (i - 0.5_dp)*dx pi = pi + 4.0_dp/(1.0_dp + x**2 ) end do!$ pi_parts(thread_num) = pi!$omp end parallel!$ pi = 0.0_dp!$ do i = 0, num_threads-1!$ pi = pi + pi_parts(i)!$ end do!$ deallocate (pi_parts) pi = pi*dx write(*,*) 'wartosc pi: ', pi end program pi_integral

W powyższym przykładzie mamy do czynienia z 2 konstrukcjami, które stworzyliśmy ręcznie, a które pojawiają się często w zastosowaniach i którym dedykowane są odpowiednie dyrektywy OpenMP. Pierwsza konstrukcja polega na rozdzieleniu pracy wykonywanej w pętli do (Fortran) lub for (C/C++) na poszczególne wątki tak, aby każdy wątek wykonywał pracę odpowiadającą jedynie pewne u zakresowi indeksów pętli. Jest to przykład ogólniejszej kategorii konstrukcji dzielących pracę (work-sharing constructs). Po drugie, wprowadzamy mechanizm zbierania wyników pracy każdego z wątków (macierz pi_parts), a następnie sumujemy uzyskane wyniki, tak aby uzyskać pożądaną wartość całki. Jest to przykład tak zwanej redukcji. Redukcja implementowana jest w OpenMP jako klauzula dyrektywy parallel.