OSError Too many open files 搭配 zip 两个 DataLoader 场景,文件描述符超限排查与解决方案

OSError: [Errno 24] Too many open files 的含义是进程打开的文件句柄(文件描述符 fd)超过操作系统的上限;在你同时 zip 两个 DataLoader 的场景里,最常见诱因是 DataLoader 的多进程 worker 持续打开图片文件、句柄没有及时回收,叠加 zip 同步迭代、循环多次加载,句柄不断累积,最终触达系统限制。zip 本身不是 bug,只是让两个 DataLoader 的文件打开行为同时发生,加速了句柄耗尽。

一、报错原因拆解

项目说明
报错编号Errno 24,文件描述符超限
触发场景for a, b in zip(dl1, dl2): 双 DataLoader 并行迭代
核心来源DataLoader 的 worker 子进程打开图片、标注文件,句柄释放不及时
加重因素num_workers 开太大、循环 epoch 很多、Dataset 里每次 open 不 close、PIL/OpenCV 隐式持有句柄
误区不是 zip 函数本身有内存泄漏,是两个 DataLoader 同时产生大量打开文件

二、快速排查命令(Linux/macOS)

查看当前进程句柄上限

ulimit -n

实时监控进程打开文件数,PID替换成你的python进程id

lsof -p | wc -l

  • 常见默认值:1024;如果你的 worker 多、同时开两个 loader,很容易打满。
  • 观察:每跑一个 batch,lsof 数量持续上涨,就是句柄泄漏。

三、分层解决方案(按推荐顺序)

  1. 优先:Dataset 里打开图片后主动 close,不要依赖 GC 自动回收

PIL Image.open() 会持有文件句柄。推荐写法:

def __getitem__(self, idx):

path = self.paths[idx]

with Image.open(path) as img:

img = img.convert("RGB").resize((224,224))

tensor = transforms.ToTensor()(img)

return tensor

with 上下文退出时立刻关闭文件,是最根本解法。

  1. 降低 num_workers,不要开太高

两个 DataLoader,每个 worker 都会独立打开文件。

比如原来 num_workers=8,改成 2~4;双 loader 场景句柄是叠加的,不要把 worker 拉满。

注意:Windows 下多进程句柄机制不一样,更容易出现这个问题。

  1. 避免无限迭代、重复实例化 DataLoader

不要在 epoch 循环内部反复 DataLoader(...),每次新建都会新建一批 worker、打开一批文件;DataLoader 放在循环外面。

正确:只初始化一次

dl1 = DataLoader(ds1, num_workers=2)

dl2 = DataLoader(ds2, num_workers=2)

for epoch in range(100):

for x,y in zip(dl1, dl2):

pass

  1. 调高系统文件句柄上限(临时兜底方案,不推荐作为首选)

临时生效(当前终端)

ulimit -n 4096

永久修改需要改 /etc/security/limits.conf,服务器环境才适合操作,本地笔记本不建议。

  1. 备选:单进程加载 num_workers=0

num_workers=0 所有加载在主进程,句柄更容易回收,代价是速度变慢,适合调试定位泄漏。

四、zip 两个 DataLoader 的额外坑点

  • zip 会以短的那个 loader 长度作为迭代终点;如果两个数据集长度不一样,短的跑完循环直接终止,这个和句柄报错无关,但经常一起踩坑。
  • DataLoader worker 是独立子进程,子进程的文件句柄不会随主进程迭代自动释放,必须靠 Dataset 内部 close。
  • 不要用 itertools.cycle 包裹 DataLoader 做无限循环,会持续累积句柄。

五、排查步骤清单

  1. lsof 监控进程句柄,确认是否持续上涨。
  2. 给所有 Image.open/cv2.imread 加上上下文管理,确保文件关闭。
  3. 减少 num_workers,双 loader 要算叠加量。
  4. 测试 num_workers=0,看报错是否消失:消失 = 问题来自 worker 子进程文件句柄泄漏。
  5. 检查是否循环内反复创建 DataLoader。

【相关 FAQ】

问题 1:OSError: [Errno 24] Too many open files,我用 zip 把两个 DataLoader 放一起迭代,是不是 zip 导致泄漏?

回答 1:zip 本身不会造成文件句柄泄漏;zip 只是让两个 DataLoader 同时在迭代,两个 DataLoader 的 worker 同时打开大量图片文件,句柄叠加累积,加速触达系统上限,根源是 Dataset 读取时文件没有及时关闭。

问题 2:同样的代码,只用单个 DataLoader 没事,zip 两个 DataLoader 就报 Too many open files,为什么?

回答 2:单个 DataLoader 打开的文件句柄总量在 ulimit 限制以内;zip 双 loader 时,两套 worker 进程同时打开文件,文件描述符数量叠加,短时间就突破系统上限,触发 Errno24。

问题 3:用 with Image.open () 之后还报 Too many open files,还有什么排查方向?

回答 3:检查是否还有其他文件读取:标注 json、npy、视频帧;另外确认是否反复新建 DataLoader、或者使用 cycle 无限循环 loader;也可以降低 num_workers,或者监控 lsof 定位是哪一类文件持续打开。

【参考资料】

PyTorch DataLoader multiprocessing file descriptor behavior

Linux ulimit file descriptor limit

PIL Image.open file handle leak issue

【免责声明】

ulimit 修改受操作系统、服务器权限限制,共享服务器不要随意调高全局句柄上限;Windows、WSL、macOS 的文件描述符机制和 Linux 有差异,部分方案效果不同。本文方案基于 PyTorch DataLoader 场景,TensorFlow DataLoader 机制不同。

本文来自作者[元簇同调使]投稿,不代表乌兰科技网立场,如若转载,请注明出处:https://www.wlcbnews.com/rgzn/202611/543.html

赞 (4)

今日大家都在搜的词:

发表回复

本站作者后才能评论

评论列表(4条)

  • 元簇同调使
    元簇同调使 2026年11月09日

    我是乌兰科技网的签约作者“元簇同调使”!

  • 元簇同调使
    元簇同调使 2026年11月09日

    希望本篇文章《OSError Too many open files 搭配 zip 两个 DataLoader 场景,文件描述符超限排查与解决方案》能对你有所帮助!

  • 元簇同调使
    元簇同调使 2026年11月09日

    本站[乌兰科技网]内容主要涵盖:互联网行业的追踪与探索

  • 元簇同调使
    元簇同调使 2026年11月09日

    本文概览:OSError: [Errno 24] Too many open files 的含义是进程打开的文件句柄(文件描述符 fd)超过操作系统的上限;在你同时 zip 两个 DataLoader 的场景里,最常见诱因是 DataLoader 的多进程 worker 持续打开图片文件、句柄没有及时回收,叠加 zip 同步迭代、循环多次加载,句柄不断累积,最终触达系统限制。zip 本身不是 bug,只是让两个 DataLoader 的文件打开行为同时发生,加速了句柄耗尽。

联系我们

联系:143 0457 151

工作时间:周一至周五,9:30-18:30,节假日休息

关注我们