fairplay89
December 13th, 2010, 09:21 PM
For my programming final I need to make a game of life using MPI. At first I was getting a redeclaration of C++ built-in type 'short' error. Now I get a file format not recognized error. If anyone has any input I would greatly appreciate it. Thanks in advance.
#include <mpi.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdio.h>
#undef SEEK_SET
#undef SEEK_END
#undef SEEK_CUR
#define HEIGHT 8
#define WIDTH 8
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)
#define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1,p,n)-BLOCK_LOW(id,p,n))
#define BLOCK_OWNER(index,p,n) (((p)*((index)+1)-1)/(n))
enum STATE {ALIVE=1, DEAD=0};
enum STATE randomCell() { return rand() % 4 == 0 ? ALIVE : DEAD; }
#define GRID
class Grid {
public:
Grid(int w, int h); // default constructor, malloc too
~Grid(); // release current memory usage
// Accessors
int getHeight() {return height;} // return height of grid
int getWidth() {return width;} // return width of grid
void print(); // print the grid with "X" and " "
void printLinear(); // Print Array in a linear fashion
int countNeighbor(int row, int col);// count a neighbor if not a border
STATE getState(int row, int col) {return grid[row][col];}
// Mutators
void randomize(); // Assign random states to each cell
void setHeight(int h) {height = h;} // Change the height value of grid
void setWidth(int w) {width = w;} // Change the width value of grid
void readFromFile(char* filename); // Read grid from file
void tickTock(int row, int col, int nRows, int nCols);
void setState(int row, int col, STATE value);
STATE** grid; // 2-D grid
int height; // height of grid
int width; // width of grid
STATE* linear; // the grid stored in a linear fashion
};
using namespace std;
//Code given in class monday 12/13
// int rank, new rank, sendbuf, numtasks, ranks1[2]=(0,1), ranks2[2]=(2,3),ranks1[2]=(4,5),ranks1[2]=(6,7)
//MPI_Group orig_group, new_group;
//MPI_Comm new_comm;
//MPI_Init(&argc,&argv);
//MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//MPI_Comm_size(MPI_COMM_WORLD, &numtaks);
//if (numtasks != NPROCS) {
// printf("must specify MP_PROCS= %d. Terminating. \n", NPROCS);
//MPI_Finalize();
//exit(0); }
//sendbuf = rank;
//extract the original group handle
//MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
//divide tasks into two distinct groups based upon rank
//if(rank < NPROCS/2) { MPI_Group_incl(orig_group, NPROC/2, ranks1, &new_group);}
//else { MPI_Group_incl(orig_group, NPROC/2, ranks2, &new_group);}
//create new communicator and then perform collective communication
//MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
//MPI_Group_rank (new_group, &new_rank);
//printf("rank=%d newrank= %d recvbuf= %d\n", rank, new_rank,recvbuf);
int main(int argc, char *argv[]) {
srand( (unsigned int) time( NULL )); // Set random seed according to time
int id; /* Process Rank */
int p; /* Number of Processes */
int iterations = 1; /* Specify the number of iterations the process for the game of life */
Grid grid(WIDTH, HEIGHT); /* 2-D Array that holds current state of grid */
MPI_Init(&argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, &id );
MPI_Comm_size( MPI_COMM_WORLD, &p );
grid.randomize(); // Or we can generae a random one each time
if( id == 0 ) {
grid.print();
printf("==================\n");
fflush(stdout);
}
int row, col, nRows, nCols, blockSize, blockStart;
// Each process works on a nr of rows at a time
col = 0; // starting column of row
nCols = grid.getWidth(); // number of columns to be worked on
// Row number and number of rows varies according to the distribution
row = BLOCK_LOW(id, p, grid.getHeight()); // starting row
nRows = BLOCK_SIZE(id, p, grid.getHeight()); // number of rows to be worked on
// The mount of data being sent is row x columns
blockSize = nRows*nCols;
// The block to be sent begins is offset by the nCols
blockStart = row*nCols;
int prevProcBlockStart, prevProcBlockSize, nextProcBlockStart, nextProcBlockSize;
if( 0 <= id-1 ) {
prevProcBlockStart = BLOCK_LOW(id-1, p, grid.getHeight()) * nCols;
prevProcBlockSize = BLOCK_SIZE(id-1, p, grid.getHeight()) * nCols;
}
if( id+1 <= p-1 ) {
nextProcBlockStart = BLOCK_LOW(id+1, p, grid.getHeight()) * nCols;
nextProcBlockSize = BLOCK_SIZE(id+1, p, grid.getHeight()) * nCols;
}
MPI_Status status;
int i;
for( i = 0; i < iterations; i++ ) {
grid.tickTock(row, col, nRows, nCols);
if( 0 <= id-1 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, id-1, 0, MPI_COMM_WORLD);
if( id+1 <= p-1 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, id+1, 0, MPI_COMM_WORLD);
if( 0 <= id-1 )
MPI_Recv((void*)&grid.linear[prevProcBlockStart], prevProcBlockSize, MPI_INT, id-1, 0, MPI_COMM_WORLD, &status);
if( id+1 <= p-1 )
MPI_Recv((void*)&grid.linear[nextProcBlockStart], nextProcBlockSize, MPI_INT, id+1, 0, MPI_COMM_WORLD, &status);
}
// Perform a gather of all results. Note that MPI_Gather doesn't quite work here
if( id != 0 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, 0, 0, MPI_COMM_WORLD);
else
for( i = 1; i < p; i++ )
MPI_Recv((void*)&grid.linear[BLOCK_LOW(i, p, grid.getHeight()) * nCols], BLOCK_SIZE(i, p, grid.getHeight()) * nCols, MPI_INT, i, 0, MPI_COMM_WORLD, &status);
MPI_Finalize();
if( id == 0 ) {
grid.print();
}
return 0;
}
#ifndef GRID
Grid(int w, int h) {
int i, j;
height = h;
width = w;
// c style memory allocation. more efficient than doing |height| allocations
linear = (STATE *) malloc( width * height * sizeof(STATE) );
grid = (STATE **) malloc( height * sizeof(STATE *) );
for( i = 0; i < height; i++ )
grid[i] = &linear[i*width];
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j ++ ) {
setState(i, j, DEAD);
}
}
}
~Grid() {
// c style memory deallocation
free(linear);
free(grid);
}
void printLinear() {
int i, j;
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j++ ) {
printf("%s", (linear[i*width + j] == ALIVE ? "X" : "."));
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
void setState(int row, int col, STATE value) {
grid[row][col] = value;
}
void randomize() {
int i, j;
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
setState(i, j, randomCell());
}
void readFromFile(char* filename) {
int i = 0, j = 0;
char c;
FILE *fp; fp = fopen(filename, "r+");
if( fp == NULL ) {
printf("file not found!\n");
fflush(stdout);
exit(0);
}
else {
do {
c = fgetc( fp );
if( c == ' ' ) setState(i, j, DEAD);
if( c == 'X' ) setState(i, j, ALIVE);
j++;
if( c == '\r' || c == '\n' || c == '$' ) {
j = 0;
i++;
}
} while( c != EOF );
}
fclose(fp);
}
void print() {
int i, j;
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j++ ) {
printf("%s", (getState(i, j) == ALIVE ? "X" : "." ));
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
}
int countNeighbor(int row, int col) {
if (0 <= row && row < width && 0 <= col && col < height)
return getState(row, col) == ALIVE ? 1 : 0;
else
return 0;
}
// col - start column
// row - start row
// nCols - number of columns to be processed
// nRows - number of rows to be processed
void tickTock(int row, int col, int nRows, int nCols) {
Grid nextState(height, width);
int i, j;
for( i = row; i < row+nRows; i++ ) {
for( j = col; j < col+nCols; j++ ) {
int alive_neighbors = countNeighbor(i-1, j+1) +
countNeighbor(i-1, j) +
countNeighbor(i-1, j-1) +
countNeighbor(i , j+1) +
countNeighbor(i , j-1) +
countNeighbor(i+1, j+1) +
countNeighbor(i+1, j) +
countNeighbor(i+1, j-1);
if( getState(i, j) == ALIVE )
if( alive_neighbors <= 1 || alive_neighbors >= 4 )
nextState.setState(i, j, DEAD);
else if ( alive_neighbors == 2 || alive_neighbors == 3 )
nextState.setState(i, j, ALIVE);
else
nextState.setState(i, j, getState(i, j));
else
if( alive_neighbors == 3 )
nextState.setState(i, j, ALIVE);
else
nextState.setState(i, j, getState(i, j));
}
}
for( i = row; i < row+nRows; i++ )
for( j = col; j < col+nCols; j++ )
setState(i, j, nextState.getState(i, j));
}
#endif
#include <mpi.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdio.h>
#undef SEEK_SET
#undef SEEK_END
#undef SEEK_CUR
#define HEIGHT 8
#define WIDTH 8
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)
#define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1,p,n)-BLOCK_LOW(id,p,n))
#define BLOCK_OWNER(index,p,n) (((p)*((index)+1)-1)/(n))
enum STATE {ALIVE=1, DEAD=0};
enum STATE randomCell() { return rand() % 4 == 0 ? ALIVE : DEAD; }
#define GRID
class Grid {
public:
Grid(int w, int h); // default constructor, malloc too
~Grid(); // release current memory usage
// Accessors
int getHeight() {return height;} // return height of grid
int getWidth() {return width;} // return width of grid
void print(); // print the grid with "X" and " "
void printLinear(); // Print Array in a linear fashion
int countNeighbor(int row, int col);// count a neighbor if not a border
STATE getState(int row, int col) {return grid[row][col];}
// Mutators
void randomize(); // Assign random states to each cell
void setHeight(int h) {height = h;} // Change the height value of grid
void setWidth(int w) {width = w;} // Change the width value of grid
void readFromFile(char* filename); // Read grid from file
void tickTock(int row, int col, int nRows, int nCols);
void setState(int row, int col, STATE value);
STATE** grid; // 2-D grid
int height; // height of grid
int width; // width of grid
STATE* linear; // the grid stored in a linear fashion
};
using namespace std;
//Code given in class monday 12/13
// int rank, new rank, sendbuf, numtasks, ranks1[2]=(0,1), ranks2[2]=(2,3),ranks1[2]=(4,5),ranks1[2]=(6,7)
//MPI_Group orig_group, new_group;
//MPI_Comm new_comm;
//MPI_Init(&argc,&argv);
//MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//MPI_Comm_size(MPI_COMM_WORLD, &numtaks);
//if (numtasks != NPROCS) {
// printf("must specify MP_PROCS= %d. Terminating. \n", NPROCS);
//MPI_Finalize();
//exit(0); }
//sendbuf = rank;
//extract the original group handle
//MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
//divide tasks into two distinct groups based upon rank
//if(rank < NPROCS/2) { MPI_Group_incl(orig_group, NPROC/2, ranks1, &new_group);}
//else { MPI_Group_incl(orig_group, NPROC/2, ranks2, &new_group);}
//create new communicator and then perform collective communication
//MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
//MPI_Group_rank (new_group, &new_rank);
//printf("rank=%d newrank= %d recvbuf= %d\n", rank, new_rank,recvbuf);
int main(int argc, char *argv[]) {
srand( (unsigned int) time( NULL )); // Set random seed according to time
int id; /* Process Rank */
int p; /* Number of Processes */
int iterations = 1; /* Specify the number of iterations the process for the game of life */
Grid grid(WIDTH, HEIGHT); /* 2-D Array that holds current state of grid */
MPI_Init(&argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, &id );
MPI_Comm_size( MPI_COMM_WORLD, &p );
grid.randomize(); // Or we can generae a random one each time
if( id == 0 ) {
grid.print();
printf("==================\n");
fflush(stdout);
}
int row, col, nRows, nCols, blockSize, blockStart;
// Each process works on a nr of rows at a time
col = 0; // starting column of row
nCols = grid.getWidth(); // number of columns to be worked on
// Row number and number of rows varies according to the distribution
row = BLOCK_LOW(id, p, grid.getHeight()); // starting row
nRows = BLOCK_SIZE(id, p, grid.getHeight()); // number of rows to be worked on
// The mount of data being sent is row x columns
blockSize = nRows*nCols;
// The block to be sent begins is offset by the nCols
blockStart = row*nCols;
int prevProcBlockStart, prevProcBlockSize, nextProcBlockStart, nextProcBlockSize;
if( 0 <= id-1 ) {
prevProcBlockStart = BLOCK_LOW(id-1, p, grid.getHeight()) * nCols;
prevProcBlockSize = BLOCK_SIZE(id-1, p, grid.getHeight()) * nCols;
}
if( id+1 <= p-1 ) {
nextProcBlockStart = BLOCK_LOW(id+1, p, grid.getHeight()) * nCols;
nextProcBlockSize = BLOCK_SIZE(id+1, p, grid.getHeight()) * nCols;
}
MPI_Status status;
int i;
for( i = 0; i < iterations; i++ ) {
grid.tickTock(row, col, nRows, nCols);
if( 0 <= id-1 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, id-1, 0, MPI_COMM_WORLD);
if( id+1 <= p-1 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, id+1, 0, MPI_COMM_WORLD);
if( 0 <= id-1 )
MPI_Recv((void*)&grid.linear[prevProcBlockStart], prevProcBlockSize, MPI_INT, id-1, 0, MPI_COMM_WORLD, &status);
if( id+1 <= p-1 )
MPI_Recv((void*)&grid.linear[nextProcBlockStart], nextProcBlockSize, MPI_INT, id+1, 0, MPI_COMM_WORLD, &status);
}
// Perform a gather of all results. Note that MPI_Gather doesn't quite work here
if( id != 0 )
MPI_Send((void*)&grid.linear[blockStart], blockSize, MPI_INT, 0, 0, MPI_COMM_WORLD);
else
for( i = 1; i < p; i++ )
MPI_Recv((void*)&grid.linear[BLOCK_LOW(i, p, grid.getHeight()) * nCols], BLOCK_SIZE(i, p, grid.getHeight()) * nCols, MPI_INT, i, 0, MPI_COMM_WORLD, &status);
MPI_Finalize();
if( id == 0 ) {
grid.print();
}
return 0;
}
#ifndef GRID
Grid(int w, int h) {
int i, j;
height = h;
width = w;
// c style memory allocation. more efficient than doing |height| allocations
linear = (STATE *) malloc( width * height * sizeof(STATE) );
grid = (STATE **) malloc( height * sizeof(STATE *) );
for( i = 0; i < height; i++ )
grid[i] = &linear[i*width];
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j ++ ) {
setState(i, j, DEAD);
}
}
}
~Grid() {
// c style memory deallocation
free(linear);
free(grid);
}
void printLinear() {
int i, j;
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j++ ) {
printf("%s", (linear[i*width + j] == ALIVE ? "X" : "."));
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
void setState(int row, int col, STATE value) {
grid[row][col] = value;
}
void randomize() {
int i, j;
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
setState(i, j, randomCell());
}
void readFromFile(char* filename) {
int i = 0, j = 0;
char c;
FILE *fp; fp = fopen(filename, "r+");
if( fp == NULL ) {
printf("file not found!\n");
fflush(stdout);
exit(0);
}
else {
do {
c = fgetc( fp );
if( c == ' ' ) setState(i, j, DEAD);
if( c == 'X' ) setState(i, j, ALIVE);
j++;
if( c == '\r' || c == '\n' || c == '$' ) {
j = 0;
i++;
}
} while( c != EOF );
}
fclose(fp);
}
void print() {
int i, j;
for( i = 0; i < height; i++ ) {
for( j = 0; j < width; j++ ) {
printf("%s", (getState(i, j) == ALIVE ? "X" : "." ));
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
}
int countNeighbor(int row, int col) {
if (0 <= row && row < width && 0 <= col && col < height)
return getState(row, col) == ALIVE ? 1 : 0;
else
return 0;
}
// col - start column
// row - start row
// nCols - number of columns to be processed
// nRows - number of rows to be processed
void tickTock(int row, int col, int nRows, int nCols) {
Grid nextState(height, width);
int i, j;
for( i = row; i < row+nRows; i++ ) {
for( j = col; j < col+nCols; j++ ) {
int alive_neighbors = countNeighbor(i-1, j+1) +
countNeighbor(i-1, j) +
countNeighbor(i-1, j-1) +
countNeighbor(i , j+1) +
countNeighbor(i , j-1) +
countNeighbor(i+1, j+1) +
countNeighbor(i+1, j) +
countNeighbor(i+1, j-1);
if( getState(i, j) == ALIVE )
if( alive_neighbors <= 1 || alive_neighbors >= 4 )
nextState.setState(i, j, DEAD);
else if ( alive_neighbors == 2 || alive_neighbors == 3 )
nextState.setState(i, j, ALIVE);
else
nextState.setState(i, j, getState(i, j));
else
if( alive_neighbors == 3 )
nextState.setState(i, j, ALIVE);
else
nextState.setState(i, j, getState(i, j));
}
}
for( i = row; i < row+nRows; i++ )
for( j = col; j < col+nCols; j++ )
setState(i, j, nextState.getState(i, j));
}
#endif