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?