为什么赢了';Python多处理工人会死吗?
我正在使用python的多处理功能将一些函数映射到一些元素上。大致如下:为什么赢了';Python多处理工人会死吗?,python,python-multiprocessing,pypy,Python,Python Multiprocessing,Pypy,我正在使用python的多处理功能将一些函数映射到一些元素上。大致如下: def computeStuff(arguments, globalData, concurrent=True): pool = multiprocessing.Pool(initializer=initWorker, initargs=(globalData,)) results = pool.map(workerFunction, list(enumerate(arguments))) retu
def computeStuff(arguments, globalData, concurrent=True):
pool = multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))
results = pool.map(workerFunction, list(enumerate(arguments)))
return results
def initWorker(globalData):
workerFunction.globalData = globalData
def workerFunction((index, argument)):
... # computation here
通常,我使用cPython和Pypy在ipython中运行测试。我注意到,生成的进程通常不会被杀死,因此它们开始累积,每个进程都使用一gig的ram。当在计算过程中按ctrl-k键时会发生这种情况,这会使多处理陷入混乱的狂乱之中。但即使让计算完成,这些进程也不会在Pypy中消亡
根据文档,当池被垃圾回收时,它应该调用terminate()
并杀死所有进程。这里发生了什么事?是否必须显式调用close()
?如果是,是否有某种上下文管理器可以正确管理关闭资源(即流程)
这是在Mac OS X Yosemite上的。PyPy的垃圾收集很慢,因此未能调用
close
意味着池将在“某个时候”清理,但这可能并不意味着“很快”
一旦池
正确地关闭
d,工作人员在完成任务时退出。在3.3 Python之前的版本中,确保关闭池的一个简单方法是:
from contextlib import closing
def computeStuff(arguments, globalData, concurrent=True):
with closing(multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))) as pool:
return pool.map(workerFunction, enumerate(arguments))
注意:我还删除了对列表
的显式转换(毫无意义,因为映射
将为您迭代枚举
迭代器),并直接返回结果(无需指定名称,只需在下一行返回)
如果要确保在异常情况下(在3.3 Python之前版本)立即终止,可以使用try/finally块,或者编写一个简单的上下文管理器(可以在使用池的其他地方重用):
终止
方法的优势在于它保证进程立即退出;理论上,如果您在主程序的其他地方使用线程,池
工作线程可能与非守护进程线程分叉,这将使进程保持活动状态,即使工作任务线程退出<代码>终止
通过强制终止进程来隐藏这一点
如果您的解释器是Python 3.3或更高版本,则终止方法内置于池中,因此with
语句,with multiprocessing.Pool(initializer=initWorker,initargs=(globalData,)不需要特殊的包装器作为池:
直接起作用。为真正的资本家标题投票可能您只需添加try:。。。最后:pool.terminate()
?也许我的问题不清楚-我是说即使计算完成,工人们也会留下来。尽管他们不应该这样做,但如果我正确理解了文档,无论如何……我想了解更多正在发生的事情。但我会试试你的建议。
from contextlib import contextmanager
@contextmanager
def terminating(obj):
try:
yield obj
finally:
obj.terminate()
def computeStuff(arguments, globalData, concurrent=True):
with terminating(multiprocessing.Pool(initializer=initWorker, initargs=(globalData,))) as pool:
return pool.map(workerFunction, enumerate(arguments))