I have written a program for the Game of Life in OpenMP with C. But the execution time is increasing with the number of threads.
Can you please help me with where I am wrong?
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include <math.h>
#include <sys/time.h>
#include<omp.h>
#define ALIVE 1
#define DEAD 0
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
int calculate(int **inputarray, int **outputarray, int height, int width) {
int neighbor, h, w, flag=0;
#pragma parallel for
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;
}
if(inputarray[h][w] != outputarray[h][w]){
flag= 1;
}
}
}
return flag;
}
int main(int argc, char *argv[]) {
omp_set_nested(1);
int generation = 0;
int i;
double starttime, endtime, time;
int height,width;
int flag = 0;
int **array1, **array2, **temparray;
if (argc!=3)
printf("You need to enter the size of the matrix and the number of generations in the comment line argument\n");
else
{
printf("The matrix size given is:%s * %s\n",argv[1], argv[1]);
height = atoi(argv[1])+2;
width = height;
array1 = allocarray(height, width);
array2 = allocarray(height, width);
if((array1 == 0) || (array2 == 0))
{
printf("Allocation of one or both of the arrays failed!\n");
exit(1);
}
initarray(array1, height, width);
printTable(array1, height, width);
starttime= gettime();
//printf("Starttime= %f", starttime);
for(i=0; i<(atoi(argv[2])); i++)
{
#pragma omp parallel num_threads(1)
flag = calculate(array1, array2, height, width);
if (flag == 0)
break;
printTable(array2, height, width);
printf("Generation %d\n", ++generation);
/* swap input and output arrays for next time through the loop: */
temparray = array1;
array1 = array2;
array2 = temparray;
}
}
endtime= gettime();
//printf("Endtime= %f", endtime);
time= (endtime-starttime);
printf("Time taken= %1f\n", time);
return 0;
}