我面临着一种特殊的情况。
我有一个MPI程序,可以创建16个MPI进程 mpirun -np 16 a.out
现在我希望所有这16个进程运行一段固定时间,比如60秒,之后他们都应该将结果报告给一个公共进程(比如排名为0的进程)。
所以我将在60秒后从0级进行收集。现在,我如何确保所有进程在60秒后停止?
伪代码:
/*All processes (except 0) are doing the following:*/
while (1) {
MPI_Send (to process 0)
MPI_Recv (from process 0)
}
/*Process 0 roughly does the following:*/
while(1) {
MPI_Recv (from any other process)
Process the request
MPI_Send (back to clients)
}
/* After 60 seconds, stop all processes and gather results at Process 0. */
1. Catch a SIGALRM signal after 60 secs.
2. Do dummy MPI_Irecv(any source) to ensure that it any client blocking on MPI_Send() is woken up.
3. Now do an MPI_Send to all clients with a special value in buffer telling them to terminate.
4. MPI_gather from all clients.
进程0的作用类似于服务器,其余的是客户端。
我尝试使用信号处理(SIGALRM),但文档说使用MPI信号处理是不安全的。
如果无法使用信号,那么我们该如何处理?
答案 0 :(得分:1)
我相信Leslie Lamport证明了分布式系统没有绝对的时间。类似于狭义相对论,每个过程从其自身的角度来看具有相对时间。也就是说,如果你想在程序启动后大约60秒停止(从外部观察者的角度来看),只有一个进程应该监视时钟并决定停止。
考虑到你所说的,过程0似乎是理想的候选者。既然你不能使用SIGALARM(我不认为任何其他异步方法真的适合像你这样的紧密同步的MPI应用程序),我的建议是在你的进程0 MPI_Recv
之后立即检查系统时间。现在减去时间与流程开始的时间,如果它大于60,则通过MPI_Send
将0信号发送到所有其他流程停止。
编辑:现在我明白过程0单独响应每个请求,程序应该有点不同。
在进程0的每个MPI_Recv
之后,检查自执行开始以来是否已经过了60秒。如果有,请响应当前客户端进程退出,然后退出循环,并执行以下操作:
for(int i = 2; i < 16; ++i) {
MPI_Status s;
MPI_Recv(buf, count, datatype, MPI_ANY, tag, comm, &s);
MPI_Send(message_to_quit, count, datatype, s.MPI_SOURCE, tag, comm);
}
这样,进程0将等待,并在自行退出之前发出其他每个进程的信号。
答案 1 :(得分:0)
Ivella给出的建议有效。除了我必须做一个更改。
在流程0中:
60秒到期后(使用gettimeofday计算) 打破while循环并执行以下操作:
进入另一个循环约5秒,其中进程0将使用MPI_Iprobe继续探测是否有任何客户端正在等待MPI_Send。
如果MPI_Iprobe将标志设置为true,则从进程0发出MPI_Recv以确保所有客户端现在都来自MPI_Send并且正在等待MPI_Recv上的响应。
此时,向每个宣布终止的客户发送一个特殊字符。
现在所有进程执行MPI_Reduce,目标设置为进程0,之后它们都终止。
60秒到期后的伪代码:
timeout = 5 secs
while (time < timeout) {
MPI_Iprobe(any_source, flag,...)
/*this is to ensure that all waiting clients are unblocked from MPI_Send*/
if (flag != 0) {
MPI_Recv(status.MPI_SOURCE);
}
}
现在, 向所有宣布终止的客户发出MPI_Send,然后发出MPI_Reduce(或收集)并退出。