Il cluster che usiamo: spaci Esercitazione: Primi Programmi con MPI http://www.na.icar.cnr.it/grid/#spacina Spacina è un cluster HP XC 6000 / Linux a 64 nodi biprocessore. La configurazione hardware dei nodi è la seguente: CPU Intel Itanium 2, Madison - 1.4 Ghz Memory 4GB RAM, PC2100 ECC registered DDR266 SDRAM Frontside Bus 200 MHz Chipset HP zx1 chipset Graphic ATI Radeon 7000 Network Interface Card Quadrics QsNetII Elan4 Network Adapter, 2 Broadcom Corporation NetXtreme BCM5701 Gigabit Ethernet, Intel Fast Ethernet Corp. 82557 Il cluster che usiamo: spaci http://www.na.icar.cnr.it/grid/#spacina Spacina è un cluster HP XC 6000 / Linux a 64 nodi biprocessore. La configurazione hardware dei nodi è la seguente: La rete di interconnessione principale è Quadrics QsNetII Elan 4. Sistema operativo Linux for High Performance Computing 3 (basato su Red Hat Enterprise Linux AS 3) Kernel Linux 2.4.21 Librerie C GNU libc 2.3.2 Primo Programma MPI: Hello World Spostarsi sotto la dir cognome (altrimenti crearla con mkdir cognome) cd cognome Copiare il file hello.c dalla home lauranto: cp /home3/lauranto/ceinge/hellompi.c. Definizione di alcune variabili per l ambiente MPI: module load hptc Compilazione mpicc c hellompi.c Generazione dell eseguibile mpicc o hellompi.exe hellompi.o (spazio, punto!!) Primi Programmi con MPI 1
Esecuzione mediante uno scheduler: LSF L'esecuzione di programmi sul cluster spaci.na.icar.cnr.it prevede l'utilizzo del resource manager LSF il quale fornisce le seguenti funzionalità: regola l'accesso ai nodi del cluster fornisce un'infrastruttura per l'esecuzione ed il monitoraggio dei programmi amministra code di job selezionando l'esecuzione di applicazioni in attesa Load Sharing Facility Esecuzione mediante uno scheduler: LSF Comando per la sottomissione di un programma, bsub bsub -o output.txt -n 2 mpirun -srun./hellompi.exe Opzioni di bsub -o nome file dove scrivere i dati di output -n numero dei processori da utilizzare -srun opzione per i programmi MPI Altre opzioni: -i nome file dove sono scritti i dati di input -e nome file dove scrivere gli (eventuali) errori di esecuzione bsub -i input.txt -e errori.txt -o output.txt -n 2 mpirun -srun./hellompi.exe Esecuzione mediante uno scheduler: LSF Esecuzione mediante uno scheduler: LSF Monitoraggio dei jobs, bjobs ceinge1@n64 ceinge1]> bjobs Visualizzazione del file di output ceinge1@n64 ceinge1]> vi output.txt JOBID USER STAT QUEUE FROM_HOST EXEC_ HOST JOB_NAME SUBMIT_TIME <423443> lauranto PEND Normal lsfhost.loc *sum.exe Feb 25 11:00 <423444> ceinge1 RUN Normal lsfhost.loc *hello.exe Feb 25 10:59 JOBID USER STAT QUEUE FROM_HOST EXEC_ HOST JOB_NAME SUBMIT_TIME <423443> lauranto PEND Normal lsfhost.loc *sum.exe Feb 25 11:00 <423444> ceinge1 RUN Normal lsfhost.loc *hello.exe Feb 25 10:59 Se il job è terminato verrà restituito all utente il messaggio ceinge1@n64 ceinge1]> bjobs No unfinished jobs Per eliminare un job in coda, bkill ceinge1@n64 ceinge1]> bkill 423443 Primi Programmi con MPI 2
Esercizio 1: messaggio di tipo broadcast Scrivere un programma che assegnato un intero, spedisca tale valore a tutti gli altri processi MPI Funzioni MPI da utilizzare: MPI_Init MPI_Comm_rank MPI_Comm_size MPI_Bcast MPI_Finalize Copiare la bozza di programma con il comando cp /home3/lauranto/ceinge/mpibcast.c. (spazio, punto!!) #include <stdio.h> #include "mpi.h" int main( int argc, char **argv ){ int rank, nproc, value; Esercizio 1: messaggio di tipo broadcast MPI_Init( COMPLETA ); MPI_Comm_rank( COMPLETA, &rank); MPI_Comm_size( COMPLETA ); if (rank == 0) { value = 100; printf( Valore intero da spedire %d \n, value); MPI_Bcast( &value, COMPLETA, MPI_COMM_WORLD ); printf( "Processo %d di %d ricevuto %d\n", rank, nproc, value ); MPI_Finalize( ); return 0; Bozza programma Prototipi funzioni MPI_Comm_rank(MPI_Comm comm, int *rank); MPI_Comm_size(MPI_Comm comm, int *nproc); MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm); Esercizio 1: messaggio di tipo broadcast Scrivere un programma che assegnato un intero, spedisca tale valore a tutti gli altri processi MPI Compilazione e generazione eseguibile mpicc -c mpibcast.c mpicc -o bcast.exe mpibcast.o Scrivere un programma in cui la prima metà di nproc processi comunica il proprio identificativo (rank) alla seconda metà secondo il seguente schema nproc = 8 Sottomissione mediante LSF bsub -o out2.txt -n 2 mpirun -srun./bcast.exe Visualizzazione dell output vi out2.txt P 0 P 1 P 2 P 3 P 4 P 5 P 6 P 7 Primi Programmi con MPI 3
Scrivere un programma in cui la prima metà di nproc processi comunica il proprio identificativo (rank) alla seconda metà secondo il seguente schema Funzioni MPI da utilizzare: MPI_Init MPI_Comm_rank MPI_Comm_size MPI_Send MPI_Recv MPI_Finalize Copiare la bozza di programma con il comando cp /home3/lauranto/ceinge/sendrecv.c. (spazio, punto!!). #define MASTER 0 int main (int argc, char **argv){ int nproc, rank, len; char hostname[mpi_max_processor_name]; int partner, message; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size(COMPLETA); MPI_Comm_rank(COMPLETA); MPI_Get_processor_name(hostname, &len); printf ("Hello from task %d on %s!\n", rank, hostname); if (rank == MASTER) printf("master: Number of MPI tasks is: %d\n",numtasks); Bozza programma 1/2 /* calcolo del partner e spedizione/ricezione con il processo partner associato */ if (taskid < numtasks/2) { partner = numtasks/2 + taskid; MPI_Send(COMPLETA, partner, 1, MPI_COMM_WORLD); else if (taskid >= numtasks/2) { partner = taskid - numtasks/2; MPI_Recv(COMPLETA, &status); /* Stampa del risultato */ printf("il processo %d ha partner il processo %d\n",taskid,message); MPI_Finalize(); Bozza programma 2/2 MPI_Send(void *buffer, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); MPI_Recv(void *buffer, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Status *status); Scrivere un programma in cui la prima metà di nproc processi comunica il proprio identificativo (rank) alla seconda metà secondo il seguente schema Compilazione e generazione eseguibile mpicc -c sendrecv.c mpicc -o sr.exe sendrecv.o Sottomissione mediante LSF bsub -o out3.txt -n 2 mpirun -srun./sr.exe Visualizzazione dell output vi out3.txt Primi Programmi con MPI 4
Esercizio 3: Modificare il programma sendrecv.c in modo che la prima metà di nproc processi si scambia il valore del proprio identificativo (rank) con la seconda metà secondo il seguente schema nproc = 8 Scrivere un programma che esegue la somma di n numeri secondo il seguente schema nproc = 4 P 0 P 1 P 2 P 3 s 0 s 1 s 2 s 3 P 0 P 4 sumtot=s 0 + s 1 P 1 P 5 P 2 P 6 sumtot=sumtot + s 2 P 3 P 7 sumtot=sumtot + s 3 Scrivere un programma che esegue la somma di n numeri Funzioni MPI da utilizzare: MPI_Init MPI_Comm_rank MPI_Comm_size MPI_Gather MPI_Send MPI_Recv MPI_Finalize Copiare la bozza di programma con il comando cp /home3/lauranto/ceinge/somma_istrat.c. (spazio, punto!!) Bozza programma 1/3 /* ----------------------- 1) fase di input -----------------------------------------------------*/ if (menum==0){ n=100; printf( numero addendi %d\n,n); vet=(float*)calloc(n,sizeof(float)); /* solo menum0 alloca memoria per vet */ for (i=0;i<n;i++) vet[i]=(float)i +1; MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); Nloc=n/nproc; Vetloc=(float*)calloc(nloc, sizeof(float)); MPI_Scatter(vet,nloc,MPI_FLOAT,vetloc,nloc,MPI_FLOAT,0,MPI_COMM_WORLD); Primi Programmi con MPI 5
Bozza programma 2/3 /* ----------------------- 2) fase di calcolo -----------------------------------------------------*/ sum=0; for(i=0;i<nloc;i++) sum+=vetloc[i]; /* sum=sum+vetloc[i] */ /* ----------------------- 3) fase di comunicazione ---------------------------------------------*/ if(menum!=0) { tag=menum; MPI_Send(&sum,1,MPI_FLOAT,0,tag,MPI_COMM_WORLD); else for(i=1;i<nproc;i++){ tag=i; MPI_Recv(&stemp,1,MPI_FLOAT,i,tag,MPI_COMM_WORLD,&info); sum+=stemp; /* ----------------------- 4) fase di output ---------------------------------------------*/ if(menum==0) printf("la somma totale vale %f\n",sum); MPI_Finalize(); return 0; Bozza programma 3/3 Scrivere un programma che esegue la somma di n numeri Fine Compilazione e generazione eseguibile mpicc -c somma_istrat.c mpicc -o sum.exe somma_istrat.o Sottomissione mediante LSF bsub -o outsum.txt -n 2 mpirun -srun./sr.exe Visualizzazione dell output vi outsum.txt Utilizzare un numero di processori divisore di 100 Primi Programmi con MPI 6