[go: up one dir, main page]

0% found this document useful (0 votes)
143 views8 pages

CSE4001 Parallel and Distributed Computing: Lab Assignment 6

This document describes an MPI program to distribute a matrix multiplication operation across multiple tasks. The master task initializes the matrices, distributes rows of one matrix and all of another matrix to worker tasks, collects the results from the workers, and prints the output. Worker tasks receive matrix data, perform their portion of the multiplication, and send the results back to the master.

Uploaded by

Sukriti Jaitly
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
143 views8 pages

CSE4001 Parallel and Distributed Computing: Lab Assignment 6

This document describes an MPI program to distribute a matrix multiplication operation across multiple tasks. The master task initializes the matrices, distributes rows of one matrix and all of another matrix to worker tasks, collects the results from the workers, and prints the output. Worker tasks receive matrix data, perform their portion of the multiplication, and send the results back to the master.

Uploaded by

Sukriti Jaitly
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

CSE4001

PARALLEL AND DISTRIBUTED COMPUTING

ANUKRITI JAIN
17BCE0519

LAB ASSIGNMENT 6
Using MPI, Design, develop and run matrix multiplication
using MPI_Send and MPI_Recv. In this code, the master task
distributes a matrix multiply operation to numtasks-1 worker
tasks.
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

#define NRA 30 /* number of rows in matrix A */


#define NCA 15 /* number of columns in matrix A */
#define NCB 7 /* number of columns in matrix B */
#define MASTER 0 /* taskid of first task */
#define FROM_MASTER 1 /* setting a message type */
#define FROM_WORKER 2 /* setting a message type */

int main (int argc, char *argv[])


{
int numtasks, /* number of tasks in partition */
taskid, /* a task identifier */
numworkers, /* number of worker tasks */
source, /* task id of message source */
dest, /* task id of message destination */
mtype, /* message type */
rows, /* rows of matrix A sent to each worker */
averow, extra, offset, /* used to determine rows sent to each worker */
i, j, k, rc; /* misc */
double a[NRA][NCA], /* matrix A to be multiplied */
b[NCA][NCB], /* matrix B to be multiplied */
c[NRA][NCB]; /* result matrix C */
MPI_Status status;

MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
if (numtasks < 2 ) {
printf("Need at least two MPI tasks. Quitting...\n");
MPI_Abort(MPI_COMM_WORLD, rc);
exit(1);
}
numworkers = numtasks-1;

/**************************** master task ************************************/


if (taskid == MASTER)
{
printf("mpi_mm has started with %d tasks.\n",numtasks);
printf("Initializing arrays...\n");
for (i=0; i<NRA; i++)
for (j=0; j<NCA; j++)
a[i][j]= i+j;
for (i=0; i<NCA; i++)
for (j=0; j<NCB; j++)
b[i][j]= i*j;

/* Send matrix data to the worker tasks */


averow = NRA/numworkers;
extra = NRA%numworkers;
offset = 0;
mtype = FROM_MASTER;
for (dest=1; dest<=numworkers; dest++)
{
rows = (dest <= extra) ? averow+1 : averow;
printf("Sending %d rows to task %d offset=%d\n",rows,dest,offset);
MPI_Send(&offset, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&a[offset][0], rows*NCA, MPI_DOUBLE, dest, mtype,
MPI_COMM_WORLD);
MPI_Send(&b, NCA*NCB, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
offset = offset + rows;
}

/* Receive results from worker tasks */


mtype = FROM_WORKER;
for (i=1; i<=numworkers; i++)
{
source = i;
MPI_Recv(&offset, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&c[offset][0], rows*NCB, MPI_DOUBLE, source, mtype,
MPI_COMM_WORLD, &status);
printf("Received results from task %d\n",source);
}

/* Print results */
printf("******************************************************\n");
printf("Result Matrix:\n");
for (i=0; i<NRA; i++)
{
printf("\n");
for (j=0; j<NCB; j++)
printf("%6.2f ", c[i][j]);
}
printf("\n******************************************************\n");
printf ("Done.\n");
}

/**************************** worker task ************************************/


if (taskid > MASTER)
{
mtype = FROM_MASTER;
MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&a, rows*NCA, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD,
&status);
MPI_Recv(&b, NCA*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD,
&status);

for (k=0; k<NCB; k++)


for (i=0; i<rows; i++)
{
c[i][k] = 0.0;
for (j=0; j<NCA; j++)
c[i][k] = c[i][k] + a[i][j] * b[j][k];
}
mtype = FROM_WORKER;
MPI_Send(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&c, rows*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD);
}
MPI_Finalize();
}
Using MPI, Design, develop and compute pi value using MPI_Send and
MPI_Recv.
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

