Mpi4py mpi_test 总是 returns 错误
Mpi4py mpi_test always returns false
我在这里找不到类似的问题,所以这里是:
为什么下面的代码总是输出(False, None)
?如果在进程 0 发送消息后 3 秒调用 test()
,它不应该是 (True, None)
吗?另外,如果我在 test()
之前调用 req.wait()
我得到了我需要的输出,但是它不是不可阻塞的,所以 test()
失去了它的目的(我想能够告诉进程 1 在它休眠的那 3 秒内收到了来自任何来源的消息)
代码:
import time
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
req = comm.isend(0, 1, tag=0);
req.wait();
elif rank == 1:
req = comm.irecv();
time.sleep(3);
print req.test();
我不是 mpi4py 方面的专家,但假设它的行为类似于它的 MPI C 对应物(这似乎是一个合理的假设)那么确实,这里没有什么惊喜。
嗯,公平地说,MPI 标准并未规定您的代码输出。保证的是,在 次 次调用 MPI_Test()
函数后,它将 return true
。这个数字可以是任何东西,因此它 return true
在第一次调用时,或者在第二次调用时,或者仅在十亿次调用之后......因此, usual/recommended 使用 MPI_Test()
函数是在这里和那里使用它,并以它的无限循环(基于其输出的退出条件)结束,或者使用 MPI_Wait()
调用。
现在,原因如下:MPI 库通常不执行显式 MPI 调用之外的任何操作。因此,为了看到非阻塞通信的进展,您必须执行 some MPI 调用。这些调用不需要与常设通信相关(通常任何 MPI 调用都会在内部触发消息队列的某种程度的进度)但您需要将手交给 MPI 库才能获得它。这就是对 MPI_Test()
的调用所做的。这也解释了为什么这不是真正与时间相关的:您对 sleep()
函数的调用确实为通信的发生提供了时间,但是由于 MPI 库没有在两者之间得到帮助,所以什么也没有真的发生了。
最后,对我的上述解释进行一些调整:
- 以上假定没有外部 机制来处理传输中的消息。然而,(远程)直接内存访问引擎,例如 InfiniBand 卡上可用的引擎,确实可以处理消息而无需进行额外的 MPI 调用。但是,这通常只会发生在节点间通信时,并且高度依赖于您的硬件和软件。
- 一些 MPI 库作为扩展提供了一种可能性,即专用于 CPU 线程以在 MPI 调用之外进行 MPI 通信。一些基于 MPICH 的 MPI 库,例如 Intel MPI,建议
MPICH_ASYNC_PROGRESS
环境变量,一旦设置为 1
,将触发创建此 MPI 通信线程以进行非阻塞通信现场。不确定 OpenMPI 是否也提供此功能...
也许这只是因为您通过编辑一个更大的程序创建了这个示例,但我只是想检查一下它们是不是对非阻塞 MPI 通信存在一些潜在的误解...
我不明白你为什么有:
req = comm.isend(0, 1, tag=0);
req.wait();
因为这在功能上与阻塞调用相同
comm.send(0, 1, tag=0);
当然,非阻塞形式意味着您稍后可以在 isend 和 wait 之间插入更多代码,这也许正是您想要做的。
我在这里找不到类似的问题,所以这里是:
为什么下面的代码总是输出(False, None)
?如果在进程 0 发送消息后 3 秒调用 test()
,它不应该是 (True, None)
吗?另外,如果我在 test()
之前调用 req.wait()
我得到了我需要的输出,但是它不是不可阻塞的,所以 test()
失去了它的目的(我想能够告诉进程 1 在它休眠的那 3 秒内收到了来自任何来源的消息)
代码:
import time
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
req = comm.isend(0, 1, tag=0);
req.wait();
elif rank == 1:
req = comm.irecv();
time.sleep(3);
print req.test();
我不是 mpi4py 方面的专家,但假设它的行为类似于它的 MPI C 对应物(这似乎是一个合理的假设)那么确实,这里没有什么惊喜。
嗯,公平地说,MPI 标准并未规定您的代码输出。保证的是,在 次 次调用 MPI_Test()
函数后,它将 return true
。这个数字可以是任何东西,因此它 return true
在第一次调用时,或者在第二次调用时,或者仅在十亿次调用之后......因此, usual/recommended 使用 MPI_Test()
函数是在这里和那里使用它,并以它的无限循环(基于其输出的退出条件)结束,或者使用 MPI_Wait()
调用。
现在,原因如下:MPI 库通常不执行显式 MPI 调用之外的任何操作。因此,为了看到非阻塞通信的进展,您必须执行 some MPI 调用。这些调用不需要与常设通信相关(通常任何 MPI 调用都会在内部触发消息队列的某种程度的进度)但您需要将手交给 MPI 库才能获得它。这就是对 MPI_Test()
的调用所做的。这也解释了为什么这不是真正与时间相关的:您对 sleep()
函数的调用确实为通信的发生提供了时间,但是由于 MPI 库没有在两者之间得到帮助,所以什么也没有真的发生了。
最后,对我的上述解释进行一些调整:
- 以上假定没有外部 机制来处理传输中的消息。然而,(远程)直接内存访问引擎,例如 InfiniBand 卡上可用的引擎,确实可以处理消息而无需进行额外的 MPI 调用。但是,这通常只会发生在节点间通信时,并且高度依赖于您的硬件和软件。
- 一些 MPI 库作为扩展提供了一种可能性,即专用于 CPU 线程以在 MPI 调用之外进行 MPI 通信。一些基于 MPICH 的 MPI 库,例如 Intel MPI,建议
MPICH_ASYNC_PROGRESS
环境变量,一旦设置为1
,将触发创建此 MPI 通信线程以进行非阻塞通信现场。不确定 OpenMPI 是否也提供此功能...
也许这只是因为您通过编辑一个更大的程序创建了这个示例,但我只是想检查一下它们是不是对非阻塞 MPI 通信存在一些潜在的误解...
我不明白你为什么有:
req = comm.isend(0, 1, tag=0);
req.wait();
因为这在功能上与阻塞调用相同
comm.send(0, 1, tag=0);
当然,非阻塞形式意味着您稍后可以在 isend 和 wait 之间插入更多代码,这也许正是您想要做的。