把一页通知交给模型,它很快开始回答;换成一本书,第一句话迟迟没有出现。另一种情况更奇怪:开头等得不久,后面却像挤牙膏一样,一小段一小段冒出来。这两种慢发生在同一条生成链上,却未必来自同一个瓶颈。
第19章已经说明,回答通常按token逐步产生。本章把镜头移到计算与存储:哪些工作必须重新做,哪些结果可以留下,以及“支持很长的输入”为什么不能直接读成“能用好全部输入”。我们采用最常见的因果、decoder-only Transformer作解释,不把这套缓存公式当成所有模型的统一结构。
1.先读输入,再逐步续写
假设输入已经切成四个token,记作A、B、C、D。prefill常译为预填充:模型处理这些已知位置,在每一层形成表示和注意力所需的K、V,并用最后位置的输出预测第一个新token。
四个输入都已知,因此在同一层内可以成批计算。因果掩码仍然有效:A不能读取B,C不能读取D。这里的并行是把许多已知位置安排在一起计算,并没有让某个位置偷看未来。不同层之间仍有依赖,后一层要用前一层的结果。
假设首次预测选中了E。下一次计算才把E作为新的输入位置,获得它的表示,再预测F。这个逐步接收新token、预测下一个token的阶段叫decode。词语容易让人误会:这里的decode不是把一份现成的完整答案翻译成人话,而是生成流程中的逐步计算。
因此,prefill已经负责产生第一个新token的预测分布;不能在时间图上凭空多算一轮“先只读完,再从零预测E”。实际服务还可能有排队、分词、网络传输和调度,这些都不属于上述纯模型计算,但用户感受到的等待包含它们。
通常分别观察两个指标:首token延迟是请求到第一个输出可见的时间;输出阶段的token间延迟描述后续生成节奏。总耗时还依赖输出有多长。只给“每秒生成多少token”,可能掩盖长输入带来的开头等待;只给首token时间,也可能掩盖后面的慢速生成。
2.为什么过去的K、V能够留下
第8章的注意力把当前查询Q与各位置的K匹配,再按份额组合V。对因果模型来说,旧位置只依赖它自己和它之前的内容。只要前缀、参数及相关计算设置不变,新token接在后面,不会回头改变旧位置已经得到的表示。
这可以逐层检查,而不必靠“过去已经发生”来猜。固定前缀A、B、C、D的token和位置编号,固定模型参数,关闭训练时随机扰动,并保持相同掩码与位置编码规则。最底层A到D的输入没有变化;第一层每个旧位置仍只读取它原来的前缀,输出就没有新的依赖。第二层收到的旧位置输入也相同,以此逐层推下去,旧K、V便保持不变。追加E只增加一个允许读取A到E的新位置,不会在旧位置行里增加对E的读取。
这里的“不变”是相同数学计算的结果。不同内核和精度可能造成很小的浮点差异;如果参数、位置计算、掩码或前缀本身改变,就必须重新判断缓存条件。依赖完整输入的双向编码器也不满足这个因果论证。
先看图1的下三角。每个有色格表示“这一行的查询允许读取这一列的键”,不是存放一个token。追加E增添一行;把D改成D′则改动了已有输入,失效边界从D开始。

