首页 文章

如何在核心空闲时添加进程,在python中执行批量计算?

提问于
浏览
3

Bash具有“wait -n”功能,可以相对简单的方式使用该功能来暂停子进程的后续执行,直到一定数量的处理器内核可用 . 例如 . 我可以做到以下几点,

for IJOB in IJOBRANGE;
do

    ./func.x ${IJOB}

    # checking the number of background processes
    # and halting the execution accordingly

    bground=( $(jobs -p) );

    if (( ${#bground[@]} >= CORES )); then
        wait -n
    fi

done || exit 1

此代码段可以批处理执行具有不同参数的任意C进程“func.x”,并始终维护子进程的固定数量的并行实例,设置为值“CORES” .

我想知道是否可以使用python脚本和python子进程(或函数)完成类似的操作 . 目前,我定义了一个python函数,设置了一个一维参数数组,并使用python多处理模块中的Pool例程来并行计算参数数组上的函数 . 池函数执行我的函数评估的设定数量(在以下示例中为CPU CORES)并等待,直到生成的进程的所有实例都已结束,然后再转移到下一批 .

import multiprocessing as mp

def func(x):

    # some computation with x

def main(j):

    # setting the parameter array
    xarray = range(j)

    pool = mp.Pool()
    pool.map(func,xarray)

我想知道是否有可能修改这个片段,以便始终执行我的子例程的固定数量的并行计算,即,只要其中一个子进程完成就添加另一个进程 . 这里的所有“func”进程都应该是独立的,执行顺序也无关紧要 . 我是python方式的新手,拥有一些有用的观点真的很棒 .

1 回答

  • 1

    在我们在评论中讨论之后,这里有一些改编自你的测试代码,显示 Pool 在为可用的工作人员分配新的任务之前不等待所有并行任务完成:

    import multiprocessing as mp
    from time import sleep, time
    
    
    def func(x):
        """sleeps for x seconds"""
        name = mp.current_process().name
        print("{} {}: sleep {}".format(time(), name, x))
        sleep(x)
        print("{} {}: done sleeping".format(time(), name))
    
    
    def main():
    
        # A pool of two processes, for the sake of simplicity
        pool = mp.Pool(processes=2)
        # Here's how that works out visually:
        #
        #    0s        1s       2s        3s
        # P1 [sleep(1)][     sleep(2)     ]
        # P2 [     sleep(2)     ][sleep(1)]
        sleeps = [1, 2, 2, 1]
        pool.map(func, sleeps)
    
    
    if __name__ == "__main__":
        main()
    

    运行此代码给出(为简化起见,简化了时间戳):

    $ python3 mp.py 
    0s: ForkPoolWorker-1: sleep 1
    0s: ForkPoolWorker-2: sleep 2
    1s: ForkPoolWorker-1: done sleeping
    1s: ForkPoolWorker-1: sleep 2
    2s: ForkPoolWorker-2: done sleeping
    2s: ForkPoolWorker-2: sleep 1
    3s: ForkPoolWorker-1: done sleeping
    3s: ForkPoolWorker-2: done sleeping
    

    我们可以看到第一个进程在开始第二个任务之前不会等待第二个进程完成其第一个任务 .

    所以我想这应该回答你提出的观点,希望我能清楚地理解你 .

相关问题