|
Example: Autonomic Parallel Matrix Multiplication
mm.c
/********************************************************
The following six lines are example statements that
will be dynamically added to complete the program.
The program will then be used as an agent code to
compose a mobile agent that will be sent to a
corresponding agency.
putenv("PMI_ROOT_HOST=shrimp.engr.ucdavis.edu");
putenv("PMI_ROOT_PORT=5130");
putenv("PMI_ROOT_LOCAL=1");
putenv("PMI_SIZE=3");
putenv("PMI_RANK=0");
double load_proration[2]={0.1,0.9};
********************************************************/
#include <mpi.h>
#include <stdio.h>
#define NRA 10 // number of rows in matrix A
#define NCA 15 // number of columns in matrix A
#define NCB 5 // 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
taskid, // task identifier
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; // misc
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
if(taskid == MASTER) {
rows = NRA;
}
else {
rows = (int)(NRA*load_proration[taskid-1]);
}
double a[rows][NCA], // matrix A to be multiplied
b[NCA][NCB], // matrix B to be multiplied
c[rows][NCB]; // result matrix C
if(taskid == MASTER) {
printf("\nNumber of worker processes : %d\n", numtasks-1);
printf("Number of rows to be distributed : %d\n", rows);
// initialize matrix a and matrix b
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 worker processes
offset = 0;
mtype = FROM_MASTER;
for(dest=1; dest<numtasks; dest++) {
rows = (int)(NRA*load_proration[dest-1]);
printf("Send %d row(s) to worker process (Rank # : %d)\n", rows, dest);
MPI_Send(&offset, 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[0][0]), NCA*NCB, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
offset = offset + rows;
}
// receive results from worker processes
mtype = FROM_WORKER;
for(source=1; source<numtasks; source++) {
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);
}
}
else {
// receive matrix data from master process
mtype = FROM_MASTER;
MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&(a[0][0]), rows*NCA, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&(b[0][0]), NCA*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
// matrix calculation
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];
}
}
}
printf("\nPartial matrix on worker process (Rank # : %d)\n\n", taskid);
for(i=0; i<rows; i++) {
for(j=0; j<NCB; j++) {
printf("%6.2f ", c[i][j]);
}
printf("\n");
}
// send results to master process
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[0][0]), rows*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD);
}
if(taskid == MASTER) {
printf("\nResultant matrix on master process (Rank # : %d)\n\n", taskid);
for(i=0; i<NRA; i++) {
for(j=0; j<NCB; j++) {
printf("%6.2f ", c[i][j]);
}
printf("\n");
}
}
MPI_Finalize();
return 0;
}
|
| Integration Engineering Laboratory | UCD MTU Sandia |