MPI Scatter / Gather变量范围

时间:2017-08-27 09:47:07

标签: c malloc mpi scatter

我正在处理MPI版本的BML自动机,但MPI_Scatter()不像我预期的那样工作。我读here对于集合通信函数,每个进程都需要它的数组副本,只需要分配的空间而不需要初始化。在我的代码中,每个进程都有一个子网格local_grid,一个只有root操作的起始大grid。我的意思是使用与MPI数据类型的Scatter-Gather通信。我为每个网格和子网格分配空间,然后仅为根初始化网格。我哪里错了?

        unsigned char*** local_grid;
        unsigned char** grid;

        MPI_Status stat;
        MPI_Datatype rowtype;

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &nproc);
        local_n = N / nproc;

        MPI_Type_contiguous(N + 2,    /* count */
                MPI_UNSIGNED_CHAR,    /* oldtype */
                &rowtype              /* newtype */
                );
        MPI_Type_commit(&rowtype);

        /* Allocate space for 3D local grids*/
        local_grid = (unsigned char***)malloc(2 * sizeof(unsigned char**));
        for(i = 0; i < 2; i++) {
            local_grid[i] = (unsigned char**)malloc((local_n + 2) * sizeof(unsigned char*));
            for(j = 0; j < local_n + 2; j++) {
                local_grid[i][j] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
            }
        }
        /* Initialize local grids*/
        for(i = 0; i < local_n + 2; i++) {
            for(j = 0; j < N + 2; j++) {
                local_grid[0][i][j] = 0;
                local_grid[1][i][j] = 0;
            }
        }
        /* Allocate 2D starting grid */
        grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
        for(i = 0; i < N + 2; i++) {
            grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
        }
        /* Root */
        if(rank == 0) {
            /* initialize 2D starting grid */
            for(i = 0; i < N; i++) {
                for(j = 0; j < N + 2; j++) {
                    grid[i][j] = (((float)rand())/RAND_MAX) > rho ? 0 : rand()%2 + 1;
                    grid[i][0] = grid[i][N+1] = 0;
                    printf("%2d ", grid[i][j]);
                }
                printf("\n");
            }
        }
        /* All */
        MPI_Scatter(grid[0], local_n, rowtype, local_grid[cur][1], local_n, rowtype, source, MPI_COMM_WORLD);

        ...

程序正确终止,但只有一个行类型行从Scatter()传递到根进程,尽管它们的编号都没有传递给任何其他进程。

1 个答案:

答案 0 :(得分:2)

问题来自您声明/分配2D阵列的方式。

您将2D数组声明为数组指针数组(例如矩阵行),但MPI需要连续的布局。

例如,您可以替换

grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
for(i = 0; i < N; i++) {
    grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}

    grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
    grid[0] = (unsigned char*)malloc(N*(N+2)*sizeof(unsigned char));
    for(i = 1; i < N; i++) {
        grid[i] = grid[i-1] + N + 2;
    }

然后使用grid[0]作为MPI_Scatter()MPI_Gather()的缓冲参数 同样的事情必须适用于local_grid[0]local_grid[1]

当你需要释放网格时,你可以简单地

free(grid[0]);
free(grid);

注意如果N不是nproc

的倍数,我认为您的程序无法正常运行