【发布时间】:2018-09-13 12:26:11
【问题描述】:
我对@987654322@ 和MPI_Irecv 有疑问。我正在研究一个图形的邻接矩阵,它是按行分布的。我们可以假设每个处理器包含一行。对于每对索引(i,j),我需要发送和接收 2 个整数。基本上,我需要从其他行接收一些其他信息才能进行计算。我是 MPI 的新手,在这里它进入无限循环,我什至不确定在 for 循环中使用 MPI_Isend 或 MPI_Irecv 是否正确,也是等待的地方。
例如,假设我们有一个包含 6 个顶点的图,因此邻接矩阵 (adjMatrix) 将是一个 6*6 矩阵,我们还有一个 6*2 矩阵来存储一些其他信息,并且最后,我们在 6 个处理器之间分配数据。因此:
|0 20 16 0 6 0 | |0 1|
|20 0 0 19 0 6 | |1 1|
addMatrix=|16 0 0 0 12 0 | M=|2 1|
|0 19 0 0 0 12| |3 1|
|6 0 12 0 0 9 | |0 0|
|0 6 0 12 9 0 | |1 0|
我们将矩阵分布如下:
P0: |0 20 16 0 6 0 | |0 1|
P1: |20 0 0 19 0 6 | |1 1|
P2: |16 0 0 0 12 0 | |2 1|
P3: |0 19 0 0 0 12| |3 1|
P4: |6 0 12 0 0 9 | |0 0|
P5: |0 6 0 12 9 0 | |1 0|
现在,每个处理器都需要更新其adjMatrix 部分。为此,他们需要来自矩阵M 某些部分的信息,该部分位于其他处理器中。例如,为了P0 更新索引(0,1) 即20,它需要能够访问矩阵M 的行1 即{1,1}。因此:
P1应该将MLocal[0][0]=1和MLocal[0][1]=1发送到P0其中P0分别以M_j0和M_j1接收它们。和
P0应该将MLocal[0][0]=0和MLocal[0][1]=1发送到P1其中P1分别以M_j0和M_j1接收它们。
for(int i=0;i<rows;i++){
for (int j=0; j<n; j++)
{
int M_j0,M_j1;
MPI_Isend(&MLocal[i][0], 1, MPI_INT, j, my_rank+i*n+j+0, MPI_COMM_WORLD, &send_request0);
MPI_Isend(&MLocal[i][1], 1, MPI_INT, j, my_rank+i*n+j+1, MPI_COMM_WORLD, &send_request1);
MPI_Irecv(&M_j0, 1, MPI_INT, j, my_rank+i*n+j+0, MPI_COMM_WORLD, &recv_request0);
MPI_Irecv(&M_j1, 1, MPI_INT, j, my_rank+i*n+j+1, MPI_COMM_WORLD, &recv_request1);
//MPI_Wait(&send_request0, &status);
//MPI_Wait(&send_request1, &status);
MPI_Wait(&recv_request0, &status);
MPI_Wait(&recv_request1, &status);
// Do something ...
}
}
然后根据 GillesGouaillardet 的建议,我将 4 MPI_Isend 和 MPI_Irecv 更改为:
MPI_Sendrecv(&MoatsLocal[i][0], 1, MPI_INT, j, my_rank+i*n+j+0, &M_j0,1, MPI_INT, my_rank, my_rank+i*n+j+0, MPI_COMM_WORLD, &status);
MPI_Sendrecv(&MoatsLocal[i][1], 1, MPI_INT, j, my_rank+i*n+j+1, &M_j1,1, MPI_INT, my_rank, my_rank+i*n+j+1, MPI_COMM_WORLD, &status);
但是,它仍然进入了一个无限循环。
更新:
我更新了代码,部分问题是因为处理器排名和匹配标签。我修复了那个部分,但它仍然容易出现死锁,我想我知道问题出在哪里。而且可能无法解决。如果我有足够数量的处理器,将每条线分配给一个处理器,即 n=p,这不会有任何问题。但问题是处理器的数量少于n,然后流不是很好地通过主对角线我通过示例解释它,让我们假设我们有 4 个处理器和n=6。假设这里是分布:
P0: |0 20 16 0 6 0 | |0 1|
P1: |20 0 0 19 0 6 | |1 1|
|16 0 0 0 12 0 | |2 1|
P2: |0 19 0 0 0 12| |3 1|
P3: |6 0 12 0 0 9 | |0 0|
|0 6 0 12 9 0 | |1 0|
这就是循环中发生的事情。
第一次迭代:
P0 向/从 P1 发送和接收 (0,1):"20" 的信息并等待(完成)
P1 向/从 P0 发送和接收 (1,0):"20" 的信息并等待(完成)
P2 向/从 P1 发送和接收 (3,1):"19" 的信息并等待
P3 向/从 P0 发送和接收 (4,1):"6" 的信息并等待
第二次迭代:
P0 向/从 P1 发送和接收 (0,2):"16" 的信息并等待
P1 向/从 P2 发送和接收 (1,3):"19" 的信息并等待(完成)
P2 正在等待 P1 (3,1):"19" 然后刚刚收到并完成!
P3 正在等待 P0 for (4,1):"6" 并等待
第三次迭代:
P0 正在等待 P1 的 (0,2):"16"
P1 向/从 P3 发送和接收 (1,5):"19" 的信息并等待
P2 向/从 P3 发送和接收 (3,5):"12" 的信息并等待
P3 正在等待 P0 的 (4,1):"6"
第四次迭代:
P0 正在等待 P1 的 (0,2):"16"
P1 正在等待 P3 的 (1,5):"19"
P2 正在等待 P3 等待 (3,5):"12"
P3 正在等待 P0 的 (4,1):"6"
现在,大家都在互相等待,我觉得没有什么办法可以解决。 ptb 建议的解决方案可能有效,我会尝试那个。
不过,任何其他想法都值得赞赏!
【问题讨论】:
-
可以使用4个请求的数组,然后
MPI_Waitall(4, ...); -
你也可以使用两个
MPI_Sendrecv() -
@GillesGouaillardet 我照你说的做了。仍然有同样的问题。
-
@GillesGouaillardet 我更新了它。任何帮助表示赞赏。
标签: c++ matrix mpi distributed-computing distributed-system