我正在使用MPI编写应用程序(实际上是mpi4py)。应用程序可能会使用MPI_Comm_spawn()
(统称在所有当前进程上)生成一些新进程,并且来自父组/通信器的某些节点可能将数据发送到子组/通信器中的一些节点,反之亦然。 (注意MPI_Comm_spawn()
和数据发送/接收正在不同的线程中发生功能[有其他功能与这个问题没有直接关系,因此我没有描述]和性能。)
因为可能会多次调用MPI_Comm_spawn()
函数,并且我希望所有节点可以相互通信,所以我目前计划使用{{1将两个组(父和子)合并为一个内部通信器,然后通过新的内部通信器发送数据(下一个MPI_Intercomm_merge()
将在新的内部通信器上发生。)
但是,由于生成和合并过程在程序运行期间发生,因此将会有一些数据通过旧的通信器发送(但可能尚未被dest接收)。我怎样才能安全地从旧的通信器切换到新的通信器(例如,能够在某些时候删除旧的通信器),同时失去最低的性能? MPI_Comm_spawn()
是我知道保证所有进程可以相互发送数据的唯一方法(因为如果我们不合并,下次我们调用MPI_Comm_merge()
时,某些进程无法直接发送数据彼此),我不介意只要它运作良好就把它改成另一种方法。
例如,在下图中,流程A,B,C是初始流程(MPI_Comm_merge()
),D是生成流程:
A和B将连续数据发送给C;在发送期间,D产生;然后C将数据发送给D.假设旧的通信器A,B和C使用的是mpiexec -np 3
,并且合并的内部通信器是comm1
。
我想要实现的是最初通过comm2
发送数据,并且在生成D之后(所有进程)切换到comm1
。缺少的是一种机制,可以知道何时C可以安全地从comm2
切换到comm1
以从A和/或B接收数据,然后我可以安全地呼叫comm2
。
简单地在切换时通过MPI_Comm_free(comm1)
发送特殊标签将是最后一个选项,因为C不知道有多少进程将数据发送给它。它确实知道有多少组进程会向其发送数据,因此可以通过引入当地领导来实现(但我想了解其他选项)。
由于comm1
,A
和B
正在处理parellel而C
/ send
和recv
正在不同的主题中发生,我们不能当我们致电spawn
时,保证没有待处理的数据。例如。如果我们想象MPI_Comm_spawn()
和A
处理B
和send
处理C
的费率相同,那么当他们调用recv
时,{{1}我只收到了来自comm_spawn
和C
的一半数据,因此我们无法将A
放在B
,但必须等到comm1
已收到C
的所有待处理数据(这是一个未知数量的消息)。
MPI或mpi4py是否提供了任何机制(例如错误代码或例外)来实现此目的?
顺便说一句,如果我的做法显然不好或者我误解了C
的做法,请指出。
(我的理解是comm1
不是集体电话;在致电MPI_Comm_free()
后,相同节点上不再允许向MPI_Comm_free()
发送/接听电话它调用MPI_Comm_free(comm1)
)
答案 0 :(得分:0)
基本上,C
会调用MPI_Comm_spawn(..., MPI_COMM_SELF, ...)
为什么不让{A,B,C}
调用MPI_Comm_spawn(..., comm1, ...)
?
MPI_Intercomm_merge()
是一个集体操作,因此您需要以某种方式“同步”您的任务,那么为什么不在MPI_Comm_spawn()
之前“同步”它们呢?
然后切换到新的通信器是微不足道的