nvidia-smi详解:从GPU利用率到工程级日志监控与故障排查
发布时间:2026/9/26 16:24:36来源:尧图网络
训练跑着跑着终端里敲下nvidia-smi看到 GPU-Util 在 30% 到 40% 之间来回跳这种事情我相信很多人都不陌生。网上一搜有人说数据加载太慢有人说是 kernel 没写好也有人怀疑自己是不是买到了有问题的卡但很少有人把话说透同样是监控 GPU 使用率不同的人看的东西完全不一样。大部分人只瞄一眼利用率百分比做底层优化和训练平台运维的人却会把显存、功耗、温度、SM 时钟、正在跑的进程一起拉出来甚至把这些指标落到带时间戳的日志文件里变成可以复盘、报警、做容量规划的数据资产。这篇文章想做的就是把从“nvidia-smi 一次性查看”到“工程级日志实践”的整个链路顺一遍。适合刚接触 GPU 开发的算法工程师、自己搭深度学习工作站的研究生以及需要维护多卡服务器或训练平台的同学参考。我会先讲清楚几个容易误读的指标再给出一批我实测下来高效的查询命令然后分享一套可以直接套用的日志采集脚本最后单独把couldnt communicate with the nvidia driver这个高频报错的排查路径完整梳理出来。1. 为什么只看“利用率”不够1.1 利用率只是“忙不忙”不是“算得快不快”nvidia-smi里的 GPU-Util 字段准确含义是在采样周期内 GPU 上有 kernel 执行的时间占 SM流处理器簇可调度时间的比例。你可以把它理解成一条高速公路的“是否有车在跑”的比率而不是“车速”或者“单位时间通过车辆数”。这里面藏着两个非常常见的误判场景。第一个场景GPU 利用率只有 30%但代码写得并不差。我遇到过不少同学拿着一张 4090 跑 PyTorch发现利用率上不去第一反应就是“代码优化不到位”结果查了半天发现是 DataLoader 的num_workers设成了 0每个 step 都在等 CPU 喂数据GPU 大部分时间是在空转等待。这时候利用率低恰恰说明硬件本身没问题瓶颈在数据管线而不是计算密度不够。第二个场景更反直觉GPU 利用率一直在 90% 以上但训练速度反而比某台利用率 60% 的机器还慢。原因也很简单如果代码里大量调用特别小的 kernel每个 kernel 的启动和调度开销远大于实际计算时间SM 确实一直处于“有活干”的状态但干的活很多是在执行内存搬运、线程块调度这类辅助操作。这种“虚假繁忙”在自研算子或者过度细粒度切分任务时特别常见。所以不要单独拿利用率来评判 GPU 工作是否正常。它只是一个“忙闲指示器”真正要判断“算得快不快”你得把功耗、时钟频率、温度放到一起交叉验证。1.2 显存、温度、功耗、时钟是“交叉验证四件套”我平时看nvidia-smi很少只看那一栏。完整的信息组合是这样的指标看什么健康信号异常信号利用率SM 是否有 kernel 在跑有大任务时较高波动剧烈且伴随吞吐下降显存占用张量/模型/缓存占了多少有任务时稳定持续缓慢上升可能是泄漏功耗当前实际功率 / 功耗上限接近 Cap 且利用率高利用率高但功耗很低温度GPU 核心温度65~85 摄氏度为常见区间超过 92 摄氏度需要考虑降频SM 时钟当前 SM 频率接近 Boost 频率明显掉频撞功耗墙或温度墙这四类指标一旦互相矛盾基本就说明有问题。比如利用率显示 100%功耗却只有 30W 左右SM 时钟也从 1700MHz 掉到 400MHz这种情况多半是撞了温度墙或者功耗墙驱动主动降频来保护硬件。反过来显存占用接近上限、利用率却只有个位数可能是代码里显存泄漏也可能是加载了一大批数据但计算还没有开始。把几个指标放到一起看比只看一个数字可靠得多。1.3 先搞清楚“谁”在用 GPU在公用服务器上nvidia-smi默认只告诉你 GPU 整体状态但往往你更想知道的是“到底是哪个进程占的显存”。默认输出最下面的 Processes 列表会列出 pid、进程名、显存占用但如果多个用户同时在跑任务这张表格会非常长。这时候我更推荐用nvidia-smi --query-compute-appspid,process_name,used_memory --formatcsv,noheader这条命令会输出类似下面的内容12345, python3, 6124 MiB 12789, python3, 8921 MiB拿到 PID 之后可以再用ps -fp pid确认用户和工作目录。遇到“GPU 显存占着但利用率是 0”的情况多半是进程已经退出但没释放显存或者是一个常驻服务卡死在等待 I/O 上。这一步能帮你快速判断要不要直接 kill 掉残留进程。2. 日常查询的正确姿势2.1 先读懂一条默认输出直接在终端敲nvidia-smi返回的信息分三块顶部是驱动和 CUDA 版本中间是每张 GPU 的运行时状态底部是进程列表。很多人忽略的是 Persistence-M 这一列它表示是否开启了持久化模式。默认情况下驱动在最后一个进程退出后会把 GPU 状态清理掉下次再调用时要重新初始化这会导致每次程序启动都有一段额外的驱动加载时间也会让nvidia-smi首次查询反应变慢。我建议在深度学习服务器上把持久化模式直接打开nvidia-smi -pm 1开了之后驱动的初始化开销被摊平频繁启停训练任务时稳定性明显更好。这个操作不会改动业务数据重启后某些系统会复位需要在启动脚本里再执行一次。2.2 定制化查询--query-gpu 才是效率神器默认输出会有大量无关信息比如风扇转速、MIG 模式之类的。在脚本里写监控、或者只想快速看关键指标时直接筛字段nvidia-smi --query-gpuindex,utilization.gpu,memory.used,memory.total,power.draw,temperature.gpu --formatcsv,noheader,nounits--formatcsv,noheader去掉表头nounits去掉 MiB、W、°C 这些单位后缀方便后续用 awk 或者 Python 解析。比较实用的字段我整理了一下字段含义用途timestamp驱动时间戳和外部日志做时间对齐utilization.gpuSM 利用率%快速判断忙闲utilization.memory显存控制器利用率%判断是否访存密集memory.used已用显存MiB排查泄漏、OOMpower.draw当前功耗W判断是否满负载power.limit功耗上限W判断是否有功耗墙temperature.gpuGPU 核心温度°C散热检查clocks.smSM 当前频率MHz判断是否掉频clocks.mem显存当前频率MHz判断显存是否降频在脚本里我通常还会把clocks.sm和clocks.mem也带上降频问题没有预计到的话很多时候要靠这两个字段才能看出来。2.3 让 nvidia-smi 滚动起来单次查看适合排查问题实时观察则用 watchwatch -n 1 nvidia-smi-n 1表示每秒刷新一次-d可以在每次刷新时高亮发生变化的部分watch -n 2 -d nvidia-smi如果机器上插了多张卡默认输出会把整个屏幕占满。我习惯只盯着关键指标看比如只关注利用率和显存watch -n 2 nvidia-smi --query-gpuindex,utilization.gpu,memory.used,temperature.gpu --formatcsv,noheader这样一张卡一行四张卡也就四行不会乱。注意有些精简版系统的watch不支持-d和彩色输出通过-c参数开颜色前最好先在机器上确认一下。3. 把 nvidia-smi 变成工程级日志采集3.1 为什么要“留痕”一次性命令再方便也存在一个致命短板没法回答“昨天凌晨三点 GPU 到底发生了什么”。我接手过一台 V100 机器同事一直抱怨显存好像不太够训练偶尔会 OOM。等他找我的时候机器已经重启过好几次了。我翻当周的日志发现显存占用从周一早上的 6000MiB 一路爬到周四晚上的 10200MiB利用率却始终不高最后定位到是某个常驻推理服务每次请求都会把中间张量累积在后端模型里相当于温水煮青蛙式泄漏。没有历史日志这种问题几乎不可能查。日志的价值不只是排障。多卡调度的时候想知道两张卡是不是负载不均衡扩容的时候想知道当前机器的利用率到底是 20% 还是 80%做训练回放时想知道显存到底是什么时候涨上去的——这些都依赖“带时间戳的历史状态”而不是当下那一刻的快照。3.2 一个可以直接套用的 Bash 采集脚本下面这个脚本我在多台服务器上用过不依赖第三方库只靠bash、date、nvidia-smi。#!/bin/bash # gpu_monitor.sh # 用法nohup ./gpu_monitor.sh my_task /dev/null 21 # 环境变量 INTERVAL 控制采样间隔默认 10 秒 INTERVAL${INTERVAL:-10} TASK_ID${1:-default} LOG_DIR/var/log/gpu_monitor mkdir -p $LOG_DIR while true; do DAY$(date %Y%m%d) TS$(date %Y-%m-%d %H:%M:%S) CSV${LOG_DIR}/${TASK_ID}_${DAY}.csv if [ ! -s $CSV ]; then echo time,task_id,gpu_id,gpu_name,utilization_percent,memory_used_mib,memory_total_mib,power_draw_w,temperature_c,sm_clock_mhz,mem_clock_mhz $CSV fi nvidia-smi --query-gpuindex,name,utilization.gpu,memory.used,memory.total,power.draw,temperature.gpu,clocks.sm,clocks.mem \ --formatcsv,noheader,nounits | \ while IFS, read -r idx name util mem_used mem_total pwr temp sm_clk mem_clk; do name$(echo $name | tr -d ) echo $TS,$TASK_ID,$idx,$name,$util,$mem_used,$mem_total,$pwr,$temp,$sm_clk,$mem_clk $CSV done sleep $INTERVAL done几个细节解释一下。TASK_ID设计成了参数这样做的好处是同一台机器上跑不同任务时可以分开记录后面对比“任务 A 的显存特征”和“任务 B 的显存特征”会非常方便。日志按天拆文件避免单个文件无限膨胀。脚本本身没有做进程去重所以同一台机器上只建议起一个采集进程否则多个进程同时写同一个 CSV 会出现行交错。用 nohup 丢后台即可nohup ./gpu_monitor.sh training_run1 /dev/null 21 。如果希望开机自启可以放到 systemd service 或者 rc.local 里脚本本身不需要交互输入。3.3 用 Python 的 pynvml 做更细的采集如果觉得 Bash 解析 CSV 不够灵活或者想直接在训练脚本内部同步采样我推荐pynvml它是 NVIDIA 官方 NVML 库的 Python 绑定pip install nvidia-ml-py一个最小示例from datetime import datetime import csv import pynvml pynvml.nvmlInit() device_count pynvml.nvmlDeviceGetCount() fieldnames [ time, gpu_index, util_percent, mem_used_mib, mem_total_mib, power_w, temp_c, sm_clock_mhz, mem_clock_mhz, ] with open(gpu_detail.csv, a, newline) as f: writer csv.DictWriter(f, fieldnamesfieldnames) for i in range(device_count): handle pynvml.nvmlDeviceGetHandleByIndex(i) util pynvml.nvmlDeviceGetUtilizationRates(handle) memory pynvml.nvmlDeviceGetMemoryInfo(handle) power pynvml.nvmlDeviceGetPowerUsage(handle) temp pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU) sm_clk pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_SM) mem_clk pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_MEM) writer.writerow({ time: datetime.now().strftime(%Y-%m-%d %H:%M:%S), gpu_index: i, util_percent: util.gpu, mem_used_mib: memory.used // (1024 * 1024), mem_total_mib: memory.total // (1024 * 1024), power_w: power / 1000.0, temp_c: temp, sm_clock_mhz: sm_clk, mem_clock_mhz: mem_clk, }) pynvml.nvmlShutdown()注意两个单位坑nvmlDeviceGetMemoryInfo返回的是字节所以要除1024 * 1024才是 MiBnvmlDeviceGetPowerUsage返回的是毫瓦要除 1000 才是瓦。这两个单位我一开始没核对日志里出现过好几条天文数字。pynvml 的优势在于可以精确选择采样点。比如你可以在每个训练 epoch 结束的时候采一次样本把 GPU 数据和 loss 变化对齐。基于命令行定时抓取做不到这种“和训练流程同步”的效果。3.4 日志轮转与目录规划日志文件一旦开始长期运行存储早晚是个问题。按天拆文件只是第一步还要考虑保留周期。我的建议是目录结构按“任务/日期”分层/var/log/gpu_monitor/ ├── training_run1_20250601.csv ├── training_run1_20250602.csv ├── inference_svc_20250601.csv └── ...如果底层是 Linux 系统直接用 logrotate 做轮转最省事。配置文件可以这样写/var/log/gpu_monitor/*.csv { daily rotate 14 compress delaycompress missingok notifempty copytruncate }copytruncate很关键。因为采集脚本持有 CSV 文件描述符普通 rename 轮转会导致脚本继续往旧 inode 写数据而copytruncate是先拷贝一份再清空原文件这样脚本不需要重启就能正常切换。虽然理论上存在极小概率的写入丢失但对于秒级采集的 GPU 日志来说可以接受。3.5 采样间隔与时间戳采样间隔推荐 5 秒到 30 秒之间。有人为了“看得更精细”把采集间隔压到 0.5 秒实际测下来有两个问题一是日志文件膨胀特别快7 天就能堆出几个 GB二是nvidia-smi本身有调用开销频繁调用会在驱动层产生不必要的负载尤其在高并发训练时会影响性能统计的准确度。训练任务用 10 秒推理任务用 5 秒长周期容量评估用 30 秒基本覆盖了我遇到的绝大多数场景。时间戳必须用本地时间而且要在多台机器之间统一时区。不然你把两台机器的日志拉到一起对比发现 GPU 利用率一个在 8 点掉下去、一个在 3 点掉下去结果只是因为两台机器一个用了 UTC 一个用了 CST这种问题排查起来非常闹心。采集脚本里最好直接写明比如date %Y-%m-%d %H:%M:%S %z把时区偏移也放进去。4. 那条经典报错“couldnt communicate with the nvidia driver”排查全集4.1 报错长什么样、什么时候容易出现完整报错是这样一行NVIDIA-SMI has failed because it couldnt communicate with the nvidia driver. Make sure that the latest NVIDIA driver is installed and running.这句话字面意思是nvidia-smi找不到驱动通信入口。最常发生的场景包括新装完 Linux 系统还没装驱动就急着跑nvidia-smi内核升级后没有重新安装对应驱动系统重启后驱动模块没有自动加载笔记本双显卡切换没切好容器环境没有把 GPU 设备挂载进去。有一点必须说在前面绝大多数情况下这个报错不是显卡坏了。我在公司处理过几十次类似工单真正硬件损坏的只有两次而且那两次机器都是插在扩展坞上被频繁热插拔折腾过。所以看到这个报错不用慌按顺序一套流程走下来基本都能定位。4.2 完整排查链路第一步是确认系统到底认不认这张卡。在终端执行lspci | grep -i nvidia如果这里能看到类似NVIDIA Corporation GA102 [GeForce RTX 3080]的输出说明 PCIe 层面的硬件枚举是正常的问题方向可以确定为驱动或权限。如果这一行都没有那么优先怀疑物理插槽接触不良、主板 BIOS 设置里把 PCIe 槽禁用了或者机器是云主机但实际没有分配 GPU 资源有些“GPU 云服务器”只是开了带虚拟 GPU 的实例物理驱动路径不一样。第二步检查内核模块有没有加载lsmod | grep nvidia正常会看到nvidia、nvidia_uvm、nvidia_drm、nvidia_modeset这几个模块。如果完全没有输出先手动加载一下modprobe nvidia加载成功后再执行nvidia-smi。如果modprobe报错或者没有任何反应就进一步看内核日志dmesg | grep -i nvidia常见错误包括版本不匹配、符号缺失、NVRM: failed to initialize等等。内核从 5.x 升到 6.x 之后旧版驱动模块经常出现这种问题解决办法一般不是抠配置文件而是直接下载对应新内核版本的驱动重新安装。第三步确认设备节点存在。驱动加载成功后系统会在/dev下创建nvidia0、nvidia1、nvidiactl、nvidia-uvm等设备文件ls -l /dev/nvidia*如果设备文件缺失或者权限不对nvidia-smi同样会报通信失败。可以尝试nvidia-modprobe重新生成设备节点或者手动授权chmod 0666 /dev/nvidia*第四步排查内核版本与驱动版本匹配关系。执行uname -r看当前内核版本再到 NVIDIA 驱动说明文档确认该版本支持的 LTS 内核范围。这里有一条铁律升级内核之后不重新安装驱动NVIDIA 模块几乎必然失效。我自己习惯是保留一条Ubuntu 的 HWE 内核回滚入口万一新内核和驱动不兼容能快速回到旧内核继续干活。第五步检查 Nouveau 驱动是否抢占。有些发行版默认加载开源的 Nouveau它和 NVIDIA 闭源驱动冲突导致后者初始化失败。要么彻底 disable Nouveauecho blacklist nouveau /etc/modprobe.d/blacklist-nvidia-nouveau.conf echo options nouveau modeset0 /etc/modprobe.d/blacklist-nvidia-nouveau.conf update-initramfs -u要么在安装 NVIDIA 驱动时选择覆盖掉它。装完之后重启再看nvidia-smi是否正常。4.3 双显卡笔记本的特殊情况热词里有个“Intel UHD Graphics NVIDIA GeForce RTX 4060 Laptop GPU”的组合这类笔记本在 Linux 下非常容易触发上面的报错。核心原因是笔记本默认会把独显切到电源门控状态驱动在省电模式下没有做初始化nvidia-smi访问时找不到活跃设备。可以先尝试强制唤醒独显nvidia-smi -L如果仍然报错检查是不是处于 PRIME 切换状态。使用prime-select把模式切到nvidiasudo prime-select nvidia sudo reboot重启之后如果nvidia-smi已经有输出再按照上一节的“内核模块 设备节点 权限”顺序确认持久化。注意这种机器在反复切换 Windows/Linux 双系统时有些 BIOS 的 Fast Boot 会导致硬件初始化状态异常进入 BIOS 关闭 Fast Boot 再试一次属于性价比极高的排查动作。4.4 容器环境下的特殊处理很多同学不是在宿主机上直接跑而是通过 Docker 起容器来跑深度学习。宿主机上nvidia-smi一切正常容器内部一执行就报 communication failed这种情况几乎都是因为设备没有挂载进来。用 Docker 运行 GPU 容器现在已经不需要手动挂/dev/nvidia*了关键是安装并配置nvidia-container-toolkit。典型流程distribution$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | sudo tee /etc/apt/sources.list.d/libnvidia-container.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit sudo systemctl restart docker然后容器启动时docker run --gpus all -it nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi--gpus all会自动帮容器挂载 GPU 设备和驱动库。如果用的是旧版 Docker 或者旧版 toolkit这部分还是有可能失败可以手动用--device/dev/nvidia0:/dev/nvidia0 --device/dev/nvidiactl:/dev/nvidiactl挂载设备文件再把/usr/lib/x86_64-linux-gnu/libnvidia-ml.so这类运行库拷进容器但复杂度会高很多能升级 toolkit 就不要手动挂载。4.5 如何让监控脚本不至于一崩到底排查完报错之后还应该想一下怎么预防下一次中断尤其是长期跑监控日志的场景。我做了三个防御动作第一个动作开启持久化模式nvidia-smi -pm 1。它能减少驱动懒加载窗口这个窗口期间nvidia-smi的响应会出现短时超时。第二个动作在采集脚本里检查退出码。如果某一次nvidia-smi失败脚本不能继续往日志里写空数据或者重复写最后一行应该记录一条告警再跳过本次采样。用 Bash 的话可以在nvidia-smi命令后面加上|| echo $TS,$TASK_ID,ERROR,nvidia-smi failed $CSV方便日志语义保持完整。第三个动作给监控脚本加一个 systemd service让它在崩溃后自动重启[Unit] DescriptionGPU monitor service [Service] ExecStart/usr/local/bin/gpu_monitor.sh default Restartalways RestartSec10 [Install] WantedBymulti-user.target需要说明的是这层防护只解决“监控进程没挂”的问题。如果驱动本身已经和内核不匹配了不管脚本怎么重启底层的nvidia-smi该失败还是失败最终还是要回到 4.2 的流程重新装驱动。5. 日志只是第一步向上对接监控平台与趋势分析5.1 轻量对接 Prometheus 的 textfile 模式单机日志做得再完善也还是偏“离线”。如果公司已经有一套基于 Prometheus 的监控体系最省事的接入方式是用 node_exporter 的 textfile collector。原理很简单node_exporter 会定时读取指定目录下以.prom结尾的文件把文件里的指标直接暴露给 Prometheus。先建目录mkdir -p /var/lib/node_exporter/textfile然后写一个采集脚本把nvidia-smi的输出转换成 Prometheus 指标格式#!/bin/bash # gpu_to_prom.sh # 放到 cron 里每 15 秒执行一次也可以 OUT_DIR/var/lib/node_exporter/textfile OUT_FILE${OUT_DIR}/gpu.prom TMP_FILE${OUT_DIR}/gpu.prom.$$ nvidia-smi --query-gpuindex,name,utilization.gpu,memory.used,memory.total,power.draw,temperature.gpu \ --formatcsv,noheader,nounits | \ while IFS, read -r index name util mem_used mem_total power temp; do cat $TMP_FILE EOF # HELP gpu_utilization_percent GPU utilization in percent. # TYPE gpu_utilization_percent gauge gpu_utilization_percent{gpu_index$index,gpu_name$name} $util # HELP gpu_memory_used_bytes Memory used on GPU in bytes. # TYPE gpu_memory_used_bytes gauge gpu_memory_used_bytes{gpu_index$index,gpu_name$name} $((mem_used * 1024 * 1024)) # HELP gpu_memory_total_bytes Total memory on GPU in bytes. # TYPE gpu_memory_total_bytes gauge gpu_memory_total_bytes{gpu_index$index,gpu_name$name} $((mem_total * 1024 * 1024)) # HELP gpu_power_watts Current GPU power draw in watts. # TYPE gpu_power_watts gauge gpu_power_watts{gpu_index$index,gpu_name$name} $power # HELP gpu_temperature_celsius Current GPU temperature in Celsius. # TYPE gpu_temperature_celsius gauge gpu_temperature_celsius{gpu_index$index,gpu_name$name} $temp EOF done mv $TMP_FILE $OUT_FILE关键点在于最后用mv移动临时文件而不是直接 append 到目标文件这样能避免 Prometheus 读到半行残留。启动 node_exporter 时加上--collector.textfile.directory/var/lib/node_exporter/textfile就能自动采集这些指标。如果是数据中心级显卡NVIDIA 官方还有 DCGM 方案能提供更细粒度的 SM 占用、NVLink 带宽、PCIe 吞吐等指标但它的部署成本更高。对个人工作站和普通训练服务器来说nvidia-smi的 textfile 模式已经够用了。5.2 在训练代码里做“指标对齐”对接了 Prometheus 之后你看到的是 GPU 侧的独立指标流。另一个非常实用的做法是把 GPU 采样直接埋进训练代码里让 GPU 指标和 loss、step、吞吐量落在同一条时间线上。pynvml 在 3.3 已经提过了这里给一个训练循环内的典型用法for step, batch in enumerate(dataloader): loss train_step(batch) if step % 50 0: handle pynvml.nvmlDeviceGetHandleByIndex(0) util pynvml.nvmlDeviceGetUtilizationRates(handle) memory pynvml.nvmlDeviceGetMemoryInfo(handle) log.append({ step: step, loss: float(loss), gpu_util: util.gpu, mem_used_mib: memory.used // (1024 * 1024), })这种做法的价值在定位 OOM 时尤其明显。显存并不是一直线性增长的某个环节会突然飙升。把显存采样点和数据 pipeline 的日志对齐后你可以精确定位到“OOM 前 20 个 step 里到底发生了什么”而不是靠猜。5.3 告警阈值别拍脑袋接入监控平台之后接下来就是配告警。最容易踩的坑是拿 GPU 利用率做一刀切告警。我见过有人给 GPU 利用率设了一个“低于 30% 就报警”的规则结果马上被推理服务误伤——低负载推理服务本来利用率就是 0因为它大部分时间在等待请求并不代表服务异常。更适合做告警的指标有三个GPU 温度超过阈值比如 92°C显存剩余低于阈值比如剩余 2GiB 以下且持续 5 分钟以及功率异常归零可能伴随掉卡或者驱动异常。这三个指标背后都有明确的硬件事件误报率低。如果确实想用利用率告警建议加一个前提条件当前确实在跑训练任务且外部吞吐量低于预期。单纯只看 GPU 利用率本身信号是高度冗余的。5.4 趋势分析才是最终目的日志和监控平台都跑起来之后回头再去看数据你会发现趋势比瞬时值有用得多。瞬时利用率 50% 说明不了任何问题但连续一周的利用率曲线能告诉你这台 GPU 到底该配给哪个团队。容量规划也一样你把所有训练任务各自的显存峰值画出来就会发现“16G 显存的机器已经跑不下三个并发任务了”这时候换 24G 或者 48G 的机器就不是拍脑袋而是有数据支撑的决策。我自己比较喜欢做的一个分析是按小时汇总平均利用率SELECT date_trunc(hour, time) AS hour, AVG(utilization_percent) AS avg_util, MAX(memory_used_mib) AS max_used_mib FROM gpu_metrics WHERE task_id training_run1 GROUP BY hour ORDER BY hour;有了这种时间粒度的一条曲线再叠加上训练代码的版本记录几乎每个性能劣化都能对上号。注意做这些分析的前提是日志采集从一开始就规范地加了时间戳、任务 ID、机器 ID否则后面一切拉取汇总都是无源之水。我在实际落地这套监控日志之后最大的感受不是“多了一张趋势图”而是当训练出问题时我能把时间轴拉到分钟级直接回看事发前后几分钟的 GPU 状态。有一次深夜大模型训练速度突然掉了一半我对比 GPU 监控日志和训练日志发现正好是数据缓存目录被清掉所有 worker 都在疯狂重新读取数据GPU 在等数据。这种问题如果还停留在手动敲一遍nvidia-smi的阶段根本来不及发现更别提定位了。最后再分享一个我常用的土办法帮你快速判断训练慢是不是卡在数据读取把采样间隔压到 0.5 秒连续盯十几秒的 GPU 利用率曲线。如果它像心跳一样“跳一下、停一下、再跳一下”大概率是 CPU 每拿到一个 batch 的间隙里 GPU 在空转瓶颈在数据管线如果利用率一直拉满但吞吐依然上不去那就要去看 kernel 规模和计算密度了。这个判断不一定绝对但作为第一轮排查方向真的能省下大把时间。
网站建设高端定制企业官网