matmult.c
/*****************************************************************/
/* */
/* Produit de matrice par double diffusion */
/* */
/*****************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <mpi.h>
#include <math.h>
/******* Fonctions d'affichage ***********/
#define VOIRD(expr) do {printf("P%d (%d,%d) <%.3d> : \t{ " #expr " = %d }\n", \
my_id,i_row,i_col,__LINE__,expr);} while(0)
#define PRINT_MESSAGE(expr) do {printf("P%d (%d,%d) <%.3d> : \t" #expr "\n", \
my_id,i_row,i_col,__LINE__);} while(0)
typedef struct {
int row; /* le nombre de lignes */
int col; /* le nombre de colonnes */
int* data; /* les valeurs */
} matrix_t;
int my_id, nb_proc;
int nb_col,nb_row; /* Largeur et hauteur de la grille */
MPI_Comm MPI_HORIZONTAL; /* Communicateur pour diffusions horizontales */
MPI_Comm MPI_VERTICAL; /* Communicateur pour diffusions verticales */
int i_col,i_row; /* Position dans la grille */
/*******************************************/
/* initialisation aléatoire de la matrice */
/*******************************************/
void mat_init_alea(matrix_t *mat,int width, int height)
{
int i;
mat->row = height;
mat->col = width;
mat->data=(int*)malloc(sizeof(int)*height*width);
for(i=0 ; i<height*width ; i++)
mat->data[i]=rand()%2;
}
/*******************************************/
/* initialisation à 0 de la matrice */
/*******************************************/
void mat_init_empty(matrix_t *mat,int width, int height)
{
mat->row = height;
mat->col = width;
mat->data=(int*)calloc((mat->row)*(mat->col),sizeof(int));
}
/*******************************************/
/* affichage de la matrice */
/*******************************************/
void mat_display(matrix_t A)
{
int i,j,t=0;
printf(" ");
for(j=0;j<A.col;j++)
printf("%.3d ",j);
printf("\n");
printf(" __");
for(j=0;j<A.col;j++)
printf("____");
printf("_\n");
for(i=0;i<A.row;i++)
{
printf("%.3d | ",i);
for(j=0;j<A.col;j++)
/*printf("%d ",A.data[i*A.row+j]);*/
printf("%.3d ",A.data[t++]);
printf("|\n");
}
printf(" --");
for(j=0;j<A.col;j++)
printf("----");
printf("-\n");
}
/*******************************************/
/* C+=A*B */
/*******************************************/
void mat_mult(matrix_t A, matrix_t B, matrix_t C)
{
int i,j,k,M,N,K,*_A,*_B,*_C;
_A=A.data;
_B=B.data;
_C=C.data;
M = C.row;
N = C.col;
K = A.col;
if((M!=A.row) || (N!=B.col) || (K!=B.row)) {
PRINT_MESSAGE("Attention, tailles incompatibles");
VOIRD(A.row);VOIRD(A.col);VOIRD(B.row);
VOIRD(C.col);VOIRD(C.row);VOIRD(C.col);
exit(1);
}
for(i=0 ; i<M ; i++)
for(j=0 ; j<N ; j++)
for(k=0 ; k<K ; k++)
_C[i*N+j]+=_A[i*K+k]*_B[k*N+j];
}
/*******************************************/
/* Initialisations la grille */
/*******************************************/
void init_communicateurs()
{
int i;
nb_col=nb_proc; nb_row=1;
/* Améliorez la disposition */
for(i=sqrt(nb_proc); i>=1 ; i--)
if (nb_proc%i==0) {
nb_row=i; nb_col=nb_proc/nb_row; break;
}
i_col = my_id % nb_col;
i_row = my_id / nb_col;
/* Partitionnez MPI_COMM_WORLD en communicateurs pour les lignes
et en communicateurs pour les colonnes */
MPI_Comm_split( MPI_COMM_WORLD, i_row, i_col, &MPI_HORIZONTAL );
MPI_Comm_split( MPI_COMM_WORLD, i_col, i_row, &MPI_VERTICAL );
/* Vérifiez que votre rang dans le nouveau communicateur
correspond bien à celui que vous attendez. */
MPI_Comm_rank(MPI_HORIZONTAL,&i_col);
MPI_Comm_rank(MPI_VERTICAL,&i_row);
}
/*******************************************/
/* Produit de matrice par double diffusion */
/*******************************************/
void parallel_mat_mult(matrix_t A, matrix_t B, matrix_t C)
{
matrix_t buf_col, buf_row;
int k;
mat_init_empty(&buf_col,1,C.row);
mat_init_empty(&buf_row,C.col,1);
for(k=0; k<(nb_col*C.col) ; k++) {
/* diffusion horizontale */
if(k/A.col == i_col) {
int i;
for(i=0;i<C.row;i++)
buf_col.data[i]=A.data[i*A.col+(k%A.col)];
}
MPI_Bcast(buf_col.data, C.row, MPI_INT, k/A.col, MPI_HORIZONTAL);
/* diffusion verticale */
if(k/B.row == i_row) {
int j;
for(j=0;j<C.col;j++)
buf_row.data[j]=B.data[(k%B.row)*B.col+j];
}
MPI_Bcast(buf_row.data, C.col, MPI_INT, k/B.row, MPI_VERTICAL);
/* produit de matrices en local */
mat_mult(buf_col, buf_row,C);
}
}
int main(int argc, char **argv)
{
int taille;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
if(argc==0)
fprintf(stderr,"Usage : %s <taille de matrice>",argv[0]);
else
taille = atoi(argv[1]);
init_communicateurs();
{
matrix_t A,B,C;
mat_init_alea(&A,taille/nb_col,taille/nb_row);
mat_init_alea(&B,taille/nb_col,taille/nb_row);
mat_init_empty(&C,taille/nb_col,taille/nb_row);
/* parallel_mat_mult(A,B,C); */
if(my_id==0) mat_display(C);
}
MPI_Finalize();
return (0);
}
Generated by GNU enscript 1.6.3.