news 2026/10/22 4:47:44

Linux GPU监控实战:从nvidia-smi到自动化运维

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux GPU监控实战:从nvidia-smi到自动化运维

1. 先跑通最基础的命令:nvidia-smi的常用参数与现场解读

我需要盯着显卡看的时候,绝大多数场景其实都跑不掉这一条命令:

nvidia-smi

输出信息量大,一眼扫过去能看到的东西非常多。我把一次实际输出贴出来,逐块拆开讲,很多朋友看了半年这张表,其实都没搞清楚每一行的真实含义。

1.1 上半部分:驱动版本、CUDA版本和卡的总览

最上面的几行,平时最容易被忽略,但排查环境问题的时候反而是命门。

+---------------------------------------------------------------------------------------+ | NVIDIA-SMI 545.23.06 Driver Version: 545.23.06 CUDA Version: 12.3 | +---------------------------------------------------------------------------------------+

第一行里有两个关键信息:Driver Version是显卡驱动的完整版本号,CUDA Version是当前驱动所支持的最高CUDA运行时版本。这两个东西经常被搞混。很多初学者以为在系统里装了CUDA Toolkit,nvidia-smi里的CUDA Version就会跟着变,其实不是。nvidia-smi显示的是驱动支持的上限,跟你是否装了CUDA Toolkit没有直接关系。只要驱动新,这里就会显示新版本。实际编译和运行程序用的是另一个版本,用nvcc --version才能看到。

检查环境不匹配的时候,我一般先看这里。比如你机器上装的是CUDA 11.8的Toolkit,但驱动显示的CUDA Version是12.3,那程序只要能跑,通常问题不大;反过来,驱动显示的版本低于你Toolkit版本,那百分之百要出幺蛾子。

再往下是四列核心信息和小表格:

| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |

这几行里,我要特别说三个容易误读的指标。

**Persistence-M(持久模式)**这一列,很多人从来没注意过。它显示On或Off,代表GPU是否启用了持久模式。如果显示Off,表示GPU在没有任何任务时会自动进入低功耗状态,下一次有进程调用时需要重新初始化。在服务器场景下我强烈建议把它打开,因为训练任务反复启停的时候,关闭持久模式会导致每次初始化都有额外的延迟,而且某些老驱动下还可能伴随显存分配异常。打开方法很简单:

sudo nvidia-smi -pm 1

Volatile Uncorr. ECC这列,很多非专业卡上是N/A,不用管。如果你的卡支持ECC显存,这列一旦出现非零数值,就要警惕——它表示发生了无法纠正的显存错误,可能预示硬件开始不稳定了。

**Compute M.(计算模式)**这一列默认是Default。如果某张卡被配置成Exclusive Process(独占进程)模式,其他用户的进程就无法再往这张卡上分配显存。多人在同一台机器上协作时,这种模式经常引发"明明有空卡,但我的任务就是起不来"的奇怪故障。排查思路往这个方向靠一靠,能少走不少弯路。

1.2 下半部分:每张卡的实时状态表

接下来的表格才是日常监控的主战场:

| 0 NVIDIA GeForce RTX 3090 Off | 00000000:01:00.0 Off | N/A | | 30% 61C P0 280W / 350W | 5213MiB / 24576MiB | 98% Default |

