Thread: Parallel code with MPI

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    1

    Parallel code with MPI

    I have written a program for the famous game of life problem. The program is running perfectly for the sequential version. Now I am trying to implement it in parallel with MPI.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include <malloc.h>
    #include <math.h>
    #include <sys/time.h>
    #include<mpi.h>
    
    #define ALIVE 1
    #define DEAD 0
    
    #if 0
    int **array = NULL;
    int **tableB = NULL;
    int HEIGHT;
    int WIDTH;
    #endif
    
    double gettime(void) {
      struct timeval tval;
      gettimeofday(&tval, NULL);
      return( (double)tval.tv_sec + (double)tval.tv_usec/1000000.0 );
    }
    
    void destroyArray(int **a, int P) {
      int i;
      for (i=0; i<P; i++)
        free(a[i]);
        free(a);
    }
    
    int **allocarray(int P, int Q) {
      int i;
      int **a;
      a = calloc(P,sizeof(int*));
      if (a == NULL) {
        printf("Error allocating memory\n");
        return 0;
        }
      /* for row major storage */
      for (i = 0; i < P; i++) {
        a[i] = calloc(Q,sizeof(int));
        if (a[i] == NULL) {
          destroyArray(a, i-1);
          return 0;
        }
      }
    return a;
    }
    
    void initarray(int **array, int height, int width) {
      int i,j; 
      for (i=1; i<height-1; i++){
        for (j=1; j<width-1; j++){
          if(drand48()>0.5){
            array[i][j] = 1;
          }
          else{
            array[i][j] = 0;
          }
        }
      }
    }
    
    //print the table; currently not using it 
    void printTable(int **table, int height, int width) {
    
                    int h, w;
                    for (h = 1; h < height-1; h++) {
                    for (w = 1; w < width-1; w++) {
                            if (table[h][w] == ALIVE) {
                                    printf(" X ");
                            } else {
                                    printf(" 0 ");
                            }
                    }
                    printf("\n");
            }
            printf("\n");
    }
    
    //decide which neighbor is alive
    
    int getNeighborValue(int **table, int row, int col) {
            if (table[row][col] == ALIVE) 
            { 
                    return 1;
            } else {
                    return 0;
            }
    }
    
    //number of neighbors alive
    
    int getNeighborCount(int **table, int row, int col) {
            int neighbor = 0;
    
            neighbor += getNeighborValue(table, row - 1, col - 1);  //top left
            neighbor += getNeighborValue(table, row - 1, col);  //top
            neighbor += getNeighborValue(table, row - 1, col + 1);  //top right
            neighbor += getNeighborValue(table, row, col - 1);  //left
            neighbor += getNeighborValue(table, row, col + 1);  //right
            neighbor += getNeighborValue(table, row + 1, col - 1);  //below left
            neighbor += getNeighborValue(table, row + 1, col);   // below
            neighbor += getNeighborValue(table, row + 1, col + 1);  //below right
            
            return neighbor;
    }
    
    //calculating the status of the cell
    
    void calculate(int **inputarray, int **outputarray, int height, int width) {
            int neighbor, h, w;
            for (h = 1; h < height-1; h++) {
                    for (w = 1; w < width-1; w++) {
                            neighbor = getNeighborCount(inputarray, h, w);
                            if (neighbor==3) {
                                    outputarray[h][w] = ALIVE;
                            } else if (neighbor == 2 && inputarray[h][w] == ALIVE) {
                                    outputarray[h][w] = ALIVE;
                            } else {
                                    outputarray[h][w] = DEAD;
                            }
                    }
            }
    }
    
    //whether two generations yield the same result
    
    int matchArray(int **array1, int **array2, int height, int width){
            int h, w;
            for(h = 0; h < height; h++){
                    for(w = 0; w < width; w++){
                            if(array1[h][w] != array2[h][w]){
                                    return 1;
                            }
                    }
            }
            return 0;
    }
    
    
    int main(int argc, char *argv[]) {
            int generation = 0;
            int i, myN, above =0, below=0 ,startrow, endrow, *counts, *offset;
            double starttime, time;
            int height,width;
            //int flag = 0;
            int **array1, **array2, **myarray=NULL;
            int rank, size;
            MPI_Status status;
    
            MPI_Init(&argc, &argv);
            MPI_Comm_rank(MPI_COMM_WORLD, &rank);
            MPI_Comm_size(MPI_COMM_WORLD, &size);
    
            if (argc!=3) {
                    printf("You need to enter the size of the matrix and the number of generations in the comment line argument\n");
                    MPI_Abort(MPI_COMM_WORLD,-1);
            }
    
            height = atoi(argv[1])+2;
            width  = height;
            //allocate required arrays in all processes
            counts = (int *)malloc(sizeof(int)*size); 
            offset = (int *)malloc(sizeof(int)*size); 
            // compute counts and offsets for the scatter operation
            for (i=0; i<size; i++) 
               counts[i] = height/size + ((i<height%size)?1:0);
            for (offset[0]=0, i=1; i<size; i++) 
               offset[i] = offset[i-1] + counts[i-1];
            myN = counts[rank]; // obtain count for current process 
            if (rank == 0) { // allocate and initialize vector in master process
               array1=allocarray(height,width);
               initarray(array1,height,width);
            }
            // allocate receive buffer in all processes
            myarray = allocarray(myN,width);
            array2 = allocarray(myN,width); 
            // distribute data equally among other processes
            MPI_Scatterv(array1, counts, offset, MPI_INT, myarray, myN, MPI_INT, 0, MPI_COMM_WORLD);
            printf("My rank is %d, size is %d, myN is %d\n", rank, size, myN);
            fflush(stdout);
            MPI_Barrier(MPI_COMM_WORLD);
            starttime = MPI_Wtime();
             
            for (rank=1; rank<=size;rank++)
            {
                    if (rank > 1)
                            above = (rank-2)%size + 1;
                    if (rank < size)
                            below = rank%size + 1;
                    startrow = (rank-1)*size +1;
                    endrow = startrow + size -1;
                    if (below != 0)
                            MPI_Send(&array1[0][endrow], width, MPI_INT, below, 0, MPI_COMM_WORLD);
                    if (above != 0)
                            MPI_Send(&array1[0][startrow], width, MPI_INT, above, 0, MPI_COMM_WORLD);
                    if (above != 0)
                            MPI_Recv(&myarray[0][0], width, MPI_INT, above, 0, MPI_COMM_WORLD, &status);
                    if (below != 0)
                            MPI_Recv(&myarray[0][endrow+1], width, MPI_INT, below, 0, MPI_COMM_WORLD, &status);
        
                    calculate(myarray, array2, myN, width);
            }
            MPI_Gatherv(array2, myN, MPI_INT, array1, counts, offset, MPI_INT, 0, MPI_COMM_WORLD);
                    //temparray = array1;
                    //array1 = array2;
                    //array2 = temparray;
    
            printTable(array1, height, width);
            
                    time= MPI_Wtime()-starttime;
                    printf("Time taken= %f\n", time); 
                    MPI_Finalize();  
                    return 0;
    }
    Could any of you point where I am wrong?
    Last edited by Salem; 02-24-2010 at 11:34 PM. Reason: Use [code][/code] tags for code!!!!

  2. #2
    Registered User jdragyn's Avatar
    Join Date
    Sep 2009
    Posts
    96
    some indentation would make this infinitely easier to digest
    C+/- programmer extraordinaire

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    > Now I am trying to implement it in parallel with MPI.
    A few words describing what exactly you're trying to do "in parallel" would help.

    Not "here's my code".
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Proposal: Code colouring
    By Perspective in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 05-14-2007, 07:23 AM
  2. Values changing without reason?
    By subtled in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 10:20 AM
  3. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 4
    Last Post: 01-16-2002, 12:04 AM