多进程返回“too many open files”,但使用“with…as”可以解决。为什么?

33

我曾使用这个答案来在Linux平台上通过多进程(multiprocessing)运行Python并行命令。

我的代码类似于:

import multiprocessing
import logging

def cycle(offset):
    # Do stuff

def run():
    for nprocess in process_per_cycle:
        logger.info("Start cycle with %d processes", nprocess)
        offsets = list(range(nprocess))
        pool = multiprocessing.Pool(nprocess)
        pool.map(cycle, offsets)

但是我一直遇到这个错误:OSError: [Errno 24] Too many open files
所以,代码打开了过多的文件描述符,即:它启动了太多进程而没有终止它们。

我使用下面这些行替换最后两行代码来修复它:

    with multiprocessing.Pool(nprocess) as pool:
        pool.map(cycle, offsets)

但我不知道那些代码是如何解决问题的。

with关键字下面发生了什么?


这里是每个进程都调用了 self.terminate()源代码 - salparadise
1
with 版本在 pool.map() 返回后隐式地调用 pool.close()。根据文档,这可以“防止向池提交更多任务。一旦所有任务都完成,工作进程将退出”。这可能会导致每个任务打开的文件被关闭。 - martineau
我错了吗,@COLDSPEED回答了这个问题,现在它被删除了吗?我没有能够深入阅读它,但我想...但现在它消失了...有人知道为什么这个问题被踩了吗? - nephewtom
嗨@cᴏʟᴅsᴘᴇᴇᴅ... 有关于这个的提示吗? - nephewtom
@nephewtom 我之前把它删掉了,因为我认为它对任何人都没有帮助。现在我已经恢复了它。 - cs95
遇到了同样的问题,对这个问题点赞! - Geek
4个回答

32

您正在循环内创建新的进程,然后忘记在完成后关闭它们。因此,会出现打开太多进程的情况。这是一个不好的主意。

您可以通过使用上下文管理器自动调用pool.terminate,或者手动调用pool.terminate来解决这个问题。另外,为什么不在循环外部创建池,然后将任务发送到进程内部呢?

pool = multiprocessing.Pool(nprocess) # initialise your pool
for nprocess in process_per_cycle:
    ...       
    pool.map(cycle, offsets) # delegate work inside your loop

pool.close() # shut down the pool

如果您需要更多信息,可以查看multiprocessing.Pool文档。


在这里,手动调用pool.terminate可能是要做的事情。 我无法在外部创建池,因为我想在每次迭代中更改它。因此,在每个迭代中,生成的进程数量都会增加。例如,如果process_per_cycle是[2, 4, 8],则每次迭代将生成2、4和8个进程。 - nephewtom
@nephewtom 是的,如果您无法使用上下文管理器,那将是另一个选择。 - cs95
@nephewtom 我解释了为什么...因为with会在你完成后自动关闭进程池。 - cs95
在这种情况下,为什么操作系统会像对待文件一样处理进程? - Sledge
@Sledge 当创建一个进程时,除非它是守护进程,否则必须明确销毁。 - cs95

3

我已经在结束和关闭进程池,但是遇到了文件描述符的数量限制。我将我的ulimit从1024更改为4096,问题得以解决。以下是具体步骤:

检查:

ulimit -n

我将其更新为4096,然后它就可以正常工作了。

ulimit -n 4096

2

很明显这是一个上下文管理器。但为什么在这里使用它会导致这个工作呢? - cs95
你可以看一下 这个 解释。 - rpanai

1
这种情况也可能发生在使用numpy.load时,确保关闭那些文件,或者避免使用它,改用pickle或torch.save torch.load等方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接