PyTorch DataLoader子类出现Too many open files错误的原因排查
自定义torchdata.DataLoader子类引发"Too many open files"问题分析与修复
你的CustomDataLoader子类实现确实存在缺陷,会导致迭代器资源无法正确释放,进而引发文件句柄泄漏和多进程资源清理失败,最终触发OSError: [Errno 24] Too many open files错误。
问题根源
- 迭代器引用泄漏:你在
__iter__方法中将父类迭代器绑定为实例属性self.super_iter,当DataLoader被多次迭代(比如多轮训练)时,旧的迭代器对象无法被垃圾回收——因为实例始终持有它的引用。 - 资源无法及时释放:当开启
pin_memory=True时,PyTorch会启动额外线程处理内存拷贝,这些线程与迭代器绑定的资源(包括多进程通信套接字、临时文件句柄)会被持续占用,最终积累超过系统文件句柄限制。
修复方案
方案一:简化迭代器实现(推荐)
直接遍历父类迭代器并修改返回值,避免持有迭代器的实例引用:
class CustomDataLoader(torchdata.DataLoader): def __init__(self, dataset, batch_size, shuffle, collate_fn=None, pin_memory=False, num_workers=4, **kwargs): super().__init__(dataset, batch_size=batch_size, shuffle=shuffle, collate_fn=collate_fn, pin_memory=pin_memory, num_workers=num_workers, **kwargs) def __iter__(self): for batch in super().__iter__(): yield batch, None, None
方案二:用局部变量维护迭代器
如果必须手动实现__next__,通过内部类封装迭代器,避免实例持有引用:
class CustomDataLoader(torchdata.DataLoader): def __init__(self, dataset, batch_size, shuffle, collate_fn=None, pin_memory=False, num_workers=4, **kwargs): super().__init__(dataset, batch_size=batch_size, shuffle=shuffle, collate_fn=collate_fn, pin_memory=pin_memory, num_workers=num_workers, **kwargs) def __iter__(self): super_iter = super().__iter__() class _InnerIter: def __init__(self, iter_obj): self.iter_obj = iter_obj def __next__(self): batch = next(self.iter_obj) return batch, None, None return _InnerIter(super_iter)
补充说明
- 禁用
pin_memory能临时解决问题,是因为关闭了额外的内存拷贝线程,减少了资源持有量,但并未解决迭代器资源泄漏的根本问题。 - 无法用公开数据集复现,可能是因为公开数据集的迭代流程更简单,或训练轮次较少,资源泄漏未达到系统阈值。
内容的提问来源于stack exchange,提问作者dasWesen
相关产品推荐
相关产品推荐

