gpt4 book ai didi

c - 在 C 中使用 MPI_Type_Vector 和 MPI_Gather

转载 作者:行者123 更新时间:2023-11-30 16:04:29 26 4
gpt4 key购买 nike

我正在尝试与 MPI 并行乘以方阵。

我使用 MPI_Type_vector 将方形子矩阵( float 组)发送到进程,以便它们可以计算子乘积。然后,对于下一次迭代,这些子矩阵将作为 MPI_Type_contigulous 发送到邻居进程(发送整个子矩阵)。这部分工作正常,本地结果正确。

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

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

举个例子,尝试澄清我的长文本:

A[16] 和 B[16]

Those really are 2D arrays, A[4][4] and B[4][4].

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

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

例如,P0 得到:

subA0[4] containing A[0], A[1], A[4] and A[5] ;
subB0[4] containing B[0], B[1], B[4] and B[5].

计算完所有内容后,根进程收集所有 subCi[4]。

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

[
subC0[0], subC0[1], subC0[2], subC0[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]]

我希望它是:

[
subC0[0], subC0[1], subC1[0], subC1[1],
subC0[2], subC0[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);

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

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

并且我获得了前面所述的结果,我必须重新排序...

关于您提出的算法:下一步将是使用 GPU 进行矩阵乘法,其中方阵乘积非常有效。 MPI 将仅用于在 CPU 之间传输矩阵。当然,届时将考验全局效率。

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

最佳答案

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

但是,我对您的解释有些困惑,并且还有一些问题想问您。如果您回答这些问题,我也许可以提供更好的建议。

  1. 您将矩阵写为 A[16]、B[16] 并称它们是 4x4。你已经把它们压平了吗?我预计它们将是 A[4][4] 等。如果您已展平矩阵,为什么要这样做?您当然可以定义 mpi_type_vector 来定义 2D 矩阵的子矩阵。
  2. 对我来说,将发送与收集相匹配似乎有点奇怪,不一定是错误的,但很奇怪。我通常希望看到聚集与分散相匹配,发送与接收相匹配。也许您可以发布足够的代码来阐明您正在使用的操作。

最后,我认为通过乘以子矩阵来乘以矩阵可能不是 MPI 的有效方法。如果您将此作为练习,请继续。但更好的算法,而且可能更容易实现,将是

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

关于c - 在 C 中使用 MPI_Type_Vector 和 MPI_Gather,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2980843/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com