繁体   English   中英

Python 多处理模块:加入超时的进程

[英]Python multiprocessing module: join processes with timeout

我正在对复杂模拟的参数进行优化。 我使用多处理模块来提高优化算法的性能。 我在http://pymotw.com/2/multiprocessing/basics.html学到了多处理的基础知识。 根据优化算法的给定参数,复杂模拟持续不同的时间,大约 1 到 5 分钟。 如果参数选择得非常糟糕,模拟可能会持续 30 分钟或更长时间,并且结果没有用。 所以我在考虑建立多处理超时,终止所有持续超过定义时间的模拟。 这是问题的抽象版本:

import numpy as np
import time
import multiprocessing

def worker(num):

    time.sleep(np.random.random()*20)

def main():

    pnum = 10    

    procs = []
    for i in range(pnum):
        p = multiprocessing.Process(target=worker, args=(i,), name = ('process_' + str(i+1)))
        procs.append(p)
        p.start()
        print 'starting', p.name

    for p in procs:
        p.join(5)
        print 'stopping', p.name

if __name__ == "__main__":
    main()

p.join(5)定义了 5 秒的超时。 由于for p in procs:的 for 循环for p in procs:程序等待 5 秒直到第一个进程完成,然后再等待 5 秒直到第二个进程完成,依此类推,但我希望程序终止所有持续时间超过5秒。 此外,如果所有进程的持续时间都不超过 5 秒,则程序不得等待这 5 秒。

如果你想杀死所有可以使用多处理池的进程,你需要为所有执行定义一个通用超时,而不是单个超时。

import numpy as np
import time
from multiprocessing import Pool

def worker(num):
    xtime = np.random.random()*20
    time.sleep(xtime)
    return xtime

def main():

    pnum = 10
    pool = Pool()
    args = range(pnum)
    pool_result = pool.map_async(worker, args)

    # wait 5 minutes for every worker to finish
    pool_result.wait(timeout=300)

    # once the timeout has finished we can try to get the results
    if pool_result.ready():
        print pool_result.get(timeout=1)

if __name__ == "__main__":
    main()

这将为您提供一个按顺序列出所有工人的返回值的列表。
更多信息: https : //docs.python.org/2/library/multiprocessing.html#module-multiprocessing.pool

您可以通过创建一个循环来执行此操作,该循环将等待一些超时秒数,并经常检查所有进程是否已完成。 如果它们没有在分配的时间内全部完成,则终止所有进程:

TIMEOUT = 5 
start = time.time()
while time.time() - start <= TIMEOUT:
    if not any(p.is_alive() for p in procs):
        # All the processes are done, break now.
        break

    time.sleep(.1)  # Just to avoid hogging the CPU
else:
    # We only enter this if we didn't 'break' above.
    print("timed out, killing all processes")
    for p in procs:
        p.terminate()
        p.join()

感谢 dano 的帮助,我找到了一个解决方案:

import numpy as np
import time
import multiprocessing

def worker(num):

    time.sleep(np.random.random()*20)

def main():

    pnum = 10    
    TIMEOUT = 5 
    procs = []
    bool_list = [True]*pnum

    for i in range(pnum):
        p = multiprocessing.Process(target=worker, args=(i,), name = ('process_' + str(i+1)))
        procs.append(p)
        p.start()
        print 'starting', p.name

    start = time.time()
    while time.time() - start <= TIMEOUT:
        for i in range(pnum):
            bool_list[i] = procs[i].is_alive()

        print bool_list

        if np.any(bool_list):  
            time.sleep(.1)  
        else:
            break
    else:
        print("timed out, killing all processes")
        for p in procs:
            p.terminate()

    for p in procs:
        print 'stopping', p.name,'=', p.is_alive()
        p.join()

if __name__ == "__main__":
    main()

这不是最优雅的方式,我相信有比使用bool_list更好的方法。 超时 5 秒后仍然存活的进程将被杀死。 如果您在工作函数中设置的时间比超时时间短,您将看到程序在达到 5 秒超时之前停止。 如果有的话,我仍然愿意接受更优雅的解决方案:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM