Loading

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

重点关注:

  • python
  • python3
  • torchrun
  • accelerate
  • 自己的训练程序
  • nvidia-persistenced
  • nv-hostengine
  • dcgm-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 通常是比整机重启更优先的恢复方案。

posted @ 2026-09-10 18:18  Do1phln  阅读(21)  评论(0)    收藏  举报