10. MPI. Definicja standardu
10. MPI. Definicja standardu
Cz
Cz
ęść
ęść
II
II
Lesław Sieniawski © 2010
Grupy proces
Grupy proces
ó
ó
w
w
Grupa
– uporz
ą
dkowany zbiór procesów
– procesy identyfikowane przez indeksy (0+)
– grupa jako obiekt posiada własny identyfikator
– skojarzona zawsze z obiektem komunikatora
– predefiniowana grupa pusta
MPI_GROUP_EMPTY
int MPI_Comm_group(MPI_Commm *comm,\
MPI_Group *group)
Tworzenie kopii grupy okre
ś
lonej komunikatorem
comm
int MPI_Group_size(MPI_Group *group,\
int *size)
obliczenie liczby procesów nale
żą
cych do grupy
group
, wynik w
size
Grupy proces
Grupy proces
ó
ó
w (2)
w (2)
Operacje mnogo
ś
ciowe
na grupach (suma,
iloczyn, ró
ż
nica):
int MPI_Group_
xxxx
(MPI_Group A,\
MPI_Group
B, MPI_Group *wynik)
gdzie
– xxxx
=
union
– suma grup, A U B
– xxxx
=
intersection
– iloczyn grup, A
∩
B
– xxxx
=
difference
– ró
ż
nica grup, A \ B
Grupy proces
Grupy proces
ó
ó
w (3)
w (3)
int MPI_Group_incl(MPI_Group group,\
int n, int *ranks,\
MPI_Group newgroup)
utworzenie nowej grupy
newgroup
przez
doł
ą
czenie nowych procesów do grupy
group
;
n
= liczba dodawanych procesów
ranks
= tablica zawieraj
ą
ca ID dodawanych procesów
Grupy proces
Grupy proces
ó
ó
w (4)
w (4)
int MPI_Group_translate_ranks \
(MPI_Group group1, int n,\
int *ranks1, MPI_Group group2,\
int *ranks2)
Okre
ś
lenie numeracji procesów wewn
ą
trz grupy
group2
utworzonej z grupy
group1
; liczba
n
-
liczebno
ść
nowej grupy,
ranks1
i
ranks2
- tablice
identyfikatorów odpowiednio pierwszej i drugiej
grupy procesów (rozmiary tablic identyczne)
int MPI_Group_free(MPI_Group group)
usuni
ę
cie grupy o identyfikatorze
group
#include <mpi.h>
#include <stdio.h>
/* oprac. LS na podstawie
Jedrzej.Ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
*/
int main(int argc, char *argv[])
{
MPI_Init(&argc,&argv);
MPI_Group wszystkie, nieparzyste, parzyste;
int i, p, Nparz, procesy0[8], procesy1[8], Lparzystych, Nrprocesu;
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_group(MPI_COMM_WORLD, &wszystkie);
// procesy z MPI_COMM_WORLD o numerach parzystych sa umieszczane w nowej grupie
Nparz = (p+1)/2;
//zero jest parzyste!
for (i=0; i<Nparz; i++) { procesy0[i] = 2*i; };
MPI_Group_incl(wszystkie, Nparz, procesy0, &parzyste);
MPI_Comm_rank(MPI_COMM_WORLD, &Nrprocesu);
if (Nrprocesu==0)
{
printf("Tworzenie grupy procesów o nrach parzystych\n");
MPI_Group_size(parzyste, &Lparzystych);
printf("Liczba procesów w nowej grupie = %d\n", Lparzystych);
MPI_Group_translate_ranks(wszystkie, Nparz, procesy0, parzyste, procesy1);
printf("Pierwotny nr Nowy nr\n");
for (i=0; i<Nparz; i++)
printf("%12d %7d\n", procesy0[i], procesy1[i]);
}
MPI_Finalize();
return 0;
}
Przyk
Przyk
ł
ł
ad #1: Tworzenie grupy proces
ad #1: Tworzenie grupy proces
ó
ó
w
w
[root@p205 openMPI]#
mpicc selParz.c -o selParz
[root@p205 openMPI]#
mpirun -n 4 --mca btl tcp,self \
selParz
Tworzenie grupy procesów o nrach parzystych
Liczba procesów w nowej grupie = 2
Pierwotny nr Nowy nr
0 0
2 1
[root@p205 openMPI]#
mpirun -n 7 --mca btl tcp,self \
selParz
Tworzenie grupy procesów o nrach parzystych
Liczba procesów w nowej grupie = 4
Pierwotny nr Nowy nr
0 0
2 1
4 2
6 3
[root@p205 openMPI]#
Przyk
Przyk
ł
ł
ad #1: Kompilacja i uruchomienie
ad #1: Kompilacja i uruchomienie
Komunikatory
Komunikatory
Komunikator
– obiekt zawieraj
ą
cy grup
ę
procesów, które mog
ą
si
ę
wzajemnie
komunikowa
ć
– Dost
ę
pny tylko poprzez swój ID
– Komunikaty MPI wskazuj
ą
komunikator
Perspektywa programisty
:
grupa
≈
komunikator
;
Grupa – lista procesów słu
żą
ca do utworzenia
komunikatora („stadium po
ś
rednie”)
Operacje na komunikatorach
Operacje na komunikatorach
int MPI_Comm_dup(MPI_Comm comm,\
MPI_Comm *newcomm)
utworzenie komunikatora
newcomm
jako duplikatu
komunikatora
comm
, zawieraj
ą
cego te same procesy
int MPI_Comm_create(MPI_Comm comm,\
MPI_Group newgroup, MPI_Comm *newcomm)
utworzenie komunikatora
newcomm
z grupy procesów
okre
ś
lonej identyfikatorem
newgroup
nale
żą
cych do
komunikatora
ź
ródłowego
comm
Operacje na komunikatorach (2)
Operacje na komunikatorach (2)
int MPI_Comm_split(MPI_Comm comm,\
int color, int key, MPI_Comm *newcomm)
utworzenie komunikatora
newcomm
przez podział zwi
ą
zanej z nim
grupy istniej
ą
cego komunikatora na rozł
ą
czne podgrupy,
color
- parametr klasyfikuj
ą
cy procesy wł
ą
czane do nowego
komunikatora,
key
– priorytet; liczba nowych komunikatorów =
liczebno
ść
zbioru ró
ż
nych warto
ś
ci parametru
color
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
Operacje na komunikatorach (3)
Operacje na komunikatorach (3)
int MPI_Comm_free(MPI_Comm comm)
usuni
ę
cie komunikatora o identyfikatorze
comm
Organizacja proces
Organizacja proces
ó
ó
w
w
w grupy i komunikatory
w grupy i komunikatory
Dynamiczny charakter
grup i komunikatorów -
tworzenie i usuwanie w czasie wykonywania
programu
Proces
–
element dowolnej liczby grup i komunika-
torów
40+ procedur
obsługi grup i komunikatorów
Organizacja proces
Organizacja proces
ó
ó
w (2)
w (2)
Typowe post
ę
powanie
:
1.
Utworzenie globalnej grupy z komunikatora
MPI_COMM_WORLD
za pomoc
ą
procedury
MPI_Comm_group
i
pobranie jej ID
2.
Zbudowanie nowej grupy jako podzbioru procesów grupy
globalnej (procedura
MPI_Group_incl
)
3.
Utworzenie komunikatora z nowej grupy (procedura
MPI_Comm_create
)
4.
Okre
ś
lenie ID (rank) procesów w nowym komunikatorze
(procedura
MPI_Comm_rank
)
5.
Przeprowadzi
ć
komunikacj
ę
(ró
ż
ne procedury
przekazywania komunikatów)
6.
Usun
ąć
nowy komunikator (
MPI_Comm_free
) i now
ą
grup
ę
(
MPI_Group_free
)
Organizacja
Organizacja
proces
proces
ó
ó
w (3)
w (3)
Cel
Cel
:
-
tworzenie grup procesów
do realizacji podobnych
funkcji
-
umo
ż
liwienie kolektywnej
komunikacji
w podzbiorze
procesów
-
umo
ż
liwienie budowania
wirtualnych topologii
procesów
-
zapewnienie bezpiecznej
komunikacji
[
ź
ródło: https://computing.llnl.gov/tutorials/mpi/]
„Lokalne” ID procesów
Komunikacja punkt
Komunikacja punkt
-
-
punkt
punkt
Od
b
ie
ra
n
ie
W
y
s
y
ła
n
ie
MPI_Irecv(buffer, count, type, source,
tag, comm, request)
Nieblokuj
ą
ce
MPI_Recv(buffer, count, type, source,
tag, comm, status)
Blokuj
ą
ce
MPI_Isend(buffer, count, type, dest,
tag, comm, request)
Nieblokuj
ą
ce
MPI_Send(buffer, count, type, dest,
tag, comm)
Blokuj
ą
ce
Wywołanie procedury
Rodzaj operacji
Komunikacja punkt
Komunikacja punkt
-
-
punkt (2)
punkt (2)
Obja
ś
nienie parametrów procedur
buffer
– wska
ź
nik bufora danych wysyłanych/odbieranych
count
– liczba elementów danych wskazanego typu
type
– wskazanie typu danych w buforze
tabela
dest
– ID procesu, do którego komunkat ma by
ć
przekazany
source
– ID procesu, który nadał komunikat, lub
MPI_ANY_SOURCE
,
gdy nadawca nie ma znaczenia
tag
– dowolna nieujemna liczba całkowita identyfikuj
ą
ca rodzaj
komunikatu lub
MPI_ANY_TAG
, gdy rodzaj nie ma znaczenia;
comm
– ID komunikatora, którego dotyczy ID nadawcy lub odbiorcy,
lub
MPI_COMM_WORLD
, gdy dotyczy wszystkich procesów
status
(dla operacji odbierania) wska
ź
nik do struktury typu
MPI_Status
request
(dla operacji nieblokuj
ą
cych) – wska
ź
nik do struktury typu
MPI_Request
przechowuj
ą
cej numer operacji, dla ewentualnego
pó
ź
niejszego wykorzystania np. dla zbadania, czy operacja si
ę
zako
ń
czyła (procedura typu
Wait
)
Typy danych w komunikatach
Typy danych w komunikatach
Dane spakowane/rozpakowane za pomoc
ą
MPI_Pack()
/
MPI_Unpack
MPI_PACKED
8 binary digits
MPI_BYTE
long double
MPI_LONG_DOUBLE
double
MPI_DOUBLE
float
MPI_FLOAT
unsigned long int
MPI_UNSIGNED_LONG
unsigned int
MPI_UNSIGNED
unsigned short int
MPI_UNSIGNED_SHORT
unsigned char
MPI_UNSIGNED_CHAR
signed long int
MPI_LONG
signed int
MPI_INT
signed short int
MPI_SHORT
signed char
MPI_CHAR
Definicja w j
ę
zyku C
Typ danych MPI
[
ź
ró
d
ło
:
h
tt
p
s
:/
/c
o
m
p
u
ti
n
g
.l
ln
l.
g
o
v
/t
u
to
ri
a
ls
/m
p
i/
]
Wybrane procedury komunikacji punkt
Wybrane procedury komunikacji punkt
-
-
punkt
punkt
int MPI_Send(void *buf, int count,\
MPI_Datatype datatype, int dest, int tag,\
MPI_Comm comm)
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
(Wysyłanie blokuj
ą
ce)
Wybrane procedury komunikacji punkt
Wybrane procedury komunikacji punkt
-
-
punkt (2)
punkt (2)
int MPI_Recv(void *buf, int count,\
MPI_Datatype datatype, int srce, int tag,\
MPI_Comm comm, MPI_Status *status)
(Odbieranie blokuj
ą
ce)
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv)
{
int numtasks, rank, dest, source, rc, count, tag=1;
char inmsg, outmsg='x';
MPI_Status Stat;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
dest = 1;
source = 1;
rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
}
else if (rank == 1) {
dest = 0;
source = 0;
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
rc = MPI_Get_count(&Stat, MPI_CHAR, &count);
printf("Task %d: Received %d char(s) from task %d with tag %d \n", rank,\
count, Stat.MPI_SOURCE, Stat.MPI_TAG);
MPI_Finalize();
}
Program #2. Ping
Program #2. Ping
-
-
pong
pong
Proces
0
wysyła ‘x’ do procesu
1
i czeka na odzew
[
ź
ródło: https://computing.llnl.gov/tutorials/mpi/]
[root@p205 openMPI]#
mpirun -n 2 --mca btl tcp,self \
ping-pong
Task 1: Received 1 char(s) from task 0 with tag 1
Task 0: Received 1 char(s) from task 1 with tag 1
[root@p205 openMPI]#
Przyk
Przyk
ł
ł
ad
ad
#2:
#2:
Kompilacja i uruchomienie
Kompilacja i uruchomienie
Synchronizacja komunikacji punkt
Synchronizacja komunikacji punkt
-
-
punkt
punkt
Ze wzgl
ę
du na współdziałanie
nadawcy
i odbiorcy:
– Synchroniczna
: oczekiwanie nadawcy na
przyst
ą
pienie odbiorcy do odbierania komunikatu
– Asynchroniczna
: z umieszczeniem przez nadawc
ę
komunikatu w buforze, gdy odbiorca nie jest
gotowy do odbierania
Ze wzgl
ę
du na blokowanie
procesu:
– Blokuj
ą
ca
: wyj
ś
cie (powrót) z funkcji
komunikacyjnej dopiero po jej zako
ń
czeniu
– Nieblokuj
ą
ca
: powrót natychmiastowy
Synchronizacja komunikacji punkt
Synchronizacja komunikacji punkt
-
-
punkt (2)
punkt (2)
Obsługa buforowania
w komunikacji asynchronicznej:
int MPI_Buffer_attach(void *buffer,\
int size)
utworzenie bufora,
size
>= rozmiar pojedynczego
komunikatu
int MPI_Buffer_detach(void *buffer,\
int size)
zwolnienie bufora wskazanego przez
buffer
o rozmiarze
size
Kombinacje tryb
Kombinacje tryb
ó
ó
w
w
wsp
wsp
ó
ó
ł
ł
dzia
dzia
ł
ł
ania i buforowania
ania i buforowania
Bez blokowania (natychmiastowy)
Immediate (
I
)
Nieblokuj
ą
cy
Nadawanie wymaga wcze
ś
niejszej
gotowo
ś
ci do odbioru
Ready (
R
)
Przygotowany
Komunikacja spotkaniowa
Synchronous
(
S
)
Synchroniczny
Umieszczenie komunikatu we
wcze
ś
niej utworzonym buforze
Buffered (
B
)
Buforowany
Opis sposobu realizacji
Nazwa w j
ę
z.
angielskim
i kod nazwy
Nazwa w j
ę
z.
polskim
np. MPI_Ssend
P
P
-
-
P: Tryb synchroniczny
P: Tryb synchroniczny
int MPI_Ssend(*buffer, count,\
datatype, dest, tag, comm, ierr)
blokada nadawcy do czasu zako
ń
czenia odbioru
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
P
P
-
-
P: Tryb buforowany
P: Tryb buforowany
int MPI_Bsend(void *buffer, int count,\
MPI_Datatype datatype, int dest, int tag,\
MPI_Comm comm, int ierr)
buforowanie komunikatu przez nadawc
ę
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
P
P
-
-
P: Tryb buforowany nieblokuj
P: Tryb buforowany nieblokuj
ą
ą
cy
cy
int MPI_Ibsend(void *buffer,\
int count, MPI_Datatype datatype,\
int dest, int tag, MPI_Comm comm,\
MPI_Request *request)
Znaczenie parametrów – jak poprzednio;
request
– identyfikator rozpocz
ę
tej operacji, do
wykorzystania przez procedury typu Wait
P
P
-
-
P: Tryb przygotowany nieblokuj
P: Tryb przygotowany nieblokuj
ą
ą
cy
cy
int MPI_Irsend(*buffer, count,\
datatype, dest, tag, comm)
operacja wysłania komunikatu wymaga wcze
ś
niejszej
gotowo
ś
ci odbiorcy (inaczej
bł
ą
d)
[
ź
ródło: jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/MPI14.pdf
Ko
Ko
ń
ń
czenie operacji nieblokuj
czenie operacji nieblokuj
ą
ą
cych
cych
MPI_Wait(MPI_Request *request,\
MPI_Status status)
blokowanie procesu
wywołuj
ą
cego te procedur
ę
do
chwili, gdy operacja wskazywana przez ID
request
zostanie zako
ń
czona (dla wysyłania oznacza to,
ż
e
bufor mo
ż
e by
ć
u
ż
yty ponownie).
Po wykonaniu procedury
MPI_Wait
zmienna
request
zawiera warto
ść
MPI_REQUEST_NULL
MPI_Waitany, MPI_Waitall, MPI_Waitsome
–
wersje procedury blokuj
ą
ce proces a
ż
zako
ń
czy si
ę
jakalokwiek
operacja, wszystkie operacje lub niektóre z nich
Ko
Ko
ń
ń
czenie operacji nieblokuj
czenie operacji nieblokuj
ą
ą
cych (2)
cych (2)
MPI_Test(MPI_Request *request,\
int *flag, MPI_Status *status)
nieblokuj
ą
ce badanie
zako
ń
czenia operacji wskazanej
przez ID
request
;
flag
=
TRUE
gdy operacja
zako
ń
czyła si
ę
,
flag
=
FALSE
w przeciwnym razie
MPI_Cancel(MPI_Request *request)
anulowanie
operacji nieblokuj
ą
cej wskazanej przez ID
request
Testowanie operacji nieblokuj
Testowanie operacji nieblokuj
ą
ą
cych
cych
MPI_Iprobe(int source, int tag,\
MPI_Comm comm, int *flag,\
MPI_Status *status)
badanie
czy w komunikatorze
comm
jest wiadomo
ść
nadana przez proces
source
i posiadaj
ą
ca etykiet
ę
równ
ą
tag
, dla której warto
ść
zmiennej
flag
jest
równa
TRUE
Wysy
Wysy
ł
ł
anie z odbieraniem
anie z odbieraniem
MPI_Sendrecv(
void *sendBuf, int sendCnt,\
MPI_Datatype sendType,int dest,int sendTag,\
void *recvBuf, int recvCnt,\
MPI_Datatype recvType,int srce,int recvTag,\
MPI_Comm comm, MPI_Status *status)
wysłanie komunikatu od
send
do
recv
i oczekiwanie na odpowied
ź
;
Elementy nazw:
send
i
recv
– odpowiednio funkcje nadawania i odbioru,
dest
i
srce
- odpowiednio ID procesu odbiorcy i nadawcy,
Cnt
– liczba,
Type
– typ danych w komunikacie,
Tag
– etykieta,
comm
– komunikator,
status
– status wykonania
Przyk
Przyk
ł
ł
ad
ad
#3:
#3:
Karuzela proces
Karuzela proces
ó
ó
w
w
0
0
2
2
1
1
Ka
ż
dy proces przekazuje swój ID
s
ą
siadowi z lewej strony,
i otrzymuje ID swojego prawego
s
ą
siada.
#include <mpi.h>
#include <stdio.h>
/* ------------------------------------------------------------------------
karuzela.c - przekazywanie komunikatow w pierscieniu procesow
Proces #i otrzyma komunikat z numerem swojego prawego sasiada, tj. i+1
Oprac. LS na podstawie http://mpi.deino.net/mpi_functions/MPI_Sendrecv.html
--------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int wlasnyID, Lprocesow, lewySasiad, prawySasiad;
char buforSend[5], buforRecv[5];
MPI_Status status;
MPI_Init(&argc,&argv);
// identyfikacja srodowiska
MPI_Comm_size(MPI_COMM_WORLD, &Lprocesow);
MPI_Comm_rank(MPI_COMM_WORLD, &wlasnyID);
// przygotowanie odpowiedzi w postaci tekstowej – wlasny ID procesu
sprintf(buforSend,"%d", wlasnyID);
// okreslenie ID sasiadow
prawySasiad = (wlasnyID + 1) % Lprocesow;
lewySasiad = wlasnyID - 1;
if (lewySasiad < 0) lewySasiad = Lprocesow - 1;
// nadanie komunikatu do sasiada z lewej strony i odebranie komunikatu od tego z prawej
// UWAGA: etykiety musza byc zgodne!
MPI_Sendrecv(\
buforSend, 5, MPI_CHAR, lewySasiad, 11,buforRecv, 5, MPI_CHAR, prawySasiad, 11,\
MPI_COMM_WORLD, &status);
// raportowanie otrzymanych komunikatow
printf("Tu proces %d. Sasiad z prawej strony ma nr %s\n", wlasnyID, buforRecv);
MPI_Finalize();
return 0;
}
Program #3. Karuzela
Program #3. Karuzela
[root@p205 openMPI]#
mpicc karuzela.c –o karuzela
[root@p205 openMPI]#
mpirun –n 4 -–mca btl tcp,self \
karuzela
Tu proces 0. Sasiad z prawej strony ma nr 1
Tu proces 3. Sasiad z prawej strony ma nr 0
Tu proces 1. Sasiad z prawej strony ma nr 2
Tu proces 2. Sasiad z prawej strony ma nr 3
[root@p205 openMPI]#
Przyk
Przyk
ł
ł
ad
ad
#3:
#3:
Kompilacja i uruchomienie
Kompilacja i uruchomienie
Wszystkie zademonstrowane tu przykłady
wykonano na maszynie o architekturze
SMP (tj. wieloprocesorowej z pami
ę
ci
ą
współdzielon
ą
)