1.什么是KV Cache?为什么要使用KV Cache?
理解此问题,首先需理解自注意机制的计算和掩码自注意力机制,在Decoder架构的模型中,每生成一个新的token,便需要重新执行一次自注意力计算,这个过程中,由于Decoder的掩码自注意力机制,导致存在大量的冗余重复计算(原因可参考大模型推理加速:看图学KV Cache),为了避免这种重复计算,提升推理效率,提出了KV Cache,即KV缓存,是指每次Decoder生成next token的过程中,将之前计算自注意力机制中K和V矩阵缓存下来,从而在生成当前token的时候避免重复之前的计算(为什么可以直接使用K和V的缓存值,而无需重复计算,可参考:大模型推理加速:看图学KV Cache)
总结使用KV Cache的原因:
- 提升推理速度: 在自回归生成任务中,每次生成新 token 时,模型需要计算当前 token 与之前所有 token 的注意力分数。如果不使用 KV Cache,每次生成新 token 都需要重新计算之前所有 token 的 Key 和 Value,这会导致计算量随着序列长度呈二次方增长,显著增加推理时间和计算资源的消耗。使用 KV Cache 可以将计算复杂度从 O(n^2) ) 降低到 O(n),显著减少计算量。
- 降低计算资源消耗: 通过减少重复计算,KV Cache 可以降低对计算资源(如 CPU 和 GPU)的需求
因此,使用KV Cache后,对于生成的每个新token,不需要传入整个序列,只需计算新的token情况,因此可以避免重新计算整个注意力矩阵。只需要以下面的方式对新token进行操作:
- 仅为新token计算新的 q、k、v 行。
- 新的 q 行将立即被使用。(这也解释了为什么没有查询缓存)
- 将新的键、值附加到现有的 K、V 缓存中。
- 通过新的 q 行和 k_cache 的转置进行矩阵向量乘法来计算新的注意力行。 通过新的注意力行和 v_cache的转置进行矩阵向量乘法来计算新的 v 行。
- 输出(仅针对最新标记)被传递到下一层。
此步骤说明参考:【大模型理论篇】Transformer KV Cache原理深入浅出
以下是一个具体的 with KV Cache和 without KV Cache对比, 因此,KV Cache可通过增加内存使用来节省重复计算,以空间换时间。
2. 使用KV Cache会带来什么问题?
-
** KV Cache占用大:** KV Cache 随着序列长度的增加会占用大量显存资源。
KV Cache的显存占用分析,假设模型的参数配置信息如下(参考【大模型理论篇】Transformer KV Cache原理深入浅出):
Transformer 中有 n_layers 个层块。
每个层块中有一个多头注意力层。
每个多头注意力层有 n_heads个注意力头,每个头的 k 和 v 的尺寸为 d_head。
需要为 K 和 V 都缓存一份。
最大上下文长度为 n_context。
精度为 n_bytes,例如对于 FP32 是 4。
推理时的批量大小为 batch_size。
那么总的显存大小为:
kv_cache_size = n_layers * n_heads * 2 * n_context * d_head * n_bytes * batch_size
简化后为:
kv_cache_size = 2 * n_bytes * n_layers * d_model * n_context * batch_size
例如,针对 OPT-30B 模型的KV Cache显存计算:
n_bytes = 2(FP16)
n_layers = 48
d_model = 7168
n_context = 1024
batch= 128
计算结果为 180,388,626,432 字节,约为 168 GB。
- 显存管理复杂: KV Cache 的大小与序列长度和批量大小动态相关,容易导致显存碎片化和显存容量不足的问题。
- 资源开销: 虽然 KV Cache 提高了推理速度,但需要额外的显存来存储缓存数据,这增加了硬件资源的需求
3. 如何缓解KV Cache带来的问题?