MPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 不会在循环中工作
Posted
技术标签:
【中文标题】MPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 不会在循环中工作【英文标题】:MPI (mpi4py) - irecv() and test() don't work in loop if first test() returned false 【发布时间】:2021-09-21 14:47:03 【问题描述】:我正在运行几个异步通信的进程。
进程 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
指定source=0
会怎样?
【参考方案1】:
您的问题是您反复发出Irecv
,但您只保留最后一个请求。因此,该消息可以被早期的Irecv
捕获,但您不再需要它了。您可以通过只执行一次Irecv
来解决此问题,然后循环执行Test
。
但是,这遇到了一个非常微妙的问题,Test
是本地的,并且可能不会强制“进步”。 Probe
和 Iprobe
都强制通信进行。
因此,您的修复并不是真正关于Test
和Probe
之间的区别,而是您已经消除了您的初始代码发出许多接收的问题。
【讨论】:
【参考方案2】:原来问题在于使用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
【讨论】:
以上是关于MPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 不会在循环中工作的主要内容,如果未能解决你的问题,请参考以下文章