Calcul parallèle : 2023-2024 2ème Année Master M2 - SSI USTHB
Série d’exercices N° 3 (MPI)
EXO1 : Hello world Un premier programme MPI
.
Les processus Pi;i>0 envoient un message (chaîne de caractères) à P0
P0 recoit p - 1 messages et les affiche
Programmation SPMD (Single Program Multiple Data)
EXO 2 :
Ecrire un programme MPI où le processus 0 envoie un tableau au processus 1
EXO3 : – Utilisation de la fonction MPI_Bcast
Ecrire un programme MPI où le processus 0 diffuse un tableau T d’entiers de taille
100. Calculer le temps consommé.
EXO4 : – Diffusion en anneau sans MPI_Bcast
Utiliser MPI_Send et MPI_Recv.
Utiliser des fonctions de communications asynchrones MPI_Isend
EXO 5 : Ecrire un programme MPI où le processus 0 diffuse aux autres processus un
ensemble d’entiers contenant dans un fichier « para.dat »
EXO6 : Ecrire un programme MPI où chaque processus écrit dans son propre fichier.
EXO7. Ecrire un programme MPI où tous les processus écrivent dans le même
fichier.
1
Série d’exercices N° 3 (MPI)-Corrigé
EXO 1: Hello World (code C, initialisation)
#include <stdio.h>
#include "mpi.h"
main(int argc, char *argv[]) {
int my_rank; /* Rang du processus */
int p; /* Nombre de processus */
int source; /* Rang de l’emetteur */
int dest; /* Rang du recepteur */
int tag = 50; /* Tag des messages */
char message[100]; /* Allocation du message */
MPI_Status status; /* Valeur de retour pour le recepteur */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
Hello World (code C, corps)
if (my_rank != 0) {
/* Creation du message */
sprintf(message, "Hello from process %d!", my_rank);
dest = 0;
/* strlen + 1 => le ’\0’ final est envoye */
MPI_Send(message, strlen(message)+1, MPI_CHAR, dest,
tag, MPI_COMM_WORLD);
} else { /* my_rank == 0 */
for (source = 1; source < p; source++) {
MPI_Recv(message, 100, MPI_CHAR, source, tag,
MPI_COMM_WORLD, &status);
printf("%s\n", message);
}
}
MPI_Finalize();
} /* main */
EXO2:
Ecrire un programme MPI où le processus 0 envoie un tableau au processus 1
/* send.c
* processor 0 sends an array to processor 1
*
*/
#include <stdio.h>
#include "mpi.h"
#define NDIM 3
2
int main(int argc, char *argv[])
{
int rank, value, size, errcode=1, src=0, dest=1, i, f[NDIM];
MPI_Status status;
FILE *fp;
char fn[80];
MPI_Init(&argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, &rank);
MPI_Comm_size( MPI_COMM_WORLD, &size);
if (size > 2) MPI_Abort(MPI_COMM_WORLD, errcode);
/* initialize */
if (rank == 0) {
for (i=0; i<NDIM; i++) f[i] = i;
} else {
for (i=0; i<NDIM; i++) f[i] = 0;
}
sprintf(fn,"array%d.dat",rank);
fp = fopen(fn,"w");
fprintf(fp,"my rank = %d (BEFORE send/recv)\n",rank);
for (i=0; i<NDIM; i++) fprintf(fp,"f[%d]=%d\n",i,f[i]);
if (rank == src)
MPI_Send(f, NDIM, MPI_INT, dest, 0, MPI_COMM_WORLD);
if (rank == dest)
MPI_Recv(f, NDIM, MPI_INT, src, 0, MPI_COMM_WORLD, &status);
fprintf(fp,"my rank = %d (AFTER send/recv)\n",rank);
for (i=0; i<NDIM; i++) fprintf(fp,"f[%d]=%d\n",i,f[i]);
fclose(fp);
MPI_Finalize( );
return 0;
}
EXO3: – Utilisation de la fonction MPI_Bcast
Ecrire un programme MPI où le processus 0 diffuse un tableau T d’entiers de
taille 100. Calculer le temps consommé.
#include <stdio.h>
#include <mpi.h>
#include <sys/time.h>
int main(int argc, char **argv)
{
int nb_proc;
int my_id;
int next;
int T[100];
double start,end;
MPI_Init(&argc,&argv);
3
MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
if (my_id == nb_proc-1) next = 0;
else next = my_id+1;
if (my_id == 0) start = MPI_Wtime();
if (my_id == 0)
{ int i; for(i=0; i<100; i++) T[i]=i; }
MPI_Bcast(T, 100, MPI_INT, 0, MPI_COMM_WORLD);
if (my_id == 0) end = MPI_Wtime();
if (my_id == 0) printf("¸Ca m’a prit %8.6f\n",(end-start));
MPI_Finalize();
return (0);
}
EXO4 : – Diffusion en anneau sans MPI_Bcast
Utiliser MPI_Send et MPI_Recv.
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int nb_proc;
int my_id;
int next;
int T[100];
MPI_Status status;
double start,end;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
if (my_id == nb_proc-1) next = 0;
else next = my_id+1;
if (my_id == 0) start = MPI_Wtime();
if (my_id == 0) { int i; for(i=0; i<100; i++) T[i]=i;
MPI_Send(T, 100, MPI_INT, next, 666,
MPI_COMM_WORLD);
}
else
{
MPI_Recv(T, 100, MPI_INT, MPI_ANY_SOURCE, 666, MPI_COMM_WORLD,
&status);
if (my_id != nb_proc-1)
MPI_Send(T, 100, MPI_INT, next, 666, MPI_COMM_WORLD);
}
if (my_id == 0) end =MPI_Wtime();
if (my_id == 0)
printf("¸Ca m’a prit %8.6f ms\n",(end-start));
MPI_Finalize();
4
return (0);
}
Utiliser des fonctions de communications asynchrones MPI_Isend
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int nb_proc;
int my_id;
int next;
int T[100];
MPI_Status status;
MPI_Request request;
double start,end;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
if (my_id == nb_proc-1) next = 0;
else next = my_id+1;
if (my_id == 0) start = MPI_Wtime();
if (my_id == 0) {
int i;
for(i=0; i<100; i++) T[i]=i;
MPI_Isend(T, 100, MPI_INT, next, 666, MPI_COMM_WORLD,&request);
}
else
{
MPI_Recv(T, 100, MPI_INT, MPI_ANY_SOURCE, 666, MPI_COMM_WORLD, &status);
if (my_id != nb_proc-1)
MPI_Isend(T,100, MPI_INT, next, 666, MPI_COMM_WORLD,&request)
}
if (my_id == 0) end = MPI_Wtime();
if (my_id == 0) printf("¸Ca m’a prit %8.6f ms\n",(end-start));
MPI_Finalize();
return (0);
}
EXO5. Un programme MPI où le processus 0 diffuse aux processeurs un
ensemble d’entier contenant dans un fichier « para.dat »
/* bcast.c
* simple MPI_Bcast example
* read in an integer from a file (para.dat) and broadcast it to all
processes
*/
#include <stdio.h>
5
#include "mpi.h"
#define ROOT 0
int main(int argc, char *argv[])
{
int size, rank, x=0;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == ROOT) {
FILE *fp = fopen("para.dat","r");
fscanf(fp,"%d",&x); fclose(fp);
}
printf("(before) my rank = %d, x = %d\n", rank, x);
MPI_Bcast(&x, 1, MPI_INT, ROOT, MPI_COMM_WORLD);
printf("(after) my rank = %d, x = %d\n", rank, x);
MPI_Finalize();
return 0;
}
EXO6 : Ecrire un programme MPI où chaque processus écrit dans son propre
fichier.
/* filewritem.c
* MPI-IO: each process writes to a (different) file
*/
#include "mpi.h"
#include <stdio.h>
#define BUFSIZE 4
int main(int argc, char *argv[])
{
int i, rank, buf[BUFSIZE];
char fname[80];
MPI_File fh;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
for (i=0; i<BUFSIZE; i++)
buf[i] = rank*BUFSIZE + i;
sprintf(fname,"mydata.%d",rank);
printf("fname = %s\n",fname);
MPI_File_open(MPI_COMM_SELF, fname,
MPI_MODE_CREATE | MPI_MODE_WRONLY,
MPI_INFO_NULL, &fh);
MPI_File_write(fh, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
6
EXO7. Ecrire un programme MPI où tous les processus écrivent dans le même
fichier.
/* all processors write to a single file
*
*/
#include "mpi.h"
#include <stdio.h>
#define BUFSIZE 4
int main(int argc, char *argv[])
{
int i, rank, buf[BUFSIZE];
MPI_File fh;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
for (i=0; i<BUFSIZE; i++)
buf[i] = rank*BUFSIZE + i;
MPI_File_open(MPI_COMM_WORLD, "mydata",
MPI_MODE_CREATE | MPI_MODE_WRONLY,
MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, rank*BUFSIZE*sizeof(int),
MPI_INT, MPI_INT,"native", MPI_INFO_NULL);
MPI_File_write(fh, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}