Python多处理 - 为什么pool.close()需要这么长才能返回?

时间:2014-08-04 11:59:51

标签: python multiprocessing

有时对函数pool.close()的调用需要花费大量时间才能返回,我想了解原因。通常,我会让每个流程返回一个大set或一个大dictmain合并它们。它看起来像这样:

def worker() :
    s = set()
    # add millions of elements to s
    return s

if __name__ == '__main__' :
    pool = multiprocessing.Pool( processes=20 )
    fullSet = set.union( * pool.imap_unordered( worker, xrange(100) ) )
    pool.close() # This takes a LOT OF TIME!
    pool.join()

正如我所说,pool.close()可能需要5分钟,10分钟或更长时间才能返回。使用词典而不是集合时会出现同样的问题。这就是documentation关于close所说的内容:

  

防止将更多任务提交到池中。一切都结束了   任务已经完成,工作进程将退出。

我想我不明白发生了什么。在fullSet = ...行之后,所有的工作都完成了,我不再需要工人了。他们在做什么花了这么多时间?

2 个答案:

答案 0 :(得分:3)

Pool.close这么长时间不太可能。仅仅因为这是the source of close

def close(self):
    debug('closing pool')
    if self._state == RUN:
        self._state = CLOSE
        self._worker_handler._state = CLOSE

所有发生的事情都是一些状态变量发生了变化。这对该方法的运行时没有可测量的影响,也不会导致它稍后返回。您可以假设close立即返回

现在,更有可能的是,你的pool.join()行是这种延迟的“罪魁祸首”。但它只是在做its job

  

等待工作进程退出。

它实质上在池中的每个进程上调用join。如果您要加入流程或线程,则正在等待以完成其工作并终止。

因此,在您的情况下,您运行了20个进程,为一组添加了一百万个元素。这需要一段时间。为了使你的主进程不要提前退出(导致子进程死机),你正在等待工作进程完成他们的工作;加入他们。因此,您所经历的工作可能会对您的工作量产生什么影响。

旁注:如果在工作函数中执行繁重的CPU工作,则不应产生比CPU具有可用硬件线程更多的进程,因为您只会从管理和切换进程中引入额外的开销。例如,对于消费者Core i7,此数字为8。

答案 1 :(得分:0)

可能是pool.imap_unordered和后续set.union结果的迭代需要很长时间。

每个工人完成一套装置后,必须将其腌制,送回原始工艺并进行打开。这需要时间和记忆。然后*必须解压缩union的所有集合才能处理。

使用map_async可能会获得更好的结果。让回调将返回的集合附加到列表中,并在每个集合上使用union循环遍历该列表。