技术

大模型推理成本是怎么省下来的?(量化 / KV Cache / 批处理)

2024 年 09 月 18 日 约 1596 字 · 4 分钟 技术
大模型推理成本是怎么省下来的?(量化 / KV Cache / 批处理)

今天跟同事聊到,回家就写了。

这阵子有个现象挺有意思:模型越来越大,可调一次 API 的价格反而一路往下掉。

这背后不是厂商在做慈善,而是推理优化这两年实打实地把成本砍了下来。最近 vLLM 这类推理框架火得不行,量化、KV Cache、连续批处理这几个词到处刷屏。今天我就借「开餐馆」这个比喻,把省钱的三大招讲明白。

先搞懂:钱到底烧在哪

把一次大模型推理,想象成餐馆出一道菜

你发一句话过去,模型不是一口气把整段答案吐出来的,而是一个字一个字地往外蹦(术语叫 token)。每蹦一个字,它都得把前面所有内容在脑子里重新过一遍,再决定下一个字是啥。

问题就出在这「重新过一遍」上:答案越长,它回头要复习的内容就越多,到后面几乎是在反复重读一篇越来越长的作文。又慢又费电——成本,就这么烧上去的。

第一招:KV Cache——别每道菜都从头熬高汤

既然模型每蹦一个字都要把前文重算一遍,那有没有办法别重算?

有。前文那部分的中间计算结果(叫 Key 和 Value),其实算一次就够了,后面完全可以存起来反复用。这就是 KV Cache

flowchart LR
  A["生成第 1 个字"] --> B["把前文算好的<br/>中间结果存进缓存"]
  B --> C["生成第 2 个字<br/>直接复用缓存"]
  C --> D["生成第 3 个字<br/>继续复用"]
  D --> E["越往后<br/>省下的重算越多"]

放餐馆里,这就好比高汤熬一锅,后面每道菜直接舀,而不是每上一道菜就重新熬一遍高汤。一下子就把那些重复的笨功夫省掉了。代价是它得占一块内存来存这锅汤——所以怎么把这块内存管好,正是 vLLM 这类框架的看家本事。

第二招:量化——把食材切小份,锅就够用了

模型的参数,默认是用很「精细」的数字格式存的(比如 16 位浮点),占地方、算起来也重。

量化(Quantization)干的事,就是把这些数字换成更粗一点的格式(比如 8 位甚至 4 位整数)。精度稍微降一丢丢,但体积和计算量大幅下降。

 不量化量化后
占的显存小一半甚至更多
跑的速度
精度满血掉一点点

打个比方:菜谱上写「盐 3.14159 克」,量化就是改成「盐一小撮」。少了那点小数,菜的味道几乎没差,可备料和操作一下子轻快多了。 关键是这点精度损失,在绝大多数场景下你根本尝不出来——这买卖,划算。

第三招:连续批处理——一锅多炒,别让灶台空着

最后这招最妙。单看一个请求,模型其实经常在干等——等显存搬数据、等某个慢请求蹦完最后一个字。灶台火开着,锅里却没几个菜,纯浪费。

那就把多个用户的请求凑一锅一起炒。传统批处理有个毛病:得等同一批里最慢的那个全做完,才能上下一批,一桌人陪一个慢性子干瞪眼

连续批处理(Continuous Batching)改进了这点:谁的菜出完了就立刻撤盘、马上把新订单补进锅里,灶台一刻不闲。

flowchart TD
  A["传统批处理"] --> B["凑齐一批一起做"]
  B --> C["必须等最慢的那个<br/>做完才能换下一批<br/>(灶台空等)"]
  D["连续批处理"] --> E["谁做完谁先走"]
  E --> F["立刻补新请求进来<br/>灶台始终满负荷"]

这一招把昂贵的 GPU 利用率拉满,单位时间能服务的人翻好几倍——分摊到每个请求头上,成本自然就薄了。这也是为啥 vLLM 跑同样的卡,吞吐能甩出原生实现一大截。

三招一起上

招数餐馆比喻省在哪
KV Cache高汤熬一锅反复舀不重复算前文
量化食材切小份显存小、算得快
连续批处理灶台一刻不闲GPU 利用率拉满

你看,API 价格一路走低,靠的不是什么魔法,而是这种「别做重复功、别用过精的料、别让灶台空着」的朴素省钱学。

说到底,推理优化的精髓和开餐馆一模一样:好吃是前提,但能不能赚钱,全看你会不会省那些看不见的功夫。


暂记于此。