根本原因是/dev/shm默认64MB被PyTorch共享内存缓存占满,解决方法包括临时扩容sudo mount -o remount,size=2G /dev/shm、永久修改/etc/fstab、改用spawn启动、降低num_workers、关闭pin_memory及定期清理残留文件。

PyTorch DataLoader num_workers > 0 时爆 OSError: [Errno 12] Cannot allocate memory 怎么办
根本原因不是显存或内存不足,而是子进程通过 fork 继承父进程地址空间后,共享内存(/dev/shm)被大量 torch.Tensor 的共享缓存占满。尤其在使用 pin_memory=True + 多 num_workers 时,每个 worker 都会尝试映射大块共享内存页,叠加后远超默认的 64MB 限制。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先确认是否真卡在共享内存:运行
df -h /dev/shm,若显示64M且已用满,基本锁定问题 - 临时扩容(重启前有效):
sudo mount -o remount,size=2G /dev/shm - 永久生效需改
/etc/fstab,加一行:shm /dev/shm tmpfs defaults,size=2G 0 0,然后sudo mount -a - 避免“治标不治本”:别盲目把
/dev/shm设到 8G+,Linux 内核对 tmpfs 有硬限制,过大反而触发 OOM killer
ulimit -l unlimited 为什么对 PyTorch 共享内存没用
ulimit -l 控制的是 mlock() 锁定物理内存的上限,而 PyTorch 的 SharedMemory(底层用 shm_open + mmap)走的是 tmpfs 路径,不受 RLIMIT_MEMLOCK 约束。设成 unlimited 不仅无效,还可能干扰其他依赖 mlock 的组件(如某些 RDMA 库)。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 检查当前限制:
ulimit -l(单位 KB),通常默认是 64KB,但和/dev/shm容量无关 - 真正要调的是
/dev/shm本身大小,不是 ulimit - 如果确实需要提高 mlock 限额(极少数场景),用
ulimit -l 262144(即 256MB),而非 unlimited
PyTorch 1.12+ 的 spawn 启动方式能绕过共享内存问题吗
不能完全绕过,但能显著缓解。默认的 fork 启动会让每个 worker 进程复制整个主进程的内存页表(即使未写入也占 /dev/shm 映射槽位);而 spawn 是 clean start,只序列化必要数据,共享内存对象按需创建、按需映射。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 必须显式设置:
torch.multiprocessing.set_start_method('spawn', force=True),且要在if __name__ == '__main__':块内最开头执行 - 注意兼容性:所有传给 worker 的参数必须可 pickle,自定义 Dataset 中不能含不可序列化的句柄(如文件对象、数据库连接)
- 性能权衡:spawn 启动稍慢,首次 batch 加载延迟略高,但长期更稳,尤其适合大模型预处理流水线
不用 root 权限怎么降低共享内存压力
在无法修改 /dev/shm 或系统配置的环境(如 Kaggle、部分云容器),只能从代码侧收敛共享内存用量。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 优先降
num_workers:设为min(4, os.cpu_count() // 2),比盲目堆 worker 更有效 - 关掉非必要共享:
DataLoader(..., pin_memory=False)(尤其 CPU 训练时);prefetch_factor=2(默认 2,别设太高) - 重用 tensor 缓存:在
__getitem__中避免每次都 new 大 tensor,用torch.empty(..., pin_memory=True)预分配 +.copy_()复用 - 警惕 transform 中的 copy:PIL 图像转 tensor 后立刻
.contiguous(),否则后续操作可能隐式触发额外共享映射
最易被忽略的一点:PyTorch 的共享内存对象不会自动清理,尤其在训练中断或 worker 异常退出时,残留的 /dev/shm/pytorch_* 文件会持续占位。定期手动清空(rm -f /dev/shm/pytorch_*)或加个 atexit handler 是必要的兜底手段。

















