文章

LLM GPU 能效治理生产实战:用分阶段 Clock Lock、Joules/Token 与热降频门禁守住吞吐

只给 GPU 设置 Power Cap,往往忽略 Prefill 与 Decode 的负载差异。本文讲解如何用分阶段时钟、每 Token 能耗和热降频门禁,在不破坏延迟 SLO 的前提下治理推理能效。

背景:GPU 利用率高,不等于能效合理

大模型推理上线后,团队通常先观察 GPU 利用率、显存占用、Token 吞吐和延迟。当机房功率或成本成为约束时,最直觉的动作是降低 GPU 的 Power Cap。这个方法对部分高计算强度任务有效,但不能被当成所有推理阶段的通用答案。

原因在于一次请求至少包含两个性质不同的阶段:

阶段特征瓶颈倾向
Prefill并行处理输入 Token,包含较大矩阵运算计算受限,易靠近功率上限
Decode每步只生成少量 Token,频繁读取权重与 KV 数据显存带宽受限,功耗常低于上限

2026 年一项针对 NVIDIA H200、约 4B 参数模型和多种注意力架构的研究发现,在其测试范围内,Decode 实际功耗常低于所设置的最低 Power Cap,因此限制并未真正触发;直接控制 SM Clock 反而形成了更清晰的能耗—吞吐前沿。这个结论不能无条件外推到所有 GPU 和模型,但它揭示了一个重要工程原则:先判断瓶颈,再选择能耗控制手段。

核心原理:Power Cap 是上限,Clock Lock 才是明确运行点

Power Cap 只在实际功耗触顶时生效

nvidia-smi --power-limit 设置的是板卡允许使用的最大功率。若工作负载实际只消耗 220W,即使上限从 700W 调到 400W,也不会自动把功耗压到 400W 以下。只有当实际需求试图超过限制时,功率管理算法才会调整性能状态。

因此,评估 Power Cap 是否有效时,不能只记录”配置值”,还必须记录:

  • 实际平均与瞬时功耗;
  • 请求与实际 GPU Clock;
  • Clock Event Reasons
  • Prefill 与 Decode 各自的吞吐和能耗。

NVIDIA 文档将 SW Power Cap、HW Thermal Slowdown、SW Thermal Slowdown 等列为导致频率下降的事件原因。若只看到 Clock 下降,却不保存事件原因,就可能把散热问题误判为节能策略生效。

Clock Lock 提供可重复的频率控制

在支持的 GPU 上,可以使用 --lock-gpu-clocks 设置 GPU 时钟范围。它比 Power Cap 更接近”指定运行点”,但仍要验证请求频率是否等于实际频率,因为硬件、固件和驱动可能对请求值进行限制或取最近支持值。

# 查询当前功率、时钟、温度与事件原因
nvidia-smi --query-gpu=uuid,power.draw.average,power.limit,clocks.current.sm,temperature.gpu,clocks_event_reasons.active \
  --format=csv

# 示例:锁定一个经过压测验证的 SM Clock
sudo nvidia-smi -i 0 --lock-gpu-clocks=<validated_clock_mhz>

# 回滚到默认时钟
sudo nvidia-smi -i 0 --reset-gpu-clocks

这里的 <validated_clock_mhz> 不能从其他 GPU 型号照抄,也不应直接使用论文中的数值。它必须来自当前硬件、模型、驱动和推理引擎组合的实际压测。

用 Joules/Token 衡量,而不是只看 Watts

瞬时功率低不一定更节能。若降频导致请求运行时间显著变长,总能耗反而可能升高。更合适的基本指标是:

request_energy_joules = ∫ power_watts(t) dt
joules_per_output_token = request_energy_joules / output_tokens
tokens_per_joule = output_tokens / request_energy_joules

生产环境还应同时约束:

  • TTFT:首 Token 延迟;
  • TPOT / ITL:相邻输出 Token 延迟;
  • P95/P99 请求延迟;
  • Token 吞吐和请求 Goodput;
  • 错误率、超时率与质量门禁。

能效策略的目标不是得到最低瓦数,而是在满足质量和 SLO 的条件下,找到更优的 Tokens/Joule

工程落地:建立分阶段、分桶的能效控制面

第一步:冻结工作负载指纹

每次能效压测都应绑定不可变指纹,至少包含:

指纹维度示例内容
模型名称、权重修订版本、量化格式
GPUSKU、驱动、CUDA、固件、BIOS 版本
推理引擎版本、Attention Backend、Kernel 配置
并行策略Tensor/Pipeline Parallel 配置
负载输入长度、输出长度、Batch Size、并发
控制参数Power Limit、请求 Clock、实际 Clock
环境温度、风扇或冷却状态、Clock Event Reasons

