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 启动间隙、同步等待或数据传输占用了时间。

关键区分:利用率(Utilization)≠ 占用率(Occupancy)≠ 性能(Performance)。利用率是时间维度上的“有活干”比例,占用率是线程块在 SM 上的驻留比例,而性能取决于实际吞吐量(如 FLOPS、带宽利用率)。

下图展示了 GPU 利用率测量中“采样窗口”与“实际执行”之间的关系,帮助理解为什么瞬时利用率会剧烈波动:

GPU 利用率采样原理与波动来源 t₀ t₀ + 1s 采样窗口 1 采样窗口 2 采样窗口 3 采样窗口 4 采样窗口 5 SM 活动 计算密集 访存停顿 空闲 计算密集 同步等待 计算密集 H2D 传输 利用率 SM 计算 访存停顿 空闲 同步 数据传输 nvidia-smi 默认每 1s 采样一次 DCGM 可精确到 100ms 粒度 采样间隔内取“有活动”即算忙

从上图可以看出,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 倍。

重要教训:仅看 nvidia-smi 的利用率数字会严重误导判断。当利用率低且波动时,必须结合 SM 占用率、访存带宽利用率、kernel 执行时间线等指标综合定位。利用率低可能是“GPU 没活干”,也可能是“GPU 在等数据”,两者的优化方向完全不同。

3.4 常见误区与复盘清单

在监控 GPU 利用率时,以下误区需要特别警惕:

  1. 误区一:利用率越高越好。实际上,利用率高但 SM 占用率低,说明 kernel 调度过于频繁,可能存在大量小 kernel 启动开销。
  2. 误区二:利用率波动就是“不稳定”。对于数据加载、预处理与训练交替进行的任务,利用率周期性波动是正常现象,关键看波动的频率和幅度是否影响端到端吞吐。
  3. 误区三:只监控 GPU 利用率,忽略 CPU 侧的瓶颈。很多情况下,GPU 利用率低是因为 CPU 来不及喂数据(数据加载瓶颈),此时应优化 DataLoader 的 num_workers、prefetch 策略等。
  4. 误区四:混淆“显存利用率”和“显存占用率”。显存利用率(Memory Utilization)是带宽使用比例,显存占用率是容量使用比例,两者没有直接关系。一个模型可能占满 40GB 显存,但显存带宽利用率只有 10%。
复盘清单(排查利用率波动时逐项检查):
  • □ 确认采样工具和采样间隔是否合适(秒级 vs 毫秒级);
  • □ 区分 SM 利用率、SM 占用率、显存带宽利用率三个指标;
  • □ 检查是否有 CPU 侧瓶颈(数据加载、预处理、同步操作);
  • □ 查看 kernel 执行时间线,确认是否存在频繁启动/销毁;
  • □ 确认是否受功耗墙或温度墙限制导致降频;
  • □ 对比同配置下不同 batch size 的利用率变化趋势。