2. nvidia-smi 指标异常与进程残留定位

为什么 nvidia-smi 的“异常”需要交叉验证

单看 nvidia-smi 默认表格,很容易把三类不同问题混为一谈:显存被真实计算任务占满、显存被已退出但未释放上下文的进程“挂住”、以及 GPU 利用率高但实际没有有效计算(空转)。定位的关键不是看一个数字,而是把 显存占用、进程列表、利用率、进程树、日志 五条线索对齐到同一个 PID 上。

下面这张图给出本节的核心判读结构:从 nvidia-smi 的三种查询模式出发,分别暴露显存、进程、利用率信号,再汇入“PID 对齐”这一判断枢纽,最终分流到三种典型结论与对应处置。

nvidia-smi 查询模式 nvidia-smi 默认表:显存总量/已用、 Utilization、温度、功耗 --query-gpu=memory.used,utilization.gpu --format=csv,noheader,nounits 可脚本化采样,观察趋势 --query-compute-apps=pid,used_memory 列出占用 GPU 的计算进程 PID 是后续对齐的主键 显存占用信号 利用率信号 进程/PID 信号 PID 对齐枢纽 显存占用 ↔ 进程列表 ↔ 进程树 ↔ 日志 ① 真实计算占用 PID 存活、进程树完整 利用率与显存同步波动 日志有对应训练/推理记录 处置:确认归属,勿误杀 ② 僵尸/残留进程 显存被占但 PID 已不存在 或父进程已退出、子进程孤儿 利用率长期 0%,显存不释放 处置:按进程树安全清理 ③ 利用率空转 Utilization 高但显存占用低 或显存高但 SM 活跃度低 常见于忙等、死循环、同步阻塞 处置:查调用栈与日志定位 清理前置:确认 PID 归属用户 → 检查是否有 checkpoint 未落盘 → 优先 SIGTERM,观察显存释放后再考虑 SIGKILL

用查询模式把“异常”变成可判读的数据

默认表格适合人眼扫一眼,但排障需要可比较、可留存的数值。下面三条命令分别对应显存、利用率、进程三个维度,建议在排障时按顺序执行并记录输出。

# 1) 显存与利用率快照(单位 MB / %,便于脚本比对)
nvidia-smi --query-gpu=index,name,memory.total,memory.used,utilization.gpu \
           --format=csv,noheader,nounits

# 2) 占用 GPU 的计算进程(PID 是主键)
nvidia-smi --query-compute-apps=gpu_uuid,pid,process_name,used_memory \
           --format=csv,noheader,nounits

# 3) 连续采样,观察利用率是否“假高”
for i in $(seq 1 10); do
  nvidia-smi --query-gpu=timestamp,utilization.gpu,memory.used \
             --format=csv,noheader,nounits
  sleep 1
done

判读要点:第 2 条命令返回的 PID 必须能在 ps 中找到。如果显存显示被占用,但 --query-compute-apps 返回空列表,或返回的 PID 在 ps -p <pid> 中已不存在,就属于典型的残留上下文——显存由驱动侧持有,进程实体已消失。

进程树与日志:确认“谁留下的”

拿到可疑 PID 后,不要直接 kill。先用进程树确认它是否还有存活的父/子进程,避免只杀掉子进程而父进程继续拉起新任务。

# 查看可疑 PID 的完整命令行与父子关系
ps -o pid,ppid,stat,etime,cmd -p <pid>
pstree -p <ppid> 2>/dev/null || ps --forest -o pid,ppid,cmd -g $(ps -o sid= -p <pid>)

# 若 PID 已不存在,从日志反查残留任务
grep -n "<pid>" /var/log/syslog 2>/dev/null | tail -20
journalctl -k --since "2 hours ago" | grep -i -E "nvrm|xid|oom"

判断依据:STAT 列出现 Z 表示僵尸进程(已退出但父进程未回收);etime 很长而利用率长期为 0,说明任务卡死或空转;日志中出现 Xid 错误码则说明 GPU 侧发生过异常,残留上下文往往与此相关。

安全清理的判定与执行

清理必须满足两个前提:确认该 PID 不属于他人正在运行的有效任务,且相关 checkpoint 已落盘或可接受丢失。满足后按“先软后硬”的顺序处理:

  1. 对残留进程发送 SIGTERM:kill -TERM <pid>,等待 5–10 秒。
  2. 重新执行 nvidia-smi --query-gpu=memory.used --format=csv,noheader,确认显存是否回落。
  3. 若显存未释放且进程已不存在,说明是驱动侧残留上下文,此时单纯 kill 无效,需要重置对应 GPU 或重启相关服务;多卡环境可用 nvidia-smi -i <index> --gpu-reset(需无进程占用且具备权限)。
  4. 清理后再次采样利用率与显存,确认回到基线值,并记录本次 PID、命令行、日志片段作为复盘依据。
不要对不确定归属的 PID 直接使用 kill -9。SIGKILL 会跳过进程清理逻辑,可能加剧显存上下文残留,也会让正在写 checkpoint 的任务损坏输出文件。
把三条查询命令写成一个小脚本,输出“时间戳, 显存已用, 利用率, PID 列表”,连续跑几分钟,就能直观区分“真实占用”“残留”“空转”三种形态,比单次快照可靠得多。