我把每一列单独标出来解释:

  • 第一列最前面的数字是GPU编号(从0开始)。多卡机器上用编号区分物理位置会很方便。
  • Fan(风扇转速百分比):30%表示风扇当前转速占最大转速的30%。注意,很多数据中心专业卡风扇是0%,因为散热靠风冷整体方案,这个地方反而不用纠结。
  • Temp(温度):61C是GPU核心当前温度。一般消费级卡到85C以上就该警惕了,长期超过90C运行会明显缩短寿命。温度墙通常在83~93C之间,具体看卡的型号和驱动设定。
  • Perf(性能状态):P0是最高性能档位,P8之类的低档位表示GPU基本空闲。性能状态作为粗略判断负载强度的参考很有效。看到P0但GPU-Util是0%,说明卡正在等数据或者陷入了某种奇怪的等待状态,这种情况后面单独说。
  • Pwr:Usage/Cap(当前功耗/最大功耗):280W / 350W表示当前实际功耗280瓦,最大功耗墙是350瓦。功耗接近上限通常说明负载很重。如果显存占用很高但功耗很低,说明任务可能卡在数据搬运或者内存带宽上,而不是算力不够。
  • Memory-Usage(显存占用/总显存):5213MiB / 24576MiB。这是最直观的显存占用数据,排查OOM就看这里。
  • GPU-Util(GPU利用率):98%代表计算单元在采样周期内的繁忙程度。这是一个非常容易被误解的指标,它不是"用了多少算力"的精确值,而是"在这段时间里,GPU的计算单元有多少时间在处理任务"的估算值。深度学习训练里30%~50%的利用率非常常见,不一定是程序有问题,更可能是数据加载、预处理或者CPU端代码拖了后腿。

我习惯把GPU-Util当作"喘息程度"来看。98%意味着GPU几乎没闲着,这时如果训练速度还是提不上去,瓶颈多半不在GPU本身;30%则意味着GPU有大把时间在等待,这时候把数据流水线调优的优先级提上来,效果立竿见影。

1.3 进程列表的两种形态:看到PID和用户名才方便追责

nvidia-smi默认输出底部会列出正在使用GPU的进程。默认显示如下:

+-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 123456 C /usr/bin/python3 5213MiB | +-----------------------------------------------------------------------------------------+

这里Type一列C表示计算进程,G表示图形/显示进程。GPU Memory Usage就是该进程在这张卡上占用的显存数量。

如果进程列表太长,或者我只需要显存和GPU利用率这类汇总数据,我经常只取上面表格那一截,不让进程列表刷屏:

nvidia-smi --query-gpu=index,temperature.gpu,utilization.gpu,memory.used,memory.total --format=csv

顺序执行下来,会输出类似:

index, temperature.gpu, utilization.gpu, memory.used, memory.total 0, 61, 98, 5213 MiB, 24576 MiB

这种简洁格式非常适合写进监控脚本或者配合后面要讲的watch做轮询。后面自动化部分我会专门演示这套组合。

不过我通常会再多加一列功耗,排查性能问题时这一列的价值很高:

nvidia-smi --query-gpu=index,utilization.gpu,power.draw,power.limit,temperature.gpu,memory.used,memory.total --format=csv,noheader

这里的noheader是去掉表头,配合脚本处理时更干净。

2. 把静态快照变成动态数据流:watch轮询与刷新间隔的细节

nvidia-smi单次执行拿到的是一张静态快照。GPU利用率上下跳动非常频繁,静态快照很容易漏掉关键峰值。比如你扫一眼看到GPU-Util是0%,实际可能前五秒负载刚结束,你只能看到"现在这一刻"的假象。

为了让数据流动起来,最简单的做法就是循环刷新。这里我强烈推荐watch,而不是自己写while循环。

watch -n 1 nvidia-smi

这条命令就是每秒钟刷新一次nvidia-smi的输出,可以把整个终端变成一块实时的显卡监控面板。实际用下来有几点经验值得记一下。

  • 刷新间隔:我通常在训练调试时用-n 1(一秒一次),观察抖动细节够用了。如果只是后台挂着保持警惕,-n 2或者-n 5就足够,刷新太频繁反而浪费CPU资源,也会让输出闪烁得让人心烦。
  • 退出操作:watch画面里直接按Ctrl+C退出。但这个细节很多人踩过坑:watch会把终端切到自己的交互模式,如果按Q退出,有时候会残留一段黑屏,按Ctrl+C是最稳妥的。
  • 高亮差异:watch默认会把每次输出中发生变化的部分高亮显示,这对肉眼观察温度、显存、利用率的变化非常友好。如果不想看到高亮,可以加-d=0关掉。