图1|固定参数与位置规则的因果注意力中,追加E不会给A到D增添依赖,因此旧计算可复用。若把D改成D′,以共同前缀A到C为安全复用边界,D及后续位置统一重算。
于是,在每一层保存旧位置的K、V,下一步就可以复用。这份按层组织的中间结果叫KV缓存。它存的是计算出来的向量,不是原文的精简摘要,也不是新增的模型权重。不同会话即使使用同一模型,输入不同,缓存通常也不同。
为什么不把旧Q也照样长期存下?逐步续写时,当前这一步主要需要新位置的查询,让它读取旧的键和值。旧位置的查询曾用于计算旧位置的输出,通常无须重新发起相同读取。缓存不是把Q、K、V三个字母中随意挑两个,而是顺着计算依赖留下未来要用的对象。
把问题具体化:E进入模型时,每一层只为E算新K、V;E的Q读取A到E的K,并汇总对应V。下一层要等本层对E的处理完成,才能形成自己的新缓存项。因此不能先在最底层计算一个E的向量,然后把它复制到所有层当成缓存。
再把“读取”写成张量形状。只看一条序列的一层、一个注意力头,设每头向量宽度为d。E进入前缓存的K、V各有4行、d列;新算的K_E、V_E各有1行、d列,追加后变成5行、d列。Q_E是1行、d列,与5个K点积得到1行、5列分数,归一化后得到5个读取权重,再加权组合5行V,得到1行、d列输出。
被省掉的是重新生成旧位置K/V及相关旧计算;新Q与旧K的匹配、新权重对旧V的组合仍要执行。因为Q_E一般不同于Q_D,不能直接沿用上一位置的注意力权重。这也是缓存会省计算、却仍要持续读取长前缀的原因。
Hugging Face的Transformers缓存说明明确区分逐层保存的旧K/V和每一步新算的部分,展示了把新键值接到旧缓存后的注意力计算。这里用它核实实际框架里的对象含义,不把文档中的简化复杂度说明当成整台机器的速度预测。Transformers缓存机制
3.在纸上走完三次预测
拿出三行纸。第一行写“处理A、B、C、D,预测E”;第二行写“处理E,预测F”;第三行写“处理F,预测G”。每行再画两栏,分别记录本轮新算的K/V与计算结束后的缓存。
第一行新算四组,缓存为A到D。第二行新算E的一组,缓存变成A到E。第三行新算F的一组,缓存变成A到F。G刚刚被选出来,还没有作为下一轮输入经过各层,所以此刻缓存没有G。这个相差一位的细节,可以检查我们是否真的理解“当前位置预测下一位置”。
若每次把整个前缀重新送入、不复用旧结果,这三次预测分别处理4、5、6个位置,共15个位置;复用缓存只处理4+1+1=6个新位置。每层的K与V投影分别对应15次和6次位置级工作。我们只是在数新旧位置,不是在报告速度快了2.5倍。
原因是缓存方案仍要做新查询对已有前缀的读取。只数每个查询可见多少位置,首次因果prefill有1+2+3+4=10对;第二轮有5对;第三轮有6对,共21对。完全重算前缀则是10+15+21=46对。两种计数衡量不同工作,不能混用成一个万能加速比。

图2|prefill处理A到D后预测E;两轮decode依次处理E、F,预测F、G。第二轮的张量路径显示新Q仍读取全部已缓存K/V。G被选出时尚未作为输入处理;位置数15对6与匹配对46对21是不同口径的教学计数。
再把D改成D′,问能不能保留原来A到D的全部缓存?不能。A到C保持相同前缀时可能仍可复用,但D及其后的结果依赖已经变化。若在最前面插入一句话,位置和前缀条件都可能改变,不能仅凭后半段文字看起来一样就拼接旧缓存。所谓前缀缓存,重用条件的核心是相同计算前缀,而不是“意思差不多”。从D开始统一重算,是按共同前缀划定的安全策略,不表示每层每个后续张量都必然改变;例如固定E嵌入生成的首层K/V可能仍相同,而高层表示会受到D变化的影响。
4.缓存省计算,却增加一笔存储
先算普通注意力实现的简化容量。假设每层都保存完整上下文,两份缓存采用相同长度和数值精度:
缓存字节数=2×层数×并行序列数×已缓存token数×KV头数×每头维度×每个数的字节数
开头的2分别对应K和V。层数表示多少层需要独立保存;并行序列数表示同时维持多少份不同序列;KV头数是键值头的数量,未必等于查询头数。每头维度描述每个头的一条向量有多少个数;最后一项把数的个数换成字节。
构造一个便于复核的例子:2层、1条序列、6个已缓存token、2个KV头、每头4维、每个数2字节。容量为2×2×1×6×2×4×2=384字节。长度翻倍到12,容量变成768字节;再同时维持两条这样的序列,就变成1536字节。
这些数故意很小,只用来跟踪乘法。真实模型还存在不同层结构、分块分配、元数据、对齐与暂存空间,不能把这个乘积直接叫作进程显存。模型权重是另一笔账,即使输入还没有一个token,也需要先安排权重的位置。
还可以反过来由预算推容量。沿用上述教学结构,每增加一个缓存位置需要384÷6=64字节。假设总预算2048字节,事先为权重与运行空间预留768字节,便只剩1280字节给KV,最多容纳20个位置。这里按各序列独立保存、暂不计分配开销;20是所有序列长度之和的上限,不是每条都能用20。两条各12位置需要1536字节,已经超出KV额度256字节。输入能放下还不够,后续生成新增的位置也会继续占用预算。
Grouped Query Attention简称GQA,让多个查询头共享一组键值头。它能减少KV头数这一因子,但没有让模型只剩同样少的查询。Qwen3公开报告的架构表就分别列出Q头和KV头;这给了我们一个真实阅读方法:估算缓存时要找对列,不能拿查询头数量代替。Qwen3技术报告,架构