没有这个指纹,同一个”Clock=某值”的结果无法复现,也不能安全迁移到其他节点池。

第二步:把 Prefill 与 Decode 分开测量

不要只跑一个混合流量压测并输出平均功耗。至少应建立以下矩阵:

维度建议分桶
阶段Prefill、Decode、端到端
输入长度短、中、长上下文
输出长度短回答、长生成
Batch/并发低、中、高
控制变量默认、不同 Power Cap、不同 SM Clock
结果TTFT、TPOT、tok/s、J/token、事件原因

Prefill 可能因降低时钟而明显损失 TTFT,Decode 则可能在某一频率以上几乎不再获得吞吐收益。最终策略应允许两个阶段使用不同配置;若系统没有物理分离 Prefill/Decode,也可按请求类型或负载桶选择保守档位。

第三步:通过 DCGM 建立统一遥测

DCGM Exporter 可以向 Prometheus 暴露 GPU 温度、功耗、总能耗、利用率和错误等指标。关键指标包括:

  • DCGM_FI_DEV_GPU_TEMP
  • DCGM_FI_DEV_POWER_USAGE
  • DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION
  • GPU 利用率、显存占用与 XID 错误

仅有节点级功耗还不够。推理网关或 Serving Worker 还需记录请求的输入/输出 Token、阶段耗时和活动 GPU UUID,才能把设备遥测与请求统计对齐。

一个可行的聚合方式是按固定时间窗计算:

window_energy = energy_counter_end - energy_counter_start
window_output_tokens = Σ completed_output_tokens
window_joules_per_token = window_energy / window_output_tokens

多租户或 Continuous Batching 环境中的请求级能耗归因通常是近似值,应明确标记归因方法,避免把节点总能耗伪装成精确账单。

第四步:生成 SLO 约束下的 Pareto 前沿

对每个工作负载桶,绘制能效前沿图:

  • 横轴:Token 吞吐或 P95 TPOT;
  • 纵轴:Tokens/Joule 或 Joules/Token;
  • 数据点:不同 Power Cap 与 Clock 组合。

只有同时满足质量和延迟门禁的点,才进入候选集合。然后选择位于 Pareto 前沿、且离热降频区域有足够余量的运行点。

建议按以下结构保存策略:

policy_id: h200-model-a-decode-medium-batch-v3
fingerprint:
  gpu_sku: H200
  model_revision: <immutable_revision>
  serving_engine: <version>
workload_bucket: decode-medium-batch
controls:
  power_limit_watts: <validated_limit>
  sm_clock_mhz: <validated_clock>
guards:
  max_p95_tpot_ms: <slo>
  max_thermal_event_rate: <threshold>
  min_tokens_per_joule: <baseline>
rollback:
  reset_gpu_clocks: true
  restore_default_power_limit: true

数值应由本环境压测生成,而不是写死在通用模板里。

第五步:把热降频作为发布门禁,而不是普通告警

温度高并不等同于已经降频,真正需要关注的是温度、Clock、功耗与事件原因的组合。至少建立以下门禁:

  1. 压测期间出现 HW Thermal Slowdown 或持续 SW Thermal Slowdown,候选策略不得发布。
  2. 实际 Clock 与目标 Clock 长时间偏离,必须标记硬件或固件不一致。
  3. 相同配置下节点间 Tokens/Joule 明显分叉,先排查散热、供电和驱动,不直接放宽阈值。
  4. Clock Event Reasons 无法采集时,能效实验只能作为探索数据,不能作为自动发布依据。

第六步:灰度和自动回滚

时钟和功率配置属于基础设施变更,应通过专用节点池或维护控制面执行,而不是让业务 Pod 任意调用特权命令。

推荐发布流程:

  1. 单卡离线基准;
  2. 节点级 1% 灰度;
  3. 按模型和长度桶扩大流量;
  4. 比较 TTFT、TPOT、Tokens/Joule、超时率和热事件;
  5. 任一 SLO 或硬件门禁失败,重置 Clock 和 Power Limit;
  6. 回滚后重新验证实际值已恢复,而不是只检查命令返回码。

适用场景

该方法更适合:

  • GPU 电力配额或机架功率密度受限的推理集群;
  • 长时间稳定运行、流量形态较可预测的在线 Serving;
  • Prefill 与 Decode 可独立调度或具有明确流量桶的系统;
  • 需要比较不同 GPU、模型或 Kernel 的能效表现;
  • 希望把能耗纳入容量和成本治理,但不接受明显延迟退化的团队。