但watch有个不太顺手的地方,它会帮你清空屏幕,把输出固定在屏幕固定位置。这本来是优点,但在某些远程终端或者记录屏幕日志的时候反而麻烦。如果你只是想把命令周期性地打印出来,用watch的另一种形态也能实现。比如:

while true; do nvidia-smi --query-gpu=index,utilization.gpu,memory.used --format=csv; sleep 1; done

这种写法会把每次结果串行往下打印,适合留下滚动记录,但刷屏速度会比较快,一般只在调试时候用。

我在实际使用中还有一个习惯:配合watch自带的高亮,在搜索"到底哪个进程把显存吃满了"这类问题时特别方便。启动watch以后不用频繁敲命令,专注盯着GPU-Util和Memory-Usage两列的变化,基本能判断出瓶颈所在。看到数值稳定在高位,说明任务在健康推进;数值一直上下乱跳,说明负载波动剧烈,可以开始怀疑数据读取不均衡或者多进程竞争。

用watch还有一个实用小技巧是配合下面的查询格式,把输出压缩成一行,非常适合在宽屏终端下多张卡一屏全看完:

watch -n 1 'nvidia-smi --query-gpu=index,utilization.gpu,memory.used,power.draw --format=csv,noheader'

多条卡的话,输出会按GPU编号顺序纵向排列,一目了然。这个模式也是我在多卡机器上最常驻的终端之一。

3. 更专业的监视面板:nvidia-smi dmon、nvtop与gpustat的搭配使用

3.1 nvidia-smi dmon:滚动刷新的专业监控模式

watch模式下整屏静态画面虽然在变,但缺少历史趋势的可读性。真正需要观察指标在一段时间内的变化轨迹时,我一般切到nvidia-smi自带的dmon模式:

nvidia-smi dmon -s pucm -d 1

参数拆解一下:

  • -s pucm:指定要显示的指标组。p是电源和温度(Power),u是GPU利用率(Utilization),c是计算核心利用率(Compute),m是显存使用(Memory)。如果你还想看PCIe相关信息和时钟频率,可以加上t参数。
  • -d 1:刷新间隔1秒。

进入dmon模式后,输出会像表格一样持续滚动:

# gpu pwr gtmp temp sm mem enc dec mclk pclk # Idx W C C % % % % MHz MHz 0 280 61 61 98 20 0 0 7000 1500

这里的sm列代表流处理器利用率,mem是显存控制器利用率,enc和dec是硬件编解码引擎占用。显卡做视频转码、视频分析任务时,enc/dec这两列的数值比GPU-Util更直接。之前有朋友跑视频处理时GPU-Util接近0,但任务一直很慢,我让他看一眼enc列,果然飙在90%以上——瓶颈在编解码器而不是通用算力。

dmon模式还有一个隐形优势:它完全不依赖任何Python包或第三方工具,任何装了NVIDIA驱动的机器上都可以直接用。远程SSH到一台环境受限的老机器时,dmon往往是唯一能用的专业监控手段。

退出dmon模式,直接按q即可。

3.2 nvtop:类htop的图形化面板

到了图形化面板这个层面,我最常用的就是nvtop。它的布局和htop非常像,每个GPU一块区域,除了顶部的实时数据外,底部还会显示历史负载曲线,很适合"肉眼回顾过去几十秒发生了什么"。

安装方式一般两种:

# Ubuntu/Debian系 sudo apt install nvtop # 或者用snap sudo snap install nvtop

如果官方源没有对应版本,也可以从源码编译,但通常没有这个必要。nvtop依赖libdrm和libncurses,装的时候缺什么补什么就行。

实际用下来我觉得nvtop最顺手的地方是按键交互:方向键可以在多块卡之间切换焦点,S键可以调出进程排序菜单。另外nvtop支持鼠标操作,在图形界面终端里点击进程行能直接查看进程详细信息,这在多人共用的大机器上排查"谁占了我的卡"非常方便。

