大模型推理成本优化六条落地手段:从PD分离到国产算力
1. 大模型推理成本为什么突然成了生死线
1.1 从"能跑通"到"跑得起"的转折点
去年这个时候,大家聊大模型推理,话题还停留在"怎么把模型部署起来""显存够不够装下权重"。今年画风完全变了,我接触的团队十个里有八个在问同一个问题:单次推理成本怎么压下来。这个转变不是偶然的。
原因很直接。模型参数从7B涨到70B再到几百B,单次请求的算力消耗翻了几十倍;用户量从内测几百人涨到日活几十万,QPS压力上来了;而最要命的是,推理是持续性支出——训练是一次性投入,推理是每天每时每刻都在烧钱。我见过一个中等规模的对话产品,上线三个月后推理账单超过了训练成本的总和,团队直接被迫做架构重构。
所以现在讨论推理成本优化,不是"锦上添花",是"生死存亡"。这篇文章我想把过去一年多踩过的坑、验证过的方案系统梳理一遍,从PD分离到国产算力,一共六条落地手段,每条都讲清楚原理、适用场景和实操细节。
1.2 成本到底花在哪:先算清楚账再谈优化
优化之前必须知道钱花在哪。大模型推理的成本结构大致分四块:
| 成本项 | 占比(典型值) | 主要影响因素 |
|---|---|---|
| GPU算力租用/折旧 | 55%-70% | 卡型、利用率、并发策略 |
| 显存占用带来的卡数 | 15%-25% | 模型大小、KV Cache、批处理 |
| 网络与存储 | 5%-10% | 跨节点通信、模型加载 |
| 运维与调度 | 5%-10% | 集群管理、弹性伸缩 |
看这张表就明白了,算力和显存占了八成以上。所以所有优化手段,本质上都在做两件事:要么让同样的卡干更多的活(提升利用率),要么让同样的活少占卡(降低资源需求)。后面讲的六条手段,你都可以往这两个筐里归。
提示:先跑一周的监控,把prefill和decode的耗时、GPU利用率、显存峰值、batch size分布都拉出来。没有数据支撑的优化都是瞎猜,我见过太多团队上来就换框架,结果瓶颈根本不在那。
2. 第一条手段:PD分离,把两种截然不同的负载拆开
2.1 为什么prefill和decode必须分开
这是我认为性价比最高的一条优化,也是最容易被忽视的。要理解它,先得搞清楚大模型推理的两个阶段在干什么。
Prefill阶段(预填充):把用户输入的整段prompt一次性喂进去,计算所有token的KV Cache。这个阶段是计算密集型,矩阵乘法拉满,GPU算力单元吃得很饱,但显存带宽用得少。
Decode阶段(解码):一个token一个token往外吐,每生成一个token都要读取全部KV Cache。这个阶段是访存密集型,算力单元大量闲置,瓶颈在显存带宽。
问题来了:如果这两个阶段跑在同一张卡上,会发生什么?prefill来的时候算力打满,decode的请求就得排队;decode在跑的时候算力闲着,prefill又插不进来。两种负载互相干扰,GPU利用率经常卡在30%-40%上不去。
PD分离的核心思路就是:用不同的机器分别跑prefill和decode,各干各的。prefill集群专门堆算力,decode集群专门优化显存带宽和并发。中间通过KV Cache的传输把两个阶段串起来。
2.2 PD分离的实操架构与KV Cache传输
落地PD分离,架构上大概是这个链路:
- 请求进来先到调度器(Router)
- 调度器把prompt发给prefill节点
- prefill节点算完KV Cache,把Cache传给对应的decode节点
- decode节点拿着Cache逐token生成,流式返回
这里最关键的技术点是KV Cache怎么传。KV Cache体积不小,一个70B模型、8K上下文,单请求的KV Cache能到几个GB。传输方案主要有三种:
- RDMA直传:延迟最低,但需要专门的网络硬件,成本高
- 共享存储中转:prefill写、decode读,实现简单但有额外延迟
- P2P显存直传:通过NVLink或类似高速互联,适合同机架部署
我实测下来,中小规模集群用共享存储中转就够了,延迟增加在可接受范围内;大规模集群上RDMA的收益才明显。
注意:PD分离不是银弹。如果你的请求prompt都很短(比如平均几十个token),prefill占比很小,分离的收益有限,反而增加了传输开销。prompt长度超过500token、decode输出较长的场景,PD分离收益最明显。
2.3 PD分离的配比计算与调优经验
prefill节点和decode节点的数量配比,是PD分离调优的核心。配比错了,要么prefill排队,要么decode闲置。
一个粗略的计算方法:统计一段时间内,prefill总耗时和decode总耗时的比值。假设prefill总耗时是decode的1/3,那prefill节点数大致是decode的1/3(还要考虑单卡性能差异)。
但实际中这个比值是动态的,所以更推荐弹性配比:用统一的资源池,根据实时负载动态调整prefill和decode的实例数。我见过做得好的团队,白天decode压力大就多分decode实例,晚上批量任务多就多分prefill实例,整体利用率能到70%以上。
踩过的坑:早期我们固定配比,结果高峰期decode严重排队,prefill却闲着。后来改成按队列长度动态调度,问题才解决。PD分离一定要配动态调度,静态配比只适合负载非常稳定的场景。
3. 第二条手段:KV Cache优化,省显存就是省钱
3.1 KV Cache为什么是显存杀手
KV Cache这个东西,理解它就能理解大模型推理一半的成本。简单说,decode阶段每生成一个token,都要用到之前所有token的Key和Value向量,这些向量必须存在显存里随时读取。序列越长,Cache越大。
算笔账:一个70B模型,假设32层、64个注意力头、head dim 128,用FP16存储。单个token的KV Cache大小是 2(K和V)× 32层 × 64头 × 128 × 2字节 = 约1MB。听起来不大?但8K上下文就是8GB,一个请求8GB!一张80G的卡,光KV Cache就只能放不到10个并发请求。
这就是为什么长上下文场景显存爆炸。KV Cache优化直接决定了你能塞多少并发,也就直接决定了单位成本。
3.2 四种KV Cache压缩手段对比
| 手段 | 原理 | 压缩比 | 精度损失 | 实现难度 |
|---|---|---|---|---|
| 量化(FP16→INT8/INT4) | 降低存储精度 | 2-4倍 | 小到中 | 低 |
| 分页管理(PagedAttention) | 按块分配,消除碎片 | 1.5-2倍有效容量 | 无 | 中 |
| 稀疏化/淘汰 | 丢弃不重要的token | 2-5倍 | 中到大 | 高 |
| 多头共享(MQA/GQA) | 多查询头共享KV | 4-8倍 | 小 | 需改模型 |
我的建议是组合使用:PagedAttention打底(几乎无损失,必做),加上INT8量化(损失可控),如果模型支持GQA那更好。稀疏化要谨慎,我见过为了省显存把关键上下文丢了的,回答质量断崖式下跌。
3.3 PagedAttention的落地细节
PagedAttention是现在主流推理框架的标配,思路借鉴了操作系统的虚拟内存分页。传统KV Cache要求连续显存,一个长序列就得占一大块连续空间,碎片严重。PagedAttention把Cache切成固定大小的block,物理上不连续,逻辑上通过页表映射。
落地时要注意几个参数:
- block size:一般16或32个token一块。太小页表开销大,太大碎片多。16是常用值。
- GPU显存预留给Cache的比例:一般留70%-80%给KV Cache,剩下的给模型权重和中间激活。
- 最大并发数:根据Cache总量和平均序列长度反推。
实测下来,PagedAttention能把有效并发提升50%以上,而且几乎不影响输出质量,属于闭眼上的优化。
实操心得:开启PagedAttention后,一定要监控block的利用率。如果发现大量block只填了一半,说明block size设大了或者序列长度分布很分散,可以调小block size。
4. 第三条手段:批处理与连续批处理,榨干每一分算力
4.1 静态批处理的致命缺陷
早期推理服务用静态批处理:攒一批请求,一起送进模型,等这批全部生成完再返回。问题很明显——短请求被长请求拖死。一个请求要生成10个token,另一个要生成500个,静态批处理下前者得等后者全部完成,GPU在等长请求的时候大量闲置。
这个缺陷在真实场景里是致命的,因为用户请求长度分布极不均匀。我统计过一个对话产品,输出长度从几个token到上千token都有,静态批处理下GPU利用率经常掉到20%以下。
4.2 连续批处理的调度逻辑
连续批处理(Continuous Batching)解决了这个问题。核心思想是:不等整批完成,任何一个请求生成结束就立刻把它踢出去,腾出的位置马上塞新请求进来。这样GPU永远在处理"当前还活着的请求",利用率大幅提升。
调度逻辑大致是:
- 维护一个运行队列和一个等待队列
- 每生成一个token,检查哪些请求已经结束(遇到结束符或达到长度上限)
- 结束的请求移出,等待队列的请求补进来
- 每步都对当前所有活跃请求做一次前向
这个机制让GPU的batch size始终保持在较高水平,实测吞吐能提升2-5倍。
4.3 批处理调优的关键参数
连续批处理有几个参数直接影响效果:
- 最大batch size:受显存限制,要结合KV Cache占用算。设太大容易OOM,设太小浪费算力。
- 调度粒度:每步调度还是每几步调度。每步调度最灵活但开销大,实际中每步调度是主流。
- 抢占策略:显存不够时,是拒绝新请求还是抢占老请求。一般优先拒绝新请求,避免影响已开始的生成。
我踩过的一个坑:早期把最大batch size设得很大,结果长请求一多就OOM,服务直接崩。后来改成动态batch size,根据当前显存余量实时调整,稳定性好了很多。批处理参数一定要留安全余量,宁可少塞几个请求,也别让服务挂掉。
5. 第四条手段:GPU虚拟化与算力切分,提升小模型利用率
5.1 什么场景需要GPU虚拟化
不是所有推理任务都需要一整张卡。很多场景下,模型小、并发低,一张卡跑一个实例利用率极低。比如:
- 7B以下的小模型,单卡能跑好几个实例
- 低频调用的专用模型,一天没几个请求
- 开发和测试环境,不需要独占整卡
这时候GPU虚拟化就派上用场了。它把一张物理卡切成多个虚拟实例,每个实例独立跑一个模型或服务,把闲置的算力利用起来。
5.2 算力切分的两种路线
GPU虚拟化主要有两条技术路线:
时间片切分:多个实例分时复用同一张卡,类似CPU的时间片轮转。实现简单,但延迟不稳定,适合对延迟不敏感的场景。
空间切分(MIG等):把GPU的SM、显存等硬件资源物理隔离成多个实例。隔离性好、延迟稳定,但切分粒度受硬件限制,且需要特定卡型支持。
| 路线 | 隔离性 | 延迟稳定性 | 硬件要求 | 适用场景 |
|---|---|---|---|---|
| 时间片切分 | 弱 | 差 | 低 | 测试、低频任务 |
| 空间切分 | 强 | 好 | 高 | 生产、多租户 |
我的经验是:生产环境优先空间切分,测试环境时间片切分够用。空间切分虽然硬件要求高,但隔离性带来的稳定性在生产环境太重要了,一个实例出问题不会影响其他实例。
5.3 虚拟化的成本账怎么算
虚拟化不是免费的,它本身有开销。切分后每个实例的算力有损耗,显存也有管理开销。所以要不要上虚拟化,得算账:
假设一张卡租用成本是X元/小时,跑一个大模型利用率60%,那有效成本是X/0.6。如果切成4个小实例,每个利用率80%,总利用率可能到85%,有效成本降到X/0.85。利用率提升带来的收益,要大于切分本身的开销,才值得做。
我见过反面案例:为了虚拟化而虚拟化,把一个大模型硬切成几份,结果通信开销和调度开销把收益全吃掉了。虚拟化适合小模型和多租户,大模型单实例跑满更划算。
6. 第五条手段:模型量化与蒸馏,从源头减少计算量
6.1 量化:用精度换成本
量化是最直接的降本手段——把模型权重和计算从FP16降到INT8甚至INT4,显存占用和算力需求都大幅下降。INT8量化通常能省一半显存,INT4能省到四分之一。
但量化有精度损失,关键是怎么把损失控制在可接受范围。现在主流的量化方法有:
- 训练后量化(PTQ):直接对训练好的模型量化,简单快速,但精度损失相对大
- 量化感知训练(QAT):训练时就模拟量化,精度保持好,但需要重新训练
- GPTQ/AWQ等:针对大模型的专门量化算法,精度和速度平衡得不错
我的建议:优先试GPTQ或AWQ这类专门算法,PTQ作为快速验证手段。实测下来,70B模型用INT4量化,在大多数任务上精度损失在1-2个百分点内,但成本直接砍到四分之一,非常划算。
6.2 蒸馏:让小模型干大模型的活
蒸馏的思路是:用大模型(教师)的输出训练小模型(学生),让小模型在特定任务上逼近大模型的效果。推理时只跑小模型,成本自然低。
蒸馏的关键是任务要聚焦。通用蒸馏很难,小模型学不会大模型的全部能力。但如果你的场景是固定的,比如只做意图分类、只做摘要,那蒸馏效果会很好。我见过一个团队把70B的摘要能力蒸馏到7B模型上,效果达到原模型的95%,成本降到十分之一。
注意:蒸馏需要大量高质量的教师输出数据,数据准备成本不低。而且蒸馏出的小模型泛化能力弱,场景一变可能就得重新蒸。蒸馏适合场景稳定、量大的业务。
6.3 量化与蒸馏的组合策略
这两条手段可以组合。常见做法是:先蒸馏出小模型,再对小模型量化。这样既减小了模型规模,又降低了单次计算精度,双重降本。
但要注意,量化和蒸馏的误差会叠加。蒸馏本身有精度损失,量化再加一层,可能就超出可接受范围了。所以组合使用时,每一环的精度损失都要留余量,最后做端到端的质量评估。
7. 第六条手段:国产算力适配,把成本结构彻底改写
7.1 为什么国产算力值得认真考虑
前面五条都是在"用同样的卡"前提下优化,国产算力是换一个成本结构。当前高端算力卡供应紧张、价格高企,而国产算力卡在政策支持和产能爬坡下,性价比优势越来越明显。
从成本角度看,国产卡的单卡算力可能不如顶级卡,但单位算力成本往往更低,而且供应稳定。对于推理这种对绝对性能要求没那么极致、但对成本极度敏感的场景,国产算力是很有竞争力的选项。
7.2 国产算力适配的实操难点
适配国产算力不是换个卡就完事,难点主要在软件栈:
- 算子库差异:不同厂商的算子库接口不同,模型代码要改
- 框架支持:主流推理框架对国产卡的适配程度参差不齐
- 精度对齐:同样的模型,不同硬件上数值精度可能有差异,要重新验证
- 性能调优:国产卡的性能特性不同,原来的调优参数不一定适用
我的实操建议是分阶段迁移:先跑通一个简单模型验证链路,再迁移核心模型,最后做性能调优。不要一上来就全量迁移,容易踩坑踩到怀疑人生。
7.3 混合算力调度:不把鸡蛋放一个篮子
最稳妥的方案是混合算力:一部分跑在国产卡上,一部分跑在原有卡上,通过统一调度层做流量分配。这样既能享受国产算力的成本优势,又能保证供应稳定性和峰值弹性。
调度层要做的关键决策是:哪些请求走国产卡,哪些走原有卡。一般按模型和SLA分:对延迟敏感的核心业务走原有卡,对成本敏感的批量业务走国产卡。我见过做得好的团队,用这套混合方案把整体推理成本压了40%以上。
| 维度 | 国产算力 | 原有算力 | 混合策略 |
|---|---|---|---|
| 单位成本 | 低 | 高 | 按业务分层 |
| 供应稳定性 | 好 | 紧张 | 互为备份 |
| 生态成熟度 | 追赶中 | 成熟 | 核心业务用成熟生态 |
| 性能 | 中高 | 高 | 峰值弹性用高性能 |
8. 六条手段怎么组合:一份可落地的优先级清单
8.1 按投入产出比排序
六条手段不是并列的,有先后。按我的经验,投入产出比从高到低大致是:
- 连续批处理:改动小、收益大,几乎必做
- PagedAttention:框架自带,开启即用
- KV Cache量化:收益明显,实现不难
- PD分离:收益大但架构改动大,适合中大规模
- 模型量化/蒸馏:从源头降本,但需要模型侧配合
- 国产算力适配:成本结构改写,但迁移成本高
建议从1、2、3开始,这三条基本不需要改架构,几天就能见效。等这些吃透了,再考虑PD分离和国产算力这种大动作。
8.2 不同规模团队的选择
- 小团队(日请求<10万):重点做连续批处理+KV Cache优化,用云上弹性算力,别自己搞集群
- 中团队(日请求10万-100万):加上PD分离和模型量化,考虑混合算力
- 大团队(日请求>100万):六条全上,自建集群+国产算力+精细化调度
8.3 一个真实的优化案例复盘
最后分享一个我参与过的案例。某对话产品,优化前单次推理成本约0.02元,日请求50万,日成本1万元。
优化过程:
- 第一步上连续批处理+PagedAttention,成本降到0.012元,日成本6000元
- 第二步KV Cache INT8量化,降到0.009元,日成本4500元
- 第三步PD分离,降到0.007元,日成本3500元
- 第四步部分流量迁到国产算力,降到0.005元,日成本2500元
整体降本75%,而且响应质量没有明显下降。这个案例说明,六条手段组合起来,效果是叠加的。
实操心得:优化是个持续过程,不是一锤子买卖。每次优化后都要重新监控、重新找瓶颈。我见过团队优化一轮就停了,结果新瓶颈出现后成本又涨回去。建立成本监控看板,把单位推理成本作为核心指标持续跟踪,这比任何单次优化都重要。
8.4 几个容易踩的坑
最后列几个我踩过或见过的坑,帮你省点时间:
- 只优化不监控:没有基线数据,优化效果无法量化,容易自嗨
- 过度追求极致压缩:把精度压到临界点,线上流量一波动就出问题
- 忽视长尾请求:平均值好看,但P99延迟爆炸,用户体验崩盘
- 一次性大改:所有优化一起上,出问题不知道是哪个引起的,要小步快跑
- 忽略运维成本:架构越复杂运维越重,省下的算力钱可能被运维人力吃掉
我个人在实际操作中的体会是,推理成本优化七分靠工程,三分靠算法。大部分收益来自把现有资源用得更充分,而不是换更牛的模型或硬件。把连续批处理、KV Cache、PD分离这些工程手段做扎实,成本自然就下来了。国产算力是锦上添花,但前提是你的软件栈已经足够高效,否则换什么卡都是浪费。