3、GPU利用率指标:利用率定义、测量方法、常见监控工具(如nvidia-smi、DCGM)
3.1 核心概念:GPU利用率的真正含义
在排查性能波动之前,必须先厘清一个关键问题:nvidia-smi 中显示的“利用率”到底在测量什么?很多工程师将其等同于“GPU 被使用的百分比”,但实际并非如此简单。
NVIDIA 官方定义中,GPU 利用率(Utilization)分为两种:
- GPU 核心利用率(SM 利用率):指在采样周期内,流式多处理器(SM)上至少有一个 warp 处于活动状态的时间占比。它反映的是“计算单元是否有活干”,而非“计算单元有多忙”。
- 显存利用率(Memory Utilization):指显存带宽被读取/写入的时间占比,同样不是容量占用率。
这里有一个最常见的认知误区:GPU 利用率 100% 并不代表计算性能已发挥到极致。它只说明 SM 始终有 warp 在调度,但可能大量 warp 因等待显存数据而处于 stalled(停顿)状态。反之,利用率低也不一定意味着 GPU 空闲——可能是 kernel 启动间隙、同步等待或数据传输占用了时间。
下图展示了 GPU 利用率测量中“采样窗口”与“实际执行”之间的关系,帮助理解为什么瞬时利用率会剧烈波动:
从上图可以看出,GPU 利用率是时间片内的布尔聚合——只要采样窗口内 SM 有任意 warp 在执行,该窗口就被计为“忙碌”。因此,频繁的 kernel 启动/销毁、同步屏障、数据传输间隙都会造成利用率统计的“虚高”或“虚低”。
3.2 测量方法:从 nvidia-smi 到 DCGM
实际工作中,最常用的测量工具是 nvidia-smi 和 DCGM(Data Center GPU Manager)。两者在测量原理、精度和适用场景上有显著差异。
3.2.1 nvidia-smi:快速查看与即时诊断
nvidia-smi 是 NVIDIA 驱动自带的命令行工具,适合人工交互式排查。常用命令如下:
# 实时刷新查看利用率(每 1 秒刷新一次)
nvidia-smi dmon -s pucvmet -d 1
# 查询当前所有 GPU 的利用率、显存、温度、功耗
nvidia-smi --query-gpu=index,utilization.gpu,utilization.memory,memory.used,temperature.gpu,power.draw \
--format=csv,noheader,nounits
# 持续记录到日志文件(用于事后分析)
nvidia-smi --query-gpu=timestamp,index,utilization.gpu,utilization.memory \
--format=csv -l 1 > gpu_util_log.csv &
nvidia-smi 的局限在于:
- 采样间隔最小 1 秒,无法捕捉毫秒级的 kernel 间隙波动;
- 只能看到整卡利用率,无法区分是哪个进程、哪个 kernel 在消耗算力;
- 对 MIG(多实例 GPU)场景支持有限。
3.2.2 DCGM:数据中心级精确监控
DCGM 是 NVIDIA 为数据中心设计的监控与管理框架,提供更细粒度、更低开销的指标采集。它通过 NVML(NVIDIA Management Library)底层接口实现,支持 Prometheus 导出、Grafana 可视化等生态集成。
DCGM 的核心优势在于:
- 高频率采样:支持 100ms 甚至更短的采样周期,能捕捉到秒级以下的利用率波动;
- 多维度指标:不仅包含 SM 利用率,还提供 SM 占用率(Occupancy)、Tensor Core 利用率、显存带宽利用率、PCIe 吞吐量等细粒度指标;
- 进程级监控:可以关联到具体 PID 和 CUDA 上下文,定位是哪个任务在消耗 GPU。
使用 DCGM 的典型方式:
# 启动 DCGM exporter(Prometheus 格式)
dcgm-exporter --collect-interval=100ms
# 查询指定指标(以 Prometheus HTTP API 为例)
curl -s 'http://localhost:9400/metrics' | grep -E 'DCGM_FI_DEV_GPU_UTIL|DCGM_FI_DEV_SM_OCCUPANCY'
| 对比维度 | nvidia-smi | DCGM |
|---|---|---|
| 默认采样间隔 | 1 秒 | 100ms(可配置) |
| 指标丰富度 | 基础利用率、显存、温度、功耗 | SM 占用率、Tensor Core、带宽、PCIe、NVLink 等 |
| 进程级关联 | 仅显示进程列表,不关联利用率 | 支持进程级指标关联 |
| 适用场景 | 单机快速排查、人工诊断 | 大规模集群监控、自动化告警、性能分析 |
| MIG 支持 | 有限 | 完整支持 |
3.3 实战案例:一次“假性饥饿”的定位过程
某训练任务在 A100 上运行,nvidia-smi 显示 GPU 利用率在 40%~60% 之间频繁跳动,但训练吞吐远低于预期。工程师初步判断是“GPU 资源不足”,准备申请更多显卡。
我们使用 DCGM 进行深入分析,发现以下关键数据:
# DCGM 采集到的关键指标(节选)
DCGM_FI_DEV_GPU_UTIL : 52.3%
DCGM_FI_DEV_SM_OCCUPANCY : 18.7% # 远低于预期
DCGM_FI_DEV_MEM_COPY_UTIL : 87.2% # 显存带宽几乎打满
DCGM_FI_DEV_GPU_TEMP : 71°C
DCGM_FI_DEV_POWER_USAGE : 285W # 接近 TDP 上限
分析结论:
- SM 占用率仅 18.7%,说明每个 SM 上驻留的线程块很少,并行度不足;
- 显存带宽利用率高达 87.2%,说明 kernel 是访存密集型,而非计算密集型;
- GPU 利用率 52.3% 的波动,本质是访存延迟导致 SM 频繁停顿,而非 GPU 真的“空闲”。
最终定位到问题根源:数据加载 pipeline 中使用了过多的 torch.Tensor.item() 操作,导致 GPU 与 CPU 之间频繁同步,打断了 kernel 的流水线执行。优化方案是将这些操作批量移到 GPU 端完成,修改后 GPU 利用率稳定在 95% 以上,训练吞吐提升 2.3 倍。
3.4 常见误区与复盘清单
在监控 GPU 利用率时,以下误区需要特别警惕:
- 误区一:利用率越高越好。实际上,利用率高但 SM 占用率低,说明 kernel 调度过于频繁,可能存在大量小 kernel 启动开销。
- 误区二:利用率波动就是“不稳定”。对于数据加载、预处理与训练交替进行的任务,利用率周期性波动是正常现象,关键看波动的频率和幅度是否影响端到端吞吐。
- 误区三:只监控 GPU 利用率,忽略 CPU 侧的瓶颈。很多情况下,GPU 利用率低是因为 CPU 来不及喂数据(数据加载瓶颈),此时应优化 DataLoader 的 num_workers、prefetch 策略等。
- 误区四:混淆“显存利用率”和“显存占用率”。显存利用率(Memory Utilization)是带宽使用比例,显存占用率是容量使用比例,两者没有直接关系。一个模型可能占满 40GB 显存,但显存带宽利用率只有 10%。
- □ 确认采样工具和采样间隔是否合适(秒级 vs 毫秒级);
- □ 区分 SM 利用率、SM 占用率、显存带宽利用率三个指标;
- □ 检查是否有 CPU 侧瓶颈(数据加载、预处理、同步操作);
- □ 查看 kernel 执行时间线,确认是否存在频繁启动/销毁;
- □ 确认是否受功耗墙或温度墙限制导致降频;
- □ 对比同配置下不同 batch size 的利用率变化趋势。