不过nvtop也有它的毛病,在纯文本终端(比如某些串口控制台)里渲染会出错,导致界面花屏。遇到这种环境,我果断退回dmon或者watch方案,不硬刚。

3.3 gpustat:一条命令拿到JSON和紧凑视图

gpustat是我解决"想快速看一眼全局"时最顺手的工具箱。它是一个Python包,安装方式:

pip install gpustat

装完之后直接执行:

gpustat -i 1

会输出一个紧凑的彩色面板,把每张卡的使用率、显存、温度、功耗、进程列表都压到几行内。对多卡机器特别友好,一排卡片看过去,哪张卡忙哪张卡闲一目了然。

gpustat还支持JSON输出:

gpustat --json

这个功能在写自动化监控脚本时价值很大,把JSON喂给采集程序,非常干净。

我一直把gpustat当作"快速总览"工具,把nvtop当作"深入观察"工具,两个搭配使用:

  • 刚开机或者准备提交任务前,跑一次gpustat看全局;
  • 任务运行中需要定位性能瓶颈时,开nvtop盯曲线;
  • 远程环境受限,啥都装不了时,用nvidia-smi dmon救场。

三个工具的功能定位差异,我整理了一个简短对比:

工具定位依赖适合场景
nvidia-smi官方基础命令无日常快照、脚本采集、环境受限
nvidia-smi dmon官方滚动监控无历史趋势观察、多指标同时跟踪
nvtop图形化面板libdrm/ncurses直观观察曲线、多卡切换、进程排序
gpustatPython便捷工具Python/pip快速总览、JSON采集、脚本集成

3.4 还有一个容易被忽略的:按需查看进程所属的GPU详细状态

偶尔会遇到一种情况:机器上有好几张卡,某个进程占着一张卡,但我记不住卡号和进程的对应关系。这时候在nvidia-smi的进程列表里已经能看到PID和显存占用,但还想知道这个进程到底用了哪张卡的多少算力,可以这样:

nvidia-smi --query-compute-apps=pid,used_gpu_memory,gpu_uuid --format=csv

这个查询能直接把进程PID和GPU的UUID对应起来,再配合前面那张卡的UUID信息,就能精确画出一条"哪个进程跑在哪张卡上"的映射关系。多卡调度排查时这套组合相当有用。

不过说实话,日常使用中我用得更粗暴:直接在nvtop的进程面板里看,排序一拉,进程对应关系立刻清楚,根本不用记UUID。

4. 数据到手只是第一步:定位占用进程、显存泄漏与多卡调度排查

监控工具能拿到大量数据,但这些数据本身不解决问题。真正考验功力的,是从数据里读出问题并找到对应的处理手段。

4.1 如何精准定位占用GPU的进程:从PID到完整命令行

当你看到某张卡显存占用很高,却不知道是谁的进程时,标准动作是执行:

nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv

这会列出所有计算进程的PID、进程名和占用的显存。有了PID之后,如果再想看到这个进程的完整启动命令,可以用:

ps -p <PID> -o args=

这一招在排查"这个python进程到底是哪个实验脚本"时太常用了。因为很多时候进程名只显示python3,根本看不出是哪个训练任务。补全命令行之后,直接就能看到脚本路径和参数,一下子就知道后台跑的到底是哪套代码。

更进一步,如果你用的是conda环境,还可以看看这个进程的可执行文件实际指向哪里:

ls -l /proc/<PID>/exe

这个软链接直接指向真实的可执行文件路径,可以帮你确认是不是被某个诡异的包装脚本套住了。

4.2 显存泄漏的经典死亡信号:进程退出后显存没回来

最常见的显存泄漏场景是:程序崩了,或者你手动Ctrl+C终止了训练,但nvidia-smi里看到那个进程还在,显存占用还挂着不放。这就是典型的"显存未释放"。

出现这种情况,先不要急着杀进程,先用ps确认一下进程是否真的还活着:

ps -p <PID> -o pid,etime,comm

如果进程确实还在,且已经是个僵尸状态,直接终结它:

