模型工程系列新篇。推理服务的成本大头是 GPU,而单模型独占一张卡是普遍的浪费——生产环境 GPU 平均利用率常常不足三成。多模型混部(一张卡同时跑多个模型)是压缩成本的直通车,这篇讲实践:怎么混、怎么调度、账怎么算。
先算浪费的账
独占模式:70B 模型占一张 80G 卡,日常 QPS 波谷时利用率 15%——85% 的算力在空转。三张卡三个模型,等于花三张卡的钱用着半张卡的算力。混部的目标:三个模型共享两张卡(甚至更少),利用率拉到 60%+——直接省一张卡的月成本。
混部的三种模式
模式一:分时复用(最简单)。一张卡按时间片轮流加载模型——低频模型平时不驻留,请求来了加载、用完卸载。适合「高频主模型 + 低频备用模型」的组合。代价是冷启动(分钟级),所以只适合 QPS 低的长尾模型。
模式二:显存共存(主流)。多个模型量化后同时驻留显存:70B AWQ 约 40G + 7B 约 10G + embedding 模型 2G,80G 卡塞得下且各留 KV Cache 余量。关键约束是 KV Cache 的动态份额:推理时上下文缓存会膨胀,三个模型同时高峰会 OOM。解法:给每个模型设显存配额(推理引擎都支持),超配额的请求排队而不是硬吃。
模式三:统一调度(进阶)。所有模型走同一个推理引擎实例(支持多模型加载的框架),引擎内部统一管理显存池和 batch——模型间的资源调度交给引擎。这是最彻底也最省心的形态,代价是引擎选型约束(不是所有框架的多模型支持都成熟)。
调度器的三个核心决策
- 路由:请求来了发给哪个实例——按模型 ID 路由是底线,进阶按负载(同模型的多个副本选闲的)
- 抢占:高峰期算力不够时牺牲谁——交互式请求(用户在等)优先于批量任务,批任务可暂停可重跑,天然是抢占的承受方
- 弹性驻留:低频模型在空闲超过 N 分钟后卸载(释放显存给高频模型),请求到达再加载。N 的取值看该模型的请求间隔分布——P95 间隔大于冷启动代价的 3 倍就值得卸
实测一组的账
改造前:3 模型 × 独占 = 3 张卡,月成本 3C,平均利用率 25%。
改造后(模式二 + 调度器):2 张卡,月成本 2C,利用率 58%,P99 延迟劣化 8%(排队引入)。
结论:省 1/3 成本,换 8% 的尾部延迟——对多数内部服务这笔账成立;对外 SLA 苛刻的服务,保留独占。
三条避坑
- 不要混到 100% 利用率:留 20% 余量,否则高峰排队会雪崩(利用率 95% 的系统排队延迟是指数增长的)
- 冷启动要预热:分时复用的模型加载慢,配合预测调度(历史流量预测提前加载)能藏掉大半等待
- 观测按模型分列:混部后故障定位复杂度上升——每个模型的 QPS/延迟/显存占用独立打点,否则出了问题分不清是谁拖垮了谁
什么时候不该混
延迟敏感的对外 API(8% 的尾部劣化不能接受)、模型迭代频繁(混部实例经常重载打断)、团队没有专人维护推理基础设施——这三种情况老老实实独占,混部省的钱不够填运维的坑。
(模型工程系列:迁移评估 → 竞技场 → 网关路由 → 扩缩容 → 评测流水线 → 本文:多模型混部)