KV Cache
背景
在推理的时候。我们可以用KV Cache来加速我们推理的速度,KV缓存的核心是怎么样避免重复计算
简单来说,KV Cache是一种在生成式AI模型(如GPT系列)进行推理时,用来存储和复用过去计算结果的内存优化技术,旨在极大提升生成速度并降低计算资源的消耗。
回忆下计算QKV
在自注意力机制中,输入序列的每个词(Token)会生成三个向量:
Query (Q):代表当前词,用于去“查询”其他词。
Key (K):代表其他词,用于被“查询”,与Q进行匹配。
Value (V):代表其他词本身携带的信息。
模型通过计算
Q
和所有K
的点积来得到注意力分数,然后用这个分数对所有的V
进行加权求和,从而得到当前词的上下文表示。在Decoder中,我们的K和V是增量更新的,当模型生成第I个词的时候,它需要关注第
1
个词到第i-1
个词的所有信息
KV Cache如何工作?
在没有KV Cache的情况下,模型生成文本的过程是这样的:
- 生成第1个词:输入Prompt,计算出所有词的
K
和V
向量,然后生成第一个新词。 - 生成第2个词:将“Prompt+ 第1个词”作为新的输入,重新计算所有这些词的
K
和V
向量,然后生成第二个新词。 - 生成第3个词:将“Prompt+ 第1个词 + 第2个词”作为新的输入,再次重新计算所有词的
K
和V
向量,然后生成第三个新词。 - …依此类推。
在这里我们会发现一个巨大的浪费:在生成第3个词时,我们重复计算了Prompt和“第1个词”的
K
和V
向量,而这些向量在之前的步骤中已经算过了,并且它们的值是不会改变的!- 生成第1个词:输入Prompt,计算出所有词的
KV Cache正是为了解决这个冗余计算问题而生的。
它的工作流程如下:
- 第一步(预填充/Prefill阶段):
- 模型接收初始Prompt(例如 “The weather is”)。
- 它一次性计算出Prompt 中所有词(“The”, “weather”, “is”)的
Key
和Value
向量。 - 然后,它将这些计算好的
K
和V
向量存储在一个专用的缓存区域里。这就是KV Cache。 - 基于这些信息,模型生成第一个新词,比如 “nice”。
- 第二步及之后(解码/Decoding阶段):
- 现在,模型要生成下一个词。它只需要将新生成的词 “nice” 作为输入。
- 模型只计算 “nice” 这个词的
Query
,Key
, 和Value
向量。 - 在计算注意力时,模型的
Query
向量(来自 “nice”)会与 KV Cache中存储的所有历史Key
向量(来自 “The”, “weather”, “is”)以及 “nice” 自己的Key
向量进行匹配。 - 然后,它将得到的注意力分数用于对 KV Cache中存储的所有历史
Value
向量 和 “nice” 自己的Value
向量进行加权求和。 - 最后,将新词 “nice” 的
K
和V
向量追加到KV Cache中,以备下一个词生成时使用。
通过这种方式,每生成一个新词,模型只需要为这一个新词进行计算,并将结果存入缓存即可,无需再处理整个历史序列。
- 第一步(预填充/Prefill阶段):
KV Cache的优缺点
优点
- 极高的推理速度:这是其最核心的优势。它将生成每个新词的计算复杂度从
O(n^2)
(n是序列长度)降低到O(n)
,因为每次只需要和历史序列做一次点积,而不需要重新计算整个历史。这使得大语言模型的实时交互成为可能。 - 降低计算量:避免了大量的冗余计算,节省了GPU的计算资源。
缺点
占用大量内存:KV Cache需要存储模型每一层、每一个注意力头的 key 和 Value向量。对于很长的上下文(Context),这个缓存会变得非常巨大,占用大量GPU显存。
- 显存占用量约等于:
2 * (层数) * (隐藏层维度) * (序列长度)
。
- 例如,对于一个像Llama 2 7B这样的模型,处理一个4096长度的序列,KV Cache就可能占用数GB的显存。
- 显存占用量约等于:
限制了最大上下文长度:由于显存是有限的,KV Cache的大小直接限制了模型能够处理的最大序列长度。一旦显存耗尽,就无法继续生成。
应对KV Cache内存挑战的技术
- 为了解决KV Cache的内存占用问题,社区也发展出了一些先进技术,例如:
- 量化(Quantization):将KV Cache中的向量从FP16(16位浮点数)压缩为INT8或INT4(8位或4位整数),以减少内存占用。
- 分组查询注意力(Grouped-Query Attention, GQA) 和 多查询注意力(Multi-Query Attention, MQA):让多个
Query
头共享同一组Key
和Value
头,从而显著减小KV Cache的尺寸。