在我的python应用程序中,我需要启动多个多处理。经理我似乎在第二个管理器启动时,第一个管理器中引用的所有对象都会得到一个INCRF。在第三次启动时,第一个和第二个管理器创建的所有对象都会获得另一个INCRF。等等我不明白为什么在一个新的过程中,一个全新的管理器的启动会导致其他管理器上托管的对象的所有这些增量,这会导致程序需要很长时间才能启动/停止。
这个小脚本完全再现了在python 2.7和3.2中测试的行为:
from __future__ import print_function
import multiprocessing, logging
# # Activate multiprocessing logging
mplog = multiprocessing.get_logger()
mplog.setLevel(multiprocessing.util.DEBUG)
mplog.addHandler(logging.StreamHandler())
objs=[]
def newman(n=50):
global objs
m=multiprocessing.Manager()
print('created')
for i in range(n):
objs.append(m.Value('i',i))
return m
print('#### first man')
m1=newman()
print ('#### second man')
m2=newman()
print ('#### third man')
m3=newman(0)
在第一个管理器启动后,记录器打印出与前50个对象的创建相关的消息。
但是,当第二个管理器启动时——在它创建任何对象之前——记录器只打印出50条INCRF消息。然后是与在管理器2上创建50个新对象有关的消息。
当第三个管理器启动时——在它创建任何对象之前——会再打印100条INCRF消息。
在m3创建之后,没有看到对象创建消息,因为我将0传递给了newman()函数。
当程序结束时,会打印类似数量的DECREF消息。
似乎,当我启动一个新的管理器时,它会创建对以前的管理器所引用的所有对象的引用。在大型应用程序中,这会转化为启动/关闭速度极慢。
有什么变通办法吗?或者至少,对为什么会发生这种情况有什么解释吗?
我想我明白了。
class BaseProxy(object):
# ...
def _incref(self):
# ...
util.debug('INCREF %r', self._token.id)
# ...
def _after_fork(self):
# ...
self._incref()
# ...
您使用的是一台使用fork创建新进程的linux机器。想法:每次启动经理时,都会分叉当前流程并调用_incref。
- 帮助我证明这一点:首先创建所有管理者,然后创建新的价值观。这是否仍在增加参考文献
- 看看实现情况