如何解决MPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 在循环中不起作用
我正在运行多个异步通信的进程。
- 进程 1 每隔一段时间向进程 2 发送一条消息。
- 进程 2 每隔一段时间检查一次消息。
- 如果没有消息可用,进程 2 会继续做其他事情,直到下一个时间间隔。
问题是:如果进程2在进程1发送任何东西之前就开始尝试接收,那么所有后续的接收也会失败。相反,如果进程 1 在进程 2 尝试接收之前发送任何消息,则所有后续接收都成功。
使用 Python 和 mpi4py
的最小示例:
import sys
from time import sleep
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
print("Process 1 started")
sys.stdout.flush()
sleep(3)
for i in range(10):
sys.stdout.flush()
comm.send(f"Message {i}",dest=1)
print(f"Process 1 sent message {i}")
sys.stdout.flush()
sleep(1)
elif rank == 1:
print("Process 2 started")
sys.stdout.flush()
sleep(1)
for i in range(1000):
req = comm.irecv()
success,message = req.test()
if success:
print(f"Process 2 received {message}")
else:
print(f"Process 2 didn't receive anything on attempt {i}")
sys.stdout.flush()
sleep(3)
给出以下输出:
Process 1 started
Process 2 started
Process 2 didn't receive anything on attempt 0
Process 1 sent message 0
Process 1 sent message 1
Process 2 didn't receive anything on attempt 1
Process 1 sent message 2
Process 1 sent message 3
Process 2 didn't receive anything on attempt 2
Process 1 sent message 4
Process 1 sent message 5
...
从进程 1 中删除第一个 sleep
会产生一个成功的发送/接收链:
Process 1 started
Process 2 started
Process 1 sent message 0
Process 1 sent message 1
Process 2 received Message 0
Process 1 sent message 2
Process 1 sent message 3
Process 2 received Message 1
Process 1 sent message 4
Process 1 sent message 5
Process 1 sent message 6
Process 2 received Message 2
我的实现中缺少什么才能使第一个版本正常工作?
解决方法
您的问题是您反复发出 Irecv
,但您只保留最后一个请求。所以消息可以被早期的 Irecv
捕获,但您不再有它的请求。您只需执行一次 Irecv
,然后循环执行 Test
即可解决此问题。
然而,这遇到了一个非常微妙的问题,即 Test
是局部的,可能不会强制“进步”。 Probe
和 Iprobe
都强制通信取得进展。
因此,您的修复并不是真正关于 Test
和 Probe
之间的区别,而是您已经消除了您的初始代码发布的许多问题。
问题出在使用 test()
来检查是否有等待传入的消息。正确的方法是使用probe
or iprobe
(不确定两者在mpi4py中的实际区别是什么):
修复后的工作示例:
if rank == 0:
print("Process 1 started")
sys.stdout.flush()
sleep(3)
for i in range(10):
sys.stdout.flush()
comm.send(i,dest=1)
print(f"Process 1 sent message {i}")
sys.stdout.flush()
sleep(1)
elif rank == 1:
print("Process 2 started")
sys.stdout.flush()
sleep(1)
for i in range(1000):
probe = comm.iprobe()
if probe:
message = comm.recv()
print(f"Process 2 received {message}")
else:
print(f"Process 2 didn't receive anything on attempt {i}")
sys.stdout.flush()
sleep(3)
https://www.mpich.org/static/docs/latest/www3/MPI_Iprobe.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。