2

我在 MPI 中使用非阻塞通信在进程之间发送各种消息。但是,我似乎陷入了僵局。我使用 PADB(请参见此处)查看消息队列并得到以下输出:

1:msg12: Operation 1 (pending_receive) status 0 (pending)
1:msg12: Rank local 4 global 4
1:msg12: Size desired 4
1:msg12: tag_wild 0
1:msg12: Tag desired 16
1:msg12: system_buffer 0
1:msg12: Buffer 0xcaad32c
1:msg12: 'Receive: 0xcac3c80'
1:msg12: 'Data: 4 * MPI_FLOAT'
--
1:msg32: Operation 0 (pending_send) status 2 (complete)
1:msg32: Rank local 4 global 4
1:msg32: Actual local 4 global 4
1:msg32: Size desired 4 actual 4
1:msg32: tag_wild 0
1:msg32: Tag desired 16 actual 16
1:msg32: system_buffer 0
1:msg32: Buffer 0xcaad32c
1:msg32: 'Send: 0xcab7c00'
1:msg32: 'Data transfer completed'
--
2:msg5: Operation 1 (pending_receive) status 0 (pending)
2:msg5: Rank local 1 global 1
2:msg5: Size desired 4
2:msg5: tag_wild 0
2:msg5: Tag desired 16
2:msg5: system_buffer 0
2:msg5: Buffer 0xabbc348
2:msg5: 'Receive: 0xabd1780'
2:msg5: 'Data: 4 * MPI_FLOAT'
--
2:msg25: Operation 0 (pending_send) status 2 (complete)
2:msg25: Rank local 1 global 1
2:msg25: Actual local 1 global 1
2:msg25: Size desired 4 actual 4
2:msg25: tag_wild 0
2:msg25: Tag desired 16 actual 16
2:msg25: system_buffer 0
2:msg25: Buffer 0xabbc348
2:msg25: 'Send: 0xabc5700'
2:msg25: 'Data transfer completed'

这似乎表明发送已完成,但所有接收都处于挂起状态(以上只是标记值为 16 的日志的一小部分)。然而,这怎么可能发生呢?如果没有相关的接收完成,发送肯定无法完成,因为在 MPI 中,所有发送和接收都必须匹配。至少我是这么认为的……

任何人都可以提供任何见解吗?

我可以提供我用来执行此操作的代码,但是无论调用它们的顺序如何,Isend 和 Irecv 肯定都应该工作,假设 MPI_Waital 在最后被调用。

更新:代码在这个要点上可用

更新:我对代码进行了各种修改,但仍然不能正常工作。新代码是相同的 gist,我得到的输出就是这个 gist。我对此代码有很多疑问/问题:

  1. 当我在它之前有一个 MPI_Barrier() 以确保在打印之前完成所有工作时,为什么最终循环的输出(打印所有数组)与其余输出穿插在一起?

  2. 从 0 级发送到 0 级是可能/明智的 - 可以吗?(当然,假设发布了正确的匹配接收)。

  3. 我在输出中得到了很多非常奇怪的长数字,我认为这是某种内存覆盖问题或变量大小问题。有趣的是,这一定是由 MPI 通信引起的,因为我将 new_array 初始化为 9999.99 的值,而通信显然导致它被更改为这些奇怪的值。任何想法为什么?

总体而言,似乎发生了一些转置(矩阵的位似乎被转置了......),但绝对不是全部 - 正是这些奇怪的数字即将出现让我最担心!

4

1 回答 1

4

使用时MPI_IsendMPI_Irecv您必须确保在等待请求完成之前不要修改缓冲区,您肯定违反了这一点。如果你让所有的收据都进入第二个矩阵而不是原地做呢?

另外,global_x2 * global_y2是您的标签,但我不确定它对于每个发送-接收对是否都是唯一的,这可能会搞砸事情。如果将其切换为发送标签(global_y2 * global_columns) + global_x2和接收标签会发生什么(global_x2 * global_columns) + global_y2

编辑:至于您关于输出的问题,我假设您通过在同一台机器上运行所有进程并仅查看标准输出来对此进行测试。当你这样做时,你的输出会被终端奇怪地缓冲,即使 printf 代码都在屏障之前执行。我有两种方法可以解决这个问题。您可以为每个进程打印到单独的文件,也可以将输出作为消息发送到进程 0 并让他进行所有实际打印。

于 2011-04-08T19:09:42.560 回答