干AI训练和GPU运维这行,谁电脑里没存过几页NVIDIA命令笔记?反正我自己是踩了不少坑之后,才慢慢把零散的命令按场景整理成了一套自己的清单。今天这篇就是把我的NVIDIA命令整理分享出来,从环境确认、日常监控、性能调优到故障排查,全部按实际用途来写,每条命令都搭配说明和避坑点,不整虚的。适合刚拿到GPU服务器准备装环境的同学,也适合日常要盯训练任务、查显存占用、做性能分析的工程师。
1. 为什么需要单独整理一套NVIDIA命令
先说个常见场景:你拿到一台带GPU的服务器,系统装好了,驱动装好了,然后跑训练脚本,结果报错某个CUDA操作失败。这时候你第一反应是不是输入nvidia-smi看看显卡认没认出来?再查一下驱动版本和CUDA版本是不是匹配?这几个操作如果每次都要现查手册,效率真的太低了。
NVIDIA命令的核心价值,就是让你在最短时间内搞清楚三件事:显卡是否正常、环境是否匹配、资源到底被谁占用。尤其是多卡训练、多人共用GPU的服务器,没有一套熟练的命令,你连“显存被谁吃了”这种基本问题都定位不了。
这套命令整理下来,覆盖的使用场景大概有这几类:
- 新机器验收:确认驱动装好、GPU全部识别、算力正常。
- 日常监控:看利用率、显存、温度、功耗,判断训练任务是否健康。
- 故障定位:驱动掉了、报CUDA版本错误、显存爆了,快速找到问题源头。
- 性能调优:锁定GPU频率、限制功耗、调整显存分配策略。
我用的环境主要是Linux服务器,也就是Ubuntu和CentOS这一类,下面的命令也以Linux为主。如果你用的是Windows,nvidia-smi本身也是可以用的,只是有些系统级参数和工具会有差异。
2. 装机第一件事:用命令确认驱动和CUDA环境
很多人拿到新机器,想都不想直接跑训练脚本,结果满屏报错。正确做法是先花两分钟把环境确认了,再开始干活。
2.1 先读懂nvidia-smi的输出
nvidia-smi是最基础的命令,任何时候你都应该先跑一下它。输出里有一堆字段,新手经常被搞懵,我逐行说下关键信息:
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 470.129.06 Driver Version: 470.129.06 CUDA Version: 11.4 | +-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |第一行有两个版本号:Driver Version是显卡驱动版本,CUDA Version是当前驱动能够支持的最高CUDA运行时版本。注意,这里显示的并不是你已经安装的CUDA Toolkit版本,只是驱动的一个“上限能力”。很多人看到CUDA 11.4就以为CUDA已经装好了,这是最常见的误解。
下面表格里的数据,重点看几个列:
- GPU:显卡编号,从0开始。多卡机器这里有0、1、2...多行。
- Name:显卡型号名称。
- Temp:当前温度,单位摄氏度。
- Pwr:Usage/Cap:当前功耗和最大功耗。
- Memory-Usage:显存使用量/总显存。
- GPU-Util:GPU计算单元利用率。
- Volatile Uncorr. ECC:不修正的ECC错误计数,专业卡上比较重要,有增长就要注意。
- Compute M.:计算模式,默认是Default,可以改成Exclusive等模式。
2.2 用命令验证CUDA Toolkit是否真的装好
驱动和CUDA Toolkit是两个东西。驱动用nvidia-smi验证,那CUDA Toolkit呢?最直接的命令是:
nvcc --version这个命令输出的是CUDA编译器的版本,它才是你写代码、编译程序时真正用到的工具链。装CUDA Toolkit的时候,它会把nvcc放到/usr/local/cuda/bin下,所以如果提示找不到命令,先检查一下环境变量,或者用完整路径:
/usr/local/cuda/bin/nvcc --version再看一个容易迷惑的点:有时候nvidia-smi显示CUDA Version是11.4,但nvcc --version显示是10.2,这种不一致正常吗?完全正常。驱动支持的CUDA版本和你安装的Toolkit版本没有强绑定,驱动只要大于等于Toolkit所需的最低版本就行。真正判断兼容性,是看程序运行时调用的运行时库和驱动支不支持。
对于编译验证,更严谨的做法是编译运行CUDA自带的示例程序。装完CUDA后,示例代码一般在/usr/local/cuda/samples/,可以编译跑一下deviceQuery:
cd /usr/local/cuda/samples/1_Utilities/deviceQuery make ./deviceQuery看到Result = PASS表示环境和硬件都正常。还有一个带宽测试bandwidthTest也建议跑一遍,尤其是刚拿到新显卡时,可以看看实际显存带宽是否正常。
2.3 驱动版本与CUDA版本的对应关系
这里补充一个常见知识:驱动版本和CUDA Toolkit不是“一对一”绑定的,而是驱动向下兼容。举个例子,一个驱动是470系列的显卡,官方支持到CUDA 11.4,那你装CUDA 11.0、11.1、11.2、11.3都是没问题的,但装CUDA 12.x就不行,因为驱动太老。
所以你在装环境之前,先nvidia-smi看驱动的CUDA Version上限,再决定装哪个版本的CUDA Toolkit,能少走很多弯路。如果发现版本不匹配,升级驱动通常比降CUDA Toolkit麻烦,因为驱动还涉及内核模块、图形界面等一堆东西。我的习惯是:拿到机器先跑一遍uname -r看内核版本,再查询官方驱动兼容列表,然后再装。
注意:千万不要在生产环境上随便用
apt upgrade或系统更新工具去更新NVIDIA驱动,很可能更新完内核模块编译失败,导致开机黑屏或驱动加载不了。驱动升级最好走官方安装包,或者使用DKMS方式管理内核模块。
3. nvidia-smi核心参数与GPU状态监控实战
nvidia-smi不带参数只能看一个静态快照。实际工作中我们需要它输出指定内容、过滤特定GPU、定时刷新,这就要用到它的一系列参数。
3.1 常用参数速查表
我把自己平时最高频的参数整理成了一张表:
| 参数 | 作用 | 示例 |
|---|---|---|
-L | 列出所有GPU设备 | nvidia-smi -L |
-i | 指定GPU编号,过滤输出 | nvidia-smi -i 1 |
-q | 查询所有GPU详细信息 | nvidia-smi -q |
-d | 只查询指定类别的详情,如温度、功耗 | nvidia-smi -q -d TEMPERATURE |
--query-gpu | 自定义查询字段,适合脚本解析 | nvidia-smi --query-gpu=name,memory.total --format=csv |
--query-compute-apps | 查询当前GPU上运行的进程 | nvidia-smi --query-compute-apps=pid,used_memory --format=csv |
-pm | 设置持久化模式,提升响应速度 | nvidia-smi -pm 1 |
-pl | 设置最大功耗值 | nvidia-smi -pl 250 |
-lgc | 锁定GPU频率 | nvidia-smi -lgc 1500 |
-rgc | 清除频率锁定 | nvidia-smi -rgc |
3.2 动态刷新监控GPU状态
看实时状态最经典的就是配合watch命令:
watch -n 1 nvidia-smi这条命令每1秒刷新一次GPU状态。我建议再配合-i精确监控某张卡,比如3号卡:
watch -n 1 nvidia-smi -i 3如果你觉得输出太宽,可以自定义查询字段,只显示经常关心的内容:
watch -n 1 nvidia-smi --query-gpu=index,utilization.gpu,utilization.memory,memory.used,memory.total,temperature.gpu,power.draw --format=csv这种自定义输出在终端里也是实时刷新的,而且宽度友好,看久了眼睛不累。适当调整刷新间隔也很重要,-n 1是一秒,如果只是粗略观察,-n 3或-n 5就够了,能减少终端闪烁和输出占用。
3.3 进程维度管理:谁在吃显存
很多时候显存爆了,需要快速找到占用显存的进程。一条命令搞定:
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv还可以配合系统命令按进程ID查详细信息:
nvidia-smi -i 0 --query-compute-apps=pid,used_memory --format=csv | awk 'NR>1 {print $1}' | xargs -I {} ps -p {} -o pid,user,cmd这里要特别提一个坑:nvidia-smi本身显示的进程权限是有限制的。如果你是用普通用户跑的,可能看不到其他用户的GPU进程详细信息,这时候要么用root,要么用fuser:
fuser -v /dev/nvidia*可以看到每个GPU设备上被哪些进程占用。清理占用进程时,千万别随手kill -9乱杀,尤其是系统进程或者别人的训练任务。正确顺序是先ps确认进程归属,再确认是否可中断,最后再kill。我自己就曾经误杀过同事的离线推理服务,教训惨痛。
3.4 显存占用排查:used、free与Shared内存
关于显存,有一个大家容易忽略的地方。nvidia-smi输出的Memory-Usage中,used是当前已使用显存,total是总显存,但你会发现这两者相减不等于真正可用的显存。因为显卡本身要预留一部分显存作为显存管理开销,专业卡还要留一部分做ECC校验。你实际能用的是total减去reserved和ECC占用的部分。
另一个容易误解的是Shared GPU Memory。现在的GPU通过CUDA统一内存或共享内存机制,可以把一部分系统内存映射给GPU使用,nvidia-smi里会显示类似+---------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | | 0 12345 C python 1024MiB | +---------------------------------------------------------+这样的进程占用表。如果你想看某个进程到底用了多少显存,从这里读最准,不要只看系统free或者top,那些看到的是系统内存,不是显存。
我自己写训练脚本时,习惯在代码里用PyTorch或TensorFlow的日志先打印一遍当前显存分配,然后和nvidia-smi对照。如果发现显存占用异常高,优先怀疑是不是历史进程没释放,再用上面的命令定位。
4. 性能调优必须掌握的高级查询与调试命令
监控是基础,调优是进阶。这部分命令能帮你回答一个关键问题:我的GPU到底跑满了没有?瓶颈在算力还是显存还是带宽?
4.1 用--query-gpu做数据导出与自动化采集
--query-gpu配合--format可以控制输出格式,支持csv、json、noheader等。noheader模式非常适合写入日志文件:
nvidia-smi --query-gpu=timestamp,index,utilization.gpu,memory.used,memory.total,temperature.gpu,power.draw --format=csv,noheader输出会像这样:
2025/01/15 10:00:01, 0, 85, 11264, 24576, 72, 350.12有了这种格式化输出,你就可以写一个循环脚本,定期把状态写入CSV,后面用Python分析或者画图都非常方便。注意timestamp字段在不同版本的nvidia-smi里可能格式略有差异,老版本不一定支持,可以用date命令自己加时间戳。
4.2 实时细粒度监控:nvidia-smi dmon与pmon
很多人不知道nvidia-smi还带两个细分监控命令。
dmon是设备监控,按设备维度每秒输出利用率、温度、功耗、显存读写等指标:
nvidia-smi dmon -c 10 -d 1-c指定循环次数,-d指定延迟秒数。这段输出对判断单卡是否在满负荷运算很有用。
pmon是进程监控,按进程维度输出每个进程的GPU利用率、显存占用、SM利用率等:
nvidia-smi pmon -c 10 -d 1这两个命令对定位“GPU利用率低但程序在跑”的问题很有效。比如你怀疑自己的训练脚本没把GPU吃满,看dmon的SM利用率和内存读写吞吐,能帮你判断是卡在计算还是卡在数据IO。
4.3 功耗与频率控制命令
先看当前功耗和限制:
nvidia-smi -q -d POWER设置功耗上限:
nvidia-smi -pl 250GPU默认功耗上限一般接近显卡的TDP,但如果机房供电或散热有限制,适当调低功耗能显著降低温度,性能损失却不明显,尤其对推理任务很划算。我在某个机房部署过一批推理服务,就是因为机房单机柜供电超限,把功耗从300W限制到250W,GPU温度直接从78度降到64度,推理延迟只涨了不到5%。
还有一种情况是显卡频率不稳定,想锁定频率来减小推理延迟抖动,用:
nvidia-smi -lgc 1500,1500-lgc后面跟的是最小和最大频率,用逗号分隔。恢复自动调整频率用-rgc。注意,不是所有显卡都支持频率锁定功能,笔记本GPU或部分低功耗卡可能会被拒绝,执行报错不必惊慌,先确认硬件是否支持。
4.4 多卡拓扑与NVLink状态检查
多卡服务器要关注卡之间的通信拓扑,尤其是做分布式训练时。查拓扑用:
nvidia-smi topo -m输出会展示GPU之间的互联方式,比如NVLink、PCIe。如果是NVLink互联,带宽比PCIe高很多,分布式训练时数据通信效率会好不少。检查NVLink链路状态:
nvidia-smi nvlink -s如果看到某条链路显示INACTIVE或ERROR,基本可以判断GPU间的NVLink连接有问题,需要检查物理连接或驱动状态。
另外,新一点的GPU支持MIG(多实例GPU),也就是把一张物理卡切分成多个独立实例。查看MIG模式:
nvidia-smi -L nvidia-smi -q -d MIG开启MIG后,在nvidia-smi -L的输出里每个GPU实例会单独列出来,比如GPU 0a、GPU 0b。这个功能对资源隔离很有用,但需要注意的是MIG模式下有些CUDA功能会受限,不是所有场景都适合开。
4.5 配合CUDA和生态工具做进一步分析
单有nvidia-smi还不够,实际调优时我还会用到这些工具:
nvtop:一个交互式的GPU监控工具,类似top,安装后直接输入nvtop就能看多卡实时状态,比watch nvidia-smi更直观。nsys/ncu:NVIDIA官方的性能分析和内核分析工具,适合对CUDA程序做深度剖析,定位内核瓶颈。nccl测试程序:如果跑分布式训练,我会用官方NCCL测试工具测一下卡间通信带宽,确认网络和拓扑没瓶颈。
这些工具各有侧重,但和NVIDIA命令配合起来,基本能覆盖从系统级到程序级的所有状态查询。
5. 高频故障排查记录:命令报错与解决方案速查
命令整理得再多,不会排查问题等于白整理。这部分是踩坑记录,都是我自己或身边同事遇到过的真实案例,整理成速查表,方便你遇到问题直接对症下药。
5.1nvidia-smi报 "NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver"
这个报错太经典了,基本就是驱动没加载或者驱动与内核不匹配。排查顺序我建议是:
lsmod | grep nvidia看内核模块有没有加载。如果没有,再查:
dmesg | grep -i nvidia看系统日志里有没有报错,通常是“unknown symbol”或“version mismatch”。然后手动加载:
modprobe nvidia如果加载报错,大概率是驱动和当前内核版本不匹配,需要重新编译驱动或者用DKMS方式安装。还有一种可能是Secure Boot开启导致第三方驱动模块被拒绝加载,这种需要在BIOS里关掉Secure Boot或者给驱动模块签名。
5.2 运行CUDA程序报 "CUDA driver version is insufficient for CUDA runtime version"
这个报错的意思是:程序编译时用的CUDA运行时版本太高,但当前驱动太老,撑不住。定位方法很简单:
nvidia-smi | grep "CUDA Version" nvcc --version如果nvidia-smi显示的CUDA版本号比nvcc版本低,那问题就是驱动太老。解决办法两个方向:升级驱动到支持更高CUDA版本的版本;或者换成更低版本的CUDA Toolkit重新编译程序,比如最省事的方式是直接在conda环境里安装对应版本的cudatoolkit:
conda install cudatoolkit=11.3这种报错在深度学习框架预编译包里也常见,比如某些版本的PyTorch自带CUDA 11.8,但机器驱动只支持CUDA 11.4,装完框架一运行就报错。解决办法就是查一下框架对CUDA版本的要求,选一个驱动支持范围内的版本。
5.3 显存OOM(Out of Memory)排查
训练时遇到CUDA out of memory,先别急着改代码,马上执行:
nvidia-smi看是不是有残留进程占着显存。常见的坑是Jupyter Notebook里的kernel没关,或者之前中断训练后Python进程没死。定位到PID之后确认一下再杀:
kill -9 PID如果确认没有残留进程,那就是代码本身显存占用过高。除了优化模型和batch size,还可以在训练脚本里加上:
import torch torch.cuda.empty_cache()但这只是清理缓存,不是根本解法。PyTorch 2.0以后有个更好用的参数,环境变量方式开启显存碎片优化:
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True这个模式下显存按需增长分配,碎片化明显减少,某些模型能把原本OOM的场景变成可训练。TensorFlow用户也可以参考类似机制,把allow_growth打开,不一次性占满全部显存。
5.4 多用户共享GPU时资源被抢
公司里一台GPU服务器多人用是常态。某天你发现训练速度忽然变慢,跑一下nvidia-smi发现GPU利用率被另一个进程拉满,这时候怎么办?
第一,明确谁在用:
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv第二,如果你的任务优先级更高,和对方协调后可以限制对方进程的GPU使用。但更合理的做法是从系统层面做资源隔离,比如用CUDA_VISIBLE_DEVICES把不同用户限制到不同GPU上:
export CUDA_VISIBLE_DEVICES=0,1如果一块卡上要分多个任务,可以用nvidia-smi -c设置计算模式为Exclusive_Process,这样一张卡同时只允许一个进程占用:
nvidia-smi -c 3计算模式的值:0是Default,1是Exclusive_Thread,2是Prohibited,3是Exclusive_Process。不同的驱动版本对数值定义有细微区别,用之前nvidia-smi -q -d COMPUTE查看当前模式,再用nvidia-smi -h确认参数含义。
5.5 GPU温度过高或功耗异常
GPU温度长时间超过85度就要警惕了。先用详细查询看看当前热状态:
nvidia-smi -q -d TEMPERATURE如果温度高,同时功耗也接近上限,检查三件事:风扇是否正常、机箱风道是否堵塞、硅脂是否老化。如果温度和功耗都正常但性能上不去,那可能是GPU撞到了功耗墙或温度墙,可以尝试降低功耗限制让显卡更稳定运行,或者清理灰尘改善散热。
对于数据中心里的专业卡,我还会留意ECC错误计数:
nvidia-smi -q -d ECC如果Volatile Uncorr. ECC出现非零值且持续增长,说明显存可能有硬件问题,尽早联系售后换卡,别等到训练中途崩了才处理。
5.6 常见报错速查表
下面这张表是我整理的故障排查速查表,基本覆盖了日常80%的问题:
| 现象 | 可能原因 | 排查命令 | 解决方向 |
|---|---|---|---|
| nvidia-smi报failed | 驱动模块未加载/不匹配 | lsmod,dmesg | 重装驱动、关Secure Boot |
| CUDA版本不足报错 | 驱动太老 | nvidia-smi,nvcc -V | 升级驱动或降CUDA版本 |
| CUDA out of memory | 显存被占用/碎片化 | nvidia-smi,ps | 杀进程,开expandable_segments |
| GPU利用率忽高忽低 | 数据加载瓶颈 | nvidia-smi dmon | 优化DataLoader,加大num_workers |
| NVLink状态异常 | 物理链路/驱动问题 | nvidia-smi nvlink -s | 检查硬件,重启机器 |
| 多卡利用率不均衡 | 网络通信瓶颈/负载不均 | nvidia-smi, NCCL测试 | 检查网络、调整数据分片策略 |
6. 实用脚本提炼:让监控命令自己干活
命令是手动的,但真正好用的应该是脚本,让它自动采集、自动判断。这里分享几个我个人常用的脚本模板,你可以直接改改拿去用。
6.1 GPU状态快照脚本
每次启动训练任务前,我习惯先自动记录一份环境快照,方便事后复盘。脚本很简单:
#!/bin/bash timestamp=$(date "+%Y%m%d_%H%M%S") logfile="gpu_snapshot_${timestamp}.log" echo "===== GPU Snapshot at ${timestamp} =====" >> $logfile nvidia-smi >> $logfile echo "" >> $logfile nvcc --version >> $logfile echo "Snapshot saved to $logfile"跑完训练之后再截一份,前后对照就很容易看出任务是否正常、有没有异常重启或者资源泄漏。
6.2 周期巡检并记录日志
如果要长时间盯一批GPU卡,比如跑一个几天的大训练,我不可能一直盯着终端,这时候让脚本定时写日志:
#!/bin/bash while true; do timestamp=$(date "+%Y-%m-%d %H:%M:%S") gpu_data=$(nvidia-smi --query-gpu=index,utilization.gpu,memory.used,memory.total,temperature.gpu,power.draw --format=csv,noheader) echo "$timestamp, $gpu_data" >> /var/log/gpu_monitor.csv sleep 60 done如果GPU利用率突然掉到0,或者温度异常超过阈值,还可以在循环里加判断,触发告警:
#!/bin/bash threshold_temp=85 while true; do temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader | sort -rn | head -1) if [ "$temp" -gt "$threshold_temp" ]; then echo "ALERT: GPU temp ${temp}C exceeded threshold!" | mail -s "GPU Temperature Alert" your_email@example.com fi sleep 300 done告警方式可以根据自己环境调整,邮件、企业微信机器人、钉钉机器人、Telegram都行,核心是把监控数据自动化和异常检测自动化。
6.3 指定GPU运行任务的配置
多卡机器上跑任务,一定要通过CUDA_VISIBLE_DEVICES指定GPU,避免任务随机占用所有卡。我通常会这样:
CUDA_VISIBLE_DEVICES=2,3 python train.py这段的意思是程序只能看到物理GPU 2和3,在程序内部它们被编号成0和1。这样既隔离了资源,又避免程序内部多卡策略跑偏。
如果担心某个任务启动时显存不够,可以先写个检查脚本:
#!/bin/bash need_mem=$1 for i in 0 1 2 3; do free_mem=$(nvidia-smi -i $i --query-gpu=memory.free --format=csv,noheader | awk '{print $1}') if [ "$free_mem" -gt "$need_mem" ]; then echo "GPU $i has enough memory, assigning task" CUDA_VISIBLE_DEVICES=$i python train.py break fi done这种脚本在多人共享的服务器上特别实用,能有效避免启动即OOM的尴尬。
6.4 个人习惯:把命令沉淀成自己的手册
最后分享一个我自己的经验。这份NVIDIA命令整理不是一次写完的,而是这几年踩坑一点点补起来的。每次遇到新问题,我都会往自己维护的笔记里加一条,从最初的十几条命令,慢慢扩展到了现在的完整体系。每次排查问题时,翻出自己笔记里的速查表,比临时查官方文档快得多。
给你一个建议:不要直接背我这边的命令列表,而是先跑一遍每条命令,看输出,理解它告诉了你什么。等到真正需要定位问题时,你就会知道该用哪一条。更重要的是,按照你自己的环境做一份命令备注,比如哪些GPU型号支持MIG、哪些机器开了持久化模式、哪几张卡的NVLink状态容易告警,这些经验都是通用文档不会告诉你的。