【发布时间】:2011-02-28 04:18:27
【问题描述】:
我正在尝试将平方矩阵与 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] 包含:
[
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 方面的专家,远非 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 并发送/接收它?
【问题讨论】: