Skip to content

第八部分 性能调优与成本优化(第 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_ACTIVEDCGM_FI_PROF_PIPE_TENSOR_ACTIVESM 实际发射指令的活跃比例、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/对象存储延迟
2batch size 太小UTIL 低但稳定,显存占用也低看任务启动参数、显存占用 <30%
3CPU 侧预处理慢GPU 空转等 CPU,节点 CPU 打满top 看 CPU 利用率、DataLoader workers 数是否为 0
4单卡跑小模型做开发调试显存占满但 UTIL≈0nvidia-smi 有进程、长时间无算力消耗
5分布式训练通信等待多卡 UTIL 忽高忽低、步调不齐看 NCCL 日志、节点间带宽、nsys 通信占比
6Jupyter/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框架内 profilingtorch.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 工具运维要会跑会看,把"体检报告"交给算法同学深入优化。

动手实验

  1. 在 GPU 节点执行 nvidia-smi dmon -s pucm -d 1,同时跑一个不带 num_workers 的小训练脚本,观察 UTIL 的锯齿状波动;再加上 num_workers=4, pin_memory=True 和 AMP,对比 UTIL 曲线变化。
  2. 在 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 用 Guaranteed QoS(requests=limits),训练 Pod 用 Burstable
  • 通过设备层面的隔离手段(MIG 切分、HAMi 算力限制)防止训练把推理挤垮;
  • 用节点压力驱逐(eviction)和优先级抢占作为兜底;
  • 灰度推进:先在 10% 节点上试点,盯 P99 延迟指标两周再扩大。

面试高频题:"同节点混部最大的风险是什么?"——答案:干扰不可控导致的在线 SLA 抖动。缓解手段是强隔离(MIG)+ 算力配额 + 严密的延迟监控与自动熔断(推理延迟超标时自动驱逐训练任务)。

30.3 超卖与共享的度量

什么是超卖

超卖(oversubscription)指"承诺出去的资源"超过"物理存在的资源"。类比航空公司超售机票:赌不是所有人同时来。

两个核心指标

  • 显存超卖比例 = 已分配显存总和 / 物理显存总和。例如 MIG 或 HAMi 场景,一张 80G 卡切分出总计 120G 的"虚拟显存",超卖比例 1.5。风险:所有租户同时写满时 OOM。
  • 算力超卖比例 = 已分配算力配额总和 / 物理算力。时间片共享、MPS 场景常见。风险:高负载时段互相争抢、延迟毛刺。

SLA 影响评估方法

  1. 统计历史同时满载概率(用 Prometheus 看各租户利用率的相关性);
  2. 设定超卖上限:推理类建议显存超卖 ≤ 1.2,开发测试类可到 2.0;
  3. 建立兜底指标:监控 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 的卡。

治理手段

  1. 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. 碎片化率监控指标:定义并监控

    • 节点级:1 - 节点空闲GPU数 / 节点总GPU数 的分布;
    • 集群级:可分配最大整卡块 / 总空闲卡数。例如空闲 20 张卡但最大连续可用(按节点)只有 4 张,碎片化就很严重;
    • 配合 Grafana 做"每节点空闲卡数热力图",一眼看出碎片分布。
  2. 小任务引导走共享/MIG:平台默认给 <0.5 卡需求的任务分配 MIG 实例或共享卡,从入口上减少整卡碎片。

本章小结

  • 配额体系 = Namespace(隔离)+ ResourceQuota(天花板)+ Volcano Queue(地板与借用)。
  • 训推混部先用节点池划分,成熟后再做同节点混部,核心是隔离与延迟监控。
  • 超卖要量化(显存/算力超卖比例)并设上限,推理类保守、开发类激进。
  • 潮汐调度 = 夜间缩推理 + 低优队列吃空闲 + 高优可抢占;前提是训练支持断点续训。
  • 碎片化靠 binpack、MIG/共享入口和碎片化率监控三管齐下。

动手实验

  1. 在 Volcano 环境创建两个队列(weight 不同),提交超过集群容量的多个 GPU Job,用 kubectl describe podgroup 观察资源按权重分配的过程。
  2. 创建两个 PriorityClass,先提交占满集群的低优任务,再提交高优任务,观察抢占过程与高优 Pod 的调度事件。
  3. 开启 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 折
5checkpoint 断点续训★★★★(是 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(持续运营)周报月报制度、预算与配额联动、低效榜、采购决策数据支撑

三条落地经验

  1. 先度量,再治理:没有可信的卡时数据就谈优化,只会沦为扯皮;
  2. 让成本回到团队头上:哪怕是内部虚拟结算(showback),也能显著改变用户行为;
  3. 用数据支撑采购:下次老板问"要不要加卡",用"当前利用率 75%、排队时长中位数 4 小时、加 N 卡可缩短到 X"来回答,而不是拍脑袋。

本章小结

  • GPU 成本 = 硬件 + 电力(功耗×PUE×电价)+ 机房网络 + 人力;自建划算的前提是利用率够高。
  • 卡时是计量基本单位;共享场景按显存/算力份额折算;OpenCost/Kubecost 可自动化分摊,但需结合利用率校正。
  • 成本优化先做"零成本的回收与提利用率",再做超卖、spot 与选型;checkpoint 断点续训是利用廉价可中断资源的前提。
  • 面向管理层:利用率月报、团队用量排行、闲置清单三张报表,标签体系是地基。
  • FinOps = Inform → Optimize → Operate 的持续循环,让每一卡时都有归属。

动手实验

  1. 按 31.1 的公式,用实际电价、PUE 估算一张卡的年电费,再折算出"元/卡时"成本。
  2. 用 PromQL 统计某 namespace 过去 24h 的卡时,结合 avg_over_time(DCGM_FI_DEV_GPU_UTIL[24h]) 算出"有效卡时"。
  3. 部署 OpenCost(helm 安装),为 GPU 配置单价,导出一份按 namespace 维度的成本分摊数据,与手算结果对比。
  4. 写一份一页纸的"集群利用率月报"模板,包含三张报表的指标口径与示例数据。

至此,第八部分结束。你已经具备从"把集群跑起来"到"把集群经营好"的完整能力:会用三种口径看利用率、会设计配额与混部策略、会把成本算清楚并推动优化。下一部分将进入综合实战与面试进阶,把全书知识串成可以讲给面试官听的完整故事。