有时调用函数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 = ...
之后,所有的工作都完成了,我不再需要工人了。他们在做什么花了这么多时间?在
可能是对}的结果进行迭代需要很长时间。在
pool.imap_unordered
和后续的{在每个工人完成一套设备的制作后,必须对其进行腌制,并将其送回原始流程中,然后将其拆下。这需要时间和记忆。然后
*
必须解压所有集合,以便union
进行处理。在使用
map_async
可能会获得更好的结果。让回调将返回的集合追加到一个列表中,并在每个集合上使用union
循环该列表。在^{} 不太可能花那么长时间。{这只是因为}
所以所有发生的就是一些状态变量改变了。这对该方法的运行时没有可测量的影响,也不会导致它稍后返回。您可以假设
close
立即返回。在现在,更有可能的是你的
pool.join()
线路是延迟的“罪魁祸首”。但它只是在做its job:它实际上对池中的每个进程调用^{} 。如果你加入了一个进程或线程,你就在积极地等待它完成工作并终止。在
所以在您的例子中,有20个进程在运行,它们向一个集合添加了一百万个元素。那需要一段时间。为了使您的主进程不会过早退出(顺便说一句,会导致子进程死亡),您正在等待工作进程完成其工作;加入它们。因此,你所经历的可能是你所做的工作量应该发生的事情。在
附带说明:如果你在你的工作函数中做了大量的CPU工作,你不应该产生比你的CPU可用的硬件线程更多的进程,因为你只会从管理和交换进程中引入额外的开销。例如,对于消费者核心i7,这个数字应该是8。在
相关问题 更多 >
编程相关推荐