GPU 显存被“僵尸进程”占着却没任务?——从定位到清理的完整实战(含脚本)
·
👩💻 适用人群:
深度学习/高性能计算的玩家们,尤其是那些在 Linux + NVIDIA GPU 环境下折腾 PyTorch、CUDA、NCCL、Slurm 的朋友们。
🖥️ 操作系统:
基本上所有主流的 Linux 发行版都适用。
🧰 驱动/库:
NVIDIA Driver、CUDA、nvidia-smi、fuser/lsof。
一、问题现象 😱
有时候,咱们的训练或者推理任务挂了之后(异常退出),会遇到一个很让人头大的情况:nvidia-smi 看起来干干净净,显示没进程占着显存,但实际上显存却还被占着!
就像这样:
+-----------------------------------------------------------------------------+
| GPU Name Persistence-M| Bus-Id | Memory-Usage |
| 2 RTX 3090 On | ... | 9210MiB / 24576MiB |
+-----------------------------------------------------------------------------+
| Processes: |
| No running processes found |
+-----------------------------------------------------------------------------+
这通常就意味着,有一些**“看不见”的 CUDA 上下文或者进程句柄**还在偷偷霸占着你的 GPU 设备文件。
二、排查与清理思路 🕵️♀️
1)显存被占,但 nvidia-smi 看不到?用 fuser / lsof 揪出那个“隐形”的占用者!
当 nvidia-smi 帮不上忙的时候,fuser 就能派上大用场了!它能告诉你,到底有哪些进程还在“扒拉”着你的 GPU 相关设备文件。
# 这三个设备文件是关键,就像是 GPU 的“大门”和“钥匙”
fuser -v /dev/nvidia2 /dev/nvidiactl /dev/nvidia-uvm
这里解释一下:
/dev/nvidia2:表示系统中的第二张 NVIDIA 显卡(从 0 开始计数,所以nvidia0是第一张,nvidia1是第二张,nvidia2则是第三张)。你需要根据实际情况调整这个数字,比如你的目标是第一张卡,那就是/dev/nvidia0。/dev/nvidiactl:这是 NVIDIA 控制设备文件,负责 GPU 的全局管理。/dev/nvidia-uvm:这是 NVIDIA 统一虚拟内存 (Unified Virtual Memory) 驱动文件,与 CUDA 运行时密切相关。
通常你会看到类似这样的输出:
USER PID ACCESS COMMAND
/dev/nvidia2: <user> 3395213 F...m python
<user> 3411215 F...m python
/dev/nvidiactl: <user> 3395213 F...m python
/dev/nvidia-uvm: <user> 3411215 F.... python
F:表示这个文件是以写入方式打开的(也就是被占用了)。m:表示通过mmap方式映射的(这可是典型的 CUDA 上下文占用方式哦)。- 一旦你看到了 PID,那就说明:这些进程还在死死拽着 GPU2 的设备句柄不放!
找到了占用者,接下来就好办了:
# 先查查这些 PID 都是干啥的,以防误杀
ps -fp 3395213,3411215
# 确认没问题后,直接“斩草除根”
# 强制杀死它们!
kill -9 3395213 3411215
五、最佳实践与预防 🛡️
- 代码里做好异常捕获:特别是在多进程/多机的训练脚本里,一定要把
try...except用起来!确保在except块里能好好释放资源,让程序优雅地退出,别留下一堆“烂摊子”。 - 别在登录终端直接跑后台:我知道
nohup ... &很方便,但如果你不盯着 PID,很容易就忘了它们的存在。推荐使用 tmux/screen 来管理会话,或者直接用专业的作业调度器(比如 Slurm、K8s),这样更稳妥。
六、结语 🎉
下次再遇到“显存被占,但又找不到进程”的诡异情况时,别慌!优先用 fuser/lsof 这对“火眼金睛”去找出真正的幕后黑手,然后按步骤清理。如果实在搞不定,单卡 reset、重载驱动甚至重启也都是备选方案。把这一套流程熟练掌握,甚至做成小脚本,以后基本就能淡定应对了。
祝大家少踩坑,多出活!👏
更多推荐
所有评论(0)