Rev 326 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* proj3.c - implements the APSP algorithm for a matrix of size 4x4.** Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)*/#include <stdio.h>#include <limits.h>#include <mpi.h>const int ROOT_NODE = 0;int numprocs;int myid;/*** NOTE: Accessing "matrices" in this program is a little strange.* I decided to implement matrices using an array. To get to a[row][col],* you would use a[row*a_size+col]. Pretty simple actually.*/int* allocate (int rows, int cols){int *temp = NULL;if ((temp = (int*) malloc (rows * cols * sizeof(int))) == NULL)printf ("Could not allocate memory for array of size: %d x %d\n", rows, cols);return temp;}void print_matrix (int *b, int n, const char *s){int i,j;if (n<=10) // n<=10{printf ("%s\n", s);for (i=0; i<n; i++){for (j=0; j<n; j++)printf ("%d\t", b[i*n+j]);printf ("\n");}printf ("\n");}else if (n<=100) // 10<n<=100{printf ("%s\n", s);// First 2 rowsfor (i=0; i<2; i++){for (j=0; j<n; j++)printf ("%d\t", b[i*n+j]);printf ("\n");}printf ("\n");// First 2 colsfor (i=0; i<n; i++){for (j=0; j<2; j++)printf ("%d\t", b[i*n+j]);printf ("\n");}}}void matrix_mult (int *b, int *c, int n){int i,j,k,ii,temp;/* Multiply our slice of the matrix, store it in c */for (ii=0; ii<n/numprocs; ii++){i = ii + myid * n/numprocs; // i is the offset into bfor (j=0; j<n; j++){// MATRIX_MULT// c[i*n+j]=0;// SHORTEST PATHc[ii*n+j] = INT_MAX;for (k=0; k<n; k++){// MATRIX MULT// c[i*n+j] += a[i*n+k] * b[k*n+j];// SHORTEST PATHif (b[i*n+k] == INT_MAX || b[k*n+j] == INT_MAX)temp = INT_MAX;elsetemp = b[i*n+k] + b[k*n+j];if (temp < c[ii*n+j])c[ii*n+j] = temp;}}}}int main (int argc, char *argv[]){const int n = 4;int *b, *c;int i, j, k, temp, t;MPI_Status status;/* Get all of the necessary info for each process */MPI_Init (&argc, &argv);MPI_Comm_rank (MPI_COMM_WORLD, &myid);MPI_Comm_size (MPI_COMM_WORLD, &numprocs);/* Do a quick sanity check for the correct number of processors */if (n % numprocs != 0){if (myid == 0){printf ("%d mod %d must be zero!\n", n, numprocs);printf ("You should probably change the -np parameter\n");}MPI_Finalize ();return 1;}/* Allocate all of b for each process, since we'll need it */b = allocate (n, n);if (myid == ROOT_NODE){/* Allocate the full c, since we need to initialize it */c = allocate (n, n);/* Initialize values */for (i=0; i<n; i++)for (j=0; j<n; j++)b[i*n+j] = INT_MAX;b[0] = 0;b[1] = 2;b[2] = INT_MAX;b[3] = 10;b[4] = 2;b[5] = 0;b[6] = 2;b[7] = INT_MAX;b[8] = INT_MAX;b[9] = 2;b[10] = 0;b[11] = 3;b[12] = 10;b[13] = INT_MAX;b[14] = 3;b[15] = 0;/* Force b[i][i] = 0 */for (i=0; i<n; i++)b[i*n+i] = 0;if (n<=100)print_matrix (b, n, "Input Matrix:");else{printf ("Beginning calculation for all shortest paths\n");printf ("for a graph with %d nodes\n", n);}}else{/* Allocate our slice of c, since that's all we need */c = allocate (n/numprocs, n);}/* Send all of b to each process, since they need all of it */MPI_Bcast (b, n*n, MPI_INT, ROOT_NODE, MPI_COMM_WORLD);/* Run our piece of the calculation.* Synchronize data with all other processes at the end of each step. */for (t=0; t<ceil(log(n-1)); t++){matrix_mult (b, c, n);MPI_Allgather (c, n*n/numprocs, MPI_INT, b, n*n/numprocs, MPI_INT, MPI_COMM_WORLD);}/* Print out the result matrix. */if (myid == ROOT_NODE){if (n<=100)print_matrix (b, n, "Result Matrix:");else{printf ("Finished calculation for all shortest paths\n");printf ("for a graph with %d nodes\n", n);}}/* Free all of the memory we allocated earlier */free (b);free (c);MPI_Finalize ();return 0;}