图3|每个位置与KV头对应4个小格,每个小格表示一个数、占2字节;一层K共有6×2×4个数,共96字节。复制为K、V两份,再为2层各存一份,得到384字节。权重与运行空间另计。
量化缓存可以减少每个数的字节数,但可能引入误差与额外转换;把缓存搬到主机内存能减轻设备压力,却增加传输;滑动窗口只保留近期部分,可限制增长,但改变可直接读取的信息范围。它们都要按模型和实现评估,不能理解成免费省空间。缓存也不等同于第29章的长期记忆,清掉缓存不代表系统删除了保存的原始对话记录。
5.长输入和长输出,贵法不同
设输入长度为N。在普通全注意力prefill里,可见匹配对大约随N的平方增长,因为许多位置都要读取各自的前缀;因果下三角只是把完整方阵减少到约一半。某些高效注意力实现能避免把整个注意力矩阵存下来,却不因此取消全部匹配计算。
在带缓存的单步decode里,只有一个新查询位置,但它仍要读取已有前缀。前缀越长,需要处理的K/V通常越多,单步注意力工作随长度增长。连续生成M个新token时,读取范围又逐步扩大,不能把整段输出看成只做一次单步工作。
这解释了常见但并非普遍的系统现象:prefill可利用较大的批量矩阵计算;decode除了计算,还可能花大量时间把权重与缓存从内存搬到计算单元。哪一部分占主导,取决于硬件、并发、模型结构与实现。把“输入贵、输出慢”背成定律,会遗漏这些条件。
多个请求一起服务时,还有资源竞争。增加批处理可能提高总吞吐,但某个用户可能等得更久;保留很多会话的长缓存,也可能挤压同时服务的人数。吞吐量回答一台机器总体处理多少工作,延迟回答一个请求等多久,两者要同时看。
还有一个常见混淆:服务商说某段提示命中了缓存,并不一定表示用户能直接访问那份KV向量。产品可能按前缀复用、会话状态或其他实现提供缓存能力,具体保存多久、何时命中、如何计费都属于服务规则。仅从接口返回一个标志,不能反推出底层每层怎样分配内存。
如果要比较两个方案,至少固定同一模型、输入长度、输出长度、并发数和精度,再分别记录首token时间与后续时间。把一次短问答与另一条长作文放在一起,就算计时毫无误差,也测不出缓存本身的收益。缓存开关改变了计算复用;内容与负载变化则同时改变了任务,因果结论需要把它们分开。
6.装得下,不等于用得好
上下文窗口规定输入、输出及某些内部token需要满足的容量限制,具体计数以模型说明为准。容量是接口和实现条件;它没有保证散落在长材料中的每条证据都能被检索,更没有保证模型会正确处理跨段关系与冲突。
可以给同一份材料做三个逐级加难的纸笔测试:先问某个明确编号对应哪个名字,再问相隔多页的两条规定谁覆盖谁,最后问一个需要同时满足日期、人员和例外条件的问题。第一题只需要定位,后两题还要整合证据和推理,不能用第一题的成功替代全部能力。
《Lost in the Middle》研究观察到,在其测试模型与任务中,相关信息所处位置会影响表现,中间位置可能更难利用。这是特定实验条件下的证据,不意味着每个后来的模型都有相同曲线;它提示评测应改变证据位置、干扰材料和所需关系,而不只把窗口数字写大。长上下文利用研究
一个实用取舍是:任务只需几条有出处的规定时,先检索再给上下文,可能比塞入整本资料更清楚;需要比较全文结构或找未知关联时,过早删减又可能丢掉关键证据。长上下文和检索并不互相替代,问题在于怎样保留完成任务需要的信息。
这与软件工程的缓存和增量计算共享一个约束:复用前,要知道结果依赖哪些输入与计算规则。KV的依赖不只是最后一段文字,还包括共同前缀的token与位置、模型参数,以及掩码等设置。只给末尾同一句话取相同名字,不能抹掉它前面不同的上下文;换过参数后,也不能继续假定旧KV有效。这里复用的是满足条件的数值计算,不是把“意思相近”当作等价。
一个小型等价性测试可以固定同一前缀与同一模型,比较“整段重算”和“按前缀缓存续算”的下一token分数,在预先规定的数值容差内核对;再修改D,检查从D开始重算是否恢复一致。这个测试检查缓存有没有改变结果。另一组固定输入、输出长度与负载的计时,才检查它是否更快。前面的容量账还要单独检查是否装得下:正确性、容量和性能各有自己的证据。
缓存是否保留还与服务生命周期有关。一次生成结束后,系统可能释放这份中间结果,也可能为后续相同前缀暂存。再次发起对话能看到旧文字,不代表上一轮的缓存一定还在;系统也可能重新读取历史,再算一遍。这是数据持久化与计算复用的又一个区别。
本章练习
题目
问题1|沿时间与依赖检查缓存
模型刚处理F并选出G时,缓存包含到哪个位置?接着把D改成D′、A到C不变,哪些旧位置可沿原有因果计算复用,哪些必须重算?说明原因。
问题2|把变动的乘数圈出来
沿用图3的2层、1序列、6token、2个KV头、4维、每数2字节。把缓存长度改为12、并行序列数改为2,其他项不变。缓存多少字节,变为几倍?整体显存是否必然同倍数变化?若总预算2048字节、为权重与运行空间预留768字节,这份缓存能否放下?仍忽略分配开销。
问题3|构造长上下文测试
同一份资料中,某条规则在开头,一条例外在中间,一条修订在末尾。请各设计一个只检查定位、检查跨段关系的问题,并说明只答对定位题能支持什么结论。
思考提示
提示1|对应问题1
区分“选出的下一个token”和“已经送入各层的当前位置”;沿图1查看一个旧位置会依赖哪些输入。
提示2|对应问题2
只改长度与序列数两个乘数。区分KV这笔账与整个进程的内存账,再从总预算减去预留空间。
提示3|对应问题3
定位题只需返回一处资料;关系题应迫使答题者同时使用至少两处,并给出适用条件。
参考答案与解析
答案1|对应问题1
缓存到F。G目前只是被选中的输出,要在下一轮成为输入才会形成自己的逐层K/V。改D后,A到C在前缀、位置及参数均相同的条件下可复用;D到F依赖改变,应重算。不能因E、F的token字面相同就保留其高层缓存,因为它们会读取已改变的前缀表示。
答案2|对应问题2
2×2×2×12×2×4×2=1536字节,是384字节的4倍。两个翻倍分别来自长度与并行序列数。整体显存还包括不随这两个乘数同样变化的模型权重、临时对象等,不能直接说也变为4倍。预算中KV可用2048−768=1280字节,1536超出256字节,因此在给定条件下放不下。
答案3|对应问题3
一种定位题是“中间那条例外规定了哪个日期?”一种关系题是“对修订生效后的该类人员,原规则还是例外适用?请结合三处证据解释。”其他能分别隔离定位与关系整合的题目也可接受。定位成功支持模型在这次位置、材料与提问条件下找到了信息;它不单独证明能处理覆盖、冲突和例外,还应改变证据位置和干扰内容复测。
下一章
现在知道了每多生成一些token,就多做一些计算、多保留一些状态。那么,故意给模型更多时间,让它多试几条解法、再检查结果,究竟怎样换来更可靠的答案?第21章把“多想一点”拆成可计数的推理时计算。