我正在尝试将平方矩阵与 MPI 并行相乘。
我使用 MPI_Type_vector 将方形子矩阵(浮点数组)发送到进程,以便它们可以计算子产品。然后,对于下一次迭代,这些子矩阵作为 MPI_Type_contiguous 发送到相邻进程(发送整个子矩阵)。这部分按预期工作,并且本地结果是正确的。
然后,我使用 MPI_Gather 和连续类型将所有本地结果发送回根进程。问题是,最终的矩阵是逐行构建的(显然,通过这种方法),而不是逐个子矩阵。
我写了一个丑陋的程序来重新排列最终的矩阵,但我想知道是否有一种直接的方式来执行发送 MPI_Type_vectors 的“逆”操作(即,发送一个值数组并直接以子数组形式排列在接收阵列)。
一个例子,试图澄清我的长文本:
A[16] 和 B[16]
这些确实是二维数组,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]。
计算完所有内容后,根进程收集所有 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 方面的专家,远非 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 传输到 CPU。当然,届时将考验全球效率。
0 你说“相同的类型定义应该适用于反向操作”。但是,我的 MPI_Vector_type 在“大”矩阵上运行良好,但无法直接在子矩阵上使用它(在 2x2 矩阵上应用 MPI_Vector_type(2, 2, 4) 会产生错误的结果,因为它需要最后两个值“在”定义的数组“之外”......)。你的意思是我应该创建另一个 MPI_Vector_type 并发送/接收它?