多任务处理在任务完成时停止生成新进程

时间:2017-07-28 17:50:13

标签: python multiprocessing

你好,我有一个像

这样的多处理程序
#this is pseudocode-ish

def worker(queue, context):
    set_context(context) #set global context within worker
    while queue.qsize() > 0:
        process(queue.get(False))

pool = multiprocessing.Pool(20, worker, (queue, global_context))
pool.close()
pool.join()

问题是global context是一个非常重的对象,所以产生每个单独的过程(酸洗/去除)需要一段时间。所以我发现的是,对于较短的队列,整个队列由前几个生成的进程处理,然后程序的其余部分卡在其余的进程中,这不可避免地无所事事,因为队列中没有任何东西。例如。每个进程需要1秒生成,但队列在2秒内处理 - 所以前两个进程在2-3秒内完成队列,然后程序的其余部分需要17秒来生成其余队列。

当队列为空时,有没有办法杀死其余的进程?或者更灵活的方式来设置池的进程数 - 例如只在需要时才生成另一个进程?

由于

1 个答案:

答案 0 :(得分:6)

无法使用multiprocessing.Pool动态生成流程。如果您想要这种类型的行为,您需要自己修改它。

对于关机,一种方法是使用multiprocessing.Pool.terminate方法。但它可能会等待所有worker完成初始化。

您还可以在工作完成后直接杀死所有工作人员。我认为他们是_pool字段,其中包含您可以强制终止的所有工作人员Process。请注意,如果不打算在外部处理,这可能会导致一些奇怪的行为。您必须确保正确清理所有管理thread,这可能很棘手。

您的设计选择非常不寻常。您正在复制call_queue。实际上,Pool应该自己处理通信,而您不需要额外的queue。如果所有广告都位于task_list且需要由process_task处理,您可以执行类似

的操作
#this is pseudocode-ish

def init(queue, context):
    set_context(context) # set global context within worker

pool = multiprocessing.Pool(20, init, (global_context,))
res = pool.map(process_task, task_list)
pool.terminate()
pool.join()

这样可以避免破坏Pool设置并且可能更有效。

最后,如果您打算多次重用池,并且global_context不会更改,则可以考虑使用loky。 (免责声明:我是这个项目的维护者之一)。 这允许您在程序中多次重用一个工作池,而无需重新设置所有内容。 一个问题是initializer没有concurrent.futures,因为它遵循initializer的API,但multiprocessing.Barrier可以使用max_workers完成并提交initializer初始化工作。这将确保initializer的每个作业都由一个工作人员运行,并且所有工作人员都运行{{1}}。