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 |