多处理返回“打开的文件太多”,但使用 `with...as` 修复它。为啥?
Posted
技术标签:
【中文标题】多处理返回“打开的文件太多”,但使用 `with...as` 修复它。为啥?【英文标题】:multiprocessing returns "too many open files" but using `with...as` fixes it. Why?多处理返回“打开的文件太多”,但使用 `with...as` 修复它。为什么? 【发布时间】:2018-01-21 18:56:02 【问题描述】:我使用this answer 在 Linux 机器上运行 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
下面发生了什么?
【问题讨论】:
这里是source code每个进程正在调用self.terminate()
with
版本在pool.map()
返回后隐式调用pool.close()
。根据文档,“防止更多任务被提交到池中。所有任务完成后,工作进程将退出”。这可能会导致每个任务已打开的打开文件被关闭。
我错了,还是@COLDSPEED 确实回答了这个问题,现在它被删除了?我无法深入阅读它,但我想......但现在它已经消失了......有人知道为什么这个问题被否决了吗?
嗨@cᴏʟᴅsᴘᴇᴇᴅ ...对此有任何提示吗?
@nephewtom 我删除了它,因为我认为它对任何人都没有帮助。我现在已经取消删除了。
【参考方案1】:
您正在循环中创建新进程,然后在完成后忘记关闭它们。结果,您有太多打开的进程。这是个坏主意。
您可以使用自动调用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 我解释了原因...因为with
会在您完成后自动关闭进程池。
为什么在这种情况下操作系统会将进程视为文件?
@Sledge 创建进程时必须明确销毁它,除非它是守护进程。【参考方案2】:
它是上下文管理器。使用 with 可确保您正确打开和关闭文件。要详细了解这一点,我推荐这篇文章https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/
【讨论】:
很明显它是一个上下文管理器。但是为什么在这里使用它会导致它起作用呢? 你可以看看this的解释。【参考方案3】:当您使用 numpy.load 时也会发生这种情况,请确保也关闭这些文件,或者避免使用它并使用 pickle 或 torch.save torch.load 等。
【讨论】:
【参考方案4】:我已经在终止和关闭池,但是文件描述符的数量有限制,我将我的 ulimit 从 1024
更改为 4096
并且它起作用了。流程如下:
检查:
ulimit -n
我将它更新为 4096 并且可以正常工作。
ulimit -n 4096
【讨论】:
以上是关于多处理返回“打开的文件太多”,但使用 `with...as` 修复它。为啥?的主要内容,如果未能解决你的问题,请参考以下文章