MPI 信号处理

5 投票
3 回答
3409 浏览
提问于 2025-04-15 12:59

在使用 mpirun 的时候,能不能在运行的代码里捕捉到信号(比如说按下 ^C 产生的 SIGINT)呢?

举个例子,我在运行一个并行的 Python 代码。当我单独运行 python blah.py 的时候,可以用 except KeyboardInterrupt 来捕捉这些错误,但当我用 mpirun -np 1 python blah.py 运行时,就捕捉不到了。

有没有人有建议?即使是找到如何在 C 或 C++ 编译的程序中捕捉信号,也会是个不错的开始。

如果我给启动的 Python 进程发送信号,它们可以正确处理这些信号;但是,如果信号是发送给父进程 orterun(比如说因为超出集群的最大运行时间,或者在终端按下控制-C),那么所有的进程会立刻被杀掉。

3 个回答

-2

这个 signal 模块可以用来设置信号处理器,使用的方法是 signal.signal

你可以为某个信号(signalnum)设置一个处理函数(handler)。这个处理函数可以是一个可以调用的 Python 对象,它需要接受两个参数(具体内容见下文),或者可以是一些特殊的值,比如 signal.SIG_IGN(忽略信号)或 signal.SIG_DFL(使用默认处理)。之前的信号处理器会被返回 ...

import signal
def ignore(sig, stack):
  print "I'm ignoring signal %d" % (sig, )

signal.signal(signal.SIGINT, ignore)
while True: pass

如果你向正在运行这个脚本的 Python 解释器发送一个 SIGINT 信号(通过 kill -INT <pid> 命令),它会打印一条消息,然后继续运行。

1

如果你使用 mpirun --nw,那么 mpirun 在启动了子进程后应该会立即结束,而不是等到这些子进程结束后才退出;如果这样可以接受的话,我认为你的进程能够自己处理信号。

3

我觉得这真的要看具体的实现。

  • 在SLURM中,我尝试使用 sbatch --signal USR1@30 来发送 SIGUSR1 信号(它的编号是30、10或16)给通过 srun 命令启动的程序。结果这个进程收到了信号 SIGUSR1 = 10

  • 对于IBM的MPI平台,具体情况可以参考这个链接

SIGINT, SIGUSR1, SIGUSR2 这些信号会被传递给进程。

  • 在MPICH中,SIGUSR1被进程管理器用来内部通知异常故障。参考链接:这个链接

  • 而Open MPI会将mpiexec中的SIGUSR1和SIGUSR2信号转发给其他进程。参考链接:这个链接

  • 对于IntelMPI,可以参考这个链接

I_MPI_JOB_SIGNAL_PROPAGATIONI_MPI_JOB_TIMEOUT_SIGNAL 可以设置来发送信号。

还有一点值得注意的是:对于很多Python脚本,它们会通过Cython调用其他库或代码,如果子进程捕获了 SIGUSR1,可能会发生一些意想不到的事情。

撰写回答