我在 MPI 中使用非阻塞通信在进程之间发送各种消息。然而,我似乎陷入了僵局。我用过PADB(see here http://padb.pittman.org.uk/)查看消息队列并得到以下输出:
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_Waitall 在最后调用。
Update:代码可在这个要点 https://gist.github.com/909004
Update:我对代码进行了各种修改,但它仍然不能正常工作。新代码位于相同的要点 https://gist.github.com/909004,我得到的输出是这个要点 https://gist.github.com/910543。我对这段代码有很多疑问/问题:
当我在最后一个循环(打印所有数组)之前有一个 MPI_Barrier() 以确保在打印之前所有工作都已完成时,为什么最终循环的输出(打印所有数组)会散布在其余输出中?
从 0 级发送到 0 级是可能/明智的 - 这样可以吗? (当然,假设发布了正确的匹配接收)。
我在输出中收到很多非常奇怪的长数字,我认为这是某种内存覆盖问题或变量大小问题。有趣的是,这一定是 MPI 通信造成的,因为我将 new_array 初始化为值 9999.99,而通信显然导致它更改为这些奇怪的值。有什么想法吗?
总的来说,似乎发生了一些转置(矩阵的位似乎被转置了......),但绝对不是全部 - 正是这些即将出现的奇怪数字让我最担心!
使用时MPI_Isend
and MPI_Irecv
您必须确保在等待请求完成之前不要修改缓冲区,并且您肯定违反了这一点。如果您将所有接收数据都放入第二个矩阵而不是就地执行会怎样?
Also, global_x2 * global_y2
是你的标签,但我不确定它对于每个发送-接收对来说都是唯一的,这可能会把事情搞砸。如果将其切换为发送标签会发生什么(global_y2 * global_columns) + global_x2
和接收标签(global_x2 * global_columns) + global_y2
.
编辑:至于您关于输出的问题,我假设您正在通过在同一台计算机上运行所有进程并仅查看标准输出来测试这一点。当您这样做时,即使 printf 代码全部在屏障之前执行,您的输出也会被终端奇怪地缓冲。我有两种方法可以解决这个问题。您可以为每个进程打印到单独的文件,也可以将输出作为消息发送到进程 0 并让他执行所有实际打印。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)