MPI广播2D数组

4

我原本要学习使用MPI进行并行编程,但是遇到了一些错误。

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


int main(int argc, char** argv)
{
    int procNum, procRank;
    int m,n;
    int sumProc = 0, sumAll = 0;
    int** arr;
    MPI_Status status;

    MPI_Init ( &argc, &argv );

    MPI_Comm_size ( MPI_COMM_WORLD, &procNum ); 
    MPI_Comm_rank ( MPI_COMM_WORLD, &procRank );

    if (procRank == 0)
    {   
        printf("Type the array size \n");
        scanf("%i %i", &m, &n); 
    }
    MPI_Bcast(&m, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

    arr = new int*[m];
    for (int i = 0; i < m; i++)
        arr[i] = new int[n];

    if (procRank == 0)
    {
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                    arr[i][j] = rand() % 30;
                    printf("%i ", arr[i][j]);
            }
            printf("\n");
        }
    }

    MPI_Bcast(&arr[0][0], m*n, MPI_INT, 0, MPI_COMM_WORLD);

    for (int i = procRank; i < n; i += procNum)
        for (int j = 0; j < m; j++)
            sumProc += arr[j][i];

    MPI_Reduce(&sumProc,&sumAll,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);

    if (procRank == 0)
    {
        printf("sumAll = %i", sumAll);
    }

    delete *arr;

    MPI_Finalize();
    return 0;
}

我正在尝试将二维数组传递给其他进程,但是当我检查时,我得到了错误的数组。 类似这样:

Original array
11 17 4
10 29 4
18 18 22

Array which camed
11 17 4
26 0 0
28 0 0

这个问题是什么?也许问题出在MPI_Bcast上。
附注:我添加了

标签。
for (int i = 0; i < m; i++)
    MPI_Bcast(arr[i], n, MPI_INT, 0, MPI_COMM_WORLD);

取代

MPI_Bcast(&arr[0][0], m*n, MPI_INT, 0, MPI_COMM_WORLD);

它解决了我的问题。

3
在你的不成功的版本中,我觉得你(错误地)假设数组在内存中是连续的。 - High Performance Mark
1个回答

3

Here

arr = new int*[m];
for (int i = 0; i < m; i++)
    arr[i] = new int[n];

您可以通过先创建指针数组,然后为每个指针创建常规 int 数组来创建 2D 数组。使用此方法,所有的数组 a[i] 都有 n 个元素大小,但不能保证在内存中连续。
以后,您可以使用指针运算和强制类型转换将指向 2D 数组的指针传递给函数。
MPI_Bcast(&arr[0][0], m*n, MPI_INT, 0, MPI_COMM_WORLD);

您假设所有数组在内存中都是连续的。由于它们并不是连续的,因此您会得到不同的值。


如何避免这种情况?或者说,使用MPI和std::vector或int**是不可能的,我只能使用像int[m][n]这样的东西吗? - Haldot
你可以使用一维数组来模拟二维数组,以避免这种情况发生,例如 arr = new int [m*n];之后的索引将会是 [i][j] -> i*n + j。这样做可以使得一维数组连续存储。 - iluvatar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接