parsort.c
/*****************************************************************/
/* */
/* Tri parallèle pair / impair en MPI */
/* */
/*****************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <mpi.h>
#include <string.h>
#define MAX_SIZE 40
#define LOGIN_SIZE 9 /* les chaînes sont AZT donc il vaut mieux un caractère de plus... */
#define BUFFER_LEN 256
#define ODD 666
#define EVEN 667
typedef struct {
char login[LOGIN_SIZE];
int uid;
int gid;
char name[MAX_SIZE];
} identifiant_t;
MPI_Datatype MPI_IDENTIFIANT_T;
int my_id, nb_proc;
void affiche(identifiant_t tab[], int nb)
{
int i;
for(i=0 ; i<nb ; i++)
printf("%s %d %d %s\n",
tab[i].login,
tab[i].uid,
tab[i].gid,
tab[i].name);
}
void affiche_local(int tag,identifiant_t tab[], int nb)
{
int i;
printf("\t P%d, étape %d\t", my_id,tag);
for(i=0 ; i<nb; i++)
printf("%d ",tab[i].uid);
printf("\n");
fflush(stdout);
}
int compare_uid(const void *a, const void *b)
{
if(((identifiant_t *)a)->uid < ((identifiant_t *)b)->uid) return -1;
else if(((identifiant_t *)a)->uid ==((identifiant_t *)b)->uid) return 0;
else return 1;
}
void begin_odd(identifiant_t *tab, int taille)
{
MPI_Status status;
if(my_id%2==1) { if(my_id!=nb_proc-1)
MPI_Recv(tab+taille,taille,MPI_IDENTIFIANT_T,my_id+1,ODD,MPI_COMM_WORLD,&status); }
else { if(my_id!=0)
MPI_Send(tab,taille,MPI_IDENTIFIANT_T,my_id-1,ODD,MPI_COMM_WORLD); }
}
void begin_even(identifiant_t *tab, int taille)
{
MPI_Status status;
if(my_id%2==0) { if(my_id!=nb_proc-1)
MPI_Recv(tab+taille,taille,MPI_IDENTIFIANT_T,my_id+1,EVEN,MPI_COMM_WORLD,&status); }
else { if(my_id!=0)
MPI_Send(tab,taille,MPI_IDENTIFIANT_T,my_id-1,EVEN,MPI_COMM_WORLD); }
}
void end_odd(identifiant_t *tab, int taille)
{
MPI_Status status;
if(my_id%2==1) { if(my_id!=nb_proc-1)
MPI_Send(tab+taille,taille,MPI_IDENTIFIANT_T,my_id+1,ODD,MPI_COMM_WORLD); }
else { if(my_id!=0)
MPI_Recv(tab,taille,MPI_IDENTIFIANT_T,my_id-1,ODD,MPI_COMM_WORLD,&status); }
}
void end_even(identifiant_t *tab, int taille)
{
MPI_Status status;
if(my_id%2==0) { if(my_id!=nb_proc-1)
MPI_Send(tab+taille,taille,MPI_IDENTIFIANT_T,my_id+1,EVEN,MPI_COMM_WORLD); }
else { if(my_id!=0)
MPI_Recv(tab,taille,MPI_IDENTIFIANT_T,my_id-1,EVEN,MPI_COMM_WORLD,&status); }
}
void odd_even(identifiant_t *tab, int taille)
{
int i;
MPI_Barrier(MPI_COMM_WORLD);
/* printf("\n"); */
for(i=0; i<nb_proc ; i++) {
if(i%2==1) { /* impaire */
begin_odd(tab,taille);
if((my_id%2==1)&&(my_id!=nb_proc-1)) qsort(tab,2*taille,sizeof(identifiant_t),compare_uid) ;
end_odd(tab,taille);
} else { /* paire */
begin_even(tab,taille);
if((my_id%2==0)&&(my_id!=nb_proc-1)) qsort(tab,2*taille,sizeof(identifiant_t),compare_uid) ;
end_even(tab,taille);
}
/* affiche_local(i,tab,taille); */
}
}
void mpi_types_initialize()
{
int count=4;
int struct_length[4]= {LOGIN_SIZE, 1, 1, MAX_SIZE};
MPI_Aint struct_offset[4];
MPI_Datatype struct_types[4];
identifiant_t id;
int i;
MPI_Address( &id.login, &struct_offset[0]) ;
MPI_Address( &id.uid, &struct_offset[1]) ;
MPI_Address( &id.gid, &struct_offset[2]) ;
MPI_Address( &id.name, &struct_offset[3]) ;
struct_types[0] = MPI_CHAR ;
struct_types[1] = MPI_INT ;
struct_types[2] = MPI_INT ;
struct_types[3] = MPI_CHAR ;
for(i=3 ; i>=0 ; i--) {
struct_offset[i] -= struct_offset[0];
}
MPI_Type_struct( count, struct_length, struct_offset, struct_types, &MPI_IDENTIFIANT_T );
MPI_Type_commit( &MPI_IDENTIFIANT_T );
}
void parse(char *filename, identifiant_t *tab[], int *nb)
{
FILE *input=fopen(filename,"r");
char buffer[BUFFER_LEN];
char *login;
char *uid;
char *gid;
char *name;
int i=0;
if (!input) {
fprintf(stderr,"Erreur d'ouverture de %s\n",filename);
exit(1);
}
fgets(buffer,BUFFER_LEN,input);
sscanf(buffer,"%d",nb);
*tab=calloc(*nb,sizeof(identifiant_t));
while (fgets(buffer,BUFFER_LEN,input))
{
login = strtok(buffer,"|\n");
uid = strtok(NULL,"|\n");
gid = strtok(NULL,"|\n");
name = strtok(NULL,"|\n");
strcpy((*tab)[i].login,login);
(*tab)[i].uid = atoi(uid);
(*tab)[i].gid = atoi(gid);
strcpy((*tab)[i].name,name);
i++;
}
}
int main(int argc, char **argv)
{
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
/* printf("Je suis le processus P%d et nous sommes %d au total.\n", */
/* my_id, nb_proc); */
mpi_types_initialize();
{
identifiant_t *tab;
identifiant_t *to_sort;
int nb,taille;
if(my_id==0) parse(argv[1],&tab,&nb);
MPI_Bcast(&nb, 1, MPI_INT, 0, MPI_COMM_WORLD);
taille = nb/nb_proc;
to_sort=calloc(2*(taille),sizeof(identifiant_t));
MPI_Scatter(tab, taille, MPI_IDENTIFIANT_T,
to_sort,taille, MPI_IDENTIFIANT_T,
0, MPI_COMM_WORLD);
/* affiche_local(-1,to_sort,taille); */
odd_even(to_sort,taille);
MPI_Gather (to_sort, taille, MPI_IDENTIFIANT_T,
tab,taille, MPI_IDENTIFIANT_T,
0, MPI_COMM_WORLD);
if(my_id==0) affiche(tab,taille*nb_proc);
}
MPI_Finalize();
return (0);
}
Generated by GNU enscript 1.6.2.