在C中使用MPI_Type_Vector和MPI_Gather

时间:2010-06-05 15:01:34

标签: c mpi

我试图将平方矩阵与MPI平行相乘。

我使用MPI_Type_vector将方形子矩阵(浮点数组)发送到进程,因此它们可以计算子产品。然后,对于下一次迭代,这些子矩阵作为MPI_Type_contiguous发送到邻居进程(发送整个子矩阵)。此部分按预期工作,并且本地结果已更正。

然后,我使用连续类型的MPI_Gather将所有本地结果发送回根进程。问题是,最终矩阵是通过子矩阵逐行而不是子矩阵构建(显然,通过这种方法)。

我编写了一个重新排列最终矩阵的丑陋程序,但我想知道是否有直接的方法来执行发送MPI_Type_vectors的“逆”操作(即,发送一个值数组并直接将其排列在一个子数组中)接收数组中的表单。)

一个例子,试图澄清我的长文:

A [16]和B [16]

  

那些真的是2D阵列,A [4] [4]和B [4] [4]。

是要乘以的4x4矩阵; C [4] [4]将包含结果;使用了4个过程(Pi与i从0到3):

Pi得到两个2x2子矩阵:subAi [4]和subBi [4];他们的产品本地存储在subCi [4]。

例如,P0得到:

  

subA0 [4]包含A [0],A [1],A [4]和A [5];
  subB0 [4]包含B [0],B [1],B [4]和B [5]。

计算完一切后,root进程会收集所有subCi [4]。

然后C [4] [4]包含:

  

[
  subC 0 [0],subC 0 [1],subC 0 [2],subC <0> [3] ],
  subC1 [0],subC1 [1],subC1 [2],subC1 [3],
  subC2 [0],subC2 [1],subC2 [2],subC2 [3],
  subC3 [0],subC3 [1],subC3 [2],subC3 [3]]

我希望如此:

  

[
  subC 0 [0],subC 0 [1],subC1 [0],subC1 [1],
  subC 0 [2],subC 0 [3],subC1 [2],subC1 [3],
  subC2 [0],subC2 [1],subC3 [0],subC3 [1],
  subC2 [2],subC2 [3],subC3 [2],subC3 [3]]

无需进一步操作。有人知道吗?

感谢您的建议。

添加回答'高绩效标记'的信息:

1好吧,我的初始矩阵是二维数组(形状为A [4] [4])。在写我的问题时,我想缩短它,我现在看到这是一个坏主意......

我确实将MPI_Type_vector定义如下,例如:

MPI_Type_vector(2, 2, 4, MPI_FLOAT, &subMatrix);

(顺便说一下,我看不出扁平阵列有什么不同。)

2我不是MPI的专家,远非它,所以我可能会做一些奇怪的事情。 以下是我的一些代码,应用于示例(只处理A,B非常相似):

从根到从进程发送子矩阵:

Master {
    for (i = 0 ; i < 2 ; i++)
        for (j = 0 ; j < 2 ; j++)
            MPI_Send(&A[j * 2][(i + j) % 2 * 2], 1, subMatrix, i + j * 2, 42, MPI_COMM_WORLD);
}

奴隶收到:

MPI_Recv(subA, 4, MPI_FLOAT, 0, 42, MPI_COMM_WORLD, &status);

然后,进程之间的交换通过subMatrixLocal的MPI_Send和MPI_Recv完成,即:

MPI_Type_contiguous(4, MPI_FLOAT, &subMatrixLocal);

完成所有本地操作后,我将所有子C矩阵收集到C:

MPI_Gather(subC, 1, subMatrixLocal, C, 1, subMatrixLocal, 0, MPI_COMM_WORLD);

我获得了之前声明的结果,我必须重新排序...

关于您提出的算法:下一步将是使用GPU进行矩阵乘法,其中方形矩阵产品是有效的。 MPI将仅用于将CPU从CPU传输到CPU。当然,全球效率将在那时进行测试。

0您说“相同的类型定义应适用于反向操作”。但是,我的MPI_Vector_type在“大”矩阵上工作正常,但是不能直接在子矩阵上使用它(在2x2矩阵上应用MPI_Vector_type(2,2,4)会产生错误的结果,因为它需要最后两个值“在”定义的数组之外...)。你的意思是我应该创建另一个MPI_Vector_type并发送/接收它吗?

1 个答案:

答案 0 :(得分:1)

你的问题的答案是有一种直接的方法来执行发送MPI_Type_vectors的“反向”操作是肯定的。如果您已经定义了一个类型向量以将子矩阵从一个进程发送到另一个进程,则相同的类型定义应该适用于反向操作。

但是,我对你的解释感到有些困惑,并为你提出了一些问题。如果你回答他们,我可能会提供更好的建议。

  1. 你把你的矩阵写成A [16],B [16]并说它们是4x4。你已经把它们夷为平地了吗?我预计它们会是A [4] [4]等。如果你把矩阵弄平了,你为什么要这样做?你当然可以定义一个mpi_type_vector来定义一个二维矩阵的子矩阵。
  2. 对我来说,似乎有点奇怪,不一定是错的,但奇怪的是,与收集匹配的发送。我通常希望看到收集与散布相匹配并通过接收发送。也许您可以发布足够的代码来阐明您正在使用的操作。
  3. 最后,我认为通过乘以子矩阵来乘以矩阵可能不是MPI的有效方法。如果你这样做是一个练习,那么继续。但是更好的算法,可能是更容易实现的算法,

    1. mpi_broadcast矩阵B到所有进程;
    2. director进程在循环中向工作进程发送A行;
    3. 工作进程计算一行C并将其发送回导演进程;
    4. 导演进程接收C行并将它们放在正确的位置。