kill -9 <PID>

杀完再执行nvidia-smi,显存额度应该立刻释放。如果显存依然被占用,但进程列表里根本看不到和它对应的进程,那很可能是进程已经消失了,但显存还卡在某个模块或者驱动内部。这种情况比较麻烦,一般的处理顺序是:

  1. 再次执行nvidia-smi查看进程列表,确认没有残留进程;
  2. 如果确认无进程但显存仍占用,尝试重启显示管理器或者GPU相关的服务;
  3. 终极方案是重启机器,这是最干净利落的做法。

在多人共用的服务器上,杀进程这类操作一定要谨慎。动手前先确认那个进程不是别人的正在运行的任务。我一直保留一个习惯:在公共机器上杀任何PID之前,先发消息或者在群里吼一声,避免误伤。

4.3 GPU-Util很低但功耗很高:一张卡到底在忙什么?

有一种很有迷惑性的现象:GPU-Util显示98%,功耗也接近上限,温度正常,但程序跑得并不快。这种状态往往不是GPU在全力计算,而是某些计算模式下的持续占用。

我遇到过一个场景:某个推理服务加载了很大的模型,请求并发激增时,GPU利用率很高,但实际每秒能处理的请求数反而下滑。用dmon一看,发现sm列利用率很低,mem列利用率很高,说明瓶颈在显存带宽,而不是流处理器算力。这类诊断如果不看dmon的细分指标,只盯着一张GPU-Util表,很容易得出"GPU很忙,所以程序应该没问题"的错误结论。

类似的经验在深度学习的卷积操作里也有体现。某些小卷积核、长条形的运算对访存带宽很敏感,sm利用率不高但显存通道很繁忙,功耗看起来也不低。想优化这种程序,方向应该是减少显存随机访问、合并小算子、使用更合理的数据布局,而不是换一块更大的卡。

4.4 多卡机器上"剩多少卡可用"的正确判断姿势

多人共用的大机器上,最常听到的问题就是"还有空卡吗?"如果你只扫一眼nvidia-smi的总显存和利用率,很容易误判。

正确的判断姿势应该是看两样东西:

  1. 显存剩余:也就是总显存减去used显存,这个数字决定你的新任务能不能分配进去;
  2. 计算空闲:GPU-Util长时间接近0%且显存也几乎是空的,才算真正空闲。

矩阵组合一下:

  • 显存有剩余,GPU-Util很高:说明这张卡有任务在跑,但还有显存余量。你能挤进去,但会跟别人抢算力,体验可能很差。
  • 显存占满,GPU-Util很高:典型满载,别想了。
  • 显存占满,GPU-Util很低:有人占了显存放着不跑,可能是任务已经崩了或者挂起,这种情况可以考虑去沟通,而不是直接开抢。
  • 显存为空,GPU-Util很低:真正空闲,随便用。

我在公共服务器上给大家的一个建议是:提交大训练任务之前,先用gpustat和nvidia-smi --query-gpu=index,memory.used,utilization.gpu --format=csv确认目标卡的这两项状态,避免"看起来有剩余显存,实际上一启动就OOM"的尴尬。

5. 让监控自己干活:日志落盘、阈值告警与后台巡检脚本

一直盯着终端看不是长久之计。真实场景里,训练任务跑上一整天,人不可能一直守着终端。我习惯把关键指标写成日志,让脚本自己盯着,有问题时再通知我。

5.1 把GPU状态定期落盘:一个最容易上手的循环采集脚本

我经常用的一个基础采集脚本长这样:

#!/bin/bash # gpu_monitor.sh while true; do timestamp=$(date '+%Y-%m-%d %H:%M:%S') gpu_status=$(nvidia-smi --query-gpu=index,temperature.gpu,utilization.gpu,memory.used,power.draw --format=csv,noheader) echo "$timestamp, $gpu_status" >> /var/log/gpu_monitor.log sleep 5 done

