Flash Attention 中的 KV 缓存 | AI生成和翻译

首页 2026.07

问题:这段Flash Attention代码中的KV缓存是什么意思?

答案:

KV缓存 = 键/值缓存。 这是自回归大语言模型生成时的一种推理优化技术,可以避免重新计算之前标记的注意力键和值。

在Transformer注意力层中:

[ Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt d})V ]

对于提示词:

法国的首都是

模型处理以下标记:

T1  T2  T3  T4  T5

在每一层中计算:

K1 V1
K2 V2
K3 V3
K4 V4
K5 V5

生成下一个标记时:

法国的首都是巴黎

新的查询只针对:

T6 = "巴黎"

不使用KV缓存:

需要重新计算K、V:

T1 T2 T3 T4 T5 T6

使用KV缓存:

缓存:
K1 V1
K2 V2
K3 V3
K4 V4
K5 V5

只需计算:

K6 V6

然后注意力:

Q6 关注:

[K1 K2 K3 K4 K5 K6]
[V1 V2 V3 V4 V5 V6]

在你的代码中

关键函数:

def flash_attn_with_kvcache(
    q,
    k_cache,
    v_cache,
    k=None,
    v=None,
    cache_seqlens=None,
    ...
):

是推理路径。

形状

q:        (B, T_new, H, D)
k_cache:  (B, T_max, H_kv, D)
v_cache:  (B, T_max, H_kv, D)

示例:

B = 1              批次大小
T_max = 32768      最大上下文长度
H = 32             注意力头数
D = 128            头部维度

内存:

k_cache:

[
 token0: [head0...head31]
 token1: [head0...head31]
 token2: ...
]

本质上是一个存储历史数据的大张量。


这部分将新标记写入缓存

if k is not None and v is not None:
    k_cache[:, pos:pos+T_new, :, :] = k
    v_cache[:, pos:pos+T_new, :, :] = v

示例:

之前:

k_cache

位置:
0  1  2  3  4  5  6  7
K  K  K  K  K  ?  ?  ?

生成标记5:

pos = 5

插入后:

0  1  2  3  4  5  6  7
K  K  K  K  K  K5 ?  ?

然后注意力使用全部历史数据

k_full = k_cache[:, :end_pos, :, :]
v_full = v_cache[:, :end_pos, :, :]

所以:

k_full:

K0 K1 K2 K3 K4 K5

然后:

Attention(
    Q5,
    K0..K5,
    V0..V5
)

模型可以”记住”之前的标记。


为什么训练不需要KV缓存

你的注释:

# Training (no KV cache)
y = flash_attn.flash_attn_func(...)

训练期间:

输入:

hello world this is GPT

你一次性处理所有标记:

Q:
q1 q2 q3 q4 q5

K:
k1 k2 k3 k4 k5

V:
v1 v2 v3 v4 v5

Flash Attention高效计算整个矩阵:

       k1 k2 k3 k4 k5

q1     x
q2     x  x
q3     x  x  x
q4     x  x  x  x
q5     x  x  x  x  x

因为因果掩码防止向前看。

无需存储KV。


为什么KV缓存对长上下文智能体很重要

对于像这样的智能体:

生成通常是:

提示词:
5万标记

输出:
2千标记

不使用KV缓存:

每个输出标记:

重新计算5万标记

成本:

5万 + 5万 + 5万 + ...

使用KV缓存:

初始提示词:
计算一次K/V

然后:

标记1 -> 仅新K/V
标记2 -> 仅新K/V
标记3 -> 仅新K/V

成本大约变为:

5万 + 2千

而不是:

5万 * 2千

权衡

KV缓存加速推理但消耗显存。

内存:

[ KV\ 内存 = 2 \times 层数 \times 序列长度 \times 头数 \times 头部维度 \times 字节数 ]

示例:

Llama 70B:

80层
64个KV头
128维
12.8万上下文
bf16

KV缓存可能达到:

数百GB

这就是为什么较新的模型使用:

以减少KV内存。


与你RTX 4070 / 本地推理的关系

你的RTX 4070:

12GB显存

长上下文的限制因素通常不是模型权重,而是KV缓存。

示例:

Qwen 32B:

权重:
~64GB bf16

本地无法运行。

但即使是较小的模型:

Qwen3 8B
12.8万上下文

可能达到:

KV缓存 > 几GB

在权重成为问题之前。

这就是为什么像这样的推理引擎:

拥有复杂的KV缓存管理。

在你的代码中,flash_attn_with_kvcache() 本质上就是这些引擎所依赖的底层原语。


AI生成和翻译,但整理分享仍需精力。如果觉得有帮助,欢迎 捐助支持。 微信:@lzwjavaWeChat QR · X: @lzwjava · 打个招呼 👋

返回 捐助