f2py 和 MPI 池:在集群上删除父作业时子进程继续

str*_*fel 5 python fortran cluster-computing mpi f2py

我运行一个30核心的Python使用群集上的工作MPIPool。当我通过无处不在的qdel <job ID>命令删除作业时,只有父进程被杀死,而子进程继续运行。换句话说:qdel使作业 ID 从队列中消失,但 30(= 核数)启动的 Python 进程仍然存在于后台,对集群负载贡献很大。此外,我只能“手动”杀死我登录的一个节点上的后台进程。

另一件使事情复杂化的事情是,我的 Python 脚本调用了一段Fortran代码(我正在使用该f2py模块来实现这一点)。我过去注意到,在本地运行程序时,Fortran 不响应Ctrl+C中断。一旦它再次到达 Python 层,程序就会中止。

我已经查阅了与 相关的文档MPIPool,我用它来并行化工作,但我没有设法查明到底哪里出错了。理想情况下,我希望子进程定期调用其父进程,并在注意到父进程不再存在时自行终止。目前看来,删除作业只是切断了将父母和孩子联系在一起的绳索,而不是删除孩子。

下面的代码片段显示了池对象如何集成到我的主代码中。此外,我使用 bash 脚本将作业提交到集群队列(包含echo 'mpirun -np '$NCORES' python '$SKRIPTNAME >> $TMPFILE)并请求我想要使用的核心数。后者应该可以正常工作。

import emcee 
from emcee.utils import MPIPool

pool = MPIPool()

    if not pool.is_master():
        pool.wait()
        sys.exit(0)

sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, pool = pool) 
pos, prob, state = sampler.run_mcmc(p0, 1000) # p0 contains the initial walker positions

pool.close()
Run Code Online (Sandbox Code Playgroud)

背景:我使用该emcee模块进行蒙特卡罗模拟。lnprob是对在特定迭代中绘制的参数集进行评估的似然函数。lnprob调用 Fortran 脚本来处理计算量大的部分。

编辑:请在下面找到问题仍然存在的最小脚本。我已经能够验证这f2py显然不会导致问题:

import numpy as np
import sys
import emcee
from emcee.utils import MPIPool

def calc_log_prob(a,b,c,d):

    for i in np.arange(1000):
        for j in np.arange(1000):
            for k in np.arange(1000):
                for g in np.arange(1000):
                    x = i + j + k + g

    return -np.abs(a + b) 

def lnprob(x):
    return calc_log_prob(*x)

ndim, nwalkers = 4, 180

p0 = [np.array([np.random.normal(loc = -5.5, scale = 2., size=1)[0], \
            np.random.normal(loc = -0.3, scale = 1., size=1)[0], \
            0.+3000.*np.random.uniform(size=1)[0], \
            -6.+3.*np.random.uniform(size=1)[0]]) for i in range(nwalkers)]

with MPIPool() as pool:

    if not pool.is_master():
        # Wait for instructions from the master process.
        pool.wait()
        sys.exit(0)

    sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, pool = pool)

    pos, prob, state = sampler.run_mcmc(p0, 560)

pool.close()
Run Code Online (Sandbox Code Playgroud)

此脚本严格遵循emcee 文档中概述的示例,并pool正确合并。老实说,我完全不知道这种故障的根源在哪里。我几乎倾向于说这个问题更多地与集群相关。