2026-10-27 · 深度笔记

GPU 云主机的三种形态:独占、容器、竞价,怎么挑

独占实例、弹性容器、竞价实例这三种 GPU 主机形态,卡的归属、回收风险和计费方式完全不同。这篇按显存归属重画一张表,并给出各自最容易踩的坑。

云主机GPU选型成本

第一次替人选 GPU 主机,我在一张表格里卡了很久。不是价格难算,是三个卖家用三种名字卖三种东西:一家叫"独占实例",一家在"Kubernetes 上跑 GPU Pod",第三家在控制台放了个"抢占式"开关。我按"每小时单价从低到高"排了序,差点直接照着最便宜的报上去。

后来我按卡的归属权重画了一遍表,思路立刻就清楚了。

独占卡:一整块 GPU 跟着实例走

最接近裸金属的形态,实例里那块卡是独占的,能装驱动、能跑 NCCL、能做张量并行。

容易忽略的细节是计费粒度。同一家厂商里,"独占卡"往往对应三种不同的付费方式:按秒、按小时、包年包月。按秒的那种最适合跑完就释放的临时任务,包年的适合常驻服务。但有个限制我一开始没注意:实例创建之后卡型基本不能改,想换显存更大的卡只能重建,数据得自己搬。

弹性容器:卡是集群的,容器分到的是"时间片"

托管容器或 K8s 形态,每个容器申请 nvidia.com/gpu: 1,看着跟独占一样,底下可能完全不同。常见实现是两种:

坑在容器里跑 nvidia-smi 时特别明显:输出的是宿主机上全部 GPU 的状态,不是你分到的那块。判断自己拿到哪块,要看宿主机注入的 NVIDIA_VISIBLE_DEVICES,而不是容器内进程用的 CUDA_VISIBLE_DEVICES。

更要命的是显存。如果是时间分片,两个容器各自 nvidia-smi 都能看到"用了 40GB / 80GB",你会以为自己还有 40GB 余量,实际两个进程在抢同一块物理显存。表现是训练跑到第三个 epoch 突然 OOM,日志里找不到任何"另一个容器"的痕迹。

MIG 则没有这个问题,切出来的实例有独立显存配额和独立算力单元。代价是切分档位固定,而且跨 MIG 实例做不了 NCCL 通信——多卡张量并行直接用不了。对训练来说,这基本等于单卡。

竞价实例:便宜,但必须按"随时会断"来设计

抢占式/竞价实例的价格通常是按需的一小截,机制一般是这样:你的出价高于当前市场价就自动开机,市场价超过出价就被回收。回收有两种通知方式——提前几分钟发 SIGTERM,或者直接停机不通知。

坑不在"便宜",在训练进度。我第一次跑微调用的就是竞价实例,checkpoint 周期设的 15 分钟。某天早上发现实例被回收了,训练停在上次保存的地方,白跑两小时。

后来改成监听 SIGTERM 同步保存:

import signal
import sys

def _bye(signum, frame):
    print("收到中断信号,先存 checkpoint 再退", flush=True)
    trainer.save_model(f"{out_dir}/checkpoint-last")
    sys.exit(0)

signal.signal(signal.SIGTERM, _bye)

这只是优雅离场的第一半。另一半是别把唯一一份权重放在会跟着实例一起被回收的盘上。我把 checkpoint 统一写到对象存储,回收前先上传,恢复时从对象存储拉。竞价实例的本地盘是否随实例一起释放,各家规则不同,这一条得单独确认。

还有个反直觉的点:折扣率不是固定的。闲时可能只有两三折,繁忙时段等于按需价。所以"用竞价能省八成"这句话在旺季不成立,真实账单要看实际时段。

一张对照表

维度独占卡实例弹性容器竞价实例
显存归属整卡独占时间分片共享 或 MIG 硬件切整卡独占(多数厂商)
容器内 nvidia-smi本机几张宿主机全部(易误判)本机几张
被回收风险无无有
多卡通信支持MIG 下不支持支持
适合训练、多卡推理微调、在线推理、弹性扩缩可中断任务、离线批处理
卡型可否事后改通常不可可,Pod 重调度重新申请即可

我现在怎么选

三条判断,顺序不能颠倒:

  1. 这个任务断了会丢多少进度? 丢几分钟 → 竞价;丢几小时 → 按需。
  2. 需要几张卡协同? 是 → 独占卡,别在容器和 MIG 上折腾。
  3. 负载有没有明显波峰波谷? 有 → 弹性容器按需扩缩;没有 → 长期独占更省。

最后补一句老话:上面提到的单价和折扣都是量级示意,不是报价。同样的卡在不同套餐里给的规格、散热、网络都不一样,价格也会调整,真实数字以官方页面为准。

接着读