3、GPU利用率分析:nvidia-smi深度解读、GPU利用率低的原因排查、MIG与多卡场景

大家好,我是你们的老朋友。今天我们来聊聊GPU利用率分析。说实话,这可能是AI训练里最容易被忽视,但又最关键的环节。我见过太多团队,模型架构调得飞起,结果一看GPU利用率不到30%——白花花的银子就这么浪费了。

嗯,咱们直接进入正题。

3.1 nvidia-smi深度解读:你真的看懂了吗?

很多人用nvidia-smi,就只看一眼显存占用和温度。其实这里面的门道多着呢。我个人习惯,每次排查性能问题,第一件事就是跑一个持续监控:

watch -n 0.5 nvidia-smi

每0.5秒刷新一次,这样才能捕捉到瞬时波动。你想想看,如果采样间隔是5秒,很多短时瓶颈就漏掉了。

咱们来拆解一下输出里的关键字段:

字段 含义 我的经验值
GPU-Util GPU计算核心利用率 理想值 > 90%,低于70%要警惕
Memory-Usage 显存使用量/总量 接近上限不一定有问题,但频繁波动要注意
Volatile GPU-Util 过去一段时间内的平均利用率 这个值容易骗人,建议看瞬时值
Temp GPU温度 超过85°C会触发降频,性能直接打七折
Pwr:Usage 当前功耗 如果远低于TDP,说明GPU没吃饱
注意:GPU-Util 100%不代表性能最优。我曾经遇到过,利用率跑满了,但实际吞吐量只有理论值的一半——原因是小算子太多,GPU在频繁切换上下文。

还有一个容易被忽略的参数:--query-gpu。我建议你用这个命令做自动化监控:

nvidia-smi --query-gpu=index,timestamp,utilization.gpu,memory.used,power.draw,temperature.gpu --format=csv -l 1

这样输出的CSV格式,可以直接导入到你的监控系统里。说白了,手动看nvidia-smi只是应急,真正的性能优化需要持续的数据采集。

3.2 GPU利用率低的原因排查:从现象到根因

为什么会这样?GPU利用率低,通常逃不出这几种情况。我按排查优先级列出来:

  1. 数据加载瓶颈——这是最常见的原因,没有之一
  2. CPU预处理过慢——数据增强、解码等操作拖了后腿
  3. 模型结构问题——小算子太多、频繁同步
  4. 通信开销过大——多卡场景下尤其明显
  5. 显存不足导致swap——这个比较隐蔽

咱们重点说说数据加载。我记得有一次帮一个团队排查,他们的ResNet-50训练,GPU利用率只有40%。一看代码,用的是默认的DataLoader,num_workers=0。嗯,这就是典型的「单线程加载,GPU干等」。

正确的做法:

# 错误示范
train_loader = DataLoader(dataset, batch_size=256, shuffle=True)

# 正确示范
train_loader = DataLoader(
    dataset, 
    batch_size=256, 
    shuffle=True,
    num_workers=8,      # 一般设为CPU核心数
    pin_memory=True,    # 加速CPU到GPU传输
    prefetch_factor=2   # 预取批次数量
)

改完之后,GPU利用率直接飙到85%以上。你想想看,就改了几个参数,训练速度翻倍。

我的小技巧:用nvtop或者nvidia-smi的-d参数看进程级别的利用率。有时候整体利用率低,但某个进程占满了显存,这可能是显存碎片化导致的。

还有一个坑——CPU bound。怎么判断?很简单:在训练时开一个htop,如果CPU利用率接近100%,而GPU利用率低,那问题就在CPU侧。我曾经遇到过一个案例,数据增强用了albumentations的复杂pipeline,每张图要处理50ms,batch_size=256时,CPU根本来不及喂数据。

解决方案:

  • 把数据增强放到GPU上做(用NVIDIA DALI)
  • 或者用更轻量的增强策略
  • 再或者增大num_workers,但注意不要超过CPU核心数太多,否则上下文切换反而更慢

3.3 MIG与多卡场景:从单卡到集群的利用率挑战

MIG(Multi-Instance GPU)是NVIDIA A100和H100上的特性。说白了,就是把一块物理GPU切成多个独立的实例。每个实例有自己的显存、缓存和计算单元,互不干扰。

我画了一张图,帮你理解MIG的架构:

物理GPU (A100 80GB) MIG实例 1g.10gb 1个计算切片 10GB显存 推理任务A MIG实例 2g.20gb 2个计算切片 20GB显存 训练任务B MIG实例 3g.40gb 3个计算切片 40GB显存 训练任务C 硬件级隔离:显存、缓存、计算单元完全独立 每个实例可运行不同任务,互不影响 利用率 95% 利用率 72% 利用率 45% → 每个MIG实例独立监控利用率 ← nvidia-smi mig -i 0 -gi 1 查看指定实例

MIG场景下,利用率分析要特别注意:每个实例的利用率是独立的。你不能只看物理GPU的整体利用率,那会掩盖问题。比如一个实例跑满了,另一个实例空闲,整体显示50%,但实际你该优化的不是整体,而是那个空闲的实例。

多卡场景就更复杂了。我遇到过最典型的问题:8卡训练,其中一张卡的利用率总是低10%。排查了半天,发现是NVLink连接有问题,那张卡和其他卡的通信带宽只有正常的一半。

排查命令:

# 检查NVLink状态
nvidia-smi nvlink --status

# 检查GPU间通信带宽
nvidia-smi nvlink --bandwidth
核心原则:多卡训练时,所有卡的利用率应该基本一致。如果出现明显偏差(超过5%),优先检查通信链路和负载均衡。

还有一个常见问题——梯度累积。很多人为了用更大的batch size,把梯度累积步数设得很大。但你知道吗?梯度累积时,GPU在forward和backward阶段是满负荷的,但在梯度同步阶段是空闲的。如果累积步数太大,空闲时间占比就会上升,整体利用率反而下降。

我的建议:梯度累积步数不要超过8步。超过这个值,收益递减,利用率反而下降。

最后,分享一个我自己的排查流程:

  1. 先看nvidia-smi的瞬时利用率,确认问题存在
  2. 用nvidia-smi dmon看更细粒度的指标(SM利用率、显存带宽)
  3. 用Nsight Systems做profiling,定位具体是哪个kernel慢
  4. 检查数据加载管线,用PyTorch的Profiler看CPU和GPU的时间线
  5. 如果是多卡,检查通信拓扑和带宽

嗯,这套流程我用了好几年,基本能覆盖90%以上的利用率问题。记住,GPU利用率低不是终点,而是起点——它告诉你「有问题」,但具体是什么问题,还得靠这些工具一步步挖下去。

可可精品资料库