按下Ctrl+C停止。写脚本时有几个细节值得注意:

  • 别把日志写到和训练数据同一个磁盘分区,避免磁盘写满影响训练任务。
  • 清理机制要有,日志挂了几天不动会变大。我一般配合logrotate或者简单地在脚本里定期归档旧日志。
  • 时间戳一定要存,没有时间轴的监控数据复盘时基本没有价值。

如果想把进程级别的信息也记录下来,可以在上面循环里再加一行:

nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv >> /var/log/gpu_procs_monitor.log

这一组日志可以用于事后复盘,比如训练任务中途性能下降,或者莫名其妙的OOM,都可以通过时间轴对齐排查。

5.2 阈值告警:温度过高、显存不足时自动提醒

光记录不够,关键异常如果发生在半夜,等第二天发现就晚了。我一般会在采集脚本里加上简单的阈值判断逻辑。比如温度超过80C时发一个提醒,显存剩余不足时也发一个提醒。实现方式不需要太复杂,bash脚本就能搞定。

#!/bin/bash while true; do temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader | awk '{print $1}') if [ "$temp" -gt 80 ]; then echo "$(date) 警告: GPU温度超过80C, 当前${temp}C" >> /var/log/gpu_warn.log # 这里可以接通知命令,比如邮件或者自定义回调脚本 fi sleep 30 done

告警通道方面,最传统的做法是发邮件,但现在很多团队会直接接到即时通讯工具的机器人接口上。这个具体怎么接,视你的团队环境而定,我这里就不展开了。

阈值选择也要讲科学。消费级显卡80C左右算安全上限,专业卡更高一些,但具体还得看卡的型号说明。我自己的经验是:温度告警阈值设置在85C左右,显存告警阈值设置在"剩余小于总显存10%"这个位置,这样既能提前发现风险,又不至于频繁误报。

5.3 用crontab替代while true:让巡检脚本更规范

while true死循环虽然简单,但有几个缺点:进程容易被误杀、没有自恢复机制、运维起来不太规范。我更推荐把脚本交给crontab调度。

先把采集脚本的核心逻辑封装成一个无循环的版本,然后用crontab每隔指定周期执行:

# 每分钟记录一次GPU状态 * * * * * /path/to/gpu_monitor_once.sh

这样的优势是:即使脚本某次执行异常,下一次调度依然会正常跑,不会因为你忘了杀循环进程导致采集永远停摆。

脚本设计成单次执行还有一个好处:可以在里面做更复杂的判断逻辑,比如连续多次检测到温度过高才触发告警,减轻误报。

#!/bin/bash # gpu_monitor_once.sh timestamp=$(date '+%Y-%m-%d %H:%M:%S') gpu_status=$(nvidia-smi --query-gpu=index,temperature.gpu,utilization.gpu,memory.used,power.draw --format=csv,noheader) echo "$timestamp, $gpu_status" >> /var/log/gpu_monitor.log # 温度告警逻辑:连续3次超过85C才告警 temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader | awk -F',' '{print $1}' | sort -rn | head -1) if [ "$temp" -gt 85 ]; then count_file=/tmp/gpu_overheat_count count=$(cat $count_file 2>/dev/null || echo 0) count=$((count+1)) echo $count > $count_file if [ "$count" -ge 3 ]; then echo "$(date) GPU温度持续过高: ${temp}C" >> /var/log/gpu_warn.log echo 0 > $count_file fi else echo 0 > /tmp/gpu_overheat_count fi

这里的连续计数逻辑是一个很实用的防抖手段。真实场景中温度短暂波动很正常,不能一超过阈值立刻告警,那会把冷静的人逼疯。连续多次超阈值才告警,既能过滤瞬时噪声,又能及时暴露持续过热问题。

5.4 把巡检结果可视化:从CSV到简单图表

日志攒到一定量以后,纯文本阅读效率就很低了。我通常会定期用Python脚本把CSV日志画成折线图,观察温度曲线、显存占用曲线、利用率曲线在长时间尺度上的变化。

