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/??