Programowanie Równoległe i Rozproszone



Podobne dokumenty
Programowanie w modelu przesyłania komunikatów specyfikacja MPI. Krzysztof Banaś Obliczenia równoległe 1

WWW

Operacje grupowego przesyłania komunikatów. Krzysztof Banaś Obliczenia równoległe 1

Programowanie Równoległe Wykład 5. MPI - Message Passing Interface. Maciej Matyka Instytut Fizyki Teoretycznej

Podstawy komunikacji między procesami PVM

Programowanie Równoległe Wykład 4. MPI - Message Passing Interface. Maciej Matyka Instytut Fizyki Teoretycznej

Operacje grupowego przesyłania komunikatów

Programowanie w modelu przesyłania komunikatów specyfikacja MPI, cd. Krzysztof Banaś Obliczenia równoległe 1

Modele programowania równoległego. Programowanie z przekazywaniem komunikatów Message-Passing Programming Rafał Walkowiak dla PR PP

Modele programowania równoległego. Programowanie z przekazywaniem komunikatów Message-Passing Programming Rafał Walkowiak

Programowanie współbieżne i rozproszone

Programowanie współbieżne... (4) Andrzej Baran 2010/11

Środowiska przetwarzania rozproszonego

Tryby komunikacji między procesami w standardzie Message Passing Interface. Piotr Stasiak Krzysztof Materla

Programowanie w modelu przesyłania komunikatów specyfikacja MPI, cd. Krzysztof Banaś Obliczenia równoległe 1

61 Topologie wirtualne

Zegary logiczne. Zakres ćwiczenia. Problem rozbieżności czasów. Koncepcja programu. Przygotowanie programu

Programowanie Współbieżne

Łamanie haseł. Zakres ćwiczenia. Przedstawienie problemu. Zadanie do samodzielnego wykonania

Rozszerzenia MPI-2 1

Message Passing Interface

Tworzenie programów równoległych cd. Krzysztof Banaś Obliczenia równoległe 1

Miary Wydajności. Efektywność programu równoległego (E) jest definiowana jako stosunek przyśpieszenia do liczby procesorów

Pierwsze kroki w środowisku PVM

Detekcja zakończenia i obraz stanu globalnego

Tworzenie programów równoległych. Krzysztof Banaś Obliczenia równoległe 1

Programowanie w standardzie MPI

Tworzenie programów równoległych. Krzysztof Banaś Obliczenia równoległe 1

Parallel Virtual Machine

Pobieranie argumentów wiersza polecenia

PVM Parallel Virtual Machine

Operacje kolektywne MPI

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Wywoływanie procedur zdalnych

Zaawansowane operacje grupowe

Moc płynąca z kart graficznych

Zdalne wywołanie procedur. Krzysztof Banaś Systemy rozproszone 1

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Zmienne, stałe i operatory

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

Wprowadzenie. System rozproszony jest kolekcją niezależnych, autonomicznych komputerów, które dla użytkownika prezentują się jak jeden komputer.

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Programowanie Równoległe Wykład 5. MPI - Message Passing Interface (część 3) Maciej Matyka Instytut Fizyki Teoretycznej

Wywoływanie procedur zdalnych

Wywoływanie procedur zdalnych

Sieciowa komunikacja procesów - XDR i RPC

Algorytmy i Struktury Danych


Zdalne wywoływanie procedur RPC. Dariusz Wawrzyniak 1

Tworzenie aplikacji rozproszonej w Sun RPC

Programowanie niskopoziomowe

Zdalne wywoływanie procedur RPC

Zdalne wywoływanie procedur RPC

Zdalne wywoływanie procedur RPC 27. października Dariusz Wawrzyniak (IIPP) 1

Programowanie współbieżne Wykład 12 MPI c.d. Rafał Skinderowicz

Zdalne wywoływanie procedur RPC 27. października 2010

Przykład MPI: zbiór Mandelbrota

Laboratorium Podstawy Przetwarzania Rozproszonego SPRAWOZDANIE z zadania SERWIS KOMPUTEROWY

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

Uzupełnienie dot. przekazywania argumentów

Aplikacja Sieciowa wątki po stronie klienta

5. Model komunikujących się procesów, komunikaty

Tworzenie programów równoległych. Krzysztof Banaś Obliczenia równoległe 1

