启动多个多处理管理器变得非常慢

时间:2014-02-17 14:31:32

标签: python multiprocessing

在我的python应用程序中,我需要启动多个multiprocessing.Manager。我似乎在第二个管理器启动时,第一个管理器中引用的所有对象都获得INCREF。 在第三次启动时,第一个和第二个管理器创建的所有对象都获得另一个INCREF。等等。 我无法理解为什么一个全新的经理的开始,在一个新的过程中,会导致所有这些INCREF关于托管在其他经理上的对象 - 这导致程序永远开始/停止。

这个小脚本完全重现了在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个INCREF消息。然后跟随有关在管理器2上创建50个新对象的消息。

当第三个管理器启动时 - 在它创建任何对象之前 - 再打印100个INCREF消息。

创建m3后没有看到对象创建消息,因为我将0传递给newman()函数。

当程序结束时,会打印相似数量的DECREF消息。

看来,当我启动一个新的管理器时,它会创建对前一个管理器引用的所有对象的引用。在一个大型应用程序中,这转换为极慢启动/关闭。

任何解决方法?或者至少,有关为什么会发生这种情况的任何解释?

1 个答案:

答案 0 :(得分:0)

我想我明白了。

class BaseProxy(object):
     # ...
     def _incref(self):
         # ...
         util.debug('INCREF %r', self._token.id)
     # ...
     def _after_fork(self):
         # ...
         self._incref()
         # ...

您正在使用使用fork创建新进程的Linux计算机。 想法:每次启动管理器时,currrent进程都会分叉并调用_incref。

  1. 帮我证明一下:首先创建所有经理,然后创建新值。这还在增加参考吗?
  2. 看看实施情况。