这一步不强制,但价值很大。比如曾经有一位同事说程序跑得慢,日志里利用率看起来也正常,但画出曲线后发现下午3点到4点之间GPU-Util一直周期性掉到20%以下,和某个定时任务重合。可视化揭示的这种隐性规律,从纯文本数字里极难发现。

画图用matplotlib就够了,核心代码不难:

import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('/var/log/gpu_monitor.log', names=['timestamp','utilization_gpu','temperature_gpu','memory_used']) df['timestamp'] = pd.to_datetime(df['timestamp']) df.set_index('timestamp', inplace=True) df['utilization_gpu'].plot(figsize=(12, 6), title='GPU Utilization over time') plt.savefig('/tmp/gpu_util_history.png', dpi=150)

这种复盘方式对分析周期性性能波动、排查半夜发生的异常也非常好用。监控数据的真正价值不在于实时盯着看,而在于拉长时间轴之后能发现规律。

6. 那些容易让监控数据"说谎"的边界情况

6.1 GPU-Util是0%但负载明明很高:计算与传输的比例

GPU-Util这个指标有一个天然盲区。它衡量的是计算单元繁忙程度,但如果任务被数据搬运卡住了,GPU计算单元可能一直在空转等待。典型例子是:

  • 显存和CPU内存之间的数据传输;
  • 多卡之间的通信(比如分布式训练的AllReduce);
  • 磁盘IO引起的整条流水线阻塞。

这种情况下GPU-Util会低得吓人。判断方法在dmon里看mem列或者pcie列,如果mem很高但sm很低,基本可以确认是内存带宽或通信瓶颈。

优化手段方向上优先考虑:数据用pin memory、用更高效的DataLoader、减少跨卡通信频率、数据预读取到显存。

6.2 多进程共享一张卡时,利用率数字会"打架"

当多个进程同时跑在同一张卡上时,nvidia-smi显示的GPU-Util是所有进程叠加后的结果。假设两个进程各占50%的算力,你看到的总利用率是90%以上,但每个进程单独看可能只分到一半不到。

这种情况下,单纯依赖GPU-Util判断单个进程的健康程度是不准确的。想单独看某个进程对算力的实际占用,建议使用更细粒度的工具,或者干脆从程序内部记录自己的步频/吞吐量来间接判断。我在跑多个小模型并行实验时,就经常以外部的实际吞吐(比如每秒处理多少样本)为主要指针,GPU-Util只作为辅助参考。

6.3 MIG模式下的nvidia-smi输出差异

如果你用的是支持MIG(多实例GPU)模式的卡,并且启用了MIG,nvidia-smi的输出会和普通模式有明显区别。它会显示出多个GPU实例(GPU Instance),每个实例有自己独立的显存和算力配额。

开启MIG后,默认的监控方式要稍微调整,因为每个实例会显示为一个独立的计算资源。我一般会查:

nvidia-smi mig -li

来列出所有MIG实例,确认具体哪个实例被哪个进程占用。MIG模式下温度、功耗这些物理指标是整卡共享的,但显存和算力是隔离的,解读数据时要分清"物理卡"和"逻辑实例"两层概念。

6.4 驱动版本过于陈旧时的兼容性盲区

如果你的nvidia-smi版本太老,一些较新的查询参数会不识别。比如--query-gpu=power.draw在旧驱动上可能返回N/A,或者直接报错。这种情况下不要慌,先跑一下:

nvidia-smi --help

看看当前版本支持哪些参数。遇到不支持的情况,可以选择升级驱动,或者退回到用dmon和粗粒度输出做监控。

这一点其实也提醒了:长时间运行的服务器,如果不定期更新驱动,不仅安全问题会积累,连基本监控手段都可能变得残缺。建议至少每个季度做一次驱动版本的例行评估。

7. 一点日常习惯的分享

自己折腾下来,我觉得Linux下监控GPU这件事,关键在于把"随时瞟一眼"变成"无处可逃"。工具本身都不难,难点在于建立一套自己顺手的工作流。

