multiprocessing.Pool产生的进程多于仅在Google Cloud上请求的进程

时间:2017-11-16 17:28:34

标签: python google-cloud-platform multiprocessing

我正在使用Python的multiprocessing.Pool类在进程间分配任务。

简单的案例按预期工作:

from multiprocessing import Pool

def evaluate:
    do_something()

pool = Pool(processes=N)
for task in tasks:
    pool.apply_async(evaluate, (data,))

产生了N个进程,它们不断地完成我传递给apply_async的任务。现在,我有另一种情况,我有许多不同的非常复杂的对象,每个对象都需要进行计算量大的活动。我最初让每个对象在它完成工作时按需创建自己的多处理.Pool,但是我最终因为打开了太多文件而遇到了OSError,尽管我会假设这些池使用后会收集垃圾。

无论如何,我认为最好为这些复杂对象中的每一个共享同一个池进行计算:

from multiprocessing import Pool

def evaluate:
    do_something()

pool = Pool(processes=N)

class ComplexClass:

    def work:
        for task in tasks:
            self.pool.apply_async(evaluate, (data,))

objects = [ComplexClass() for i in range(50)]

for complex in objects:
    complex.pool = pool


while True:
    for complex in objects:
        complex.work()

现在,当我在我的一台计算机上运行它(OS X,Python = 3.4)时,它的运行方式与预期一致。产生了N个进程,每个复杂对象在每个进程中分配它们的任务。但是,当我在另一台计算机上运行它(运行Ubuntu的Google Cloud实例,Python = 3.5)时,会产生大量进程(>> N),整个程序因争用而停止运行。

如果我查看游泳池以获取更多信息:

import random
random_object = random.sample(objects, 1)
print (random_object.pool.processes)

>>> N

一切看起来都很正确。但它显然不是。可能会发生什么想法?

更新

我添加了一些额外的日志记录。为简单起见,我将池大小设置为1。在池中,当任务完成时,我使用os.getpid()从多处理模块打印current_process(),以及任务的pid。结果是这样的:

<ForkProcess(ForkPoolWorker-1, started daemon)>, PID: 5122
<ForkProcess(ForkPoolWorker-1, started daemon)>, PID: 5122
<ForkProcess(ForkPoolWorker-1, started daemon)>, PID: 5122
<ForkProcess(ForkPoolWorker-1, started daemon)>, PID: 5122
...

再次,看看使用htop的实际活动,我看到许多进程(每个对象共享多处理池一个)都在消耗CPU周期,因为这种情况正在发生,导致操作系统争用太多,进展非常缓慢。 5122似乎是父进程。

2 个答案:

答案 0 :(得分:1)

1。实现了无限循环

如果实现无限循环,则它将像无限循环一样运行。 您的示例(由于其他原因完全无效)...

while True:
    for complex in objects:
        complex.work()

2。生成还是分叉过程?

即使上面的代码仅显示了一些摘要,但您一方面不能期望在Windows / MacOS和Linux上获得相同的结果。前者产生过程,后者派生它们。如果使用可能具有状态的全局变量,则在一种环境上开发而在另一种环境上运行时会遇到麻烦。

请确保不要在进程中使用全局statefull变量。只需明确地传递它们,或以其他方式摆脱它们。

3。使用程序,而不是脚本

编写具有最低要求的程序,使其具有__main__。特别是,当您使用多处理时,您需要此。在该名称空间中实例化Pool。

答案 1 :(得分:0)

1)您的问题包含的代码与您运行的代码不同(相关代码的语法不正确,根本无法运行)。
2)多处理模块在错误处理/报告工作中发生的错误方面非常糟糕。 问题非常可能出现在您无法显示的代码中。您显示的代码(如果已修复)将永远工作并占用CPU,但它不会因太多打开的文件或进程而导致错误。