大语言模型KV缓存只存K和V向量,从不存Q的原因
大语言模型是自回归生成的,每次从它之前的所有已有词中预测出下一个词。一次遍历n个输入词的前向传播会生成n个隐藏状态,但只有最后一个隐藏状态会被转换为输出概率,用来生成下一个新的词。<br><br>我们用10个词组成的输入提示来分步解释计算过程:第一步是预填充阶段,全部10个提示词会一次性并行输入模型完成计算,每一层的10个位置都会各自生成一个查询(Q)向量、一个键(K)向量和一个值(V)向量。
这个阶段计算量很大,第一个输出词响应延迟主要来自这里。<br><br>要生成第11个输出词,只需要第10个位置的隐藏状态,将它转换为词表的概率分布,经过采样就能得到第11个词。<br><br>最后一个位置的隐藏状态,来自前馈网络输出的最后一行。
前馈网络按位置独立计算,因此这一行又来自注意力输出的最后一行,我们只需要理清注意力最后一行的计算逻辑。<br><br>10个词的QK转置相乘会得到10×10的注意力矩阵,第i行是第i个Q和所有K的点积,第10行只有第10个Q(Q₁₀)参与计算。前9个Q只出现在对应前9行,对应的隐藏状态已经不需要了,可以直接丢弃。
<br><br>注意力矩阵第10行经过softmax处理后,会和所有V₁到V₁₀相乘,得到注意力输出的最后一行。也就是说,生成最后一个隐藏状态只需要三个要素:Q₁₀、所有的K、所有的V。<br><br>接下来生成第12个词时,需要第11行的隐藏状态,计算需要Q₁₁,以及K₁到K₁₁、V₁到V₁₁。
在因果掩码规则下,每个位置的K和V只由这个位置和它之前的词决定,加入新词不会改变之前位置的K和V。<br><br>因此每一步解码只需要保留之前所有位置的K和V,只计算新位置的Q、K、V。新位置的Q只用一次,不需要跨步骤缓存,所以KV缓存只存K和V。
<br><br>KV缓存只是大语言模型服务栈中四层缓存的其中一层,另外三层分别是服务端前缀缓存、服务商按次收费的提示缓存,以及完全跳过模型的语义缓存。<br><br>在经典的投机解码双模型方案中,两个模型各维护自己的KV缓存。草稿模型逐词生成扩展自身缓存,目标模型一次性处理草稿生成的所有词,读取自己缓存的前缀计算对应K和V,不使用草稿模型的缓存。
如果输出被拒绝,两个模型都会回滚到最后一个被接受的词。而DeepSeek、Gemma采用的MTP类草稿方案,会共享目标模型的缓存,只需要管理一组缓存。