不适合直接套用的场景包括:流量极端稀疏、GPU 经常空闲、硬件遥测不完整、节点散热状态不稳定,或者模型和内核版本频繁变化但没有配置指纹。

常见误区

误区一:Power Cap 越低,能耗一定越低。 Power Cap 只有在实际功耗触顶时才起作用;即使功率下降,也可能因为运行时间增加而提高总 Joules。

误区二:看到 GPU Utilization 接近 100% 就认为计算受限。 利用率指标表示引擎在采样周期内是否活跃,不直接说明瓶颈位于计算、HBM、互联还是 Kernel Launch。能效调优仍需结合吞吐对 Clock 的敏感性和性能计数器。

误区三:只测端到端平均值。 平均值会掩盖 Prefill 与 Decode 的差异,也会把短请求和长请求混在一起。最终策略必须按阶段和工作负载桶解释。

误区四:只记录请求 Clock,不记录实际 Clock。 驱动可能选择最近支持频率,固件也可能限制持续频率。没有实际 Clock 和事件原因,实验结果无法审计。

误区五:把节点能耗精确分摊到每个请求。 Continuous Batching、共享 GPU 和后台系统功耗使请求级归因天然存在误差。应公开分摊方法和误差边界,计费前还需额外校准。

上线检查清单

  • 最近 30 天文章主题已完成 exact、near 与 family duplicate 检查。
  • 模型、GPU、驱动、推理引擎和 Kernel 配置已形成不可变指纹。
  • Prefill、Decode 与端到端分别完成长度和 Batch 分桶压测。
  • 同时记录 Power Limit、实际功耗、请求/实际 Clock、温度和 Clock Event Reasons。
  • 使用 Joules/Token 或 Tokens/Joule,而不是只比较 Watts。
  • 候选运行点满足 TTFT、TPOT、P95/P99、错误率和质量门禁。
  • 已确认不存在持续的功率或热降频事件。
  • 时钟和功率修改由受控基础设施组件执行,业务容器无直接特权。
  • 灰度策略按 GPU SKU、模型版本和工作负载桶隔离。
  • 回滚会恢复默认 Clock/Power Limit,并验证实际状态。

延伸 FAQ

如何判断 Decode 是否适合降低 SM Clock? 观察不同 Clock 下的 TPOT、Token 吞吐和实际功耗。如果降低 Clock 后吞吐基本不变、功耗下降且没有错误或热事件,说明当前桶可能不是计算受限。结论只对该模型、Batch、上下文和 GPU 指纹有效。

DCGM 的瞬时功率足够计算请求能耗吗? 对持续时间足够长的窗口,可以通过功率积分或硬件能量计数器估算。对很短的请求,采样频率、计数器粒度和共享负载会带来较大误差,更适合按时间窗或批次聚合,而不是声称精确到单请求。

参考资料

  1. NVIDIA System Management Interface Documentation
  2. NVIDIA NVML API Reference Guide
  3. NVIDIA DCGM Exporter Documentation
  4. NVIDIA DCGM Feature Overview
  5. The Illusion of Power Capping in LLM Decode: A Phase-Aware Energy Characterisation Across Attention Architectures
  6. Position: LLM Inference Should Be Evaluated as Energy-to-Token Production

常见问题

给 GPU 设置更低的 Power Cap,为什么 Decode 阶段可能几乎没有变化?
Power Cap 是功率上限而不是目标值。如果 Decode 本身受显存带宽限制,实际功耗始终低于上限,驱动就不会因为该上限进一步降频,吞吐和能耗可能基本不变。
能否为所有模型统一配置一个固定 SM Clock?
不建议。模型结构、批大小、上下文长度、量化方式和推理内核都会改变计算与内存瓶颈,应按工作负载指纹和长度、批次分桶建立独立的能耗—吞吐前沿。
Joules/Token 可以直接作为唯一上线指标吗?
不能。它必须与 TTFT、TPOT、P95 延迟、错误率和质量门禁联合使用,否则可能通过过度降频降低能耗,却破坏用户体验或有效吞吐。
Power Cap 和 Clock Lock 应该二选一吗?
不必。Power Cap 适合作为机架或节点的功率安全上限,Clock Lock 可用于控制特定工作负载的运行点。生产上可保留合理的功率上限,再通过经过验证的 Clock 策略优化能效,但必须确认两者不会共同触发非预期降频。