c语言 - 使用MPI_Sendrecv进行康威生命游戏,但程序无法在边界中交换数据



我正在尝试编写Conway的《人生游戏》的代码,模式是Rabbit。我使用笛卡尔二维方法建立了一个进程组,它们之间的通信是MPI_Sandrecv。但是这个代码不起作用,当我运行它时,它一直挂在那里,没有任何响应。我花了很长时间才找到问题,但我没有任何进展。你能帮我弄清楚吗?我会很高兴的!

#include <stdio.h>
#include "mpi.h"
#include <math.h>
#include <stdlib.h>
#define array 20
#define arrayhalf (array/2)
main(int argc, char *argv[])
{
    int ndims = 2, ierr;
    int p, my_rank, my_cart_rank;
    MPI_Comm comm2d;
    MPI_Datatype newtype;
    int dims[ndims], coord[ndims];
    int wrap_around[ndims];
    int reorder, nrows, ncols;
    int x[arrayhalf+2][arrayhalf+2], x2[arrayhalf+2][arrayhalf+2], x_rev[array+4][array+4];
    int left, right, down, top;
    MPI_Status status;
    int tag_up = 20, tag_down =21, tag_left = 22, tag_right = 23;
    long start, stop;
    /*** start up initial MPI environment ***/
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &p);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    /* hardcore 2 processes in each dimension */
    nrows = ncols = (int) sqrt(p);
    dims[0] = dims[1] = 2;
    /* create cartesian topology for processes */
    MPI_Dims_create(p, ndims, dims);
    /*if (my_rank == 0)
        printf("PW[%d]/[%d%]: PEdims = [%d x %d] n", my_rank, p, dims[0], dims[1]);*/
    /* create cartesian mapping, and check it is created either correct or wrong */
    wrap_around[0] = wrap_around[1] = 1; /*set periodicity to be true */
    reorder = 0;
    ierr = 0;
    ierr = MPI_Cart_create(MPI_COMM_WORLD, ndims, dims, wrap_around, reorder, &comm2d);
    if (ierr != 0)
        printf("ERROR[%d] creating CARTn", ierr);
    MPI_Type_vector( arrayhalf, 1, arrayhalf+2, MPI_INT, &newtype);
    MPI_Type_commit( &newtype );
    /* get the neighbour process, which is useful for hola exchange */
    int SHIFT_ROW = 0;
    int SHIFT_COL = 1;
    int DISP = 1;

    /*** load pattern ***/
    /* initialize the data array */
    int i, j ;
    for (i = 0; i < arrayhalf + 2 ; i++)
        for (j = 0; j < arrayhalf + 2; j++)
        {
            x[i][j] = 0;
            x2[i][j] = 0;
        }
    if (my_rank == 0)
    {
        int r,c;
        r = arrayhalf / 2;
        c = arrayhalf / 2;
        /* rabbits pattern
            1       1 1 1
            1 1 1   1
              1
        */
        x[r][c] = 1;
        x[r][c+4] = 1;
        x[r][c+5] = 1;
        x[r][c+6] = 1;
        x[r+1][c] = 1;
        x[r+1][c+1] = 1;
        x[r+1][c+2] = 1;
        x[r+1][c+5] = 1;
        x[r+2][c+1] = 1;
    }
    /*** calculate the next generation ***/
    int row, col;
    int steps;
    steps = atoi(argv[1]); /* get the generation number from command line */
    start = MPI_Wtime();
    int soc;
    int destination;
    for (i = 1; i <= steps; i++)
    {
        /*** use hola exchange in boundary elements ***/
        int * send_buffer = (int*) malloc((arrayhalf)*sizeof(int));
        int * recv_buffer = (int*) malloc((arrayhalf)*sizeof(int));
        /*int * send_buffer = (int *) calloc(arrayhalf,sizeof(int));
        int * recv_buffer = (int *) calloc(arrayhalf,sizeof(int));
        */
        /* to up */
        MPI_Cart_shift(comm2d, 1, 1, &soc,&destination);
        MPI_Sendrecv( &x[1][1], arrayhalf, MPI_INT, destination, tag_up,& x[arrayhalf + 1][1], arrayhalf, MPI_INT, soc, tag_up, comm2d, &status );
        /* to down */
        MPI_Cart_shift(comm2d, 1, 1, &destination,&soc);
        MPI_Sendrecv( &x[arrayhalf][1], arrayhalf, MPI_INT, destination, tag_down,& x[0][1], arrayhalf, MPI_INT, soc, tag_down, comm2d, &status);
        /* to left */
        MPI_Cart_shift(comm2d, 0, 1, &destination,&soc);
        MPI_Sendrecv( &x[1][1], 1,newtype, destination, tag_left,& x[1][arrayhalf+1], 1, newtype, soc, tag_left, comm2d, &status );
        /*for (j=0;j<arrayhalf;j++) {
            send_buffer[j]=x[j+1][1];
        }
        MPI_Sendrecv( send_buffer, arrayhalf,MPI_INT, destination, tag_left,recv_buffer, arrayhalf, MPI_INT, soc, tag_left, comm2d, &status );
        for (j=0;j<arrayhalf;j++) {
            x[j+1][arrayhalf+1]=recv_buffer[j];
        }
        */
        /* to right */
        MPI_Cart_shift(comm2d, 0, 1, &soc,&destination);
        MPI_Sendrecv( &x[1][arrayhalf], 1, newtype, destination, tag_right, &x[1][0], 1, newtype, soc, tag_right, comm2d, &status );
        /*for (j=0;j<arrayhalf;j++) {
            send_buffer[j]=x[j+1][arrayhalf];
        }
        MPI_Sendrecv( send_buffer, arrayhalf,MPI_INT, destination, tag_right,recv_buffer, arrayhalf, MPI_INT, soc, tag_right, comm2d, &status );
        for (j=0;j<arrayhalf;j++) {
            x[j+1][1]=recv_buffer[j];
        }
        */
        /*** sum the neighbour values and get the next generation ***/
        for (row = 1; row < arrayhalf; row++)
        {
            for (col = 1; col < arrayhalf; col++)
            {
                int neighbor;
                neighbor = x[row - 1][col - 1] + x[row - 1][col] + x[row - 1][col + 1] + x[row][col - 1] +
                           x[row][col + 1] +
                           x[row + 1][col - 1] + x[row + 1][col] + x[row + 1][col + 1];
                if (neighbor == 3)
                {
                    x2[row][col] = 1;
                }
                else if (x[row][col] == 1 && neighbor == 2)
                {
                    x2[row][col] = 1;
                }
                else
                {
                    x2[row][col] = 0;
                }
            }
        }
        /* used to be swap */
        for (row = 1; row < arrayhalf; row++)
        {
            for (col = 1; col < arrayhalf; col++)
            {
                x[row][col] = x2[row][col];
            }
        }
        free(send_buffer);
        free(recv_buffer);
    }

    /*** print the final generation ***/
    int population = 0;
