2 d数组的MPI数据类型

dks*_*dks 3 arrays types 2d mpi

我需要将一个整数数组(基本上是一个2 d数组)传递给root的所有处理器.我在C程序中使用MPI.如何声明2 d数组的MPI数据类型以及如何发送消息(我应该使用广播还是分散)

sus*_*att 12

您需要使用Broadcast,因为您希望将相同消息的副本发送到每个进程.Scatter会分解消息并在进程之间分配块.

至于如何发送数据:HIndexed数据类型适合您.

假设您的2d数组定义如下:

int N;            // number of arrays (first dimension)
int sizes[N];     // number of elements in each array (second dimensions)
int* arrays[N];   // pointers to the start of each array
Run Code Online (Sandbox Code Playgroud)

首先,您必须计算每个数组的起始地址的位移,相对于数据类型的起始地址,它可以是第一个数组的起始地址,以方便:

MPI_Aint base;
MPI_Address(arrays[0], &base);
MPI_Aint* displacements = new int[N];
for (int i=0; i<N; ++i)
{
    MPI_Address(arrays[i], &displacements[i]);
    displacements[i] -= base;
}
Run Code Online (Sandbox Code Playgroud)

那么你的类型的定义是:

MPI_Datatype newType;
MPI_Type_hindexed(N, sizes, displacements, MPI_INTEGER, &newType);
MPI_Type_commit(&newType);
Run Code Online (Sandbox Code Playgroud)

此定义将创建一个数据类型,其中包含一个接一个地打包的所有数组.完成此操作后,您只需将数据作为此类型的单个对象发送:

MPI_Bcast(arrays, 1, newType, root, comm);   // 'root' and 'comm' is whatever you need
Run Code Online (Sandbox Code Playgroud)

但是,你还没有完成.接收进程需要知道您要发送的数组的大小:如果在编译时无法获得该知识,则必须首先发送包含该数据的单独消息(简单的整数数组).如果N,sizes并且arrays在接收进程上定义类似,并且分配了足够的空间来填充数组,那么所有接收进程需要做的是定义相同的数据类型(与发送者完全相同的代码),然后接收发送者的消息作为该类型的单个实例:

MPI_Bcast(arrays, 1, newType, root, comm);    // 'root' and 'comm' must have the same value as in the sender's code
Run Code Online (Sandbox Code Playgroud)

瞧!所有进程现在都有一个数组副本.

当然,如果将2d数组的第二维固定为某个值,事情会变得容易多了M.在这种情况下,最简单的解决方案是将其存储在单个int[N*M]数组中:C++将保证它是所有连续的内存,因此您可以在不定义自定义数据类型的情况下广播它,如下所示:

MPI_Bcast(arrays, N*M, MPI_INTEGER, root, comm);
Run Code Online (Sandbox Code Playgroud)

注意:您可能会使用Indexed类型而不是HIndexed.不同之处在于,在Indexed中,displacements数组以元素数量给出,而在HIndexed中,它是字节数(H代表异类).如果您要使用Indexed,那么给出的值displacements必须除以sizeof(int).但是,我不确定在堆上的任意位置定义的整数数组是否保证在C++中"排列"到整数限制,并且在任何情况下,HIndexed版本都有(略微)较少的代码并产生相同的结果.


Hig*_*ark 4

如果您要发送连续的数据块(我认为 C 数组是连续的,但我是一名 Fortran 程序员,不太确定),您不需要声明新的 MPI 数据类型,尽管有一些原因可能会导致您这样做想要。分散用于将数组分布到多个进程中;您可以使用 scatter 将数组的每一行发送到不同的进程。因此,对于连续整数数组的示例,最简单的选择是广播,如下所示(考虑到我糟糕的 C 技能):

MPI_Bcast(&buf, numRows*numCols, MPI_INT, root, MPI_COMM_WORLD)
Run Code Online (Sandbox Code Playgroud)

在哪里

&buf是数组中第一个元素的地址

numRows*numCols当然,是二维数组中元素的数量

MPI_INT是(可能)您将使用的内在数据类型

root是广播数组的进程的等级

MPI_COMM_WORLD是通常的默认通信器,如果需要可以更改

并且不要忘记广播是一个集体操作,所有进程都进行相同的调用。

如果您的数组不连续,请再次发布一些示例数组大小,我们将弄清楚如何定义 MPI 数据类型。