1 Le funzioni di MPI MPI è una libreria che comprende: Funzioni per definire l ambiente Funzioni per comunicazioni uno a uno Funzioni percomunicazioni collettive Funzioni peroperazioni collettive 2 1
3 operazione fondamentale 4 2
La comunicazione di un messaggio La comunicazione di un messaggio può coinvolgere due o più processori. Per comunicazioni che coinvolgono solo due processori Per comunicazioni che coinvolgono più processori Si considerano funzioni MPI per comunicazioni uno a uno Si considerano funzioni MPI per comunicazioni collettive 5 6 3
Deadlock Due o più processi si bloccano a vicenda aspettando che uno esegua una azione che serve all altro per terminare la comunicazione e procedere nell esecuzione del programma Problema non facilmente rilevabile Utilizzare comunicazioni bloccanti può causare un deadlock se la modalità è sincrona o il messaggio è di dimensioni maggiori del buffer di sistema 7 Rank=0 send(a,1) recv(b,1) Rank=1 send(a,0) recv(b,0) Unsafe program 0 manda ad 1 il suo vettore a e riceve in b il vettore a di 1 1 manda a 0 il suo vettore a e riceve in b il vettore a di 0 se la modalità è sincrona ci sono due send in attesa di due receive, che possono essere eseguite solo se le send sono completate! 8 4
Rank=0 send(a,1) Rank=1 recv(b,0) recv(b,1) send(a,1) In questo caso semplice si evita facendo attenzione all ordine 9 Necessità di una funzione che gestisca internamente l ordine delle operazioni di send e receive MPI_Sendrecv è utile quando un processo deve contemporaneamente inviare e ricevere dati 10 5
0 1 0 manda ad 1 il suo vettore a e riceve in b il vettore a di 1 1 manda a 0 il suo vettore a e riceve in b il vettore a di 0 11 12 6
MPI_Sendrecv(voidvoid *sbuf, int scount, MPI_Datatype sdatatype, int dest, int stag,void *rbuf,int rcount, MPI_Datatype rdatatype,int recv, int rtag,mpi_comm comm,mpi_status*status); La prima metà di argomenti è relativa alla send la seconda alla receive 13 Comunicazione tipo shift tutti i processi, tranne l ultimo, inviano un messaggio al processo di rank successivo tutti i processi, tranne il primo,ricevono i messaggio inviato dal processo di rank seguente shift di un dato all interno di una catena di processi sendrecv 14 7
shift circolare periodico tutti i processi, tranne l ultimo, inviano un messaggio al processo di rank successivo l ultimo invia un messaggio al primo processo 15 esercizio Shift circolare periodico su tre processori di un array A di interi 16 8
Comunicazione collettive di un messaggio 17 Comunicazioni collettive : 0 3 1 4 2 Nel connumicator com1 P 0 comunica con tutti gli altri processori Communicator com1 3 0 D ABCD 2 A C Communicator com2 1 B P 0 distribuisce a tutti i processori di com2 un elemento del proprio vettore 18 9
Spedizione collettiva, uno a molti: Broadcast 19 Spedizione collettiva, uno a molti: #include <stdio.h> #include mpi.h int main(int argc, char *argv[]) { int menum, nproc; int n, tag, num; MPI_Status info; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&menum); if(menum==0) { scanf( %d,&n); } MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); MPI_Finalize(); return 0; } 20 10
MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); Il processore P 0 spedisce n, di tipo MPI_INT e di dimensione 1, a tutti i processori dell ambiente ente MPI_COMM_WORLD. one to all 21 In generale : MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm); Il processore con identificativo root spedisce a tutti i processori del comunicator comm lo stesso dato memorizzato in *buffer. Count, datatype, comm devono essere uguali per ogni processore di comm. 22 11
In dettaglio : MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm); *buffer count indirizzo del dato da spedire numero dei dati da spedire datatype tipo dei dati da spedire root comm identificativo del processore che spedisce a tutti identificativo del communicator 23 MPI_Bcast invia a tutti gli stessi dati Se si vogliono inviare dati diversi ad ogni processore Spedizione collettiva di tipo: data scatter Se tutti i processori vogliono inviare dati al root Spedizione collettiva di tipo: data gather 24 12
Spedizione collettiva di tipo: data scatter Un processore distribuisce i propri dati agli altri se stesso compreso 25 Spedizione collettiva di tipo: data gather Tutti i processori spediscono i propri dati ad un processore assegnato (es al processore P 0 ) 26 13
il processo root (P 0 ) divide in N parti uguali un insieme di dati contigui in memoria invia una parte ad ogni processo in ordine di rank one to all 27 ogni processo,incluso il root (P 0 ) invia il contenuto del proprio send buffer al processo root il processo root riceve i dati e li ordina in funzione del rank del processo sender all to one 28 14
Lo scatter in MPI MPI_Scatter(void *send_buff, int send_count, MPI_Datatype send_type, void *recv_buff,int recv_count, MPI _ Datatype recv _ type, int root, MPI_Comm comm); Il processore con identificativo root distribuisce i dati contenuti in send_buff. Il contenuto disend_buff_ viene suddiviso in nproc segmenti ciascuno di lunghezza send_count Il primo segmento viene affidato al processore con identificativo 0, il secondo al processore con identificativo 1, il terzo al processore con identificativo 2, etc. 29 Lo scatter in MPI: in dettaglio MPI_Scatter(void *send_buff, int send_count, MPI_Datatype send_type, void *recv_buff,int recv_count, MPI_Datatype recv_type, int root, MPI_Comm comm); *send_buff indirizzo del dato da spedire send_count numero dei dati da spedire send_type tipo dei dati da spedire *recv_buff indirizzo del dato in cui ricevere recv_count numero dei dati da ricevere recv_type tipo dei dati da ricevere root identificativo del processore che spedisce a tutti comm identificativo del communicator 30 15
Spedizione collettiva di tipo scatter: #include <stdio.h> #include mpi.h int main(int argc, char *argv[]) { int menum, nproc; int a[100]; int a2[10]; int root=0; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&nproc); MPI_Comm_rank(MPI_COMM_WORLD,&menum); if (menum==0).inizializza a. MPI_Scatter(a,10,MPI_INT,a2,10,MPI_Int,root,MPI_COMM_WORLD); MPI_Finalize(); return 0; } 31 Il gather in MPI MPI_Gather(void *send_buff, int send_count, MPI_Datatype datatype, void *recv_buff,int recv_count, MPI_Datatype recv_type, int root, MPI_Comm comm); Gli argomentirecv_ sono significativi solo per il processore root L argomento Largomentorecv_countrecv count è il numero di dati da ricevere da ogni processore, non è il numero totale dei dati da ricevere. 32 16
raccolta collettiva di tipo gather: #include <stdio.h> #include mpi.h int main(int argc, char *argv[]) { int menum, nproc; int a[nproc]; int a2; int root=0; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&nproc); MPI_Comm_rank(MPI_COMM_WORLD,&menum); a2=menum; if (menum==0) MPI_Gather(a2,1,MPI_INT,a,1,MPI_Int,root,MPI_COMM_WORLD); MPI_Finalize(); return 0; } 33 Il gather in MPI MPI_Gather(void *send_buff, int send_count, MPI_Datatype datatype, void *recv_buff,int recv_count, MPI_Datatype recv_type, int root, MPI_Comm comm); Ogni processore di comm spedisce il contenuto di *send_buff al processore con identificativo root Il processore con identificativo root concatena i dati ricevuti in recv_buff, memorizzando prima i dati ricevuti dal processore 0, poi i dati ricevuti dal processore 1, poi quelli ricevuti dal processore 2, etc 34 17
Se i dati sono di dimensione diversa MPI_SCATTERV MPI_GATHERV 35 Spedizione collettiva di tipo: all gather è equivalente ad un operazione di gather in cui successivamente il processo root (P 0 )esegue un broadcast è più conveniente ed efficiente che eseguire le due operazioni in sequenza all to all 36 18
Allgather in MPI: in dettaglio MPI_Allgather(void *send_buff, int send_count, MPI_Datatype sendtype, void *recv_buff,int recv_count, MPI_Datatype recv_type,mpi_comm comm); *send_buff indirizzo del dato da spedire send_count numero dei dati da spedire sendtype tipo dei dati da spedire *recv_buff indirizzo del riceive buffer recv_count numero di dati da ricevere da ogni processore recv_type comm tipo dei dati da ricevere identificativo del communicator 37 Le operazioni collettive. 38 19
Caratteristiche delle operazioni collettive Inoltre Le operazioni collettive sono eseguite da tutti i processori appartenenti ad un communicator. Tutti i processori che eseguono l operazione collettiva eseguono almeno una comunicazione. L operazione collettiva può richiedere una sincronizzazione. Tutte le operazioni collettive sono bloccanti. 39 Scopo delle operazioni collettive Le operazioni collettive permettono: La Sincronizzazione dei processori. L esecuzione dioperazioni globali (es. ricerca del massimo in un vettore distribuito fra i processori). Gestione ottimizzata i t degli input/output t t seguendo uno schema ad albero. 40 20
MPI_Barrier(MPI_COMM_WORLD); Ogni processore dell ambiente MPI_COMM_WORLD può procedere solo quando tutti gli altri avranno richiamato questa routine. P 0 Attende Esegue P P 2 1 Attende Esegue Attende Esegue Stop 41 Sincronizzazione dei processori : #include <stdio.h> #include mpi.h int main(int argc, char *argv[]) { MPI_Init(&argc,&argv); MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMMON_WORLD); MPI_Finalize(); } 42 21
In generale : MPI_Barrier(MPI_CommMPI_Comm comm); Questa routine fornisce un meccanismo sincronizzante per tutti i processori del communicator comm. Ogni processore si ferma fin quando tutti i processori di comm non n eseguono MPI_Barrier. 43 Operazioni di riduzione MPI possiede una classe di operazioni collettive chiamate operazioni di riduzione. In ciascuna operazione di riduzione tuttitti i processori di un communicator contribuiscono al risultato di un operazione. 44 22
Operazione collettiva : reduce 45 Un semplice programma : #include <stdio.h> #include mpi.h int main(int argc, char *argv[]) { int menum, nproc; int sum, sumtot; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&menum); MPI_Comm_size(MPI_COMM_WORLD,&nproc); sum=nproc; sumtot=0; sum+=menum; MPI_Reduce(&sum,&sumtot,1,MPI_INT,MPI_SUM,0, MPI_COMM_WORLD); printf( Sono %d sum=%d sumtot=%d\n,menum,sum,sumtot); } MPI_Finalize(); return 0; 46 23
Nel programma : MPI_Reduce(&sum,&sumtot,1,MPI_INT,MPI_SUM, 0, MPI_COMM_WORLD); Il processore P 0 otterrà la somma dei elementi sum, di tipo MPI_INT e di dimensione 1, distribuiti tra tutti i processori del communicator MPI_COMM_WORLD. Il risultato lo pone nella propria variabile sumtot. 47 Operazioni di Reduce : Le operazioni globali di Reduce sono implementate in maniera efficiente in quanto: 1) Ottimizzano le comunicazioni tra i processori del communicator coinvolto. Le comunicazioni vengono eseguite seguendo uno schema ad albero. 2) Sfruttano la proprietà associativa e/o la proprietà commutativa. 48 24
In Generale : MPI_Reduce(void *operand, void *result, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); Tutti i processori di comm combinano i propri dati memorizzati in *operand utilizzando l operazione op. Il risultato viene memorizzato in *result di proprietà del processore con identificativo root Count, datatype, comm devono essere uguali per ogni processore di comm. 49 In dettaglio : MPI_Reduce(void *operand, void *result, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); *operand indirizzo dei dati su cui effettuare l operazione. *result indirizzo del dato contenente il risultato. count numero dei dati su cui effettuare l operazione. datatype t tipo degli elementi da spedire. op operazione effettuata. root identificativo del processore che conterrà il risultato comm identificativo del communicator 50 25
Operazione collettiva: Reduce L argomento op, che descrive l operazione da eseguire sugli operandi operand, distribuiti fra i processori può essere scelto fra i seguenti valori predefiniti: MPI_MAX MPI_MIN Massimo di un vettore distribuito Minimo di un vettore distribuito MPI_SUM MPI_PROD Somma componente per componente fra vettori distribuiti Prodotto componente per componente fra vettori distribuiti 51 Operazione collettiva: Reduce MPI_MAXLOC MPI_MINLOCMINLOC Massimo e indice di un vettore Minimo e indice di un vettore combina coppie di valori (x i,ind i ) e restituisce (x,ind) x=max(min) x i, ind= corrispondente indice 52 26
Operazione collettiva : all reduce 53 Riduzione +replicazione : MPI_Allreduce(void *operand, void *result, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm); *operand indirizzo dei dati su cui effettuare l operazione. *result indirizzo del dato contenente il risultato. count numero dei dati su cui effettuare l operazione. datatype t tipo degli elementi da spedire. op operazione effettuata. comm identificativo del communicator 54 27
Si possono definire operatori ad-hoc MPI_Op_create 55 Misurare il tempo double MPI_Wtime(void void) 56 28
57 29