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;
}