-
-
Save rehrumesh/b103636b6337baafb52f to your computer and use it in GitHub Desktop.
/********************************************************************** | |
* MPI-based matrix multiplication AxB=C | |
*********************************************************************/ | |
#include <stdio.h> | |
#include "mpi.h" | |
#define N 4 /* number of rows and columns in matrix */ | |
MPI_Status status; | |
double a[N][N],b[N][N],c[N][N]; | |
main(int argc, char **argv) | |
{ | |
int numtasks,taskid,numworkers,source,dest,rows,offset,i,j,k; | |
struct timeval start, stop; | |
MPI_Init(&argc, &argv); | |
MPI_Comm_rank(MPI_COMM_WORLD, &taskid); | |
MPI_Comm_size(MPI_COMM_WORLD, &numtasks); | |
numworkers = numtasks-1; | |
/*---------------------------- master ----------------------------*/ | |
if (taskid == 0) { | |
for (i=0; i<N; i++) { | |
for (j=0; j<N; j++) { | |
a[i][j]= 1.0; | |
b[i][j]= 2.0; | |
} | |
} | |
gettimeofday(&start, 0); | |
/* send matrix data to the worker tasks */ | |
rows = N/numworkers; | |
offset = 0; | |
for (dest=1; dest<=numworkers; dest++) | |
{ | |
MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); | |
MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); | |
MPI_Send(&a[offset][0], rows*N, MPI_DOUBLE,dest,1, MPI_COMM_WORLD); | |
MPI_Send(&b, N*N, MPI_DOUBLE, dest, 1, MPI_COMM_WORLD); | |
offset = offset + rows; | |
} | |
/* wait for results from all worker tasks */ | |
for (i=1; i<=numworkers; i++) | |
{ | |
source = i; | |
MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); | |
MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); | |
MPI_Recv(&c[offset][0], rows*N, MPI_DOUBLE, source, 2, MPI_COMM_WORLD, &status); | |
} | |
gettimeofday(&stop, 0); | |
printf("Here is the result matrix:\n"); | |
for (i=0; i<N; i++) { | |
for (j=0; j<N; j++) | |
printf("%6.2f ", c[i][j]); | |
printf ("\n"); | |
} | |
fprintf(stdout,"Time = %.6f\n\n", | |
(stop.tv_sec+stop.tv_usec*1e-6)-(start.tv_sec+start.tv_usec*1e-6)); | |
} | |
/*---------------------------- worker----------------------------*/ | |
if (taskid > 0) { | |
source = 0; | |
MPI_Recv(&offset, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status); | |
MPI_Recv(&rows, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status); | |
MPI_Recv(&a, rows*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status); | |
MPI_Recv(&b, N*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status); | |
/* Matrix multiplication */ | |
for (k=0; k<N; k++) | |
for (i=0; i<rows; i++) { | |
c[i][k] = 0.0; | |
for (j=0; j<N; j++) | |
c[i][k] = c[i][k] + a[i][j] * b[j][k]; | |
} | |
MPI_Send(&offset, 1, MPI_INT, 0, 2, MPI_COMM_WORLD); | |
MPI_Send(&rows, 1, MPI_INT, 0, 2, MPI_COMM_WORLD); | |
MPI_Send(&c, rows*N, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD); | |
} | |
MPI_Finalize(); | |
} |
This is easy to catch.
Is there any optimisation involved in changing the nesting structure of loops?
for (i=0; i<rows; i++) {
for (j=0; j<N; j++) {
c[i][j] = 0.0;
for (k=0; k<N; k++)
c[i][j] = c[i][j] + a[i][k] * b[k][j];
}
}
You can pass 2D arrays like this as they are not guaranteed to be continuous...
This code has a lot of issues....multiplication does not take offsets into account
Ayiya,
How does the slaves get the 2D array c ?
Does the master and slaves has different c arrays or are they all reference to same ?
the Code is correct. Please add following Includes to the top of the code:
#include <time.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
The multiplication does not need to take offset into account.
Each process receives a full copy of the empty array "c".
Each process puts their own multiplication into c, and returns.
Then in the main process, it is decided where to "save" this version of c, into the master version of c (this is the ultimate, final version).
Mas ini pake bahasa apa yah menjalankan programnya