简单阐述内部原理的KV cache

回复 Erfan: KV cache 解决的是大模型生成时重复计算的问题。 先看没有它的情况。模型是一个词一个词往外蹦的,每生成一个新 token,都要让它和前面所有 token 做一次注意力计算。注意力需要每个历史 token 的 K(Key,相当于"标签")和 V(Value,相当于"内容")。如果每一步都把整段历史重新过一遍,算的基本是同样的东西,成本随长度平方级地涨。 KV cache 的做法是:每个 token 在每一层算出的 K 和 V 只算一次,存起来。生成新 token 时,只为这一个新 token 算 Q、K、V,把新的 K、V 追加到缓存末尾,然后用新 token 的 Q 去和缓存里所有的 K 比相似度,再按权重加权求和缓存里的 V,得到输出。这样每一步的主要工作变成了"新 token 对历史的一次查询",不用重算历史。 可以类比开会记笔记:每个人发言的要点(标签和内容)记在本子上,新人发言时直接对照本子看,不用让所有人把之前的话再讲一遍。 代价是显存。缓存大小大致是:2 × 层数 × KV 头数 × 每头维度 × 序列长度 × 每个数的字节数。上下文越长,占的显存越多,所以长上下文通常是显存先扛不住。 实际推理里还有几个相关概念。一是 prefill 和 decode 两阶段:prompt 部分可以并行算完并填满缓存,之后的 decode 才是一个一个 token 地生成,这一步通常受显存带宽限制。二是 GQA、MQA 这类结构,让多个 Query 头共享较少的 K、V 头,直接把缓存缩小。三是量化 KV cache,把 K、V 存成更低精度。四是 PagedAttention(vLLM 的做法),像操作系统分页一样管理缓存,减少碎片。五是 prefix caching,多个请求共用相同的系统提示词时复用前缀的缓存。 一句话总结:KV cache 用显存换计算,把每步的成本从"重算整段历史"降到"只算新 token 加一次查询"。