SH

Soloharness

概念 · 辨析 · Agent

← 返回概念辨析

Concept Contrast Fable

预填充和解码阶段,一个吃进问题算一遍全量注意力,一个吐着字一个一个往前走

预填充阶段一次性处理输入序列的全部 token,并行计算它们的注意力,产出第一个 token 的生成状态。解码阶段此后逐个自回归地生成每个后续 token,每次只算新增 token 对历史的注意力。两个阶段拼成一次完整的推理调用,但计算特征和瓶颈完全不同。

寓言

驿道上有两个弯,第一个弯车马齐进山,第二个弯一辆一辆过吊桥

北地有一条驿道,从京城到边关一共八百里,中间最费时间的是两段路。第一段叫龙门湾,队伍从平原突然进入两山夹峙的峡谷。所有车马在谷口齐头并进,前面的路宽,容得下十骑并行——这段快、猛,一口气把全队推过峡谷。第二段叫一线桥,出了峡谷是窄窄的木悬桥,每次只能过一骑。一骑接一骑,无法并行。

驿道的调度官老秦管这条路管了十五年。他计算时间从来不算总里程,而是把龙门湾和一线桥拆开算。龙门湾的用时只取决于队伍的总重量和编队宽度——编队越宽、马力越足,过得越快。一线桥的用时取决于总长度再除以每骑速度——跟编队无关,跟天气、风速和每骑的刹停反应有关。

有一年朝廷给驿道拨了一笔提速预算。老秦第一个方案全压在龙门湾上:拓宽谷口、铺硬地、多买十匹快马。三个工程做完,龙门湾快了一倍。但一线桥没动。全年整体用时只减了一成——龙门湾本来就是过路全程里占比不到两成的那一段。好马坏马在谷口能体现差异,到了桥头全是排队的命。

第二年换了方案,预算一分为二。第一笔给龙门湾重铺路面,第二笔给一线桥加装滑轨、把木悬桥换成两骑并行的小拱桥。两段工程同步推进,全年整体用时减了四成。老秦在年终账单上跟新来的驿务主管讲:龙门湾是批量处理的并行阶段,一线桥是逐个通过的串行阶段。提速要分两段看,只盯着一头烧钱,剩下的全是浪费。

老秦把这条经验写进驿道手册:先有一段能让整队齐头并进的宽路,再有一段只能逐骑通过的窄桥。宽路要看总重量、编队和马力;窄桥要看每一骑落蹄之间的间隙。前一段追求一次推过更多人,后一段追求每一步都不断档。

老秦后来给沿线的每个驿站挂了一张路线图表,图上龙门湾标「并行·吞吐优先」,一线桥标「串行·时延优先」。他告诉驿卒:队伍卡在哪段,你就用哪段的策略去调。不要用修谷口的方法去修桥,桥不认马力。

后来有新调度官来接手,跟老秦抱怨一线桥还是太慢。老秦翻开记录:你们去年给桥投的所有预算,只换了每骑上桥时的提示灯,那是龙门湾该做的事情——并行段才需要提前备马。串行段真正需要的是把过桥间隙降到最低,让每匹马落蹄时桥面不回弹。

预填充阶段

推理的第一个阶段,输入的全部 token 一次性进入模型,并行计算注意力和中间状态。计算密集、吞吐优先,瓶颈在算力。输出第一个生成 token 的隐藏状态。

解码阶段

推理的第二个阶段,逐个自回归地生成每个新 token。每次只计算新 token 对历史的注意力。内存访问密集、时延敏感,瓶颈在 KV 缓存的读写。

故事对应

  • 龙门湾谷口:prefill——输入一次性并行处理,吞吐导向
  • 一线桥木悬桥:decode——逐个 token 串行生成,时延导向
  • 老秦分两段算时间:prefill 和 decode 的计算特征和瓶颈分离
  • 第一年只投龙门湾:优化 prefill 但 decode 拖后腿——整体延迟改善有限
  • 第二年两段都投:prefill 和 decode 分别优化才能实现整体提速
  • 路线图标并行和串行:系统监控里 prefill 和 decode 的指标面板分开
  • 提示灯的浪费:用 prefill 的优化方法去优化 decode,完全不对路

落到推理性能优化

排查推理延迟时,先拆开看瓶颈在 prefill 还是 decode。Prefill 慢表现为首 token 延迟高——输入越长越慢,优化方向是批处理、并行计算和显存带宽。Decode 慢表现为每个后续 token 的间隔时间长——优化方向是 KV 缓存布局、内存访问模式和投机解码。买 GPU 时如果业务以长输入短输出为主(如翻译、摘要),prefill 算力更重要;以长输出为主(如代码生成、写作),decode 的内存带宽和缓存架构要先看。两个阶段跑在同样的硬件上,但掏钱买卡的时候要看清楚是哪个阶段在吃钱。