Mechanizmy komunikacji grupowej w bibliotece PVM

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

1. Tworzenie nowego projektu.

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Obliczenia równoległe i rozproszone. Praca zbiorowa pod redakcją Andrzeja Karbowskiego i Ewy Niewiadomskiej-Szynkiewicz

Architektury systemów równoległych

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Dzisiejszy wykład. Programowanie w Perlu. Usuwanie elementów z początku tablicy. Dodawanie elementów do początku tablic

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Ćwiczenie nr: 9 Obliczenia rozproszone MPI

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Gniazda BSD. komunikacja bezpołączeniowa

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

1 Podstawy c++ w pigułce.

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Programowanie współbieżne... (12) Andrzej Baran 2010/11

r 2r Rysunek 1 Koło wpisane w kwadrat

Wprowadzenie do MPI. Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego Uniwersytet Warszawski

Programowanie obiektowe

Programowanie procesorów graficznych NVIDIA (rdzenie CUDA) Wykład nr 1

Struktury. Przykład W8_1

2018 Marcin Kukliński. Niesforne bity i bajty

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

76.Struktura oprogramowania rozproszonego.

IPC: Kolejki komunikatów

Łagodne wprowadzenie do Message Passing Interface (MPI)

Shared memory and messages. Functions. process 0. process 1. program 0. program 0. data 0. data 1. program 1. data 0. data 1.

Programowanie współbieżne... (2)

Wstęp do programowania

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Programowanie równoległe i rozproszone. Praca zbiorowa pod redakcją Andrzeja Karbowskiego i Ewy Niewiadomskiej-Szynkiewicz

ZASADY PROGRAMOWANIA KOMPUTERÓW

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.

Wstęp do Programowania, laboratorium 02

Programowanie Proceduralne

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

Transkrypt:

Programowanie Równoległe i Rozproszone Lucjan Stapp Wydział Matematyki i Nauk Informacyjnych Politechnika Warszawska (l.stapp@mini.pw.edu.pl) 1/54 PRiR - wstęp Parallel Virtual Machine() zestaw narzędzi do tworzenia oprogramowania dla sieci równolegle połączonych sekwencyjnych i/lub równoległych komputerów. Został zaprojektowany i stworzony by umożliwić łączenie komputerów o różnych konfiguracjach sprzętowych w jeden równolegle działający komputer. Stworzony w latach 90- tych; Do dziś jest to aktywny projekt: http://www.csm.ornl.gov/pvm/. Aktualna wersja to 3.4.6 z 2001 r. 2/54 PRiR Parallel Virtual Machine() nie jest wg. dzisiejszych definicji maszyna wirtualną. To zarządca zrównoleglonych procesów. 3/54 PRiR 1

umożliwia stworzenie" z pewnej ilości komputerów (mogą być sekwencyjne i/lub równoległe) jednego równoległego systemu. Podstawowe zasady: Użytkownik definiuje zbiór maszyn, na których wykonywany jest program. Zbiór ten jest dynamiczny (można dodawać i/lub usuwać węzły w trakcie działania); Przezroczystość sprzętowa; Przekazywanie danych w oparciu o model przekazywanie komunikatów (message passing); Heterogeniczność systemu; Wspomaganie wieloprocesowości. 4/54 PRiR Schemat działania 5/54 PRiR umożliwia stworzenie" z pewnej ilości komputerów (mogą być sekwencyjne i/lub równoległe) w jeden równoległy. Odbywa się to na zasadzie dołączania kolejnych węzłów (komputerów), na których został zainstalowany i odpowiednio skonfigurowany. Podłączanie węzła składa się z grubsza z 3 etapów: 1. połączenia przez remote shell rsh, 2. uruchomieniu demona pvmd3 (dalej oznaczanego jako pvmd) 3. dostarczenia demonowi informacji o parametrach istniejącej sieci. 6/54 PRiR 2

