Skip to content

Instantly share code, notes, and snippets.

@rehrumesh
Created May 31, 2015 13:37
Show Gist options
  • Save rehrumesh/b103636b6337baafb52f to your computer and use it in GitHub Desktop.
Save rehrumesh/b103636b6337baafb52f to your computer and use it in GitHub Desktop.
Matrix multiplication using MPI
/**********************************************************************
* 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();
}
@prakhar987
Copy link

This code has a lot of issues....multiplication does not take offsets into account

@malshanucsc
Copy link

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 ?

@SamToorchi
Copy link

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>

@SaadBazaz
Copy link

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment