Python多处理为什么池.关闭()花了这么长时间才回来?

2024-09-25 08:33:27 发布

您现在位置:Python中文网/ 问答频道 /正文

有时调用函数pool.close()需要很长时间才能返回,我想了解原因。通常,我会让每个进程返回一个大的set或一个大的dict,然后{}合并它们。看起来像这样:

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的描述:

Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit.

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


Tags: thetoclose进程def原因dicttasks
2条回答

可能是对pool.imap_unordered和后续的{}的结果进行迭代需要很长时间。在

在每个工人完成一套设备的制作后,必须对其进行腌制,并将其送回原始流程中,然后将其拆下。这需要时间和记忆。然后*必须解压所有集合,以便union进行处理。在

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

^{}不太可能花那么长时间。{这只是因为}

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

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

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

Wait for the worker processes to exit.

它实际上对池中的每个进程调用^{}。如果你加入了一个进程或线程,你就在积极地等待它完成工作并终止。在

所以在您的例子中,有20个进程在运行,它们向一个集合添加了一百万个元素。那需要一段时间。为了使您的主进程不会过早退出(顺便说一句,会导致子进程死亡),您正在等待工作进程完成其工作;加入它们。因此,你所经历的可能是你所做的工作量应该发生的事情。在

附带说明:如果你在你的工作函数中做了大量的CPU工作,你不应该产生比你的CPU可用的硬件线程更多的进程,因为你只会从管理和交换进程中引入额外的开销。例如,对于消费者核心i7,这个数字应该是8。在

相关问题 更多 >