Schemat architektury 7/54 PRiR można używać pisząc programy w różnych językach, tu omówione zostanie ich zastosowanie w językach C i C++. Standardowo, mamy do dyspozycji zestaw funkcji z parametrami. Umożliwia to przekazywanie argumentów jako wartości zmiennych i/lub wskaźników oraz zwracanie przez funkcje odpowiednich wartości Dodatkowo, mamy do dyspozycji zestaw makr i stałych systemowych (np. errno i pvm_errno do obsługi błędów) ułatwia to rozróżnianie różnych wyjść. 8/54 PRiR Każdemu procesowi (zwanemu zadaniem task) w momencie rejestracji nadawany jest jego unikalny numer typu integer (task identifier - TID). Ten identyfikator jest niezależny zarówno od sprzętu, na którym pracuje proces jak i od architektury systemu. Identyfikator jest unikalny i może być uważany za adres procesu. Identyfikator można wykorzystywać przy różnych procedurach - można przesłać informacje pod dany adres, można zdalnie "zabić" proces o danym identyfikatorze itp. 9/54 PRiR 3

Czasami pracujemy w grupach zadań. Każdej takiej grupie można nadać nazwę (numer). Zadanie otrzymuje też swój unikalny identyfikator w grupie. Identyfikatory w grupie zawsze zaczynają się od zera i stopniowo rosną. Mamy wydzielony zestaw procedur odnoszący się do grup. Nie zostaną one omówione w ramach tego wykładu. 10/54 PRiR startowy program #include "pvm3.h main() int cc, tid, msgtag; char buf[100]; printf( to ja t%x\n", pvm_mytid()); /* pobranie identyfikatora funkcją pvm_mytid */ cc = pvm_spawn( Czesc wszystkim", (char**)0, 0, "", 1,&tid); /*rozesłanie info funkcją pvm_spawn */ if (cc == 1) /*jeżeli spawn się udał */ msgtag = 1; pvm_recv(tid, msgtag); /*odebranie od innych */ pvm_upkstr(buf); printf( od t%x: %s\n", tid, buf); else printf( nie można wykonac czesc wszystkim \n"); pvm_exit(); /*wyjście z pvm*/ 11/54 PRiR #include "pvm3.h main() int ptid, msgtag; char buf[100]; ptid = pvm_parent(); /* pobranie adresu rodzica */ strcpy(buf, czesc wszytkim odebrane od"); gethostname(buf + strlen(buf), 64); msgtag = 1; pvm_initsend(pvmdatadefault); pvm_pkstr(buf); pvm_send(ptid, msgtag); /* te 3 instrukcje to przesłanie odpowiedzi: inicjalizacja bufora do przesłania umieszczenie danych wysłanie */ pvm_exit(); /*wyjście z pvm*/ odbiorca 12/54 PRiR 4

W rozróżniamy trzy możliwe organizacje zadań, co umożliwia nam różne strategie wykonywania obliczeń: Najbardziej popularny model to crowd computing : wiele procesów, na ogół wykonujących ten sam kod, z wymianą informacji poprzez przesyłanie pomiędzy procesami odpowiednich wiadomości Model master slave ; Model jeden nadzorca jedno ręcznie wystartowane zadanie odpowiada za podział zadań, reszta liczy; tree computation najczęściej stosowany dla algorytmów typu divide-and-conquer ; model hybrydowy ; 13/54 PRiR Schemat architektury Master slave nie ma komunikacji między niewolnikami 14/54 PRiR schemat mastera /*rozmieszczenie początkowe */ for (i=0; i < NumWorkers; i++ ) pvm_spawn(<worker name>); // Uruchomienie niewolnika i pvm_send(<worker tid i>,999); /* przesłanie zadania do niewolnika */ /* Odbieranie - przesyłanie */ while (WorkToDo) pvm_recv(888) // Odbieranie wyników pvm_send(<available worker tid>,999) /* przesłanie kolejnego zadania do available worker /* zebranie wyników */ for (i=0; i < NumWorkers; i++ ) pvm_recv(888) // Odebranie wynikow pvm_kill(<worker tid i>)//zakończenie pracy niewolnika i 15/54 PRiR 5