我个人的习惯大致是这样:训练任务提交后,先用gpustat看一眼全局状态,确认任务已经挂到正确的卡上;然后开一个watch窗口挂在旁边,把刷新间隔设成2秒,观察前两分钟的负载曲线是否正常;确认稳定后,就把watch窗口关掉,转而依赖后台的日志采集脚本和阈值告警,只在需要深度排查时才打开nvtop或者nvidia-smi dmon。

最后再分享一个小技巧吧:如果你经常需要在不同机器上切换查看GPU状态,建议把最常用的几条命令写成shell别名,比如:

alias gpu='nvidia-smi' alias gpuwatch='watch -n 2 nvidia-smi' alias gputop='nvtop' alias gpudmon='nvidia-smi dmon -s pucm -d 1'

一键调用,省得每次敲一长串参数。我自己的shell配置里已经躺了这些别名很久了,确实能提高日常操作的效率。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 4:47:28

卫星仿真中的轨道与姿态动力学建模:从四元数到PD控制实战

简介&#xff1a;一份围绕卫星建模、卫星控制及轨道/姿态动力学主题的MATLAB实验代码包&#xff0c;面向航天工程、飞行器设计等相关专业学生与科研入门者&#xff0c;适用于课程设计、毕业设计或自学仿真练习。代码包共包含22个m文件&#xff0c;压缩后仅10KB&#xff0c;按功…

作者头像 李华
网站建设 2026/10/22 4:45:51

GitHub趋势周报:AI推理优化与本地部署项目精选

1. 为什么我要手动整理一份GitHub趋势周报每周五下午&#xff0c;我会固定花两个小时做一件事&#xff1a;把这一周GitHub上冒出来的热门项目过一遍&#xff0c;筛出真正值得动手试的那几个&#xff0c;写成一份给自己团队看的趋势周报。这个习惯从2023年保持到现在&#xff0c…

作者头像 李华
网站建设 2026/10/22 4:45:26

AI业务流架构设计:连接模型与业务的中间层实践

1. 这个训练营到底在教什么&#xff1a;剥离营销话术后的技术内核“闪学it-AI业务流架构师训练营”——光看名字&#xff0c;很多人第一反应是&#xff1a;又一个堆砌热词的速成班&#xff1f;AI、架构师、业务流&#xff0c;三个高大上的词摞在一起&#xff0c;像极了招聘JD里…

作者头像 李华
网站建设 2026/10/22 4:45:25

GitHub趋势周报:AI应用落地、前端提速与基础设施成本治理

每次刷新 GitHub Trending&#xff0c;总有一种在提前偷看下个季度技术风向的感觉。这一周&#xff08;2026 年第 40 周&#xff09;的榜单尤其有意思&#xff1a;AI 模型本身刷屏的时代正在收尾&#xff0c;真正霸榜的是一批把 AI 塞进实际场景的工具链&#xff1b;前端方向不…

作者头像 李华
网站建设 2026/10/22 4:45:19

AI双热点:OpenAI数学论文与个人代理协议解析

今天打开信息流&#xff0c;整个AI圈基本被两条消息刷屏&#xff1a;OpenAI 在同一时间窗口内一口气公开了 722 篇数学相关的研究论文&#xff0c;Meta 则联合零售巨头沃尔玛发布了「个人代理协议」。按往常经验&#xff0c;一个机构一次性放出几十篇论文已经算大动作&#xff…

作者头像 李华
网站建设 2026/10/22 4:42:21

YOLOv8自定义数据集训练全流程:数据准备、参数调优与部署实践

做目标检测开发这几年&#xff0c;YOLO系列我从v3一路用到v8&#xff0c;说实话&#xff0c;以前给别人讲训练流程&#xff0c;我都是直接甩一段命令让他自己跑。但后来发现&#xff0c;真正卡住新手的往往不是训练那一下&#xff0c;而是训练之前的数据准备和训练之后的结果分…

作者头像 李华