gpt4 book ai didi

c++ - 在 for 循环中使用 MPI_Irecv 和 MPI_Isend

转载 作者:行者123 更新时间:2023-11-28 01:35:09 27 4
gpt4 key购买 nike

MPI_IsendMPI_Irecv 有问题。我正在研究按行分布的图的邻接矩阵。我们可以假设每个处理器包含一行。对于每对索引 (i,j) 我需要发送和接收 2 个整数。基本上,我需要从其他行接收一些其他信息才能进行计算。我是 MPI 的新手,在这里它进入了无限循环,我什至不确定它是否是在 for 循环中使用 MPI_IsendMPI_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 should send MLocal[0][0]=1 and MLocal[0][1]=1 to P0 in which P0 receives them as M_j0 and M_j1, respectively.

And

P0 should send MLocal[0][0]=0 and MLocal[0][1]=1 to P1 in which P1 receives them as M_j0 and M_j1, respectively.

    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_IsendMPI_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);

但是,它仍然会进入无限循环。

UPDATE:

我更新了代码,部分问题是因为处理器排名和匹配标签。我修复了那部分,但它仍然容易死锁,我想我知道问题出在哪里。而且可能无法解决。如果我有足够数量的处理器,将每一行分配给一个处理器,即 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 send and receive to/from P1 information for (0,1):"20" and wait(done)

P1 send and receive to/from P0 information for (1,0):"20" and wait(done)

P2 send and receive to/from P1 information for (3,1):"19" and wait

P3 send and receive to/from P0 information for (4,1):"6" and wait

第二次迭代:

P0 send and receive to/from P1 information for (0,2):"16" and wait

P1 send and receive to/from P2 information for (1,3):"19" and wait(done)

P2 was wainting for P1 (3,1):"19" then just recieved it and done!

P3 is waiting for P0 for (4,1):"6" and wait

第三次迭代:

P0 is waiting for P1 for (0,2):"16"

P1 send and receive to/from P3 information for (1,5):"19" and wait

P2 send and receive to/from P3 information for (3,5):"12" and wait

P3 is waiting for P0 for (4,1):"6"

第四次迭代:

P0 is waiting for P1 for (0,2):"16"

P1 is waiting for P3 for (1,5):"19"

P2 is waiting for P3 for (3,5):"12"

P3 is waiting for P0 for (4,1):"6"

现在都是互相等待,我觉得没有办法解决。 ptb 建议的解决方案可能有效,我会尝试那个。

不过,任何其他想法表示赞赏!

最佳答案

您发布的代码存在一些问题

  1. 每个处理器将循环遍历。但是在您的描述中,行分布在处理器之间,因此这可能是一个错误。
  2. 发送和接收的目的地和来源是相同的。因此,如果您考虑 j=0 的情况,MPI_Isend(...,j,...) 意味着每个级别都会向根进程发送一些内容。随后调用 MPI_IRecv(...,j,...), MPI_Wait,这意味着每个进程都将等待来自根进程的发送,但该发送永远不会到来。
  3. MPI_SendRecv 调用有相同的基本问题

挑战在于您需要发送和接收调用来匹配。一种方法(不一定是最高性能的)是通过 MPI_Isend 循环发布所有发送,然后使用 MPI_Probe、MPI_Recv 处理每个等级的 recvs(因为 recvs 的数量是发送的数量,你知道如何许多)。伪代码示例:

int send_count = 0;
for (int j=0; j<n; j++) {
if (matrix_entry[j] != 0) {
call MPI_Isend(M_local, 2, MPI_INT, j, 0, ...)
send_count++;
}
}
while (send_count) {
MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, comm, status)
/* get source from status and then call recv */
MPI_Recv(M_j01, 2, MPI_INTEGER, status(MPI_SOURCE), ...)
/* Do something with M_j01 */
send_count--;
}

关于c++ - 在 for 循环中使用 MPI_Irecv 和 MPI_Isend,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49642581/

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