主题
第八部分 性能调优与成本优化(第 29~31 章)
在前面七个部分中,你已经掌握了 GPU 硬件、驱动与容器化、虚拟化与共享技术、K8s 集群搭建与 GPU 调度、训练与推理平台搭建、可观测性体系和故障处理。换句话说:集群已经能跑起来了,也有人用了。
但"能跑"和"跑得好、跑得省"是两回事。现实中你会不断听到两类灵魂拷问:
- 来自老板:"几十万一张的卡,利用率怎么才 20%?"
- 来自用户:"我的任务怎么又排队了?能不能再买点卡?"
本部分解决的就是这两个问题:怎么把利用率提上去,怎么把成本算清楚、降下来。这是 GPU 平台运维工程师从"会干活"走向"会经营"的关键一步,也是面试高级岗位(平台负责人、架构师)时的高频考点。
本部分地图
| 章节 | 核心问题 | 你将学会 |
|---|---|---|
| 第 29 章 GPU 利用率分析与提升 | 卡到底忙不忙?不忙怎么办? | 三种利用率口径、低利用率原因清单、提升手段、自动发现低利用率任务 |
| 第 30 章 资源治理:配额、混部与超卖 | 卡怎么分才公平又高效? | ResourceQuota/Volcano 配额、训推混部、超卖度量、潮汐调度、抢占、碎片化治理 |
| 第 31 章 成本核算与运营 | 一张卡一年花多少钱?怎么省? | 成本构成、卡时计量、成本优化清单、运营报表、FinOps 落地 |
第 29 章 GPU 利用率分析与提升
本章目标
- 说清"GPU 利用率"的三种口径及其差异,不再被单一数字误导
- 掌握低利用率的典型原因清单,形成排查套路
- 了解用户侧提升手段,能与算法工程师对话
- 掌握运维侧抓手:低利用率自动发现、闲置回收、制度配套
- 会跑、会看常见 profiling 工具(nsys、PyTorch Profiler 等)
29.1 "利用率"的三种口径
是什么
当你执行 nvidia-smi 看到 GPU-Util: 95% 时,这个数字的真实含义是:在过去一个采样周期内,GPU 上至少有一个 kernel 在执行的时间占比。注意它的陷阱:
- 哪怕只有一个 SM(流式多处理器)在跑一个很小的 kernel,也算"忙";
- 它在等待显存数据、等网络通信的空转时间,只要期间有 kernel 挂着,也算"忙"。
所以 nvidia-smi 的 95% 不代表算力用到了 95%,它只代表"没闲着"。
三种口径对比
| 口径 | 指标来源 | 含义 | 采集方式 |
|---|---|---|---|
| SM active(设备利用率) | DCGM_FI_DEV_GPU_UTIL | 采样周期内有 kernel 活跃的时间占比(nvidia-smi 显示的就是它) | nvidia-smi、dcgm-exporter + Prometheus |
| 显存带宽利用率 | DCGM_FI_DEV_MEM_COPY_UTIL | 显存读写带宽被占用的时间占比 | dcgm-exporter、nvidia-smi dmon |
| Tensor Core / 算力利用率 | PROF 指标,如 DCGM_FI_PROF_SM_ACTIVE、DCGM_FI_PROF_PIPE_TENSOR_ACTIVE | SM 实际发射指令的活跃比例、Tensor Core 流水线的活跃比例 | dcgm-exporter(需开启 PROF 指标)、nsys/ncu |
PROF 系列指标比 UTIL 系列"诚实"得多。一个
DCGM_FI_DEV_GPU_UTIL=95%但SM_ACTIVE=25%的任务,说明大量时间在等数据(内存墙、通信墙),算力并没真正用满。
采集方式示例
用 nvidia-smi 直接查看:
bash
nvidia-smi # 常规视图,GPU-Util 列即 DCGM_FI_DEV_GPU_UTIL
nvidia-smi dmon -s pucm -d 1 # 秒级采样:功耗/利用率/SM时钟/显存dcgm-exporter 开启 PROF 指标(编辑其默认指标配置文件):
csv
# /etc/dcgm-exporter/default-counters.csv 追加
DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active.
DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned.
DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident to maximum.
DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active.
DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active.注意:PROF 指标在 MIG、vGPU 或共享切分场景下可能不可用或语义变化,启用前先小范围验证。
运维视角的看数建议
- 日常巡检看 UTIL:快速发现"完全闲置"的卡(UTIL=0 但有进程占显存,多半是挂机);
- 深度分析看 PROF:UTIL 高但业务抱怨慢时,用
SM_ACTIVE/DRAM_ACTIVE/PIPE_TENSOR_ACTIVE判断瓶颈在算力、显存带宽还是数据供给。
29.2 利用率低的典型原因清单
这是本章最实用的一节。看到低利用率,按下面的清单逐条排查:
| # | 原因 | 典型表现 | 快速判断方法 |
|---|---|---|---|
| 1 | 数据加载瓶颈(I/O 慢) | UTIL 呈"锯齿状"周期性掉 0 | 看节点磁盘/网络 I/O、dataloader 耗时、NFS/对象存储延迟 |
| 2 | batch size 太小 | UTIL 低但稳定,显存占用也低 | 看任务启动参数、显存占用 <30% |
| 3 | CPU 侧预处理慢 | GPU 空转等 CPU,节点 CPU 打满 | top 看 CPU 利用率、DataLoader workers 数是否为 0 |
| 4 | 单卡跑小模型做开发调试 | 显存占满但 UTIL≈0 | nvidia-smi 有进程、长时间无算力消耗 |
| 5 | 分布式训练通信等待 | 多卡 UTIL 忽高忽低、步调不齐 | 看 NCCL 日志、节点间带宽、nsys 通信占比 |
| 6 | Jupyter/IDE 挂机占卡 | 显存被占、UTIL 长期为 0、无训练日志产出 | 查 Pod 内进程存活时间 vs GPU 计算时间 |
记忆口诀:"等数据、等 CPU、等通信、等保存、纯挂机"——五个"等"覆盖了 90% 的低利用率场景。
29.3 提升手段(用户侧)
运维工程师不一定要亲自改训练代码,但必须能说清楚方向,才能与算法同学有效沟通、在月报中给出建议。
1)增大 batch size / 梯度累积
显存没吃满时优先增大 batch。显存不够时用梯度累积(accumulation steps)达到等效大 batch:
python
# PyTorch 梯度累积示意
accum_steps = 4
for i, (x, y) in enumerate(loader):
loss = model(x, y).loss / accum_steps
loss.backward()
if (i + 1) % accum_steps == 0:
optimizer.step()
optimizer.zero_grad()2)混合精度训练(AMP)
用 FP16/BF16 替代 FP32,算力吞吐通常可提升 2~3 倍,还能省一半显存。核心就三步:torch.cuda.amp.autocast() 包住前向、GradScaler 缩放 loss 后反向、scaler.step(optimizer) 更新参数。
运维视角:A100/H100 上 BF16 是"免费的午餐",如果用户还在用 FP32 训练,这是月报里最值得写的一条建议。
3)DataLoader 优化
python
DataLoader(dataset, batch_size=256,
num_workers=8, # 多进程预处理,别用 0
pin_memory=True, # 锁页内存,加速 H2D 拷贝
persistent_workers=True)同时确保训练数据放在本地 NVMe 或高性能并行文件系统上,而不是慢速 NFS。
4)算子融合与编译
python
model = torch.compile(model) # PyTorch 2.x 一行即可,常带来 10%~50% 提升此外还有 FlashAttention、xFormers、fused optimizer 等,属算法侧工作,运维了解名词即可。
5)网络与存储优化(运维主战场)
- 分布式训练走 RDMA/IB 而非 TCP(确认 NCCL 日志中出现
NET/IB); - 数据集用本地缓存或 JuiceFS/Alluxio 加速层;
- 节点盘用 NVMe,避免训练与日志争抢同一块慢盘。
29.4 运维侧抓手
1)低利用率自动发现(Prometheus 规则)
yaml
# dcgm-exporter 已接入 Prometheus 为前提
groups:
- name: gpu-low-utilization
rules:
- alert: GPULowUtilization
# 连续 2 小时平均利用率低于 15%,且显存被占用(排除真空闲)
expr: |
avg_over_time(DCGM_FI_DEV_GPU_UTIL[2h]) < 15
and on (gpu, instance)
DCGM_FI_DEV_FB_USED > 1024
for: 10m
labels:
severity: info
annotations:
summary: "GPU {{ $labels.gpu }} on {{ $labels.instance }} 利用率持续偏低"配合第八部分之前的标签体系(给 dcgm-exporter 指标关联上 Pod 的 namespace/owner),即可直接定位到"哪个团队哪个任务"。
2)周报制度
每周自动生成"低利用率任务 Top N"报表,邮件/IM 推送给团队负责人。核心口径:卡时 × 平均利用率 = 有效卡时,晒出"浪费卡时"比晒利用率更能触动人心。
3)回收闲置 Jupyter
生产上常见的做法是给开发环境加 idle timeout:平台定时扫描"连续 N 小时无 GPU 计算(结合 Prometheus 查询该 Pod 的利用率)且无终端活动"的 Notebook Pod,先通知、后自动 scale 到 0,保留 PVC 数据,用户下次一键拉起。简化实现可用 cron 脚本遍历 app=jupyter 的 Pod 并按上述条件打标/缩容。
4)排队机制倒逼释放
当集群存在排队时,用户自然有动力释放闲置资源(占着不用也会被同事"围观")。配合下一章的优先级与抢占机制,让"占着不用"的卡能被高优任务抢走,从制度上消灭挂机。
29.5 profiling 工具运维视角简介
深入优化是算法侧的工作,但运维要能跑、会看、知道该把谁拉进来。
| 工具 | 用途 | 一句话用法 | 运维关注点 |
|---|---|---|---|
| nsys(Nsight Systems) | 时间线级分析:CPU/GPU/通信谁在等谁 | nsys profile -o report python train.py | 看 GPU 空隙(gap)在哪一段:数据加载?NCCL? |
| ncu(Nsight Compute) | 单 kernel 级深度分析 | ncu --set full python train.py | 开销大,一般只在单 kernel 疑点时用 |
| PyTorch Profiler | 框架内 profiling | torch.profiler.profile(...) 导出 TensorBoard/Chrome trace | 用户自助工具,运维负责装好镜像与插件 |
| dlprof | 基于 nsys 的 DL 专用聚合报告 | dlprof python train.py | 快速输出"迭代时间分解",适合给用户第一份体检报告 |
运维侧的典型动作:在平台镜像中预装工具链(apt-get install nsight-systems-cli nsight-compute,或 pip install nvidia-dlprof pytorch-tb-profiler)。给用户的标准话术:"先跑 dlprof 出个报告,如果 GPU 空隙主要在 DataLoader 段,先加 workers 和 pin_memory;如果在 NCCL 段,找运维查网络。"
本章小结
- "利用率"有三个口径:SM active(容易虚高)、显存带宽、Tensor Core/PROF(更真实)。日常巡检看 UTIL,深度分析看 PROF。
- 低利用率九成是五个"等":等数据、等 CPU、等通信、等保存、纯挂机。
- 提升手段分两层:用户侧(batch/AMP/DataLoader/编译)与运维侧(网络存储优化、自动发现、闲置回收、制度倒逼)。
- profiling 工具运维要会跑会看,把"体检报告"交给算法同学深入优化。
动手实验
- 在 GPU 节点执行
nvidia-smi dmon -s pucm -d 1,同时跑一个不带num_workers的小训练脚本,观察 UTIL 的锯齿状波动;再加上num_workers=4, pin_memory=True和 AMP,对比 UTIL 曲线变化。 - 在 Prometheus 中添加
GPULowUtilization规则,故意让一个占卡不计算的进程(torch.zeros(1000, device='cuda')后挂起)挂一小时,验证告警触发。
第 30 章 资源治理:配额、混部与超卖
本章目标
- 设计多租户配额体系(Namespace + ResourceQuota + 队列)
- 理解训练与推理混部的策略与取舍
- 会度量超卖比例并评估 SLA 影响
- 掌握潮汐调度、优先级抢占、碎片化治理的工程做法
30.1 多租户资源治理模型
是什么与为什么
一个集群多个团队共用,如果没有配额,结局必然是"先到先得、强者通吃"。资源治理要解决三个问题:每个团队最多能用多少(上限)、至少能用到多少(保障)、超额时谁先让(优先级)。
三层体系
| 层次 | 组件 | 作用 |
|---|---|---|
| 租户隔离 | Namespace(+ RBAC) | 每个团队一个命名空间,权限边界 |
| 静态配额 | ResourceQuota | 限制命名空间内资源总量(含 GPU) |
| 动态排队 | Volcano Queue | 跨命名空间的队列权重、容量保障与借用 |
示例
yaml
# 团队 A 的静态配额:最多 16 张卡、128 核 CPU、512G 内存
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.nvidia.com/gpu: "16"
requests.cpu: "128"
requests.memory: 512Gi
---
# Volcano 队列:team-a 保障 8 卡,最多可借用到 16 卡
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: team-a
spec:
weight: 2 # 空闲资源按 weight 比例分配
capability:
nvidia.com/gpu: "16"
reclaimable: true # 允许被高优队列回收设计经验:ResourceQuota 管"天花板",Queue 管"地板"(保障量);各队列保障量之和应 ≤ 集群总算力,超出部分靠"借用+回收"动态调节;给 GPU 配额的同时一定要配 CPU/内存配额,否则会出现"GPU 没超、内存先爆"的怪象。
30.2 训练与推理混部
两类负载的本质差异
| 维度 | 在线推理 | 离线训练 |
|---|---|---|
| 目标 | 低延迟(P99 达标) | 高吞吐(尽快跑完) |
| 负载特征 | 随流量波动(白天高夜间低) | 启动后持续满载 |
| 可中断性 | 不可中断(中断=故障) | 可 checkpoint 续训 |
| 资源诉求 | 稳定、需要预留余量 | 有多少吃多少 |
两种混部策略
策略一:节点池划分(推荐起步)
训练节点池与推理节点池物理隔离,用 taint/toleration + nodeSelector 保证互不干扰。优点:简单、稳定、好算账;缺点:资源利用率天花板低。
策略二:同节点混部(进阶)
同一节点上,推理服务作为"高优先级在线负载",训练任务作为"低优先级离线负载"填充空隙。要点:
- 推理 Pod 用
GuaranteedQoS(requests=limits),训练 Pod 用Burstable; - 通过设备层面的隔离手段(MIG 切分、HAMi 算力限制)防止训练把推理挤垮;
- 用节点压力驱逐(eviction)和优先级抢占作为兜底;
- 灰度推进:先在 10% 节点上试点,盯 P99 延迟指标两周再扩大。
面试高频题:"同节点混部最大的风险是什么?"——答案:干扰不可控导致的在线 SLA 抖动。缓解手段是强隔离(MIG)+ 算力配额 + 严密的延迟监控与自动熔断(推理延迟超标时自动驱逐训练任务)。
30.3 超卖与共享的度量
什么是超卖
超卖(oversubscription)指"承诺出去的资源"超过"物理存在的资源"。类比航空公司超售机票:赌不是所有人同时来。
两个核心指标
- 显存超卖比例 = 已分配显存总和 / 物理显存总和。例如 MIG 或 HAMi 场景,一张 80G 卡切分出总计 120G 的"虚拟显存",超卖比例 1.5。风险:所有租户同时写满时 OOM。
- 算力超卖比例 = 已分配算力配额总和 / 物理算力。时间片共享、MPS 场景常见。风险:高负载时段互相争抢、延迟毛刺。
SLA 影响评估方法
- 统计历史同时满载概率(用 Prometheus 看各租户利用率的相关性);
- 设定超卖上限:推理类建议显存超卖 ≤ 1.2,开发测试类可到 2.0;
- 建立兜底指标:监控
SM_ACTIVE争抢程度与推理 P99,超标自动告警并触发扩容或驱逐。
30.4 潮汐调度
是什么
在线推理流量白天高、夜间低;训练任务不在乎什么时候跑。潮汐调度就是"白天资源给推理,夜间资源给训练"的弹性切换,把同一份硬件用出两份价值。
实现思路(HPA + 队列优先级)
yaml
# 夜间自动缩推理副本(用 CronHPA 或 KEDA 的 cron scaler)
apiVersion: autoscaling.keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: inference-night-scale
spec:
scaleTargetRef:
name: my-inference-service
triggers:
- type: cron
metadata:
timezone: Asia/Shanghai
start: 0 23 * * * # 23:00 缩容
end: 0 7 * * * # 07:00 恢复
desiredReplicas: "2" # 夜间最小副本释放出的资源如何被训练吃掉?靠队列优先级:训练任务跑在 reclaimable 的低优队列里,平时排队,夜间推理缩容后 Volcano 自动放行;早上推理扩容、资源不足时,通过抢占机制(见 30.5)把训练任务踢回队列。
关键前提:训练任务必须支持 checkpoint 断点续训(见 31.3),否则被抢占就是灾难。
30.5 优先级与抢占
K8s 原生 PriorityClass
yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-inference
value: 1000000 # 数值越大优先级越高
globalDefault: false
preemptionPolicy: PreemptLowerPriority # 允许抢占低优 Pod
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority-training
value: 1000
preemptionPolicy: Never # 训练任务不抢占别人,只被抢占Pod 中通过 priorityClassName 引用。节点资源不足时,调度器会驱逐低优 Pod 为高优 Pod 腾位置。
Volcano 的 preempt 与 reclaim
Volcano 在队列层面提供更精细的两个动作:
- preempt:队列内部,高优任务抢占低优任务;
- reclaim:队列之间,队列 A 借给队列 B 的资源,当 A 有新任务时可以"收回来"。
yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
name: guaranteed-research
spec:
weight: 1
reclaimable: true # 借出的资源可被回收实践建议:优先级层级不要太多,3~4 层足够(在线推理 > 关键训练 > 普通训练 > 开发测试);被抢占的训练任务要自动重排队(Volcano Job 的 minAvailable + 重启策略),而不是直接失败;抢占要有"冷却时间"和频率限制,防止抖动场景下反复抢占。
30.6 碎片化治理
是什么
集群里明明还有 20 张卡的总量空闲,却调度不出一个 8 卡任务——空闲 GPU 像"碎玻璃"一样分散在各节点上,这就是碎片化。典型的还有"小任务占整卡":一个只用 8G 显存的调试任务占着一整张 80G 的卡。
治理手段
- binpack 调度策略:调度时优先把任务"塞"到已部分占用的节点上,让空闲卡尽量聚合成整节点空闲。Volcano 中配置:
yaml
# volcano-scheduler-configmap 片段
actions: "enqueue, allocate, backfill"
tiers:
- plugins:
- name: priority
- name: gang
- name: conformance
- plugins:
- name: drf
- name: predicates
- name: proportion
- name: binpack # 关键:开启装箱
arguments:
binpack.weight: 10
binpack.gpu: 5碎片化率监控指标:定义并监控
- 节点级:
1 - 节点空闲GPU数 / 节点总GPU数的分布; - 集群级:可分配最大整卡块 / 总空闲卡数。例如空闲 20 张卡但最大连续可用(按节点)只有 4 张,碎片化就很严重;
- 配合 Grafana 做"每节点空闲卡数热力图",一眼看出碎片分布。
- 节点级:
小任务引导走共享/MIG:平台默认给 <0.5 卡需求的任务分配 MIG 实例或共享卡,从入口上减少整卡碎片。
本章小结
- 配额体系 = Namespace(隔离)+ ResourceQuota(天花板)+ Volcano Queue(地板与借用)。
- 训推混部先用节点池划分,成熟后再做同节点混部,核心是隔离与延迟监控。
- 超卖要量化(显存/算力超卖比例)并设上限,推理类保守、开发类激进。
- 潮汐调度 = 夜间缩推理 + 低优队列吃空闲 + 高优可抢占;前提是训练支持断点续训。
- 碎片化靠 binpack、MIG/共享入口和碎片化率监控三管齐下。
动手实验
- 在 Volcano 环境创建两个队列(weight 不同),提交超过集群容量的多个 GPU Job,用
kubectl describe podgroup观察资源按权重分配的过程。 - 创建两个 PriorityClass,先提交占满集群的低优任务,再提交高优任务,观察抢占过程与高优 Pod 的调度事件。
- 开启 binpack 插件后连续提交多个单卡任务,对比开启前后的任务节点分布差异。
第 31 章 成本核算与运营
本章目标
- 说清 GPU 集群的成本构成与估算方法
- 掌握卡时计量与共享场景计费拆分
- 输出一份可落地的成本优化清单
- 会面向管理层做运营报表
- 理解 FinOps 理念在 GPU 平台的落地方式
31.1 GPU 成本构成
是什么
一台 8 卡 GPU 服务器的真实成本远不止采购价。完整的 TCO(总拥有成本)包括:
| 成本项 | 估算方法 | 典型占比(自建,粗略) |
|---|---|---|
| 硬件采购/租用 | 采购价按 3~5 年折旧;或云租用月价 | 60%~70% |
| 电力 | 单卡功耗 × 卡数 × PUE × 电价 | 10%~20% |
| 机房与网络 | 机柜租金、IB/RoCE 组网、存储 | 10% |
| 运维人力 | 平台团队人力分摊 | 5%~15% |
电力估算方法(重点公式)
单卡年电费 = 单卡实际功耗(kW) × 8760(小时) × PUE × 电价(元/kWh)举例:H100 SXM TDP 700W,实际训练平均功耗约 500W,PUE 取 1.4,工业电价 0.8 元/kWh:0.5 × 8760 × 1.4 × 0.8 ≈ 4906 元/卡/年。一台 8 卡服务器(含 CPU、网卡等约 1.2 倍系统系数)年电费约 4.7 万元——五年下来电费接近半张卡钱,这就是为什么"闲置=烧钱"。
PUE(Power Usage Effectiveness)= 机房总耗电 / IT 设备耗电。越接近 1 越好,普通机房 1.4~1.6,优秀液冷机房可到 1.2 以下。
云租用的对照口径
云上按量 H100 单卡约 20~40 元/小时(随市场波动大)。自建集群通常 2~3 年可回本,但前提是利用率足够高——利用率低于 40% 时,自建往往不如租用划算。这是给管理层做决策时最关键的一个换算。
31.2 算力计量
卡时(GPU-hour)
卡时 = 占用 GPU 数量 × 占用时长,是算力计量的基本单位。例如:8 卡训练跑了 12 小时 = 96 卡时。
计量实现:从 K8s 调度事件和 Pod 生命周期中提取"申请了 nvidia.com/gpu 的 Pod 的运行时长",按 namespace/团队聚合。伪逻辑:
promql
# 某团队当日卡时(每小时采样的卡数积分近似)
sum_over_time(
sum by (namespace) (
kube_pod_container_resource_requests{resource="nvidia_com_gpu"}
* on(pod) group_left() (kube_pod_status_phase{phase="Running"} == 1)
)[24h:1h]
)共享/切分场景怎么计费
| 场景 | 建议计量口径 |
|---|---|
| MIG | 按实例规格的"分数卡时":如 1g.10gb 记 1/7 卡时(按算力份额) |
| 显存切分(HAMi 等) | 按显存申请量占比折算卡时,或单独制定"显存时"单价 |
| 时间片共享 | 按整卡申请计费(用户独占感强、争抢自担),或按实际 PROF 利用率折算"有效卡时" |
有效卡时(占用卡时 × 平均 SM 利用率)是更"讲理"的口径,适合内部成本分摊时给用户看:"你占了 100 卡时,但有效只用了 30,请优化或释放。"
OpenCost / Kubecost 简介
- OpenCost(CNCF 项目):开源的 K8s 成本计量工具,按 namespace/Pod/label 维度分摊成本。对 GPU 的支持体现在可以把 GPU 设为独立计价资源,按申请量分摊。
- Kubecost:基于 OpenCost 的商业产品,UI 更完善,支持云账单对账、节省建议(如闲置资源识别)。
部署 OpenCost 后在配置中为 GPU 设定单价(参考 31.1 的 TCO 折算出"元/卡时"),即可自动生成团队维度的成本报表。注意:它们计量的是申请量而非实际用量,GPU 场景建议结合 dcgm-exporter 的利用率数据做二次校正。
31.3 成本优化清单
按"投入产出比"从高到低排序,可直接作为季度优化专项的检查表:
| # | 手段 | 预期收益 | 要点 |
|---|---|---|---|
| 1 | 提升利用率(第 29 章全套动作) | ★★★★★ | 利用率从 30%→60% 等于卡数翻倍 |
| 2 | 回收闲置资源(Jupyter、僵尸任务) | ★★★★★ | 几乎零成本,先做 |
| 3 | 合理超卖与共享(第 30 章) | ★★★★ | 推理场景收益最大 |
| 4 | 竞价/按量实例跑可中断任务 | ★★★★ | 云上 spot 价常为按量 3~5 折 |
| 5 | checkpoint 断点续训 | ★★★★(是 4 的前提) | 周期性保存 + 自动恢复 |
| 6 | 合理选型 | ★★★ | 推理用 L40S/A10/L4 而非 H100 |
| 7 | 模型侧优化(量化、蒸馏、vLLM) | ★★★ | 推理成本可降数倍,算法侧主导 |
| 8 | 电力与机房优化(液冷、PUE) | ★★ | 大规模集群才显著 |
spot 实例 + 断点续训的配合
python
# 训练脚本的关键模式:周期性保存 + 启动时自动恢复
state = torch.load(CKPT) if os.path.exists(CKPT) else {"epoch": 0}
for epoch in range(state["epoch"], total_epochs):
... # 训练
if epoch % save_every == 0:
torch.save({"model": model.state_dict(), "epoch": epoch}, CKPT)平台侧配合:spot 节点打 taint 并利用云厂商的缩容前预警(一般提前 30 秒~2 分钟),K8s 层用优雅退出(preStop 触发紧急 checkpoint)。
合理选型示例
| 业务 | 推荐卡型 | 理由 |
|---|---|---|
| 大模型训练 | H100/H800/A100 | 需要大显存 + 高速互联(NVLink/IB) |
| 大模型推理(高并发) | L40S / A100 | 显存够、FP8 推理性价比好 |
| 中小模型推理 | L4 / A10 / T4 | 单卡成本低、功耗低 |
| 开发调试 | 共享卡 / MIG 小实例 | 没必要占整卡 |
31.4 面向管理的报表
给管理层看报表的原则:少讲技术指标,多讲钱和趋势。推荐三张报表:
1)集群利用率月报
核心指标口径:
- 分配率 = 已分配卡数 / 总卡数(调度视角);
- 利用率 = 加权平均 SM active(真实干活视角);
- 有效卡时率 = 有效卡时 / 总卡时(最终答案)。
Grafana 面板建议:三指标同图趋势曲线 + 按团队堆叠面积图。月末截图配一段结论即可成报。
2)团队用量排行
口径:团队月卡时、月有效卡时、折算成本(卡时 × 单卡时成本)。排行榜的前 3 名写清业务产出,后 3 名(高占用低有效)给出改进建议。这是推动资源流转最有力的工具——没有团队愿意上"低效榜"。
3)闲置资源清单
口径:连续 7 天平均利用率 <10% 且占显存的任务,列出负责人、占卡数、月浪费金额(占卡数 × 单卡月成本)。每月例行发送,给一周整改期,到期未处理自动回收。
Grafana 落地提示:三张报表的数据源都是已有的 Prometheus(dcgm-exporter + kube-state-metrics),关键是标签体系——确保 GPU 指标能关联到 namespace → 团队 → 负责人,这个映射表(可用 CMDB 或一个 ConfigMap 维护)是报表系统的地基。
31.5 FinOps 理念在 GPU 平台的落地
是什么
FinOps(Finance + DevOps)是一套"让花钱的人对成本有感知、让管钱的人看得懂技术"的协作方法论。它有三个循环阶段:Inform(看得见)→ Optimize(优得动)→ Operate(持续管)。
在 GPU 平台的落地映射
| FinOps 阶段 | GPU 平台动作 |
|---|---|
| Inform(成本可见) | 卡时计量、团队分摊报表、单卡时成本核算(31.2/31.4) |
| Optimize(成本优化) | 利用率提升、超卖、spot、选型优化(29/30 章 + 31.3) |
| Operate(持续运营) | 周报月报制度、预算与配额联动、低效榜、采购决策数据支撑 |
三条落地经验:
- 先度量,再治理:没有可信的卡时数据就谈优化,只会沦为扯皮;
- 让成本回到团队头上:哪怕是内部虚拟结算(showback),也能显著改变用户行为;
- 用数据支撑采购:下次老板问"要不要加卡",用"当前利用率 75%、排队时长中位数 4 小时、加 N 卡可缩短到 X"来回答,而不是拍脑袋。
本章小结
- GPU 成本 = 硬件 + 电力(功耗×PUE×电价)+ 机房网络 + 人力;自建划算的前提是利用率够高。
- 卡时是计量基本单位;共享场景按显存/算力份额折算;OpenCost/Kubecost 可自动化分摊,但需结合利用率校正。
- 成本优化先做"零成本的回收与提利用率",再做超卖、spot 与选型;checkpoint 断点续训是利用廉价可中断资源的前提。
- 面向管理层:利用率月报、团队用量排行、闲置清单三张报表,标签体系是地基。
- FinOps = Inform → Optimize → Operate 的持续循环,让每一卡时都有归属。
动手实验
- 按 31.1 的公式,用实际电价、PUE 估算一张卡的年电费,再折算出"元/卡时"成本。
- 用 PromQL 统计某 namespace 过去 24h 的卡时,结合
avg_over_time(DCGM_FI_DEV_GPU_UTIL[24h])算出"有效卡时"。 - 部署 OpenCost(helm 安装),为 GPU 配置单价,导出一份按 namespace 维度的成本分摊数据,与手算结果对比。
- 写一份一页纸的"集群利用率月报"模板,包含三张报表的指标口径与示例数据。
至此,第八部分结束。你已经具备从"把集群跑起来"到"把集群经营好"的完整能力:会用三种口径看利用率、会设计配额与混部策略、会把成本算清楚并推动优化。下一部分将进入综合实战与面试进阶,把全书知识串成可以讲给面试官听的完整故事。