2 d数组的MPI数据类型

时间:2010-04-16 08:18:55

标签: arrays 2d mpi types

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

4 个答案:

答案 0 :(得分: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

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

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;
}

然后您的类型定义为:

MPI_Datatype newType;
MPI_Type_hindexed(N, sizes, displacements, MPI_INTEGER, &newType);
MPI_Type_commit(&newType);

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

MPI_Bcast(arrays, 1, newType, root, comm);   // 'root' and 'comm' is whatever you need

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

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

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

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

MPI_Bcast(arrays, N*M, MPI_INTEGER, root, comm);

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

答案 1 :(得分:3)

如果要发送一个连续的数据块(我认为C数组是连续的,但我是Fortran程序员而且不是非常确定),你不需要声明一个新的MPI数据类型,尽管有一些原因为什么你可能想要。散射用于分配多个进程中的数组;您可以使用scatter将数组的每一行发送到另一个进程。所以对于一个连续的整数数组的例子,你最简单的选择是广播,就像这样(记住我糟糕的C技能):

MPI_Bcast(&buf, numRows*numCols, MPI_INT, root, MPI_COMM_WORLD)

,其中

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

numRows*numCols当然是2D数组中元素的数量

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

root是广播数组

的进程的等级

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

不要忘记广播是一项集体运作,所有流程都会进行同样的呼叫。

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

答案 2 :(得分:0)

MPI_Send(tempmat,16,MPI_INT,0,0,MPI_COMM_WORLD);

MPI_Recv(resultmaster,16,MPI_INT,MPI_ANY_SOURCE , 0, MPI_COMM_WORLD, &stat);

使用上述API时,我只获得第一行矩阵。

答案 3 :(得分:-1)

您的数组数组无法直接传递给另一个进程,因为虚拟地址可能不同;也就是说,带有指向其他数组的指针的第一个维度数组在任何其他进程中都没有意义。因此,您必须单独传递每个阵列,并在接收器端手动重新组装“2d阵列”。

2)广播与分散。广播将完整数组发送到通信器中的所有其他MPI等级。 Scatter,OTOH,在所有其他MPI等级上分配源数组。即with broadcast每个rank接收一个源数组的副本,散布每个rank接收一个不同的数组部分。