【问题标题】:Scattering a contiguous 2D Array using MPI使用 MPI 散射连续的 2D 阵列
【发布时间】:2016-08-25 17:21:50
【问题描述】:

我似乎没有做对,我想分散一个 2D 块并打印分散的部分,这是为了测试目的
这就是我想要做的......

#include <stdio.h>
#include <stdlib.h>
#include "mpi/mpi.h"

void print2D(int**, int, int);

int main(int argc, char* argv[])
{
    int rank, pSize, r1, c1, rowsPerProcess, i, j;
    int** matA = NULL, **partMat = NULL;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &pSize);

    if(rank == 0)
    {
    scanf("%d%d", &r1, &c1);
        rowsPerProcess = r1/pSize; // number of rows assigned to each process (Assume this produces no remainder)

    //Contiguous allocation
        int* mat1D = (int*)malloc(r1 * c1 * sizeof(int));
        matA = (int**)malloc(r1 * sizeof(int*));
        for(i=0; i<r1; i++)
          matA[i] = &mat1D[i * c1];

    for(i=0; i<r1; i++) //Fill the 2D array
      for(j=0; j<c1; j++)
        matA[i][j] = i + j;

    printf("Original Matrix:\n");
    print2D(matA, r1, c1);
    }

    MPI_Bcast(&c1, 1, MPI_INT, 0, MPI_COMM_WORLD); //Columns
    MPI_Bcast(&rowsPerProcess, 1, MPI_INT, 0, MPI_COMM_WORLD); //Rows in every process

    //Again, contiguous allocation for the partial 2D array
    int* partMat1D = (int*)malloc(rowsPerProcess * c1 * sizeof(int));
    partMat = (int**)malloc(rowsPerProcess * sizeof(int*));
    for(i=0; i<rowsPerProcess; i++)
          partMat[i] = &partMat1D[i * c1];

    MPI_Scatter(&(matA[0][0]), rowsPerProcess * c1, MPI_INT, &(partMat[0][0]),
    rowsPerProcess * c1, MPI_INT, 0, MPI_COMM_WORLD);

    printf("FROM PROCESS %d:\n", rank);
    print2D(partMat, rowsPerProcess, c1);

    MPI_Finalize();
    return 0;
}

void print2D(int** mat, int row, int col)
{
    if(mat != NULL)
    {
        int i, j;
        for(i=0; i<row; i++)
        {
            for(j=0; j<col; j++)
                printf("%d  ", mat[i][j]);
            printf("\n");
        }
    }
}

我在使用 4 个进程运行此程序时收到分段错误错误
例如

8 3
Original Matrix:
0  1  2  
1  2  3  
2  3  4  
3  4  5  
4  5  6  
5  6  7  
6  7  8  
7  8  9  
FROM PROCESS 0:
0  1  2  
1  2  3  

===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   PID 2637 RUNNING AT minix-VirtualBox
=   EXIT CODE: 139
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions

只有进程 0 正确打印它的部分。 我使用 MPI_Scatter 错了吗?我该如何解决这个问题?
我如何正确分散这个 2D 块?

【问题讨论】:

    标签: c multidimensional-array mpi


    【解决方案1】:

    在非主进程上,将matA 初始化为NULL,然后继续计算表达式&amp;matA[0][0]。这取消了matA 的引用,甚至在您的进程进入MPI_Scatter() 之前就崩溃了。


    由于您使用 C 进行编程,因此您可以避免使用双指针:自 C99 以来,C 就内置了非常好的多维数组支持,您可以使用它来让您的生活更轻松。只需将matA 声明为指向行数组的指针

    int (*matA)[c1];
    

    然后为其分配r1 行的数组

    matA = malloc(r1*sizeof(*matA));
    

    之后,您可以使用上面代码中使用的相同代码填充数组:

    for(i=0; i<r1; i++) //Fill the 2D array
      for(j=0; j<c1; j++)
        matA[i][j] = i + j;
    

    此外,由于您的 2D 数组只需要一个 malloc() 调用,您也可以通过一个 free() 调用来处理它:

    free(matA);
    

    注意:你不能在 C++ 中这样做,它不像 C 那样支持可变长度数组,而且可能永远不会。这是 C 比 C++ 强大得多的少数几个方面之一。

    【讨论】:

    • 感谢这个二维数组提示!但我用 NULL 删除了这个初始化,我仍然有同样的错误
    • 问题不在于使用NULL 进行初始化,而是未能使用一些实际上可以取消引用的有意义的值进行初始化。
    • 那你有什么建议?在散射之前将整个 matA 矩阵广播到所有进程?
    • 不,绝对不是。如果我使用了您的分配,我会将mat1D 传递给MPI_Scatter()。但我宁愿使用 C99 2D-array 版本并调用 MPI_Scatter() 只需将matA 作为第一个参数。在这种情况下,matA 在非根进程上是否为 NULL 无关紧要,因为它永远不会被取消引用。
    • 哦,我现在明白了!我让所有进程都能看到 mat1D 和 partMat1D 并将调用更改为 MPI_Scatter(mat1D, rowsPerProcess * c1, MPI_INT, partMat1D, rowsPerProcess * c1, MPI_INT, 0, MPI_COMM_WORLD); 并且它起作用了..我想我会切换到你建议的二维数组版本..知道如何将int (*matA)[c1]; 传递给我的@987654341 @函数
    猜你喜欢
    • 2020-03-30
    • 2017-12-23
    • 2021-12-20
    • 2018-05-22
    • 2011-06-09
    • 2023-03-17
    • 2016-02-04
    • 2015-06-02
    相关资源
    最近更新 更多