51. Metody komunikacji nieblokującej.
Transkrypt
51. Metody komunikacji nieblokującej.
51. Metody komunikacji nieblokującej. Funkcje nieblokujace różnia sie od wersji blokujacych przedrostkiem „I” (immediate) w nazwie oraz jednym dodatkowym argumentem: request, który jest używany do sprawdzenia, czy dana operacja została zakończona Wysyłanie nieblokujące • Funkcja MPI Isend: (standardowa) int MPI Isend( void *buf, int count, MPI Datatype datatype, int dest, int tag, MPI Comm comm, MPI Request *request) • Funkcja MPI Ibsend: (buforowana) int MPI Ibsend( void *buf, int count, MPI Datatype datatype, int dest, int tag, MPI Comm comm, MPI Request *request) • Funkcja MPI Issend: (synchroniczna) int MPI Issend( void *buf, int count, MPI Datatype datatype, int dest, int tag, MPI Comm comm, MPI Request *request) • Funkcja MPI Irsend: (natychmiastowa) int MPI Irsend( void *buf, int count, MPI Datatype datatype, int dest, int tag, MPI Comm comm, MPI Request *request) Odbiór nieblokujący Funkcja MPI Irecv: – nie ma argumentu MPI Status – może odbierać także komunikaty wysyłane w spospób blokujący (i vice-versa) int MPI Irecv( void *buf, int count, MPI Datatype datatype, int source, int tag, MPI Comm comm, MPI Request *request) Funkcja MPI Wait: – pozwala czekać na zakończenie nieblokującej operacji(wysyłania, odbierania) wskazanej przez argument request – pod adresem status wpisuje status zakończonej operacji – po zakończeniu funkcja wpisuje pod adresem request wartość MPI REQUEST NULL int MPI Wait(MPI Request *request, MPI Status *status) Funkcja MPI Test: – jeżeli operacja o uchwycie wskazywanym przez request skończyła się, to funkcja działa jak MPI Wait i dodatkowo pod adresem flag wpisuje wartość true – jeżeli operacja się nie zakończyła, funkcja pod adresem flag wpisuje false i powraca int MPI Wait(MPI Request *request, int *flag, MPI Status *status) Jeśli funkcje MPI Wait i MPI Test sygnalizują zakończenie operacji, to następuje zwolnienie zajmowanych przez nią zasobów. Jawnie można zwolnić zasoby funkcją int MPI Request free(MPI Request *request) Funkcja MPI Waitany: – czeka na zakończenie jakiejkolwiek z count operacji na uchwytach przkazanych w tablicy array of requests – indeks (z array of requests) zakończonej operacji jest zapisywany pod adresem index – status operacji zapisywany pod adresem status – jeśli kilka operacji się zakończyło, funkcja wybiera tylko jedną z nich (dla pozostałych można wywołać ją ponownie) – zasoby są zwalniane, a w odpowiednią pozycję tablicy array of requests wpisywane MPI REQUEST NULL int MPI Waitany( int count, MPI Request *array of requests, int *index, MPI Status *status) Pozostałe funkcje: • Funkcja MPI Testany int MPI Testany( int count, MPI Request *request, int *index, int *flag, MPI Status *status) • Funkcja MPI Waitall int MPI Waitall( int count, MPI Request *array of requests, MPI Status *array of statuses) • Funkcja MPI Testall int MPI Testall( int count, MPI Request *array of requests, int *flag, MPI Status *array of statuses) Anulowanie komunikacji: int MPI Cancel(MPI Request *request) – pozwala przerwać oczekującą nieblokującą komunikację – nie oznacza to zwolnienia zasobów (należy użyć MPI Request Free, MPI Wait lub MPI Test) – użycie tej funkcji może znacznie spowalniać wykonanie, nie należy jej nadużywać – sprawdzenie czy anulowanie się powiodło umożliwia funkcja MPI Test cancelled int MPI Test cancelled(MPI Status *status, int *flag) /jeśli flag=true to status jest nieokreślony/ Sprawdzanie rozmiaru bufora Funkcja MPI Iprobe /wersja nieblokująca (flag=true jeśli komunikat jest gotowy do odbioru)/ int MPI Iprobe( int source, int tag, MPI Comm comm , int *flag, MPI Status *status) 52. Komunikacja łączona. • Operacja Send-Receive łączy w jednym wywołaniu wysyłanie komunikatu do określonego odbiorcy oraz odbiór od określonego nadawcy innego komunikatu. • Użyteczna w cyklicznych operacjach przesunięć: odporna na powstawanie blokad(deadlock) • Funkcja MPI Sendrecv: (blokująca) int MPI Sendrecv ( void *sendbuf, int sendcount, MPI Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI Datatype recvtype, int source, int recvtag, MPI Comm comm, MPI Status status) 53. Stosowanie typów pochodnych. • Typ pochodny można zdefiniować za pomocą specjalnej funkcji (patrz następne pytania) • Po zdefiniowaniu nowego typu należy go ustanowić (skompilować) przed użyciem typu do przesyłania komunikatów ale nie koniecznie przed definiowaniem kolejnych typów pochodnych • Po zakończeniu używania typu należy zwolnić przydzielone mu zasoby 54. Mapowanie typów. Określa rozłożenie w pamięci obiektów tworzących dany typ danych • Typemap - mapa typu - jest to sekwencja par: ( typ podstawowy, przesunięcie w pamieci/w bajtach/ ) typemap={(type0 , disp0 ), ..., (typen−1 , dispn−1 )} • Sygnatura typu - lista typów zawarytch w typemap: type signature={type0 , ..., typen−1 } • lb - dolne ograniczenie przesunięć: lb(typemap) = minj (dispj ) • ub - górne ograniczenie przesunięć: ub(typemap) = maxj (dispj +sizeof(typej )) • extent - zakres (różnica ub-lb powiększona o wyrównanie): extent(typemap) = ub(typemap) - lb(typemap) + pad 55. Tworzenie typów pochodnych i ich rodzaje. Ustanowienie typu: int MPI Type commit (MPI Datatype *datatype) • ustanawia wskazany typ do komunikacji • ustanowiony typ może dalej służyć do tworzenia dalszych typów pochodnych • system może dokonać kompilacji wewnętrznej reprezentacji typu pod kątem optymalizacji komunikacji go wykorzystujących Zwolnienie typu: int MPI Type free (MPI Datatype *datatype) • zwalnia zasoby zaalokowane przez wskazny typ • ustawia wskazanie datatype na MPI DATATYPE NULL • zaległ komunikacje wykorzystujące typ będą dokończone normalnie (opoźnienie dealokacji) • funkcja nie wpływa na stan typów pochodnych od datatype Rodzaje: 1.Tablica typów int MPI Type contiguous (int count, MPI Datatype oldtype, MPI Datatype *newtype) • najprostszy konstruktor typu pochodnego • argument count określa liczbę elementów w tablicy • argumant oldtype określa typ składowy • wynikowy identyfikator typu jest umieszczany pod adresem newtype • przesunięcia powiększane o zakres typu składowego 2.Wektor int MPI Type vector ( int count, int blocklength, int stride, MPI Datatype oldtype, MPI Datatype *newtype) • definiuje typ składający się z count bloków, zawierających blocklength elementów typu oldtype każdy • między początkami bloków występują odstępy o długości stride elementów oldtype 3.Wektor heterogeniczny int MPI Type hvector ( MPI Aint count, int blocklength, int stride, MPI Datatype oldtype, MPI Datatype *newtype) • argument stride określa przesunięcia wyrażone w bajtach, a nie w długościach zakresu elementu oldtype • typ podstawowy MPI Aint odnosi się do adresów (liczba całkowita przechowująca adres na danej architekturze) 4.Wektor indeksowany int MPI Type indexed ( int count, int *array of blocklengths, int *array of displacements, MPI Datatype oldtype, MPI Datatype *newtype) • tablica array of blocklengths określa ilości powieleń count bloków o zakresach odpowiadających zakresowi typu oldtype • dla każdego powielenia przesunięcie wyrażone w jednostkach zakresu typu oldtype jest pobierane z odpowiedniego pola tablicy array of displacements • argument count określa także rozmiar tablic array of blocklengths i array of displacements 5.Wektor indeksowany heterogeniczny int MPI Type hindexed ( int count, int *array of blocklengths, MPI Aint *array of displacements, MPI Datatype oldtype, MPI Datatype *newtype) • przesunięcia w tablicy array of displacements wyrażone są w bajtach 6.Struktura int MPI Type struct ( int count, int *array of blocklengths, MPI Aint *array of displacements, MPI Datatype *array of types, MPI Datatype *newtype) • definiuje najogólniejszą postać typu pochodnego • typ newtype składa się z count bloków, każdy o innym typie i długości zakresu • typy poszczególnych bloków określa tablica array of types, a ich długości (wyrażone liczbą elementów składowych) tablica array of blocklengths • elementy tablicy array of displacements określają przesunięcie bloków względem początku Funkcje pomocnicze • int MPI Address (void *location, MPI Aint *address) zwraca adres położenia w pamięci • int MPI Type extent (MPI datatype datatype, MPI Aint *extent) zwraca długość zakresu danego typu • int MPI Type size (MPI datatype datatype, int *size) zwraca całkowitą wielkość(w bajtach) elementów składowych typu • stała MPI BOTTOM oznacza początek obszaru pamięci adresowanego absolutnie np. z użyciem MPI Address Przykład: