【问题标题】:MPI (mpi4py) - irecv() and test() don't work in loop if first test() returned falseMPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 不会在循环中工作
【发布时间】: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 会怎样?

标签: python mpi mpi4py


【解决方案1】:

您的问题是您反复发出Irecv,但您只保留最后一个请求。因此,该消息可以被早期的Irecv 捕获,但您不再需要它了。您可以通过只执行一次Irecv 来解决此问题,然后循环执行Test

但是,这遇到了一个非常微妙的问题,Test 是本地的,并且可能不会强制“进步”。 ProbeIprobe 都强制通信进行。

因此,您的修复并不是真正关于TestProbe 之间的区别,而是您已经消除了您的初始代码发出许多接收的问题。

【讨论】:

    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-31
      • 2016-03-28
      • 2021-03-16
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多