wersja do druku - Instytut Informatyki Teoretycznej i Stosowanej
Transkrypt
wersja do druku - Instytut Informatyki Teoretycznej i Stosowanej
Plan wykładu Koncepcja standardu MPI, jego zalety i wady Programowanie aplikacji równoległych i rozproszonych Komunikacja typu punkt-punkt Komunikacja grupowa Wstep ˛ do standardu MPI-2 Mechanizm komunikacji jednostronnej i jego cechy charakterystyczne Wykład 8 Sposoby dynamicznego zarzadzania ˛ procesami wprowadzone w standardzie MPI-2 Dr inż. Tomasz Olas [email protected] Równoległe operacje wejścia/wyjścia MPI-IO i ich cechy Pozostałe rozszerzenia i modyfikacje wprowadzone w standardzie MPI-2 Instytut Informatyki Teoretycznej i Stosowanej Politechnika Cz˛estochowska Wykład 8 – p. 1/?? Koncepcja standardu MPI Wykład 8 – p. 2/?? Komunikacja typu punkt-punkt Standard MPI (Message Passing Interface) definije bibliotek˛e dla jezyków ˛ C/C++ i Fortran do tworzenia programów równoległych dla modelu z wymiana˛ komunikatów. Program składa sie˛ z procesów (zazwyczaj działajacych ˛ na różnych jednostkach obliczeniowych - procesorach lub rdzeniach), które komunikuja˛ sie˛ przy pomocy komunikatów. Standard MPI został stworzony dla komputerów masywnie równoległych, jednakże w chwili obecnej pozwala na efektywna˛ realizacje˛ przetwarzania równoległego na klastrach, a nawet architekturach z pamieci ˛ a˛ współdzielona. ˛ Podstawowym mechanizmem wymiany danych pomiedzy ˛ procesami jest komunikacja typu punkt-punkt: nadawca wysyła komunikat do odbiorcy przy pomocy funkcji MPI_Send, odbiorca odbiera komunikat od nadawcy, wykorzystujac ˛ do tego celu funkcje˛ MPI_Recv Funkcje MPI_Send/MPI_Recv sa˛ blokujace ˛ - procesy czekaja˛ na wykonanie komunikacji. W standardzie MPI udostepniono ˛ również komunikacje˛ nieblokujac ˛ a: ˛ MPI_Irecv(...); ... MPI_Wait(...); ... Zaleta˛ standardu MPI jest wysoka wydajność oraz możliwość efektywnej obługi dużej liczby procesów. // // // // inicjalizacja nieblokujacego ˛ odebrania komunikatau wykonanie pracy niezależnej od odbieranych danych czekanie na zakończenie komunikacji wykonanie pracy, która jest zależna od odebranych danych Wada˛ jest stosunkowo złożony sposób tworzenia programów równoległych - należy rozdzielić zadania na poszczególne procesy oraz w jawny sposób zadać komunikacje˛ pomiedzy ˛ nimi. Wykład 8 – p. 3/?? Wykład 8 – p. 4/?? MPI-2 - nowe elementy Komunikacja grupowa Komunikacja grupowa to taka, w której wystepuje grupa procesów. W standardzie MPI-2 wprowadzono trzy główne modyfikacje: Każdy proces z grupy wywołuje taka˛ sama˛ funkcje. ˛ równoległe wejście/wyjście, W standardzie MPI zdefiniowano nastepuj ˛ ace ˛ funkcje do komunikacji grupowej: komunikacja jednostronna, MPI_Barrier - synchronizacja procesów w postaci bramki, MPI_Bcast - rozgłaszanie jeden do wszystkich, MPI_Gather - zbieranie wszyscy do jednego, MPI_Allgather - zbieranie wszyscy do wszystkich, MPI_Scatter - rozpraszanie jeden do wszystkich, MPI_Reduce - redukcja wszyscy do jednego, MPI_Alltoall - rozpraszanie wszyscy do wszystkich, MPI_Allreduce - redukcja połaczona ˛ z rozgłaszaniem. dynamiczne zarzadzanie ˛ procesami. Ponadto w porównaniu do standardu MPI 1.1 uścislono standard MPI, uwzgledniono ˛ przetwarzanie wielowatkowe, ˛ umożliwiono łaczenie ˛ modułów w napisanych w różnych jezykach, ˛ dodano rozszerzone operacje komunikacji zbiorowej. Wykład 8 – p. 6/?? Wykład 8 – p. 5/?? Dynamiczne zarzadzanie ˛ procesami Sprawdzenie wersji MPI Poczawszy ˛ od wersji 1.2 standardu MPI można przeprowadzić kontrole˛ wersji używnej biblioteki MPI. W standardzie MPI-1 liczba procesorów była statyczna - ustalana w momencie uruchomienia programu i nie mogła zostać zmieniona. Podczas kompilacji można skorzystać z dyrektyw MPI_VERSION i MPI_SUBVERSION, które przechowuja˛ odpowienio liczbe˛ całkowita˛ określajac ˛ a˛ numer wersji i podwersji biblioteki MPI: W standardzie MPI-2 wspiera dynamiczne zarzadzanie ˛ procesami: możliwość tworzenia nowych procesów w trakcie działania programu, jak również ich usuwania, udostepnia ˛ mechanizm umożliwiajacy ˛ nawiazanie ˛ komunikacji pomiedzy ˛ nowo utworzonymi procesami, a istniejac ˛ a˛ aplikacja˛ MPI, #define MPI_VERSION 2 #define MPI_SUBVERSION 0 Podczas wykonania programu MPI można skorzystać z funkcji MPI_Get_version: możliwość przesyłania zmiennych typu MPI_Info pomiedzy ˛ procesami. int MPI_Get_version( int *version, int *subversion ) udostepnia ˛ również mechanizm umożliwiajacy ˛ nawiazanie ˛ komunikacji pomiedzy ˛ dwoma zupełnie odrebnymi ˛ aplikacjami MPI (nawet jeżeli jedna nie uruchomiła drugiej). gdzie: version - przez ten argument zostaje zwrócony numer wersji, subversion - pozwala na pobranie numeru podwersji. Wykład 8 – p. 7/?? Wykład 8 – p. 8/?? Funkcja MPI_Comm_spawn Uruchamianie procesów Aplikacja MPI może utworzyć nowy proces przy wykorzystaniu funkcji MPI_Comm_spawn i MPI_Comm_spawn_multiple bed ˛ acych ˛ interfejsem do zewnetrznego ˛ zarzadcy ˛ procesów. Funkcja MPI_Comm_spawn umożliwia utworzenie nowych procesów i nawiazanie ˛ z nim komunikacji przy pomocy wspólnego komunikatora rodzica i potomka (intercommunicator ). Funkcja MPI_Comm_spawn_multiple umożliwia utworzenie procesów wykorzystujacych ˛ różne pliki wykonywalne z takimi samymi, lub różnymi argumentami wywołania. Funkcja MPI_Comm_spawn: int MPI_Comm_spawn(char *command, char *argv[], int maxprocs, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *intercomm, int array_of_errcodes[]) Stara sie˛ utworzyć maxprocs nowych identycznych kopii programu MPI przekazanego poprzez parametr command z argumentami wywołania znajdujacymi ˛ sie˛ w argv (może sie˛ to nie udać np. z powodu braku wolnych zasobów). Poprzez parametr intercomm zwracany jest inter-komunikator który zawiera procesy rodzica w grupie lokalnej (local group) oraz procesy potomne w grupie zdalnej (remote group). Proces jest reprezentowany w MPI przez pare˛ (group, rank), Utworzone procesy maja˛ własny komunikator MPI\_COMM\_WORLD, który jest różny od tego, używanego przez procesy rodziców. Wykład 8 – p. 9/?? Wykład 8 – p. 10/?? Funkcja MPI_Comm_get_parent Tworzenie procesów - ograniczenia Funkcja MPI_Comm_get_parent: W chwili tworzenia programu trudno jest założyć, ile procesów może zostać utworzonych (jest do zależne od środowiska w jakim program bedzie ˛ działał). W zwiazku ˛ z tym decyzja o liczbie uruchamianych procesów musi być podjeta ˛ w trakcie działania programu (co w wielu wypadkach możne znacznie skomplikować implementacje). ˛ int MPI_Comm_get_parent(MPI_Comm *parent) Jeżeli proces został stworzony przy pomocy funkcji MPI_Comm_spawn lub MPI_Comm_spawn_multiple funkcja MPI_Comm_get_parent zwraca dowiazanie ˛ do komunikatora rodzica (parent intracommunicator ), w przeciwnym wypadku zwraca MPI_COMM_NULL. Intra-komunikator jest tworzony w momencie wywołania funkcji MPI_init i jest taki sam, jak intra-komunikator zwracany dla rodzica w momencie tworzenia procesu (zwracany w funkcjach MPI_Comm_spawn i MPI_Comm_spawn_multiple). Można do tego celu wykorzystać funkcje˛ MPI_Comm_get_attr: int size, flag; MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, &size, &flag); gdzie po wykonaniu funkcji: flag - określa, czy MPI obsługuje MPI_UNIVERSE_SIZE, size - to w takim wypadku zwraca liczbe˛ procesów - 1, jakie moga˛ być uruchomione (w przypadku size równego 1 nie może zostać uruchomiony żaden nowy proces). Ponadto ze wzgledu ˛ na wydajność lepszym rozwiazaniem ˛ jest uruchomienie w momencie startu aplikacji (mpiexec) tyle procesów, ile jest konieczne, zamiast tworzyć je dynamicznie. Wykład 8 – p. 11/?? Wykład 8 – p. 12/?? Master - przykład Worker - przykład #include "mpi.h" #include <iostream> #include "mpi.h" #include <iostream> int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); MPI_Comm everyone; MPI_Comm_spawn("worker", MPI_ARGV_NULL, 2, MPI_INFO_NULL, 0, MPI_COMM_SELF, &everyone, MPI_ERRCODES_IGNORE); MPI_Comm parent; MPI_Comm_get_parent(&parent); if (parent == MPI_COMM_NULL) std::cerr << "Error - Brak rodzica!"; MPI_Finalize(); return 0; int size; MPI_Comm_remote_size(parent, &size); if (size != 1) std::cerr << "Error - Cos poszlo nie tak"; } MPI_Finalize(); return 0; } Wykład 8 – p. 13/?? Funkcja MPI_Comm_spawn Wykład 8 – p. 14/?? Funkcja MPI_Comm_spawn_multiple int MPI_Comm_spawn(char *command, char *argv[], int maxprocs, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *intercomm, int array_of_errcodes[]) int MPI_Comm_spawn_multiple(int count, char *array_of_commands[], char **array_of_argv[], int array_of_maxprocs[], MPI_Info array_of_info[], int root, MPI_Comm comm, MPI_Comm *intercomm, int array_of_errcodes[]) gdzie: gdzie: command - nazwa programu, z którego bed ˛ a˛ tworzone nowe procesy, argv - argumenty wywołania, jakie bed ˛ a˛ przekazane do tworzonych procesów, count - liczba komend (rozmiar talicy array_of_commands), maxprocs - maksymalna liczba tworzonych procesów, array_of_commands - tablica z nazwami programów, z których bed ˛ a˛ tworzone nowe procesy, info - zbiór par (klucz, wartość) informujacych ˛ system gdzie i jak maja˛ zostać utworzone nowe array_of_argv - tablica z argumentami wywołania, jakie bed ˛ a˛ przekazane do tworzonych procesy, procesów, root - identyfikator procesu tworzace ˛ procesy potomne, array_of_maxprocs - maksymalna liczba tworzonych procesów dla poszczególnych komend, comm - intra-komunikator zawierajacy ˛ grupe˛ utworzonych procesów, array_of_info - tablica zbiórów par (klucz, wartość) informujacych ˛ system gdzie i jak maja˛ intercomm - inter-komunikator bed ˛ acy ˛ uchwytem pomiedzy ˛ oryginalna˛ grupa˛ procesów, a zostać utworzone nowe procesy, grupa˛ nowoutworzonych procesów, root - identyfikator procesu tworzace ˛ procesy potomne, array_of_errcodes - tablica błedów ˛ o rozmiarze maxprocs (po jednym kodzie dla każdego comm - intra-komunikator zawierajacy ˛ grupe˛ utworzonych procesów, procesu). intercomm - inter-komunikator bed ˛ acy ˛ uchwytem pomiedzy ˛ oryginalna˛ grupa˛ procesów, a grupa˛ nowoutworzonych procesów, array_of_errcodes - tablica błedów ˛ o rozmiarze maxprocs (po jednym kodzie dla każdego procesu). Wykład 8 – p. 15/?? Wykład 8 – p. 16/?? Komunikacja jednostronna Operacje w komunikacji jednostronnej W ramach standard MPI-1 udostepnione ˛ zostały mechanizmy komunikacji dwustronnej (nadawca i odbiorca jawnie uczestnicza˛ w komunikacji): W MPI-2 wprowadzono trzy operacje komunikacji jednostronnej: jeden proces wysyła komunikat (rodzina funkcji MPI_send), MPI_Put (remote write) - zapisywanie danych, MPI_Get (remote read) - pobieranie danych, MPI_Accumulate (remote update) - modyfikacja danych (np. drugi proces odbiera komunikat (rodzina funkcji MPI_recv). sumowanie). W standardzie MPI-2 rozszerzono mechanizmy komunikacji poprzez dodanie trybu pamieci ˛ zdalnej RMA (Remote Memory Access) jeden proces definiuje wszystkie parametry komunikacji (zarówno zwiazane ˛ z wysyłaniem danych, jak i ich odbieraniem). Komunikacja jednostronna wymaga jawnego użycia specjalnych funkcji synchronizujacych ˛ (w przypadku trybu blokujacego ˛ w MPI-1 synchronizacja była realizowana w sposób niejawny). Wykład 8 – p. 17/?? Okno dostepu ˛ do pamieci ˛ Wykład 8 – p. 18/?? Zapis danych Aby można było wykorzystać operacje komunikacji jednostronnej należy utworzyć tzw. okno dostepu ˛ do pamieci. ˛ Funkcja˛ służac ˛ a˛ do zapisywania danych do pamieci ˛ innego procesu jest funkcja MPI_Put: Tworzenie okna polega na wydzieleniu fragmentu już zaalokowanej pamieci ˛ procesu, do której bed ˛ a˛ miały dostep ˛ inne procesy w trybie RMA. int MPI_Put(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) Proces zapisuje do pamieci ˛ procesu target_rank dane o rozmiarze origin_count znajdujace ˛ sie˛ pod adresem origin_addr. Utworzenie okna dostepu ˛ do pamieci ˛ jest operacja˛ komunikacji zbiorowej. Do tego celu służy funkcja MPI_Win_create: int MPI_Win_create(void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win) Dane zostaja˛ umieszczone w pamieci ˛ procesu docelowego pod adresem określonym przez okno win oraz przesunieciem ˛ target_disp. Tworzone jest okno o rozmiarze size, zaczynajace ˛ sie˛ od base. Zwracany jest obiekt win, który jest wykorzystywany w operacjach komunikacyjnych. Do usuniecia ˛ utworzonego okna służy funkcja MPI_Win_free. Wykład 8 – p. 19/?? Wykład 8 – p. 20/?? Odczyt danych Funkcja MPI_Accumulate Funkcja˛ służac ˛ a˛ do odczytywania danych z pamieci ˛ innego procesu jest funkcja MPI_Get: Funkcja MPI_Accumulate wykonuje określona˛ operacje˛ (np. sumowanie) na zawartości lokalnego i docelowego bufora: int MPI_Get(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) int MPI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win) Proces pobiera z pamieci ˛ procesu target_rank dane, które zostaja˛ umieszczone w buforze origin_addr. Zapisywanych jest origin_count elementów typu origin_datatype. Dane zostaja˛ pobrane z pamieci ˛ procesu target_rank spod adresu określonego przez poczatek ˛ okna win i przesuniecia ˛ target_disp. Wynik operacji op wykonanej na lokalnym (origin_addr) i docelowym (określonym przez target_disp i win) buforze jest zapisywany w pamieci ˛ zdalnej. Można wykonywać wiele operacji akumulacji w tym samym czasie przez różne procesy korzystajac ˛ z tego samego bufora docelowego. Po wykonaniu operacji MPI_Get należy wykonać operacje˛ synchronizacji. Korzystanie z lokalnego bufora origin_addr należy odłożyć aż do zakończenia synchronizacji. Wykład 8 – p. 22/?? Wykład 8 – p. 21/?? Synchronizacja Funkcja MPI_Win_fence Synchronizacje˛ RMA można podzielić na: Funkcja MPI_Win_fence synchronizuje wszystkie operacje RMA wykonywane na danym oknie dostepu ˛ do pamieci: ˛ z udziałem procesu zdalnego (active target), int MPI_Win_fence(int assert, MPI_Win win) tylko z udziałem procesów źródłowych (passive target). win - okno, którego operacje bed ˛ a˛ synchronizowane, assert - umożliwia przekazanie wskazówek optymalizacyjnych. Jest operacja˛ typu active target. Wykład 8 – p. 23/?? Wykład 8 – p. 24/?? Pozostałe sposoby synchronizacji Funkcja MPI_Win_create int MPI_Win_create(void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win) Poniższe funkcje umożliwiaja˛ ograniczenie synchronizacji do minimum - jedynie pary procesów korzystajacych ˛ ze wspólnej pamieci ˛ uczestnicza˛ w synchronizacji: gdzie: base - adres, od którego bedzie ˛ zaczynało sie˛ okno, MPI_Win_start, MPI_Win_wait, MPI_Win_post, MPI_Win_complete. size - rozmiar okna w bajtach, disp_unit - jednostka (czynnik skalujacy) ˛ do przesuniecia ˛ w bajtach, info - uchwyt do danych informacyjnych, comm - procesy wchodzace ˛ w skład tej grupy bed ˛ a˛ mogły korzystać z utworzonego okna Analogicznie, jak w przypadku modelu programowania z pamieci ˛ a˛ współdzielona˛ udostepniono ˛ funkcje, umożliwiajace ˛ procesowi zablokowanie korzystania z okna w danym czasie innym procesom (mechanizm zamków, rygli). Sa˛ to operacje typu passive target: pamieci, ˛ win - zwracany obiekt okna, wykorzystywany nastepnie ˛ w operacjach komunikacji jednostronnej. MPI_Win_lock, MPI_Win_unlock. Wykład 8 – p. 26/?? Wykład 8 – p. 25/?? Funkcja MPI_Put Funkcja MPI_Win_free Funkcja MPI_Win_free usuwa obiekt okna dostepu ˛ do pamieci. ˛ Usuwanie obiektu okna może być wykonywane tylko po ukończonej synchronizacji. int MPI_Win_free(MPI_Win *win) int MPI_Put(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) gdzie: origin_addr - adres poczatkowy ˛ bufora źródłowego, gdzie: origin_count - liczba elementów bufora źródłowego, win - uchwyt do okna, które bedzie ˛ usuwane. origin_datatype - typ elementu bufora źródłowego, target_rank - identyfikator procesu, w którym bed ˛ a˛ zapisywane dane, target_disp - przesuniecie ˛ wzgledem ˛ poczatku ˛ okna obszaru do którego bed ˛ a˛ zapisywane dane, target_count - liczba elementów bufora docelowego, target_datatype - typ elementu bufora docelowego, win - uchwyt do wcześniej utworzonego okna wykorzystywanego do komunikacji. Wykład 8 – p. 27/?? Wykład 8 – p. 28/?? Funkcja MPI_Get Funkcja MPI_Accumulate int MPI_Get(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) int MPI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win) gdzie: gdzie: origin_addr - adres poczatkowy ˛ bufora docelowego, origin_count - liczba elementów bufora docelowego, origin_addr - adres poczatkowy ˛ bufora źródłowego, origin_datatype - typ elementu bufora docelowego, origin_count - liczba elementów bufora źródłowego, target_rank - identyfikator procesu, z pamieci ˛ którego bed ˛ a˛ odczytywane dane, origin_datatype - typ elementu bufora źródłowego, target_disp - przesuniecie ˛ wzgledem ˛ poczatku ˛ okna obszaru, z którego bed ˛ a˛ odczytywane target_rank - identyfikator procesu, w którym bed ˛ a˛ zapisywane dane, dane, target_disp - przesuniecie ˛ wzgledem ˛ poczatku ˛ okna obszaru do którego bed ˛ a˛ zapisywane target_count - liczba elementów bufora źródłowego, dane, target_datatype - typ elementu bufora źródłowego, target_count - liczba elementów bufora docelowego, win - uchwyt do wcześniej utworzonego okna wykorzystywanego do komunikacji. target_datatype - typ elementu bufora docelowego, op - typ operacji - moga˛ być wykorzystywane te same operacje, co w przypadku MPI_Reduce: MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD, MPI_LAND, MPI_BAND, MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR, MPI_MAXLOC, MPI_MINLOC, win - uchwyt do wcześniej utworzonego okna wykorzystywanego do komunikacji. Wykład 8 – p. 29/?? Wykład 8 – p. 30/?? Proste rozwiazanie ˛ równoległego we/wy Sekwencyjne wejście/wyjście Procesy wysyłaja˛ dane do procesu 0, który zapisuje je do pliku Najprostsze rozwiazanie ˛ równoległe - każdy proces posiada własny plik, z którego czyta i zapisuje dane. Zaletami sa˛ pełna równoległość oraz duża wydajność. Wadami - obsługa wielu małych plików oraz problemy przy korzystaniu z plików dla innej liczby procesów. Wykład 8 – p. 31/?? Wykład 8 – p. 32/?? Równoległe we/wy - motywacja Równoległe we/wy - prosty przykład Sekwenyjne we/wy jest proste, ale charakteryzuje sie˛ niska˛ wydajnościa, ˛ w przypadku gdy jeden proces korzysta z jednego pliku lub problemami zwiazanymi ˛ z zarzadzeniem ˛ wieloma plikami, w przypadku gdy każdy proces wykorzystuje swój własny plik. Każdy proces odczytuje lub zapisuje dane korzystajac ˛ ze wspólnego pliku z/do przydzielonego mu fragmentu pliku. Istnieje wiele aplikacji, które wymagaja˛ aby: był możliwy równoległy dostep ˛ do jednego pliku przez wiele procesów, dostep ˛ mógł być realizowany jednocześnie, procesy mogły odczytywać te same dane, tworzony był pojedynczy plik, ze wzgledu ˛ na konieczność współpracy z innymmi narz˛edziami. Rozwiazaniem ˛ jest równoległe wejście/wyjście. Wykład 8 – p. 33/?? Otwarcie i zamkniecie ˛ pliku Wykład 8 – p. 34/?? Indywidualne pozycje pliku Do otwarcia pliku służy polecenie MPI_File_open: int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) Otwiera plik o nazwie filename na wszystkich procesach z komunikatora comm. MPI obsługuje jedna˛ pozycje˛ pliku (przesuniecie ˛ wzgledem ˛ poczatku ˛ pliku) dla procesu i uchwytu do pliku. Każdy proces może ustawić swoja˛ pozycje˛ pliku w taki sposób, aby czytał lub zapisywał przydzielony mu fragment pliku. Do ustawienia lokalnej pozycji pliku służy funkcja MPI_File_seek: Jest operacja˛ kolektywna˛ - wszystkie procesy z grupy comm musza˛ wywołać funkcje˛ MPI_File_Open z takimi samymi wartościami amode i filename. Do zamkniecia ˛ pliku służy polecenie MPI_File_close: int MPI_File_close(MPI_File *fh) Zamykany jest wcześniej otwarty plik, na który wskazuje uchwyt fh. Przy zamykaniu pliku wykonywana jest synchronizacja. int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence) Modyfikuje lokalna˛ pozycje˛ pliku zwiazanego ˛ z uchwytem fh w nastepuj ˛ acy ˛ sposób: MPI_SEEK_SET - pozycja pliku jest ustawiana na offset, MPI_SEEK_CUR - pozycja pliku jest zwiekszana ˛ o offset, MPI_SEEK_END - pozycja pliku jest ustawiana na koniec pliku i dodawany jest do niej offest (w takim przypadku offset powinien mieć wartość ujemna). ˛ Wykład 8 – p. 35/?? Wykład 8 – p. 36/?? Czytanie z pliku Zapis do pliku Do czytania z pliku można wykorzystać funkcje MPI_File_read: int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) Odczytuje count elementów typu datatype z pliku określonego przez uchwyt fh do bufora buf poczawszy ˛ od aktualnej lokalnej pozycji pliku. Wersja˛ grupowa˛ funkcji MPI_File_read jest funkcja MPI_File_read_all: Zapis do pliku można zrealizować przy pomocy funkcji MPI_File_write: int MPI_File_write(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) Zapisuje count elementów typu datatype do pliku określonego przez uchwyt fh z bufora buf poczawszy ˛ od aktualnej lokalnej pozycji pliku. Wersja˛ grupowa˛ funkcji MPI_File_write jest funkcja MPI_File_write_all: int MPI_File_read_all(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) int MPI_File_write_all(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) Wykład 8 – p. 37/?? Operacje nieblokujace ˛ Wykład 8 – p. 38/?? Inne rodzaje operacji plikowych Istnieja˛ nieblokujace ˛ wersje operacji do odczytu i zapisu: W standardzie MPI zdefiniowano znacznie wiecej ˛ funkcji i sposobów realizacji operacji na plikach, np: int MPI_File_iread(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Request *request) Funkcje czytajace ˛ i zapisujace ˛ dane z/do pliku z określeniem od którego miejsca w pliku dane maja˛ być pobierane/zapisywane: MPI_File_read_at i MPI_File_write_at. int MPI_File_iwrite(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Request *request) Oczekiwanie na zakończenie operacji na pliku może być zrealizowane przez funkcje MPI_Wait przy wykorzystaniu parametru request (podobnie, jak w przypadku nieblokujacego ˛ odebrania komunikatu). Wykorzystywane sa˛ one najcz˛eściej do nałożenia w czasie obliczeń i operacji plikowych. Wykład 8 – p. 39/?? Funkcje realizujace ˛ zapis/odczyt przy wykorzystaniu wspólnej pozycji pliku (pozycja pliku jest współdzielona przez wszystkie procesy z komunikatora comm podanego w funkcji MPI_File_open): MPI_File_read_shared i MPI_File_write_shared oraz ich odpowiedniki grupowe MPI_File_read_ordered i MPI_File_write_ordered. Inne funkcje. Wykład 8 – p. 40/?? Funkcja MPI_File_Open Funkcja MPI_File_delete Do otwarcia pliku służy funkcja MPI_File_Open: Do usuniecia ˛ pliku służy funkcja MPI_File_Delete: int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) int MPI_File_delete(char *filename, MPI_Info info) gdzie: gdzie: filename - nazwa usuwanego pliku, comm - intra-komunikator - wszystkie procesy wchodzace ˛ w skład tego komunikatora info - obiekt info, bed ˛ a˛ miały dostep ˛ do pliku, Jeżeli plik nie istnie zgłaszany jest bład ˛ (MPI_ERR_NO_SUCH_FILE). filename - nazwa otwieranego pliku, amode - tryb dostepu ˛ do pliku (MPI_MODE_RDONLY - tylko do odczytu, MPI_MODE_RDWR do odczytu i zapisu, MPI_MODE_WRONLY - tylko do zapisu, MPI_MODE_CREATE - tworzy ˛ jeżeli plik już istnieje, plik jeżeli nie istnieje, MPI_MODE_EXCL - bład, MPI_MODE_DELETE_ON_CLOSE - usuniecie ˛ pliku przy zamknieciu, ˛ MPI_MODE_SEQUENTIAL - dostep ˛ do pliku może być tylko sekwencyjny, MPI_MODE_APPEND - wszystkie wskażniki do pliku sa˛ ustawiane na koniec pliku), info - obiekt info, fh - uchwyt do pliku, Wykład 8 – p. 41/?? Wykład 8 – p. 42/?? Funkcja MPI_File_write_at Funkcja MPI_File_read_at int MPI_File_write_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) int MPI_File_read_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) gdzie: gdzie: fh - uchwyt do pliku, do którego bed ˛ a˛ zapisywane dane, fh - uchwyt do pliku, z którego bed ˛ a˛ odczytywane dane, offset - przesuniecie ˛ wzgledem ˛ poczatku ˛ pliku określajace, ˛ od którego miejsca bed ˛ a˛ offset - przesuniecie ˛ wzgledem ˛ poczatku ˛ pliku określajace, ˛ od którego miejsca bed ˛ a˛ zapisywane dane, odczytywane dane, buf - bufor z którego bed ˛ a˛ pobierane dane do zapisu, buf - bufor, do którego bed ˛ a˛ zapisywane dane odczytane z pliku, count - liczba zapisywanych elementów, count - liczba odczytywanych elementów, datatype - typ zapisywanych elementów, datatype - typ odczytywanych elementów, status - obiekt statusu. status - obiekt statusu. Wykład 8 – p. 43/?? Wykład 8 – p. 44/??