int* A;
int process_num = dims[0]*dims[1];
int row_indx;
int col_indx;
int k;
if(my_rank == 0)
{
    A = (int*) malloc((arrayhalf+2)*(arrayhalf+2)*sizeof(int));
    for (k= 1; k< process_num; k++)
    {
        MPI_Recv(A,(arrayhalf+2)*(arrayhalf+2), MPI_INT,k, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        for (i = 0; i<arrayhalf+2; i++)
        {
            for (j = 0; j<arrayhalf+2; j++)
            {
                row_indx = (k%dims[1])*(arrayhalf+2)+i;
                col_indx = (k/dims[0]*(arrayhalf+2))+j;
                x_rev[row_indx][col_indx] = A[i*(arrayhalf+2)+j];
            }
        }
    }
    for (i = 0; i<arrayhalf+2; i++)
    {
        for (j = 0; j<arrayhalf+2; j++)
        {
            x_rev[i][j] = x[i][j];
        }
    }
    for (row = 0; row < array+4; row++) {
        for (col = 0; col < array+4; col++)
        {
            printf("%2d",x_rev[row][col]);
            if(x_rev[row][col]==1)
            {
                population = population + 1;
            }
        }
        printf("n");
    }
    stop = MPI_Wtime();
    printf("Running Time: %fn ",stop-start);
    printf("Population: %dn",population);
    printf("Generation: %dn",steps);
}
else{
    A = (int*) malloc((array+4)*(array+4)*sizeof(int));
    for (i=0; i< arrayhalf +2; i++)
    {
        for(j = 0; j<arrayhalf+2; j++)
        {
            A[i*(arrayhalf+2)+j] = x[i][j];
        }
    }
    MPI_Send(A,(arrayhalf+2)*(arrayhalf+2),MPI_INT,0,0,MPI_COMM_WORLD);
}
MPI_Comm_free( &comm2d );
MPI_Type_free( &newtype );
free(A);
MPI_Finalize();
}

我想我发现了错误。它在176号线。排名0正试图收听来自排名0的消息,但排名0没有向自己发送消息。您应该从1而不是0开始循环。

最新更新