模型工程系列新篇。推理服务的冷启动——从「实例拉起」到「可以服务」的那段黑暗时间:拉镜像 30 秒、加载权重 60 秒、预热 KV Cache 20 秒——扩容、更新、故障恢复全部被它拖慢。这篇讲冷启动的完整拆解和三板斧优化。
先把冷启动拆开
- 调度阶段:集群分配合适的 GPU 节点(抢占/排队时间,秒~分钟)
- 拉取镜像:推理镜像通常 5~20GB(CUDA 运行时+依赖+代码),首次拉取分钟级
- 加载权重:从对象存储/本地盘读权重进显存——70B 量化后 40G,机械盘 vs NVMe vs 本地缓存差距巨大
- 初始化:CUDA context、引擎初始化、KV Cache 预分配
- 预热:发几条真实请求把 JIT/缓存/连接池热起来(跳过的代价是首批用户请求超时)
各段占比因部署而异,优化的第一步是分段计时——很多团队只有一个「启动慢」的笼统感知,不知道该打哪一段。
三板斧
斧一:镜像瘦身与预拉取
- 分层设计:基础层(CUDA/依赖,变动少)+ 应用层(代码,变动多)——日常更新只推应用层
- 节点池预拉取:集群在空闲时把非常新镜像推到所有候选节点——真正扩容时本地命中,拉取归零
- 极端手段:把权重从镜像里拆出来(镜像只含代码),权重走专门的分发通道(见斧二)
斧二:权重就近缓存
权重是大头(数十 GB),从远端对象存储拉是冷启动的非常慢一环。三级布局:
- 节点本地 NVMe 缓存:首次加载后留副本,同节点再启秒读
- 机房级缓存服务:P2P 分发(BitTorrent 类协议在同机房传权重,实测能吃满内网带宽)
- 对象存储只做非常终回源
配合「模型-节点亲和性」调度(要用模型 X 的实例优先调度到已有 X 缓存的节点),权重加载从分钟压到秒级。
斧三:延迟加载与并行初始化
- 权重的分层加载:先加载前面几层就开始接受请求(首个请求慢一点但不用等全量)——部分推理引擎支持 lazy loading
- 初始化并行化:权重加载、CUDA 初始化、依赖服务连接本来是串行的——改并行后总时长取非常长段而非总和,实测普遍省 30%+
两个配套机制
预热探针:实例标记「就绪」前,调度器自动发 N 条合成请求(覆盖典型输入长度),把首请求的超时风险消化在上线前。探针请求要用真实分布的合成数据——过短的预热请求热不透长文本的路径。
冷启动预算进 SLA:把「扩容响应时间」当作推理服务的明确 SLA(比如「扩容请求到可服务 <90 秒」),有了预算才有优化的靶子和验收标准——「尽快」不是一个工程指标。
优化后的对比账
某 7B 服务优化前后(真实数据骨架):
- 优化前:拉镜像 90s + 权重 45s + 初始化 30s + 预热 20s ≈ 3 分钟
- 优化后:镜像预拉取(0s)+ 权重本地缓存(8s)+ 并行初始化(20s)+ 预热(15s)≈ 43 秒
这 2 分多钟的差值,在故障切换时是事故时长的差值,在大促扩容时是丢单率的差值——冷启动优化是那种「平时看不见、关键时刻救命」的基础设施投资。
(模型工程系列:迁移评估 → 竞技场 → 网关路由 → 扩缩容 → 评测流水线 → 多模型混部 → 版本管理 → 本文:冷启动优化)