mpirun注意到节点sing-cs-linux-lab-160上具有PID 0的进程等级0在信号11(分段故障)上退出

时间:2018-08-06 17:17:39

标签: c

我有以下代码来运行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);
}

0 个答案:

没有答案