void srandom (unsigned seed);


double dboard (int darts);
#define DARTS 50000 /* number of throws at dartboard */
#define ROUNDS 100 /* number of times "darts" is iterated */
#define MASTER 0 /* task ID of master task */

int main (int argc, char *argv[])


{
double homepi, /* value of pi calculated by current task */
pi, /* average of pi after "darts" is thrown */
avepi, /* average pi value for all iterations */
pirecv, /* pi received from worker */
pisum; /* sum of workers pi values */
int taskid, /* task ID - also used as seed number */
numtasks, /* number of tasks */
source, /* source of incoming message */
mtype, /* message type */
rc, /* return code */
i, n;
MPI_Status status;

/* Obtain number of tasks and task ID */


MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
printf ("MPI task %d has started...\n", taskid);

/* Set seed for random number generator equal to task ID */


srandom (taskid);

avepi = 0;
for (i = 0; i < ROUNDS; i++) {
/* All tasks calculate pi using dartboard algorithm */
homepi = dboard(DARTS);

/* Workers send homepi to master */


/* - Message type will be set to the iteration count */
if (taskid != MASTER) {
mtype = i;
rc = MPI_Send(&homepi, 1, MPI_DOUBLE,
MASTER, mtype, MPI_COMM_WORLD);
}
else
{
/* Master receives messages from all workers */
/* - Message type will be set to the iteration count */
/* - Message source will be set to the wildcard DONTCARE: */
/* a message can be received from any task, as long as the */
/* message types match */
/* - The return code will be checked, and a message displayed */
/* if a problem occurred */
mtype = i;
pisum = 0;
for (n = 1; n < numtasks; n++) {
rc = MPI_Recv(&pirecv, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
mtype, MPI_COMM_WORLD, &status);
/* keep running total of pi */
pisum = pisum + pirecv;
}
/* Master calculates the average value of pi for this iteration */
pi = (pisum + homepi)/numtasks;
/* Master calculates the average value of pi over all iterations */
avepi = ((avepi * i) + pi)/(i + 1);
printf(" After %8d throws, average value of pi = %10.8f\n",
(DARTS * (i + 1)),avepi);
}
}

if (taskid == MASTER)
printf ("\nReal value of PI: 3.1415926535897 \n");

MPI_Finalize();
return 0;
}

double dboard(int darts)


{
#define sqr(x) ((x)*(x))
long random(void);
double x_coord, y_coord, pi, r;
int score, n;
unsigned int cconst; /* must be 4-bytes in size */
/*************************************************************************
* The cconst variable must be 4 bytes. We check this and bail if it is
* not the right size
************************************************************************/
if (sizeof(cconst) != 4) {
printf("Wrong data size for cconst variable in dboard routine!\n");
printf("See comments in source file. Quitting.\n");
exit(1);
}
/* 2 bit shifted to MAX_RAND later used to scale random number between 0 and 1 */
cconst = 2 << (31 - 1);
score = 0;

/* "throw darts at board" */


for (n = 1; n <= darts; n++) {
/* generate random numbers for x and y coordinates */
r = (double)random()/cconst;
x_coord = (2.0 * r) - 1.0;
r = (double)random()/cconst;
y_coord = (2.0 * r) - 1.0;

/* if dart lands in circle, increment score */


if ((sqr(x_coord) + sqr(y_coord)) <= 1.0)
score++;
}

/* calculate pi */
pi = 4.0 * (double)score/(double)darts;
return(pi);
}

You might also like