schemat niewolnika while (1) pvm_recv(999); //pobranie zadania result = Calculations(task;)//obliczenia pvm_send(<master tid>,888); // Przeslanie wyników do mastera Uwaga: W podanym schemacie nie ma komunikacji między niewolnikami. 16/54 PRiR schemat drzewa W tym podejściu zadania (procesy) są tworzone dynamicznie w czasie wraz z postępem obliczeń. Równocześnie tworzona jest relacja ojciec dziecko (jak w drzewie). Podejście to różni się od poprzedniego właśnie tą budową relacji (w master slave jest to raczej gwiazda). Jest głównie stosowane, gdy nie znamy z góry liczby potrzebnych procesów (np. WBS, devide and conquer). 17/54 PRiR int tid = pvm_mytid( void ) sterowanie Procedura pvm_mytid() zwraca identyfikator TID. Może być wywoływana wielokrotnie. Przyjęło się ją wywoływać jako pierwszą, by równocześnie zapewnić wpisanie tego procesu do. int info = pvm_exit( void ) Procedura pvm_exit() informuje lokalnego demona że proces opuszcza. Nie zabija procesu. Na ogół używana przed zakończeniem programu. 18/54 PRiR 6

sterowanie int numt = pvm_spawn(char *task, char **argv, int flag, char *where, int ntask, int *tids ) Procedura pvm_spawn() uruchamia ntask kopii pliku wykonalnego na maszynie wirtualnej. Jej podstawowe parametry to: argv wskaźnik do tablicy z parametrami (może być NULL), flag specyfikuje opcje. pvm_spawn zwraca, ile kopii udało się uruchomić. int info = pvm_kill( int tid ) Zabija proces on identyfikatorze tid. int info = pvm_catchout( FILE *ff ) Zbiera i wysyła na wyjście wyniki od poprzednio uruchomionych dzieci procesu. 19/54 PRiR informacje int tid = pvm_parent( void ) Zwraca tid rodzica. int info = pvm_config( int *nhost, int *narch, struct pvmhostinfo **hostp Zwraca informacje o maszynie wirtualnej, takie jak ilość węzłów nhost, hostp jest wskaźnikiem do utworzonej przez użytkownika tablicy pvmhostinfo o zadanej strukturze, która musi być wielkości >= nhost. Otrzymujemy w niej m.in. informacje o demonach, nazwach węzłów, a także o relatywnej prędkości CPU maszyny, na której uruchamiana jest ta instrukcja. 20/54 PRiR operacje dodawania i usuwania int info = pvm_addhosts( char **hosts, int nhost, int *infos) int info = pvm_delhosts( char **hosts, int nhost, int *infos) Dodanie i usunięcie węzła. 21/54 PRiR 7

przekazywanie danych int bufid = pvm_initsend( int encoding ) Wywoływana przed przesłaniem informacji. Czyści bufor (lub tworzy nowy) do przesłania informacji. Zwraca identyfikator bufora. Dopuszczalne wartości encoding to: PvmDataDefault - kodowanie XDR (external Data Representation) http://www.cisco.com/en/us/docs/ios/sw_upgrades /interlink/r2_0/rpc_pr/rpxdesc.html; PvmDataRaw brak kodowania; PvmDataInPlace w buforze są tylko informacje o wielkości danych i wskaźnik na miejsce, gdzie te dane są umieszczone. Przy przesyłaniu (pvm_send()) następuje kopiowanie bezpośrednio do pamięci odbiorcy. 22/54 PRiR pakowanie danych int info = pvm_pkbyte( char *cp, int nitem, int stride ) int info = pvm_pkcplx( float *xp, int nitem, int stride ) int info = pvm_pkdcplx( double *zp, int nitem, int stride ) int info = pvm_pkdouble( double *dp, int nitem, int stride ) int info = pvm_pkfloat( float *fp, int nitem, int stride ) int info = pvm_pkint( int *np, int nitem, int stride ) int info = pvm_pklong( long *np, int nitem, int stride ) int info = pvm_pkshort( short *np, int nitem, int stride ) int info = pvm_pkstr( char *cp ) Powyższe procedury pakują macierz danych danego typu do aktywnego bufora. Można włożyć wiele różnych typów danych, wywołując te procedury wielokrotnie. Dane są wyjmowane po przesłaniu w tej samej kolejności co zostały włożone; nitem oznacza ilość danych. 23/54 PRiR przekazywanie danych int info = pvm_send( int tid, int msgtag ) Natychmiastowe przesłanie danych do procesu TID int info = pvm_mcast( int *tids, int ntask, int msgtag ) Rozesłanie informacji metoda broadcastdo wszystkich procesów o TID w tablicy ntasks. 24/54 PRiR 8

przekazywanie danych int bufid = pvm_recv( int tid, int msgtag ) Blokowany odbiór; odbiorca czeka, aż coś będzie od nadawcy tid. int bufid = pvm_nrecv( int tid, int msgtag ) Nieblokowany odbiór; jeżeli nie ma co odebrać, zwraca 0. int bufid = pvm_probe( int tid, int msgtag ) Warto używać przy nieblokowanym odbiorze; sprawdza zawartość bufora. int info = pvm_bufinfo( int bufid, int *bytes, int *msgtag, int *tid ) Sprawdzenie, co jest w buforze bufid. 25/54 PRiR /* Fork Join Example Demonstrates how to spawn processes and exchange messages */ /* defines and prototypes for the library */ #include <pvm3.h> /* Maximum number of children this program will spawn */ #define MAXNCHILD 20 /* Tag to use for the joing message */ #define JOINTAG 11 int main(int argc, char* argv[]) /* number of tasks to spawn, use 3 as the default */ int ntask = 3; /* return code from pvm calls */ int info; /* my task id */ int mytid; /* my parents task id */ int myparent; /* children task id array */ int child[maxnchild]; int i, mydata, buf, len, tag, tid; /* find out my task id number */ mytid = pvm_mytid(); /* check for error */ if (mytid < 0) /* print out the error */ pvm_perror(argv[0]); /* exit the program */ return -1; przykład 26/54 PRiR przykład /* find my parent's task id number */ myparent = pvm_parent(); /* exit if there is some error other than PvmNoParent */ if ((myparent < 0) && (myparent!= PvmNoParent)) pvm_perror(argv[0]); pvm_exit(); return -1; /* if I don't have a parent then I am the parent */ if (myparent == PvmNoParent) /* find out how many tasks to spawn */ if (argc == 2) ntask = atoi(argv[1]); /* make sure ntask is legal */ if ((ntask < 1) (ntask > MAXNCHILD)) pvm_exit(); return 0; /* spawn the child tasks */ info = pvm_spawn(argv[0], (char**)0, PvmTaskDefault, (char*)0, ntask, child); 27/54 PRiR 9

/* print out the task ids */ for (i = 0; i < ntask; i++) if (child[i] < 0) /* print the error code in decimal*/ printf(" %d", child[i]); else /* print the task id in hex */ printf("t%x\t", child[i]); putchar('\n'); /* make sure spawn succeeded */ if (info == 0) pvm_exit(); return -1; /* only expect responses from those spawned correctly */ ntask = info; for (i = 0; i < ntask; i++) /* recv a message from any child process */ buf = pvm_recv(-1, JOINTAG); if (buf < 0) pvm_perror("calling recv"); info = pvm_bufinfo(buf, &len, &tag, &tid); if (info < 0) pvm_perror("calling pvm_bufinfo"); info = pvm_upkint(&mydata, 1, 1); if (info < 0) pvm_perror("calling pvm_upkint"); if (mydata!= tid) printf("this should not happen!\n"); printf("length %d, Tag %d, Tid t%x\n", len, tag, tid); przykład 28/54 PRiR przykład pvm_exit(); return 0; /* i'm a child */ info = pvm_initsend(pvmdatadefault); if (info < 0) pvm_perror("calling pvm_initsend"); pvm_exit(); return -1; info = pvm_pkint(&mytid, 1, 1); if (info < 0) pvm_perror("calling pvm_pkint"); pvm_exit(); return -1; info = pvm_send(myparent, JOINTAG); if (info < 0) pvm_perror("calling pvm_send"); pvm_exit(); return -1; pvm_exit(); return 0; 29/54 PRiR Więcej przykładów: przykłady http://www.netlib.org/pvm3/book/node55.html 30/54 PRiR 10

MPI - wstęp Message PassingInterface (MPI) protokół komunikacyjny będący standardemprzesyłania komunikatów pomiędzy procesami programów równoległych działających na jednym lub więcej komputerach. Interfejs ten wraz z protokołem oraz semantyką specyfikuje, jak jego elementy winny się zachowywać w dowolnej implementacji. Celami MPI są wysoka jakość, skalowalnośćoraz przenośność. MPI jest dominującym modelem wykorzystywanym obecnie w klastrach komputerów oraz superkomputerach. http://pl.wikipedia.org/wiki/message_passing_interface 31/54 PRiR MPI - wstęp Obecnie występują 2 najpopularniejsze wersje: wersja 1.2 (tj. MPI-1, gotowy w maju 1994), która kładzie nacisk na przekazywanie wiadomości oraz jest zaopatrzona w statyczne środowisko uruchomieniowe oraz MPI-2.1 (MPI-2, ukończona w 1998), która zawiera kilka dodatków jak równoległe I/O, dynamiczne zarządzanie procesami oraz zarządzanie operacjami pamięci. Specyfikacja MPI-2 zawiera ponad 500 funkcji dla ANSI C, ANSI Fortran (Fortran90) oraz ANSI C++. Warto zauważyć, iż MPI-2 jest głównie nadzbiorem MPI-1, mimo iż część funkcji została wymieniona. Programy napisane w standardzie 1.2 są kompatybilne z MPI-2. http://pl.wikipedia.org/wiki/message_passing_interface 32/54 PRiR MPI - wstęp Po wprowadzeniu, nowszy standard nie cieszył się dużą popularnością, ponieważ rok wcześniej opracowano MPICH, w którym zaimplementowano część poprawek wprowadzanych w MPI-2. MPICH to najczęściej stosowana implementacja MPI. MPICH to ogólnodostępna, darmowa i przenośna implementacja standardu MPI. Pozwala na przekazywanie komunikatów pomiędzy aplikacjami działającymi równolegle. Nadaje się do stosowania na małych klastrach. http://pl.wikipedia.org/wiki/message_passing_interface 33/54 PRiR 11

/* "Hello World" MPI Test Program */ #include <mpi.h> #include <stdio.h> #include <string.h> #define BUFSIZE 128 #define TAG 0 int main(int argc, char *argv[]) char idstr[32]; char buff[bufsize]; int numprocs; int myid; int i; MPI_Status stat; /* MPI programs start with MPI_Init; all 'N' processes exist thereafter */ MPI_Init(&argc,&argv); /* find out how big the MPI world is */ MPI_Comm_size(MPI_COMM_WORLD,&numprocs); /* and this processes' rank is */ MPI_Comm_rank(MPI_COMM_WORLD,&myid); MPI przykład 34/54 PRiR MPI przykład /* At this point, all programs are running equivalently, the rank distinguishes the roles of the programs in the model, with rank 0 often used specially... */ if(myid == 0) printf("%d: We have %d processors\n", myid, numprocs); for(i=1;i<numprocs;i++) printf(buff, "Hello %d! ", i); MPI_Send(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD); for(i=1;i<numprocs;i++) MPI_Recv(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD, &stat); printf("%d: %s\n", myid, buff); else /* receive from rank 0: */ MPI_Recv(buff, BUFSIZE, MPI_CHAR, 0, TAG, MPI_COMM_WORLD, &stat); printf(idstr, "Processor %d ", myid); strncat(buff, idstr, BUFSIZE-1); strncat(buff, "reporting for duty\n", BUFSIZE-1); /* send to rank 0: */ MPI_Send(buff, BUFSIZE, MPI_CHAR, 0, TAG, MPI_COMM_WORLD); /* MPI programs end with MPI Finalize; this is a weak synchronization point */ MPI_Finalize(); return 0; 35/54 PRiR MPI - wstęp MPI jest z wyglądu bardzo podobna do. Podstawowa różnica tkwi w modelu obliczeń. W większości implementacji MPI, stały zbiór procesów jest tworzony na początku obliczeń, przy czym obowiązuje zasada; jeden proces jeden procesor. MPI jest raczej podejściem typu MIMD, jakkolwiek można go też używać zlecając wszystkim elementom wykonywanie tego samego oprogramowania, uzależnionego od parametrów symetria kodu. Główny nacisk w MPI jest położony na mechanizmy komunikacyjne pomiędzy procesami. Dopuszczamy dwa rodzaje komunikacji: point-to-point pomiędzy dwoma konkretnymi procesami; komunikacja zbiorowa (collective) np. broadcast. 36/54 PRiR 12

MPI - wstęp MPI umożliwia sprawdzanie wiadomości ułatwia to komunikacje asynchroniczną. W MPI mamy możliwość wykorzystywania komunikacji modularnej przy pomocy mechanizmu zwanego komunikatorem (communicator). Mechanizm ten umożliwia programistom tworzenie modułów, które zawierają wewnętrzne struktury komunikacyjne. 37/54 PRiR MPI - wstęp W MPI łatwo oprogramowywuje się algorytmy, w których wyraźne jest powiązanie pomiędzy procesem a procesorem. Można tu wykorzystać komunikację typu point-to-point (lub komunikację zbiorową), by zapewnić odpowiednie przesyłanie komunikatów. Algorytmy, które tworzą zadania dynamicznie (lub wymuszają kilka procesów na procesorze) powinny być odpowiednio modyfikowane (poprawiane??), by można je było uruchomić używając MPI. Jeżeli jest to trudne (lub nie potrafimy tego zrobić), MPI nie jest dobrym narzędziem. 38/54 PRiR MPI - wstęp Na starcie wszystkie uruchomione procesy są elementami standardowego komunikatora globalnego MPI_COMM_WORLD. 39/54 PRiR 13

MPI - jądro Podstawą MPI jest 6 funkcji: MPI_INIT: Rozpoczyna obliczenia w MPI. MPI_FINALIZE: Kończy obliczenia. MPI_COMM_SIZE: Określa liczbę procesów. MPI_COMM_RANK: Zwraca identyfikator my_process (globalny lub lokalny) MPI_SEND: Nadanie wiadomości. MPI_RECV: Odebranie wiadomości. Przy pomocy tych 6 funkcji można napisać większość programów wykorzystujących MPI. 40/54 PRiR Podstawą MPI jest 6 funkcji: MPI - przykład void main() MPI_INIT(); // Rozpoczęcie obliczeń MPI_COMM_SIZE(MPI_COMM_WORLD, count); // ile jest procesów MPI_COMM_RANK(MPI_COMM_WORLD, myid) // określenie mego ID print("i am", myid, "of", count) MPI_FINALIZE() //Koniec Typowy start. 41/54 PRiR Podstawą MPI jest 6 funkcji: void main() MPI przykład 2 MPI_INIT(); // Rozpoczęcie obliczeń MPI_COMM_SIZE(MPI_COMM_WORLD, count) // ile jest procesów if (count!=2) return (-1); // muszą być dwa procesy MPI_COMM_RANK(MPI_COMM_WORLD, myid); // określenie mego ID if (myid=0) my_send(100); else my_receive(100); MPI_FINALIZE(); //Koniec void my_send( int ile) for(int i=0, i<ile, i++) MPI_SEND (i,1,mpi_int,1,0,mpi_comm_world); /*przesłanie ile razy po jednym int do procesu o id=0 w MPI_COMM_WORLD*/ i= - 1; MPI_SEND (i,1,mpi_int,1,0,mpi_comm_world); /*koniec danych */ 42/54 PRiR 14

Podstawą MPI jest 6 funkcji: MPI przykład 2 void my_receive( int ile) MPI_RECEIVE (msg,1,mpi_int,0,0,mpi_comm_world, status); while (msg!=-1) zrob_cos(msg) MPI_RECEIVE (msg,1,mpi_int,0,0,mpi_comm_world, status); /*koniec danych */ Dwuprocesorowe przekazanie wiadomości. 43/54 PRiR MPI operacje globalne Operacje globalne: Barrier: Synchronizacja wszystkich procesów Broadcast: Wysłanie danych z jednego procesu do wszystkich pozostałych. Gather: Pobranie danych z wszystkich procesów do jednego. Scatter: Rozpraszanie danych z jednego procesu do pozostałych. Reduction operations: Suma, mnożenie itp. rozproszonych danych. Ułatwiają tworzenie bardziej skomplikowanych algorytmów. 44/54 PRiR MPI operacje globalne MPI_BCAST MPI_GATHER MPI_SCATTER 45/54 PRiR 15

MPI operacje redukcji Dane początkowe MPI_REDUCE; operator MPI_MIN; root= 0 MPI_ALLREDUCE; operator MPI_MIN MPI_REDUCE; operator MPI_SUM; root= 1 46/54 PRiR MPI operacje redukcji Operatory dopuszczalne w operacjach redukcji: Maksimum i minimum MPI_MAX, MPI_MIN Suma i iloczyn MPI_SUM, MPI_PROD Logiczne and, or, xor MPI_LAND, MPI_LOR, MPI_LXOR Bitowe and, or, xor MPI_BAND, MPI_BOR,MPI_BXOR 47/54 PRiR MPI komunikatory Globalny komunikator: MPI_COMM_WORLD Tworzenie i obsługę nowego komunikatora umożliwiają 4 funkcje: MPI_COMM_DUP duplikacja (tworzenie kopii) istniejącego komunikatora MPI_COMM_SPLIT tworzenie nowego komunikatora, procesy wchodzące w skład komunikatora mogą się komunikować między sobą bez interferencji z procesami spoza komunikatora MPI_INTERCOMM_CREATE tworzenie interkomunikatora (intercommunicator) przez podział komunikatora na dwie grupy MPI_COMM_FREE- zwolnienie (zamkniecie) komunikatora 48/54 PRiR 16

MPI komunikatory Największe zastosowanie ma MPI_COMM_SPLIT: MPI_COMM_SPLIT(comm, color, key, newcomm) comm stary komunikator; poprzez jego podział stworzymy nowy color nazwa (kolor) nowego komunikatora key id procesu newcomm nowy komunikator Uwaga: jeżeli newcomm o odpowiednim kolorze nie istnieje, komunikator jest tworzony i proces jest dodawany; jeżeli istnieje, tylko dodajemy proces 49/54 PRiR MPI komunikatory MPI_Comm comm, newcomm; int myid, color; MPI_Comm_rank(comm, &myid); color = myid%3; MPI_Comm_split(comm, color, myid, &newcomm); Stworzenie 3 nowych komunikatorów jak na rysunku 50/54 PRiR MPI komunikatory Komunikacja między komunikatorami. Komunikator stworzony przez MPI_COMM_SPLIT (także MPI_COMM_WORLD) może być używany do wymiany danych pomiędzy stworzona grupą jest to parametr w operacjach przesyłania danych. Można też tworzyć interkomunikatory pomiędzy grupami i wtedy można przekazywać dane pomiędzy wszystkimi elementami pierwszej i drugiej grupy. MPI_INTERCOMM_CREATE(comm, local_leader, peercomm, remote_leader, tag, intercomm) 51/54 PRiR 17

MPI komunikatory Przykład: Podzielimy 8 procesów na dwie grupy (parzyste, nieparzyste), następnie stworzymy lokalny interkomunikatori przy jego pomocy przekażemy dane. 52/54 PRiR MPI komunikatory Przykład (cd): int comm, intercomm, myid, newid; MPI_COMM_SIZE (MPI_COMM_WORLD,&count); /* zakładamy parzysta ilosc procesow i BRAK bledow komunikacyjnych*/ MPI_COMM_RANK (MPI_COMM_WORLD, &myid); MPI_COMM_SPLIT (MPI_COMM_WORLD, myid%2,myid,&comm); MPI_COMM_RANK (comm, %newid); if(newid%2==0) // nadawca MPI_INTERCOMM_CREATE (comm, 0,MPI_COMM_WORLD, 1,99, &intercom); /* stworzenie nowego interkomunikatora */ MPI_SEND(msg,1,type,newid,0,99, intercom;) /* wysylamy 1 informacje z bufora msg typu type do odbiorcy w nowym interkomunikatorze */ Else //odbiorca MPI_INTERCOMM_CREATE (comm, 0,MPI_COMM_WORLD, 1,99, &intercom); MPI_RECEIVE(msg,1,type,newid,0,99, intercom); MPI_COMM_FREE(intercom) MPI_COMM_FREE(com) 53/54 PRiR MPI + CUDA CUDA (NVIDIA scomputeunifieddevice Architecture) umożliwia wykorzystanie procesorów graficznych do obliczeń równoległych większość dzisiejszych superkomputerów wykorzystuje procesory graficzne. MPI jest wygodnym narzędziem do budowy grup procesorów i wymiany danych pomiędzy nimi także w tym zakresie. Więcej np. w pracy: An MPI-CUDA Implementation for Massively Parallel Incompressible Flow Computations on Multi-GPU Clusters Dana A. Jacobsen, Julien C. Thibault, and Inanc Senocaky 54/54 PRiR 18