tensorflow 占用 /dev/shm 不释放是因 tf.data.cache() 默认写入共享内存、parallel_interleave 预取暂存及子进程异常退出残留文件三者叠加所致,需分别通过指定磁盘缓存路径、限制并行度、避免多进程生成器来治理。

TensorFlow 占用大量共享内存(/dev/shm)且不释放,根本不是“泄漏”,而是 tf.data.Dataset 缓存、多进程预取和临时文件残留三者叠加的结果。
tf.data.cache() 无 filename 参数时直接写进 /dev/shm
默认情况下,.cache() 不带 filename 参数时,TensorFlow 会把缓存数据写入系统共享内存(/dev/shm),而不是磁盘。这个区域大小通常只有 64MB(取决于 shmmax 设置),但 TensorFlow 会不断追加——一旦填满,nvidia-smi 看不到显存涨,df -h /dev/shm 却可能显示 100% 占用,甚至触发 OOM Killer。
- 验证方式:
ls -lh /dev/shm | grep tensorflow或find /dev/shm -name "*tensorflow*" -ls - 错误写法:
dataset = dataset.batch(32).cache()→ 每个 batch 都被序列化塞进 shm - 安全写法:
.cache(filename="/tmp/tf_cache_abc"),强制落地到磁盘 - 更轻量替代:
.cache().prefetch(tf.data.AUTOTUNE)改成.prefetch(tf.data.AUTOTUNE)(去掉 cache)
tf.data.experimental.parallel_interleave + num_parallel_calls 踩中 shm 写入热点
当使用 parallel_interleave 加载多个 TFRecord 或图像路径,并开启 num_parallel_calls=tf.data.AUTOTUNE 时,TensorFlow 会在预取阶段把解码后的 tensor 临时暂存在 /dev/shm 中——尤其在小文件多、解码快、消费慢的场景下,shm 区域迅速堆积未消费完的缓冲块。
- 现象:
lsof +D /dev/shm显示大量tensorflow_*文件句柄处于DEL状态(已 unlink 但进程未关闭 fd) - 解决办法:显式限制并行度,比如
num_parallel_calls=2;或改用interleave(..., cycle_length=2, num_parallel_calls=1) - 关键点:不要依赖
AUTOTUNE在资源受限环境自动收敛——它只看 CPU 核数,不管 shm 容量
子进程未退出导致 shm 文件无法真正删除
TensorFlow 的 tf.data.Dataset.from_generator() 或自定义 map 函数若启用了多进程(如 tf.data.Options().experimental_deterministic=False + num_parallel_calls),底层会 fork 子进程处理数据。这些子进程崩溃、被 kill 或异常退出时,可能没来得及清理自己创建的 shm 文件,导致文件虽被 unlink,但 inode 仍被占用,/dev/shm 空间不释放。
- 排查命令:
ipcs -m查看共享内存段(注意 key 和 cpid);ps -o pid,ppid,comm -p $(cat /proc/*/task/*/status 2>/dev/null | grep -B1 "Shmid.*[0-9]" | head -1 | awk '{print $NF}')(粗略定位持有者) - 临时缓解:
sudo rm -f /dev/shm/tensorflow_*(需 root 权限,且确保无活跃进程正在读写) - 长期方案:避免
from_generator;改用Dataset.from_tensor_slices().map(..., num_parallel_calls=1),彻底规避多进程 shm 交互
真正难处理的是 shm 占用和 GPU 显存释放的耦合:你调了 tf.keras.backend.clear_session(),显存可能降了,但 /dev/shm 还是满的;反之,清空 shm 后,下次训练又因缓存缺失而卡顿。它们属于不同资源层,必须分开治理——别指望一个操作同时搞定两者。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











