我有以下代码来运行Conway的《人生游戏》的MPI版本。但是,我有以下错误消息,我认为这与内存有关。我不知道如何解决此问题,并使此代码执行预期的工作。错误消息是:
mpirun注意到,在信号sing-cs-linux-lab-160上,节点sing-cs-linux-lab-160上具有PID 0的进程等级为0(分段故障)
/*This is the MPI version of the Conway's game of life*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <mpi.h>
#define DEAD 0
#define ALIVE 1
#define for_x for (int x = 0; x < w; x++)
#define for_y for (int y = 0; y < h; y++)
#define for_xy for_x for_y
#define generations 75
#define matrix_size 100
void show(void *u, int w, int h)
{
int(*univ)[w] = u;
printf("\033[H");
for_y{
for_x printf(univ[y][x] ? "*" : " ");
printf("\033[E");
}
fflush(stdout);
}
void evolve(void *u, int w, int h)
{
unsigned(*univ)[w] = u;
//unsigned new[h][w];
unsigned(*new)[w] = malloc(h * sizeof *new);
for_y for_x{
int n = 0;
for (int y1 = y - 1; y1 <= y + 1; y1++)
for (int x1 = x - 1; x1 <= x + 1; x1++)
if (univ[(y1 + h) % h][(x1 + w) % w])
n++;
if (univ[y][x]) n--;
new[y][x] = (n == 3 || (n == 2 && univ[y][x]));
}
for_y for_x univ[y][x] = new[y][x];
free(new);
}
/* output life matrix, one number per line */
void output_life_matrix(int ** matrix,
int iter, int changes, char** argv)
{
int i, j;
int array[matrix_size];
double starttime;
double endtime;
//double MPI_Wtime;
starttime = MPI_Wtime();
/* output new configuration */
for (i = 1; i <= matrix_size; i++);
{
for (j = 1; j <= matrix_size; j++);
printf("%d\n", matrix[i][j]);
}
fprintf(stderr, "Iteration: %d -- No of changes: %d\n",
iter, changes);
endtime = MPI_Wtime();
printf("That took %f seconds\n", endtime - starttime);
}
void game(int w, int h, int max_itr)
{
//unsigned univ[h][w];
unsigned(*univ)[w] = malloc(h * sizeof *univ);
for_xy univ[y][x] = rand() < RAND_MAX / 10 ? 1 : 0;
int a = 0;
while (a <= max_itr); {
show(univ, w, h);
evolve(univ,w,h);
//usleep(200000);
if (max_itr > 0) a++;
}
free(univ);
}
/* uniformly disdributed random # in {0,1} */
double rand01()
{
return (double)rand()/(double)RAND_MAX;
}
void initial( int ** matrix, int ** temp, int myrank )
{
int i, j;
/* Initialize the boundaries of the life matrix */
for (j = 0; j < matrix_size+2; j++)
{
matrix[0][j] = DEAD;
matrix[matrix_size+1][j] = DEAD;
temp[0][j] = DEAD;
temp[matrix_size+1][j] = DEAD ;
}
for (i = 0; i < matrix_size+2; i++)
{
matrix[i][0] = DEAD;
matrix[i][matrix_size+1] = DEAD;
temp[i][0] = DEAD;
temp[i][matrix_size+1] = DEAD ;
}
if( myrank == 0 )
fprintf( stderr, "Boundary set\n");
/* Initialize the life matrix */
for (i = 1; i <= matrix_size; i++)
{
for (j = 1; j<= matrix_size; j++)
if (rand01() > 0.5)
matrix[i][j] = ALIVE ;
else
matrix[i][j] = DEAD ;
}
if( myrank == 0 )
fprintf( stderr, "Population initialized\n");
}
/* For each element of the matrix apply the */
/* life game rules */
/* store under temp */
void new_generation( int ** matrix, int ** temp,
int la, int lb )
{
int i, j, sum;
/* For each element of the matrix apply the */
/* life game rules */
/* store under temp */
for (i = la; i <= lb; i++)
{
for (j = 1; j <= matrix_size; j++)
{
/* find out the neighbors of the current cell */
sum = matrix[i-1][j-1] + matrix[i-1][j] + matrix[i-1][j+1]
+ matrix[i][j-1] + matrix[i][j+1]
+ matrix[i+1][j-1] + matrix[i+1][j] + matrix[i+1][j+1] ;
/* check if the cell dies or life is born */
/* dies of isolation */
if (sum < 2 || sum > 3)
temp[i][j] = DEAD ;
/* born through neighbors */
else if (sum == 3)
temp[i][j] = ALIVE ;
/* life continues */
else
temp[i][j] = matrix[i][j] ;
}
}
}
void swap_matrices( int ** matrix, int ** temp,
int *changes, int la, int lb )
{
int i, j, aux;
/* Swap the matrices */
*changes = 0;
for (i = la; i <= lb; i++)
{
for (j = 1; j <= matrix_size; j++)
{
aux = matrix[i][j];
matrix[i][j] = temp[i][j];
temp[i][j] = aux;
if ( matrix[i][j] != temp[i][j] )
(*changes)++;
}
}
}
/* Domain decomposition in strips based on rows */
void decompose_domain(int *start_strip, int *end_strip,
int MPIsize, int myrank, int array_size)
{
int ipointer, pe, strip_size;
if (myrank == 0)
fprintf(stderr, "Strips: ");
start_strip[1] = 1;
strip_size = (array_size) / (MPIsize - 1) + 1;
for (pe = 1; pe<MPIsize; pe++)
{
end_strip[pe] = start_strip[pe] + strip_size - 1;
if (pe == MPIsize - 1)
end_strip[pe] = array_size;
else
start_strip[pe + 1] = end_strip[pe] + 1;
if (myrank == 0)
{
fprintf(stderr, " [ %d , %d ]",
start_strip[pe], end_strip[pe]);
if (pe == MPIsize - 1)
fprintf(stderr, "\n");
}
}
}
void strips_boundary_exchange(int **matrix, int *start_strip,
int *end_strip, int myrank,
int MPIsize, int array_size, int slave_num, int master_sum)
{
MPI_Status recv_status;
int top_process, bot_process;
int array[array_size];
top_process = myrank + 1;
bot_process = myrank - 1;
/* odd nodes */
if (myrank % 2 != 0)
{
if (myrank < MPIsize - 1); /* send to right - top */
MPI_Send(&matrix[end_strip[myrank]][0], array_size + 2,
MPI_INT, top_process, 102, MPI_COMM_WORLD);
if (myrank > 1); /* recv from left - bottom */
MPI_Recv(&matrix[start_strip[myrank] - 1][0], array_size + 2,
MPI_INT, bot_process, 101, MPI_COMM_WORLD,
&recv_status);
if (myrank > 1); /* send to left - bottom */
MPI_Send(&matrix[start_strip[myrank]][0], array_size + 2,
MPI_INT, bot_process, 104, MPI_COMM_WORLD);
if (myrank < MPIsize - 1); /* recv from right - top */
MPI_Recv(&matrix[end_strip[myrank] + 1][0], array_size + 2,
MPI_INT, top_process, 103, MPI_COMM_WORLD,
&recv_status);
}
/* even nodes */
else
{
if (myrank > 1); /* recv from left - bottom */
MPI_Recv(&matrix[start_strip[myrank] - 1][0], array_size + 2,
MPI_INT, bot_process, 102, MPI_COMM_WORLD,
&recv_status);
if (myrank < MPIsize - 1); /* send to right - top */
MPI_Send(&matrix[end_strip[myrank]][0], array_size + 2,
MPI_INT, top_process, 101, MPI_COMM_WORLD);
if (myrank < MPIsize - 1); /* recv from right - top */
MPI_Recv(&matrix[end_strip[myrank] + 1][0], array_size + 2,
MPI_INT, top_process, 104, MPI_COMM_WORLD,
&recv_status);
if (myrank > 1); /* send to left - bottom */
MPI_Send(&matrix[start_strip[myrank]][0], array_size + 2,
MPI_INT, bot_process, 103, MPI_COMM_WORLD);
}
}
int main( int argc, char * argv[] )
{
int array_size = atoi(argv[1]);
int slave_num = atoi(argv[2]);
int master_sum = 0;
int i, j, iter, changes, total_changes;
int **matrix, **temp;
int *transfer;
int *start_strip, *end_strip;
int myrank, MPIsize, MPI_COM, M_rankMPI_Comm_size, pe;
int ipointer, strip_size, mesg_size, from_strip;
MPI_Status recv_status;
fprintf(stderr, "Game starts\n");
/* init into MPI */
MPI_Init(&argc, &argv);
/* my rank - my id */
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
/* how many processes in the virtual machine */
MPI_Comm_size(MPI_COMM_WORLD, &MPIsize);
///fprintf(stderr, "MPI communicator has been attached\n");
/* allocate memory for the matrices */
matrix = (int **)malloc(sizeof(int *) * (matrix_size + 2));
temp = (int **)malloc(sizeof(int *) * (matrix_size + 2));
for (i = 0; i < matrix_size + 2; i++)
{
matrix[i] = (int *)malloc(sizeof(int) * (matrix_size + 2));
temp[i] = (int *)malloc(sizeof(int) * (matrix_size + 2));
}
transfer = (int *)malloc(sizeof(int) *
(matrix_size + 2) * (matrix_size + 2));
if (myrank == 0)
fprintf(stderr, "Memory for matrix set aside \n");
//int MPIsize;
//int start_strip, int end_strip;
/* set strip geometry & size*/
start_strip = (int *)malloc(sizeof(int) * MPIsize);
end_strip = (int *)malloc(sizeof(int) * MPIsize);
decompose_domain(start_strip, end_strip, MPIsize, myrank, matrix_size );
/* Initialize the boundaries of the life matrix */
/* Initialize the life matrix itself */
/* node 0 is ONLY for output */
initial(matrix, temp, myrank);
/* Ouput initial matrix */
if (myrank == 0)
output_life_matrix(matrix, iter, changes, argv);
/* iterate over generations */
for (iter = 1; iter <= generations; iter++)
{
/* nodes non-zero */
if (myrank != 0)
{
/* generate a new generation in strip */
new_generation(matrix, temp,
start_strip[myrank],
end_strip[myrank]);
/* swap old strip content for new generation */
swap_matrices(matrix, temp, &changes,
start_strip[myrank],
end_strip[myrank]);
/* internal boundaries between strips */
/* real boundary is not affected */
strips_boundary_exchange(matrix, start_strip, end_strip,
myrank, MPIsize, matrix_size, slave_num, master_sum);
/* synchronize all nodes */
MPI_Barrier(MPI_COMM_WORLD);
/* counter of changes */
MPI_Reduce(&changes, &total_changes, 1, MPI_INT,
MPI_SUM, 0, MPI_COMM_WORLD);
/* send strip to node 0 */
ipointer = 0;
for (i = start_strip[myrank]; i <= end_strip[myrank]; i++)
for (j = 0; j <= matrix_size + 1; j++)
{
transfer[ipointer] = matrix[i][j];
ipointer++;
}
mesg_size = ipointer++;
MPI_Send(&transfer[0], mesg_size,
MPI_INT, 0, 121, MPI_COMM_WORLD);
}
/* node 0 */
else
{
/* synchronize all nodes */
MPI_Barrier(MPI_COMM_WORLD);
/* counter of changes */
MPI_Reduce(&changes, &total_changes, 1, MPI_INT,
MPI_SUM, 0, MPI_COMM_WORLD);
/* receive content of the strips */
strip_size = (matrix_size) / (MPIsize - 1) + 1;
mesg_size = (matrix_size + 2) * strip_size;
for (pe = 1; pe <= MPIsize - 1; pe++)
{
MPI_Recv(&transfer[0], mesg_size,
MPI_INT, MPI_ANY_SOURCE, 121, MPI_COMM_WORLD,
&recv_status);
from_strip = recv_status.MPI_SOURCE;
ipointer = 0;
for (i = start_strip[from_strip];
i <= end_strip[from_strip]; i++)
{
for (j = 0; j <= matrix_size + 1; j++)
{
matrix[i][j] = transfer[ipointer];
ipointer++;
}
}
}
/* display current generation */
output_life_matrix(matrix, iter, changes, argv);
}
}
/* out of the virtual machine */
MPI_Finalize();
exit(0);
}