Linux 下清理 GPU 幽灵进程与无法释放显存的问题
在多 GPU Linux 工作站上,有时会遇到这样一种情况:
nvidia-smi显示某张 GPU 仍然占用大量显存;gpustat看不到对应 PID;nvidia-smi --gpu-reset -i 0提示 GPU 正在被其他进程占用;- 相关训练任务实际上已经结束。
这类问题通常意味着 GPU 设备节点仍被某些进程、守护进程或异常 CUDA 上下文占用。
本文记录一套针对 GPU0 无图形输出,且目标是彻底清空 GPU0 的处理流程。
1. 查看 GPU0 当前状态
先检查 GPU0:
nvidia-smi -i 0
如果可以直接看到异常计算进程 PID,优先尝试正常结束:
kill PID
如果无法退出:
kill -9 PID
然后再次检查:
nvidia-smi -i 0
2. 使用 fuser 查找所有占用 GPU0 的进程
即使 nvidia-smi 看不到 PID,Linux 文件描述符层面通常仍能找到打开 /dev/nvidia0 的进程:
sudo fuser -v /dev/nvidia0
如果只想获取 PID:
sudo fuser /dev/nvidia0
进一步查看这些 PID 的详细信息:
for p in $(sudo fuser /dev/nvidia0 2>/dev/null); do
ps -p "$p" -o pid,ppid,user,state,wchan:32,etime,cmd
done
重点关注:
pythonpython3torchrunaccelerate- 自己的训练程序
nvidia-persistencednv-hostenginedcgm-exporter
3. 如果目标是直接清空 GPU0
前提条件:
- GPU0 不承担 Xorg、Wayland 等图形输出;
- GPU0 上没有需要保留的任务;
- 其他 GPU 上可能仍有正常任务。
不要直接执行:
sudo fuser -k /dev/nvidia*
因为这可能误杀其他 GPU 上的正常任务。
应该只针对:
/dev/nvidia0
先发送 TERM:
sudo fuser -k -TERM /dev/nvidia0
等待几秒:
sleep 3
如果仍有进程,再强制结束:
sudo fuser -k -KILL /dev/nvidia0
然后检查:
sudo fuser -v /dev/nvidia0
4. 停止可能持续占用 GPU 的 NVIDIA 服务
有些系统服务会持续打开 GPU 设备节点,导致 GPU reset 失败。
先停止 NVIDIA persistence daemon:
sudo systemctl stop nvidia-persistenced 2>/dev/null
如果安装了 NVIDIA DCGM:
sudo systemctl stop nvidia-dcgm 2>/dev/null
同时停止可能残留的 nv-hostengine:
sudo pkill -9 nv-hostengine 2>/dev/null
然后再次清理 GPU0:
sudo fuser -k -TERM /dev/nvidia0
sleep 2
sudo fuser -k -KILL /dev/nvidia0
sleep 2
再次检查:
sudo fuser -v /dev/nvidia0
5. 重置 GPU0
确认 GPU0 不再被正常任务占用后,执行:
sudo nvidia-smi --gpu-reset -i 0
然后查看显存是否已经释放:
nvidia-smi -i 0
如果 reset 成功,GPU0 通常会恢复到空闲状态。
最后重新启动 persistence daemon:
sudo systemctl start nvidia-persistenced
6. 可直接复制执行的一套命令
如果已经确认:
- GPU0 没有图形输出;
- GPU0 上所有任务都可以清理;
- GPU1、GPU2、GPU3 上可能仍有正常任务;
可以执行:
sudo systemctl stop nvidia-persistenced 2>/dev/null
sudo systemctl stop nvidia-dcgm 2>/dev/null
sudo pkill -9 nv-hostengine 2>/dev/null
sudo fuser -k -TERM /dev/nvidia0
sleep 2
sudo fuser -k -KILL /dev/nvidia0
sleep 2
sudo fuser -v /dev/nvidia0
sudo nvidia-smi --gpu-reset -i 0
nvidia-smi -i 0
sudo systemctl start nvidia-persistenced 2>/dev/null
核心原则:
只处理
/dev/nvidia0,避免误伤其他 GPU。
7. 如果 kill -9 仍然杀不掉
如果执行:
sudo fuser -v /dev/nvidia0
仍然能看到 PID,可以进一步检查进程状态:
for p in $(sudo fuser /dev/nvidia0 2>/dev/null); do
ps -p "$p" -o pid,ppid,user,state,wchan:32,etime,cmd
done
重点看 STATE。
如果状态是:
D
说明进程处于 Linux 的 uninterruptible sleep 状态。
这通常意味着进程阻塞在:
- NVIDIA 驱动调用;
- CUDA kernel;
- PCIe / GPU I/O;
- 内核态 GPU 操作。
这种情况下:
kill -9 PID
也无法立即终止进程。
如果同时满足:
- PID 处于
D状态; - 显存无法释放;
gpu-reset仍提示 GPU 被占用;
那么问题通常已经进入驱动或内核层面。
继续反复执行 kill -9 基本没有意义,可能需要:
- 重载 NVIDIA 驱动;
- 重启相关 NVIDIA 服务;
- 最终重启系统。
8. 不建议执行的命令
多 GPU 工作站尤其不要直接执行:
sudo fuser -k /dev/nvidia*
也不要轻易执行:
sudo fuser -k /dev/nvidiactl
或:
sudo fuser -k /dev/nvidia-uvm
这些设备节点可能被多张 GPU 和多个 CUDA 任务共享。
如果 GPU1、GPU2、GPU3 上还有正常训练任务,这种操作可能把其他卡上的任务一起杀掉。
9. 推荐处理流程
整体流程可以概括为:
nvidia-smi
↓
fuser /dev/nvidia0
↓
确认 PID
↓
TERM / KILL
↓
停止 nvidia-persistenced / DCGM
↓
再次清理 /dev/nvidia0
↓
nvidia-smi --gpu-reset -i 0
对于多 GPU 服务器,最重要的是控制清理范围。
如果只想清理 GPU0,就始终围绕:
/dev/nvidia0
操作,避免直接处理:
/dev/nvidia*
/dev/nvidiactl
/dev/nvidia-uvm
总结
这套方法适合处理以下问题:
- 深度学习训练异常退出;
- CUDA context 残留;
gpustat看不到 PID;nvidia-smi显示显存被占用,但进程列表为空;gpu-reset提示 GPU 正在被占用;- 多 GPU 服务器只想清理其中一张卡。
对于没有图形输出的独立计算 GPU,fuser + kill + gpu-reset 通常是比整机重启更优先的恢复方案。

浙公网安备 33010602011771号