当前位置: 首页 > news >正文

LLM笔记(九)KV缓存调研

KV 缓存 (Key-Value Cache) 技术详解

KV 缓存(Key-Value Cache)是在 Transformer 模型(尤其是 Decoder-Only 架构或 Encoder-Decoder 架构的 Decoder 部分)进行自回归 (auto-regressive) 推理生成序列时,一种至关重要的优化技术。其核心目标是显著提高生成速度并大幅减少冗余计算。

1. 为什么需要 KV 缓存?

在自回归生成模式下,模型一次生成一个词元 (token)。例如,要生成句子 “A B C D”,过程如下:

  1. 输入 <start>,模型预测 “A”。
  2. 输入 <start> A,模型预测 “B”。
  3. 输入 <start> A B,模型预测 “C”。
  4. 输入 <start> A B C,模型预测 “D”。

注意到,在第3步计算 “C” 时,Transformer 的自注意力机制需要计算当前词元 “B” (作为 Query) 与之前所有词元 <start>, “A”, “B” (作为 Key 和 Value) 之间的注意力。其中,<start> 和 “A” 的 Key ( K K K) 和 Value ( V V V) 向量在第2步生成 “B” 时已经计算过了。如果没有 KV 缓存,这些 K K K V V V 向量会在每一步都被重新计算,造成巨大的计算浪费,尤其是当序列变长时,这种浪费会急剧增加。

KV 缓存的核心思想对于已经处理过的词元,将其在自注意力层中计算出的 Key 和 Value 向量存储起来,在后续生成步骤中直接复用,避免重复计算。

2. KV 缓存的工作流程

以 Decoder 的自注意力层为例(Encoder-Decoder 架构中的 Cross-Attention 也可以应用类似思想,但 Encoder 的 K K K, V V V 通常只需计算一次):

  1. 初始状态: 缓存为空。
  2. 生成第 1 个词元 ( t = 1 t=1 t=1):
    • 输入是起始符 (e.g., <bos>)。
    • 模型为这个输入词元计算其 Query ( Q 1 Q_1 Q1),Key ( K 1 K_1 K1),和 Value ( V 1 V_1 V1) 向量。
    • 注意力计算: Attention ( Q 1 , K 1 , V 1 ) \text{Attention}(Q_1, K_1, V_1) Attention(Q1,K1,V1)
    • 缓存: 将 K 1 K_1 K1 V 1 V_1 V1 存储到 KV 缓存中。
  3. 生成第 2 个词元 ( t = 2 t=2 t=2):
    • 输入是第 1 个生成的词元。
    • 模型为这个新词元计算其 Query ( Q 2 Q_2 Q2),Key ( K 2 K_2 K2),和 Value ( V 2 V_2 V2) 向量。
    • 从缓存中检索: 取出之前存储的 K 1 , V 1 K_1, V_1 K1,V1
    • 注意力计算: Q 2 Q_2 Q2 需要与所有历史词元的 Key 进行交互。此时,有效的 Keys 是 [ K 1 (cached) , K 2 (new) ] [K_1 \text{ (cached)}, K_2 \text{ (new)}] [K1 (cached),K2 (new)],有效的 Values 是 [ V 1 (cached) , V 2 (new) ] [V_1 \text{ (cached)}, V_2 \text{ (new)}] [V1 (cached),V2 (new)]
    • 缓存: 将新计算的 K 2 K_2 K2 V 2 V_2 V2 追加到 KV 缓存中。缓存现在包含 [ K 1 , K 2 ] [K_1, K_2] [K1,K2] [ V 1 , V 2 ] [V_1, V_2] [V1,V2]
  4. 生成第 i i i-个词元 ( t = i t=i t=i):
    • 输入是第 i − 1 i-1 i1 个生成的词元。
    • 模型为这个新词元计算其 Query ( Q i Q_i Qi),Key ( K i K_i Ki),和 Value ( V i V_i Vi) 向量。
    • 从缓存中检索: 取出之前存储的 [ K 1 , . . . , K i − 1 ] [K_1, ..., K_{i-1}] [K1,...,Ki1] [ V 1 , . . . , V i − 1 ] [V_1, ..., V_{i-1}] [V1,...,Vi1]
    • 注意力计算: Q i Q_i Qi [ K 1 , . . . , K i − 1 , K i ] [K_1, ..., K_{i-1}, K_i] [K1,...,Ki1,Ki] [ V 1 , . . . , V i − 1 , V i ] [V_1, ..., V_{i-1}, V_i] [V1,...,Vi1,Vi] 进行交互。
    • 缓存: 将新计算的 K i K_i Ki V i V_i Vi 追加到 KV 缓存中。

这个过程在每个 Decoder 层的自注意力模块中都会发生。

3. KV 缓存出现的位置

KV 缓存主要应用于 Transformer 推理阶段的以下注意力模块:

  1. Decoder 的 Masked Multi-Head Self-Attention 层:

    • 这是 KV 缓存最典型的应用场景。
    • 在自回归生成的每一步,当前生成词元的 Q Q Q 会与**所有先前已生成词元(其 K K K, V V V 已被缓存)以及当前词元自身(其 K K K, V V V 刚被计算)**进行注意力计算。
    • 缓存的是已处理过的目标序列词元 K K K V V V 向量。
  2. Decoder 的 Multi-Head Encoder-Decoder Attention (Cross-Attention) 层 (对于 Encoder-Decoder 模型如原始 Transformer, BART, T5):

    • 在这种注意力中,Query ( Q Q Q) 来自 Decoder 的前一子层输出。
    • Key ( K K K) 和 Value ( V V V) 来自 Encoder 的最终输出
    • 由于 Encoder 的输出在整个 Decoder 生成过程中是固定不变的,因此 Encoder 输出的 K K K V V V 向量只需要在 Decoder 开始生成第一个词元之前计算一次,然后就可以被视为一个静态的 KV 缓存,供 Decoder 的每一层、每一步生成时重复使用。这种情况下,“缓存” 更像是 “预计算和复用”。

Encoder-Only 模型 (如 BERT) 在进行非自回归任务 (如分类、NER) 时,通常一次性处理整个输入序列,不需要逐步生成,因此不直接使用这种动态增长的 KV 缓存。Decoder-Only 模型 (如 GPT 系列) 则严重依赖 KV 缓存进行高效的文本生成。

4. KV 缓存的优势与计算复杂度分析

4.1 不使用 KV 缓存的计算复杂度

假设生成长度为 L L L 的序列,隐藏维度为 d d d

  • t t t 步复杂度: O ( t ⋅ d 2 + t 2 ⋅ d ) O(t \cdot d^2 + t^2 \cdot d) O(td2+t2d)
  • 总复杂度: ∑ t = 1 L O ( t ⋅ d 2 + t 2 ⋅ d ) = O ( L 2 ⋅ d 2 + L 3 ⋅ d ) \sum_{t=1}^{L} O(t \cdot d^2 + t^2 \cdot d) = O(L^2 \cdot d^2 + L^3 \cdot d) t=1LO(td2+t2d)=O(L2d2+L3d)。对于长序列,近似为 O ( L 3 ⋅ d ) O(L^3 \cdot d) O(L3d)
4.2 使用 KV 缓存的计算复杂度
  • t t t 步复杂度: O ( d 2 + t ⋅ d ) O(d^2 + t \cdot d) O(d2+td) (仅为新词元计算 QKV,然后与历史 KV 交互)
  • 总复杂度: ∑ t = 1 L O ( d 2 + t ⋅ d ) = O ( L ⋅ d 2 + L 2 ⋅ d ) \sum_{t=1}^{L} O(d^2 + t \cdot d) = O(L \cdot d^2 + L^2 \cdot d) t=1LO(d2+td)=O(Ld2+L2d)
4.3 KV 缓存的其他优势
  • 显著减少计算量: 将复杂度从 O ( L 3 ⋅ d ) O(L^3 \cdot d) O(L3d) 级降低到 O ( L 2 ⋅ d ) O(L^2 \cdot d) O(L2d) 级,使长序列生成在实践中成为可能。
  • 大幅提升推理速度: 计算量的减少直接转化为推理时间的缩短。
  • 内存权衡: 需要额外的内存空间来存储这些 K K K V V V 向量。KV 缓存的空间复杂度约为 O ( L ⋅ d m o d e l ⋅ b ⋅ n l a y e r s ) O(L \cdot d_{model} \cdot b \cdot n_{layers}) O(Ldmodelbnlayers),或更细致地表示为 O ( L ⋅ d h e a d ⋅ n h e a d s ⋅ b ⋅ n l a y e r s ) O(L \cdot d_{head} \cdot n_{heads} \cdot b \cdot n_{layers}) O(Ldheadnheadsbnlayers)
    • L L L: 序列长度
    • d m o d e l d_{model} dmodel: 模型隐藏维度 ( d h e a d ⋅ n h e a d s d_{head} \cdot n_{heads} dheadnheads)
    • d h e a d d_{head} dhead: 每个注意力头的维度
    • n h e a d s n_{heads} nheads: 注意力头的数量
    • b b b: 批次大小 (batch_size)
    • n l a y e r s n_{layers} nlayers: 模型层数
  • 对于非常长的序列,KV 缓存本身也会变得很大,催生了如 Multi-Query Attention (MQA) 和 Grouped-Query Attention (GQA) 等技术来减小 KV 缓存的体积。

5. 实现细节

  • 数据结构: KV 缓存通常为每个 Decoder 层维护一组张量。这些张量的形状通常是 [batch_size, num_heads, current_sequence_length, head_dim]。通常会为 Key 和 Value 分别维护这样的张量,或者将它们堆叠在一个额外的维度上,例如 [2, batch_size, num_heads, current_sequence_length, head_dim]。在 Hugging Face Transformers 等库中,这通常表现为 past_key_values 的元组,每个元素对应一层的 K 和 V 缓存。
  • 动态扩展与预分配:
    • 在实践中,为了效率,可能会预先分配一个最大序列长度 L m a x L_{max} Lmax 的缓存空间,然后用一个指针或索引 (如 past_length) 跟踪当前实际填充到的长度。
    • current_sequence_length 增长时,新的 K , V K, V K,V 向量会被拼接到已缓存张量的相应维度上(通常是序列长度维度)。
  • 跨层传递: 在多层 Decoder 中,每一层的 KV 缓存是独立的。当模型生成下一个词元时,会将上一时间步所有层的 KV 缓存状态传递给当前时间步对应的层。

6. KV 缓存与掩码 (Masking) 的关系

  • KV 缓存与 Sequence Mask (Look-ahead Mask / Causal Mask) 紧密相关且协同工作。
  • 训练时,Sequence Mask 通过在注意力分数矩阵上添加一个上三角的负无穷矩阵,确保模型在预测第 i i i 个词元时,只能关注到 0 0 0 i i i 位置的词元,防止信息泄露。
  • 带 KV 缓存的推理时,这种 “只能看过去” 的特性是通过缓存的构建方式自然实现的。因为在生成第 i i i 个词元时,KV 缓存中只包含了 0 0 0 i − 1 i-1 i1 位置词元的 K K K V V V。当前词元 i i i Q Q Q 会与这些缓存的 K , V K, V K,V 以及自身新计算的 K , V K, V K,V 进行交互。模型物理上无法访问未来词元的 K , V K, V K,V,因为它们尚未被计算和缓存。
  • 因此,在推理时,显式的上三角掩码矩阵可能不再需要以训练时完全相同的方式构建,或者其作用由缓存机制和仅与当前及过去 Key/Value 交互的过程隐式完成。注意力计算简化为 Q i Q_i Qi [ K 1 , . . . , K i ] [K_1, ..., K_i] [K1,...,Ki] [ V 1 , . . . , V i ] [V_1, ..., V_i] [V1,...,Vi] 进行交互。

主流注意力机制变体与 KV 缓存

1. FlashAttention

  • 核心思想: 一种 IO 感知的精确注意力算法,通过**分块(Tiling)核函数融合(Kernel Fusion)**技术,将 QK^T 矩阵乘、Softmax 以及与 V 的乘积等操作合并为单一或少数几个 GPU 核函数。这显著减少了对 GPU 高带宽内存(HBM)的读写次数,将中间结果尽可能保留在更快的 SRAM 中。
  • 与 KV 缓存结合:
    • FlashAttention 在处理 KV 缓存时,可以按块(Tile)加载和访问 KV 缓存中的数据。
    • 新生成的 KV 对仅在缓存的尾部追加,FlashAttention 可以高效地处理这种动态增长的缓存,而无需重排整个缓存内容。它优化了使用这些缓存 K 和 V 进行注意力计算的过程。

2. Grouped Query Attention (GQA)

  • 核心思想: 一种折衷于多头注意力 (MHA) 和多查询注意力 (MQA) 的方案。它将查询头 (Query heads) 分成若干组,每组内的查询头共享同一份 Key 和 Value 投影。即 num_kv_heads 小于 num_query_heads,但大于1。
  • 缓存优化:
    • 每组查询头共享一对 K 和 V 向量,因此 KV 缓存的大小仅取决于 num_kv_heads
    • 缓存规模相对于 MHA 显著缩减(缩减比例为 num_query_heads / num_kv_heads),但通常比 MQA 提供更好的模型质量。

3. Multi-Query Attention (MQA)

  • 核心思想: 所有查询头共享单一的 Key 和 Value 投影。即 num_kv_heads = 1
  • 缓存影响:
    • KV 缓存的体积大幅减小,只需要为每层存储一个 K 和一个 V 张量(或者说,它们的维度对应于单个 KV 头)。
    • 显著降低了从内存加载 K 和 V 的带宽瓶颈,尤其在长序列生成时,内存带宽往往是主要瓶颈。

KV 缓存优化与压缩技术

1. 低精度存储 (Quantized KV Cache)

  • 方法: 将 KV 缓存中的浮点数(如 FP32 或 FP16)量化为较低精度的表示,如 INT8、INT4,甚至更低。在进行注意力计算时,这些量化后的值会被在线解量化(de-quantize)回浮点数。
  • 动态量化: 可以根据每层或每个数据块(Tile)的统计范围(如最大值、最小值)动态确定量化参数。
  • 优势: 显著减少 KV 缓存的内存占用,从而支持更长的上下文或更大的批次。

2. 块级缓存 (Block-wise Caching / PagedAttention)

  • 思想: 将逻辑上的连续序列在物理内存中划分为固定大小的非连续块(Pages)。KV 缓存不再需要一个巨大的连续内存区域,而是由这些小块组成。
  • 优势:
    • 更灵活的内存管理,减少内存碎片。
    • 可以更有效地处理不同长度序列的批处理(Batching)。
    • 支持非常长的上下文长度,因为物理内存可以按需分配给这些块。vLLM 中的 PagedAttention 是此技术的典型实现。

3. 稀疏近邻缓存 (Sparse Attention Cache / Sliding Window Attention with Cache)

  • 思路: 对于非常长的序列,并非所有历史 KV 对当前词元的贡献都一样大。可以只缓存一个固定大小的滑动窗口内的 KV,或者只缓存与当前查询最相关的(如通过某种稀疏化策略选择的)top-k KV。
  • 应用: 适用于需要处理极长文档但注意力可以集中的场景,如长文本摘要、检索增强生成。

4. 动态剪枝 (Adaptive Pruning / Eviction)

  • 方法: 根据 KV 对的“重要性”(例如,基于其注意力权重、访问频率或某种学习到的掩码)动态地从缓存中剪枝或驱逐贡献较低的 KV 对。
  • 实现: 在缓存达到容量上限时,优先保留更重要的 KV,丢弃不重要的,从而在有限的缓存空间内最大化效益。

主流大模型的 KV 缓存实现概览

1. GPT-4 与 GPT-3 系列 (OpenAI)

  • 架构: 多层 Decoder-Only Transformer。
  • 缓存接口: OpenAI API 在 completionchat.completion 调用中隐式维护 past_key_values(或等效机制)。返回的 past_key_values 通常是元组,每个元素对应一层,包含形状如 [2, batch_size, num_heads, seq_len, head_dim] 的张量 (2 代表 K 和 V)。
  • 预分配策略: 通常基于最大上下文长度预分配张量,利用指针或索引跟踪实际 past_length 来控制有效区域,避免频繁的内存重新分配。
  • 跨请求持久化: 在同一对话或会话中,可以通过传递 past_key_values 来增量填充缓存,支持高效的多轮对话或连续生成。

2. LLaMA 系列 (Meta)

  • 架构: Decoder-Only 结构,后续版本(如 LLaMA 2)开始支持 Grouped-Query Attention (GQA) 以优化 KV 缓存。
  • 缓存管理:
    • 实现上通常采用连续的内存块来存储所有层的 KV 值,以减少 GPU Kernel 调用的开销。
    • 内存对齐(contiguous buffer)以优化显存访问效率。
    • 支持动态批处理,可以将多个不同长度序列的 KV 缓存拼接到同一张量中,通过注意力掩码来处理不同序列的有效长度。
  • FlashAttention 集成: 很多基于 LLaMA 的实现(包括 Hugging Face Transformers)都支持或默认启用 FlashAttention 来加速注意力计算并减少显存占用。

3. Mistral 系列 (Mistral AI)

  • 架构: Decoder-Only,一个显著特点是其模型(如 Mistral 7B)采用了 Grouped-Query Attention (GQA),并且在更小的模型(如 Mixtral 的 MoE 架构中的专家模型)可能也采用类似 MQA/GQA 的高效注意力机制。Mistral 7B 使用 num_kv_heads=8 (对于32个查询头),而其 MoE 模型可能每个专家有更少的 KV 头。
  • KV 缓存策略:
    • 由于 GQA 的使用,KV 缓存大小得到显著优化。
    • 部分实现可能会结合低精度存储(如 8-bit 或 4-bit 量化)来进一步压缩 KV 缓存。
    • 内存对齐以满足硬件的高效访问要求。

推理引擎中的 KV 缓存工程化优化

1. DeepSpeed-Inference

DeepSpeed-Inference 在 KV 缓存管理和优化方面提供了诸多先进特性:

  • 1.1 存储结构与接口:
    • 内部维护与 Hugging Face Transformers past_key_values 兼容的缓存接口,但实际采用自研的高效数据结构来管理 KV 对。
    • 在 C++ API 层面,用户首次调用时传入完整上下文,DeepSpeed 会在内部初始化 KV 缓存并在后续调用中自动复用;即使用户传入了 layer_past,当前实现也可能基于内部管理机制运行。 [citeturn0search0]
  • 1.2 预分配与动态增长:
    • 初始化时,根据指定的最大序列长度 (max_seq_len) 一次性分配连续的 GPU 内存池,用于存放所有层、所有头的 KV 张量。
    • 生成新 Token 时,仅在内存池尾部追加新计算的 KV,通过指针 past_length 跟踪有效范围,避免了频繁的内存分配和数据迁移开销。 [citeturn0search3]
  • 1.3 跨请求持久化与复用:
    • 支持同一会话内的多次增量推理请求(multi-turn generation),复用首次调用分配的 KV 缓存。
  • 1.4 冷热分层调度与 ZeRO-Inference:
    • 在 ZeRO-Inference 模式下,KV 缓存可以进行分层存储:频繁访问的“热”数据保留在 GPU,较少访问的“冷”数据可以自动卸载 (Offload) 到 CPU 主存,甚至进一步 Spill 到 NVMe SSD。 [citeturn0search3]
    • 通过后台异步 I/O 线程管理冷热数据的迁移,对用户透明地扩展了有效上下文长度,同时兼顾延迟和成本。
  • 1.5 缓存压缩与量化:
    • KV 缓存可以与权重量化(如 INT8/INT4)结合使用。KV 缓存本身也可以被量化存储,在计算时在线解压,以进一步降低内存占用,HuggingFace 与 DeepSpeed 的示例中展示了结合权重量化可带来显著的吞吐提升。 [citeturn0search1]
  • 1.6 注意力机制与缓存结合:
    • FlashAttention 一体化内核: DeepSpeed 提供了基于 Triton 等实现的自研 Attention Fusion Kernel,将 QKV 投影、点积、Softmax 等操作合并,减少内存读写。KV 缓存以分块(tile/block)形式高效馈入此融合流水线。 [citeturn0search3]
    • MQA/GQA 兼容: 对模型采用的 MQA 或 GQA 类型透明兼容。缓存池会根据模型实际输出的 KV 张量形状(即 num_kv_heads)来分配内存,自然受益于 MQA/GQA 带来的缓存缩减。
  • 1.7 异步 I/O 与内存池:
    • 在 ZeRO Offload 模式下,构建统一的大页内存池(HugePage)并预留最大 KV 缓存空间。异步 I/O 任务负责将溢出的 KV 缓存页在不同存储层级间迁移,避免阻塞推理主线程,降低尾延迟。

2. TensorRT 与 CUDA Kernel Fusion

  • 专用插件: NVIDIA TensorRT 提供了如 MultiHeadAttention 等插件,可以内部高效管理 past_key_values。一些实现会提供专门的 TransformersKernel 来批量管理。
  • 内存管理: 利用统一大页内存池,减少 TLB (Translation Lookaside Buffer) misses 和内存碎片。
  • 融合内核: 将 QKV 投影、注意力计算等操作深度融合成单个或少数 CUDA Kernel,通常支持 INT8 等低精度计算,直接在 Kernel 内部处理 KV 缓存的读取和更新。

3. vLLM

  • PagedAttention: 核心优化技术,通过将 KV 缓存划分为非连续的物理内存块(Pages),实现了高效的内存共享和管理,显著提高了吞吐量并允许更长的上下文。
  • 分层调度: 实现了 Hot KV (GPU) 与 Cold KV (CPU/Disk) 的分层管理,但其主要创新在于 PagedAttention 对 GPU 内存的高效利用。
  • 动态批次与连续批处理 (Continuous Batching): 能够跨请求高效地合并处理,并动态调整批次,与 PagedAttention 结合能更好地复用和管理 KV 缓存。

4. FasterTransformer (NVIDIA)

  • 全 GPU 缓存管理: KV 缓存主要在 GPU 端进行管理,支持将多个请求(Batch)或多个 Beam Search 路径的 KV 张量进行合并以优化计算。
  • 自研 Buffer Manager: 实现高效的内存分配和复用策略,通常是一次性分配较大 Buffer,然后内部进行子块管理。
  • 融合内核: 大量使用自定义的 CUDA Kernel,融合了包括注意力、LayerNorm、激活函数在内的多个操作,并针对 Tensor Core 进行深度优化。Beam Search 相关的 KV 管理也深度融合。

5. ONNX Runtime

  • ORTTransformer 扩展: ONNX Runtime 提供了针对 Transformer 模型的优化扩展,支持 past_key_values 作为图输入/输出。
  • 内置 TensorCache: 部分执行提供程序 (Execution Provider) 可能包含内置的张量缓存机制,可以将 KV 缓存 Spill 到主机内存。
  • 图优化: 通过节点融合、常量折叠等图级别优化,间接提升包含 KV 缓存操作的模型的执行效率。

通用 KV 缓存工程策略总结

  • 热 vs 冷分层存储: 将频繁访问的 KV(通常是最近生成的)保留在高速缓存(GPU显存),较旧或访问频率较低的 KV 迁移到较慢但容量更大的存储(CPU内存、SSD)。
  • 异步预加载/写回: 使用后台线程在不同存储层级间异步地移动 KV 数据,避免阻塞主推理流程。
  • 统一内存池 & 大页内存: 预先分配一块大的、连续的(或逻辑上连续的,如通过 Paging 管理的)内存作为 KV 缓存池,并尽可能使用大页内存以减少地址翻译开销和内存碎片。
  • 选择合适的注意力变体: 采用 MQA 或 GQA 可以从根本上减少 KV 缓存的大小和带宽需求。
  • 量化: 对 KV 缓存本身进行低精度量化是节省内存的有效手段。
  • Kernel Fusion: 将与 KV 缓存交互的多个计算步骤融合成一个或少数几个 GPU Kernel,是提升性能的关键。

DeepSeek 模型中 KV 缓存的关键实现与优化策略深度解析

大语言模型 (LLM) 的推理效率在很大程度上取决于其处理和管理上下文信息的能力,其中键值 (KV) 缓存扮演着核心角色。DeepSeek Technologies 通过其 DeepSeek 系列模型,特别是 V2 和 V3 版本,展示了在 KV 缓存优化方面的卓越创新。本文将深度解析 DeepSeek 模型中 KV 缓存的关键实现机制与优化策略,探讨其如何通过多头潜在注意力 (MLA)、先进量化技术、精细化的缓存管理以及硬件协同设计,实现领先的性能和效率。

I. DeepSeek 模型中 KV 缓存简介

A. 大语言模型中高效 KV 缓存的必要性
在自回归大语言模型的推理过程中,键值 (KV) 缓存扮演着至关重要的角色。若无 KV 缓存,模型在生成每个新词元 (token) 时,都需要对所有先前生成的词元重新计算注意力,这将导致每个词元的计算复杂度随序列长度二次方增长,进而使得生成 N 个词元的总复杂度达到 O(N³) ¹。KV 缓存通过存储先前所有词元在注意力层产生的中间键 (K) 张量和值 (V) 张量来缓解这一问题。当生成新词元时,模型能够复用这些缓存的 K 和 V 张量,仅需为当前词元计算新的 K 和 V。这种机制在初始预填充 (prefill) 之后,将每个词元的生成复杂度降低至 O(N)(与序列长度成线性关系),从而使整体生成复杂度降至 O(N²) ¹。这一优化对于 LLM 处理长序列并在可接受的延迟内响应至关重要。然而,这种计算上的节省是以显著的内存消耗为代价的,因为 KV 缓存需要存储上下文中每个词元、每一层、每一个注意力头的张量数据 ¹。

KV 缓存不仅是一项速度优化,更是实现长上下文窗口 LLM 实际应用的关键推动因素。若无此机制,重新计算所有先前词元状态的计算成本将使得处理数千词元(如 DeepSeek 模型所支持的)的长序列在实践中变得不可行。正如 ¹ 所明确指出的,在没有缓存的情况下,由于每一步都涉及 O(N²) 的注意力计算,生成 N 个词元的成本为 O(N³);而有了缓存,总体成本则降至 O(N²)。这种复杂度的显著降低,使得处理长达数万词元的序列成为可能。

然而,KV 缓存的巨大内存占用(通常会超过模型参数本身的体积 ³)是驱动 DeepSeek 等公司开发高级压缩和管理技术的主要原因。这个所谓的“内存墙”问题 ⁴ 直接决定了在给定硬件上能够处理的最大上下文长度。例如,⁶ 指出,如果 DeepSeek-V3 使用标准的多头注意力 (MHA),其在处理 128k 词元序列时的 KV 缓存将需要高达 213.5 GB 的内存。这一数字往往超出了单个 GPU 的可用显存,使得未经优化的 KV 缓存成为长上下文处理的直接瓶颈,从而凸显了 DeepSeek 采用的内存节省策略的必要性。

B. DeepSeek KV 缓存优化的架构理念
DeepSeek 系列模型,包括 V2 和 V3 版本,其设计始终强调经济高效的训练和推理性能 ⁵。这一理念的核心组成部分便是对 KV 缓存的极致优化。DeepSeek V2 和 V3 采用了一种被称为“独特 KV 缓存 (unique KV cache)”的方法,旨在仅存储必要的键值对,从而最大限度地减少冗余和内存占用 ¹⁰。这一理念最突出的体现便是其多头潜在注意力 (Multi-Head Latent Attention, MLA) 机制。从 V2 到 V3 的演进过程展示了 DeepSeek 在这些缓存策略上的持续改进,不断解决性能瓶颈并增强内存管理能力 ¹¹。

早期对 DeepSeek V2/V3 中“独特 KV 缓存”的描述 ¹⁰,很可能指的就是其多头潜在注意力 (MLA) 机制所带来的效果。MLA 通过存储压缩后的潜在向量而非每个头完整的 K 和 V 张量,本质上创建了一种“独特”且压缩的表示,从而避免了传统 MHA 的冗余。如 ¹⁰ 所述,独特 KV 缓存“仅存储 Transformer 模型运算过程中产生的必要键值对”并“避免重复数据存储”。MLA 通过将多个键和值头压缩成每个词元一个较小的潜在向量 ⁶,精确地实现了这一目标,两者特性完美契合。

DeepSeek 对 KV 缓存优化的关注点不仅仅在于提升推理速度,更是一项战略性举措,旨在降低硬件门槛和运营成本,从而使强大的 LLM 技术更易于普及 ¹¹。例如,¹¹ 直接将优化的 KV 缓存与“更低的硬件需求(显存模块)”和“更高的能效”联系起来。¹³ 则强调了 DeepSeek 极具竞争力的 API 定价,这在一定程度上也得益于此类效率提升。这表明其技术选择背后蕴含着更广泛的战略考量。

II. 多头潜在注意力 (MLA):DeepSeek KV 缓存策略的核心

A. MLA 原理:低秩压缩与潜在向量表示
多头潜在注意力 (MLA) 是 DeepSeek 在 KV 缓存优化方面的核心创新,贯穿于 DeepSeek-V2 和 V3 模型的设计之中 ⁴。与传统注意力机制为每个注意力头缓存完整的高维 K 和 V 向量不同,MLA 采用了一种低秩压缩技术。它将 K 和 V 的信息压缩到一个远小于原始表示的共享“潜在”向量中 ⁶。这个潜在向量才是实际被缓存的内容。以 DeepSeek-V3 为例,词元嵌入被下投影 (down-projection) 到一个 512 维的潜在向量 ⁶。当需要进行注意力计算时,这个压缩的潜在向量可以被上投影 (up-projection) 回注意力头所需的高维空间 ⁶。这种方法极大地减少了 KV 缓存所需的内存。DeepSeek-V2 通过 MLA 将 KV 缓存大小相较于 DeepSeek 67B 减少了 93.3% ⁸。据估计,对于一个 128k 词元的序列,DeepSeek-V3 的 MLA 缓存大小约为 7.6 GB,而如果采用标准的 MHA,则可能需要 213.5 GB ⁶。

MLA 中的上投影步骤,虽然表面上增加了计算开销,但对于在积极压缩后仍保持模型的表达能力至关重要。这代表了一种深思熟虑的设计权衡:用注意力计算过程中(如果显式执行上投影)的更多计算换取内存占用和数据移动量的大幅减少 ¹⁸。¹⁸ 指出,MLA“采用上投影矩阵来增强表达能力,以额外的计算换取通信开销的降低”。同时,⁶ 详细描述了用于压缩的“KV Down”矩阵以及用于投影的“Key Up”和“Value Up”矩阵。这种对下投影和上投影的明确提及,突显了在压缩与维持模型性能之间的平衡。

“潜在向量”这一术语至关重要。正是这种压缩表示构成了基于 MLA 的 DeepSeek 模型中 KV 缓存的实际内容,这也是观察到的显著内存节省的直接来源 ⁴。⁶ 明确指出:“词元嵌入的压缩版本——这个 512 维的潜在向量——是每个词元唯一被缓存的向量。”这一点在 ⁴ 中得到重申,证实了缓存存储的是这些紧凑的潜在形式,而非完整的 K/V 对。

B. MLA 中的 c_t_KV 潜在向量与 k_t_R RoPE 组件
深入探究 DeepSeek-V3 MLA 中缓存元素的具体细节,该架构为每个词元主要存储两个组件:一个压缩的键值表示,记为 c t K V c_{t}^{KV} ctKV;以及一个与旋转位置编码 (Rotary Position Embedding, RoPE) 相关的独立组件 k t R k_{t}^{R} ktR ¹⁵。 c t K V c_{t}^{KV} ctKV 是对原始键和值信息的低秩联合压缩。根据 DataCrunch 对 DeepSeek-V3 论文 (arXiv:2412.19437) 的分析 ¹⁶,在 DeepSeek V3 中,这个缓存的压缩值组件 ( C v C_v Cv) 的维度是 512。而 k t R k_{t}^{R} ktR 组件的维度是 64,专门用于 RoPE。在注意力计算中使用的有效键维度 © 是通过将 C v C_v Cv 与 RoPE 嵌入相结合形成的,即 512+64=576。

在 DeepSeek-V3 的 MLA 中,将 RoPE 特定组件 ( k t R k_{t}^{R} ktR) 与主要内容潜在向量 ( c t K V c_{t}^{KV} ctKV) 分开并独立缓存,是一项精密的设计。这种解耦可能增强了位置编码的稳定性和精度,特别是对于极长的序列(高达 128K 词元),因为它允许 RoPE 的处理与主要内容压缩分离开来 ⁷。¹² 提到,标准的 RoPE 与 MLA 的压缩结合会导致“效率瓶颈”,促使 DeepSeek 使用“专用向量”来改进 RoPE。⁷(Martin Fowler 对 DeepSeek V3 论文的总结)指出:“改进的 RoPE 处理:V2 仅部分解耦了键,但 V3 扩展了这一概念,以实现更稳定的 128K 上下文。它们跟踪一个‘解耦的共享键’,以减少极长生成过程中的数值漂移。”这个“解耦的共享键”极有可能就是 k t R k_{t}^{R} ktR 组件。

有效键维度(例如,由 512 维的 c t K V c_{t}^{KV} ctKV 派生的值部分和 64 维的 k t R k_{t}^{R} ktR 构成的 576 维)的构建 ¹⁶,意味着查询向量与一个已经整合了位置信息和压缩内容的表示进行交互。这与将 RoPE 应用于完全上投影的高维键不同。¹⁶ 明确指出有效键维度 K/C 是 KaTeX parse error: Expected 'EOF', got '_' at position 17: …_v + \text{RoPE_̲dim}。这表明 RoPE 组件在主要注意力分数计算之前或作为其一部分,与潜在向量信息结合以形成键表示,这可能发生在压缩或部分投影的空间内。

C. “矩阵吸收”优化
MLA 的一项关键工程优化是“矩阵吸收”技巧 (matrix absorption trick) ¹⁶。该技术避免了在每次注意力计算期间显式地将压缩潜在向量上投影回其完整头维度的计算成本和内存带宽。取而代之的是,上投影矩阵(例如 W u k W_{uk} Wuk W u v W_{uv} Wuv)的权重被数学上“吸收”到注意力层中的其他矩阵中,例如查询投影矩阵或输出投影矩阵 ¹⁷。这使得核心的注意力计算(打分和值聚合)能够直接在压缩的潜在空间中进行,从而显著减少了开销 ¹⁶。

矩阵吸收对于 MLA 实现高算术强度 (arithmetic intensity,即每字节数据移动的浮点运算次数) 至关重要。通过将主要的注意力计算保持在压缩空间内,它相对于执行的浮点运算次数,极大地减少了进出内存的数据移动量 ¹⁶。DataCrunch 的分析 ¹⁶ 明确指出,通过权重吸收,“查询被投影到压缩维度 C,并且注意力计算(打分和输出聚合)发生在这个压缩空间中。”他们的分析表3显示,由于内存带宽使用显著降低,MLA 注意力的 FLOPs/Byte 比率要高得多,这是直接在较小的压缩数据上操作的结果。

该技术有效地使得 MLA 在核心注意力步骤中表现得像一个多查询注意力 (MQA) 系统,其中所有查询头都关注一个单一的、共享的(但由于初始压缩和定制投影而信息丰富)从潜在向量派生出的键值表示 ¹⁶。¹⁷ 指出:“每个查询头实际上都关注相同的键和值,这意味着组头大小为一。”¹⁶ 也呼应了这一点,解释说由于权重吸收,MLA 可以被视为拥有一个由所有查询头共享的单一键值头。

D. 与旋转位置编码 (RoPE) 的交互
RoPE 对于向 Transformer 注入位置信息至关重要。DeepSeek V2 和 V3 特别改进了 RoPE 与 MLA 的集成,以确保效率和稳定性,尤其是在 MLA 的压缩和长上下文场景下。这促成了一种“解耦 RoPE (decoupled RoPE)”策略 ¹²。如第 II.B 节所述,DeepSeek-V3 在主要潜在内容向量 c t K V c_{t}^{KV} ctKV(与 512 维值组件相关)之外,还缓存了一个独特的 RoPE 相关组件 k t R k_{t}^{R} ktR(维度 64)⁷。这个 k t R k_{t}^{R} ktR 与从 c t K V c_{t}^{KV} ctKV 派生的信息结合,形成用于注意力计算的有效键表示(维度 576)。这种“解耦共享键”方法有助于减少在极长的生成序列中的数值漂移 ⁷。

DeepSeek MLA 中 RoPE 处理方式的演进(从 V2 中的部分解耦到 V3 中更彻底的“解耦共享键” k t R k_{t}^{R} ktR)是一项必要的调整,旨在实现对极长上下文(128K 词元)的稳定和准确处理。当与积极的潜在向量压缩简单结合时,标准的 RoPE 应用可能会遭受数值不稳定或成为效率瓶颈的问题 ⁷。¹² 明确提到标准的 RoPE 与 MLA 压缩结合“造成了效率瓶颈”。⁷ (Martin Fowler 的总结) 强调 V3 的“解耦共享键”专门用于“减少极长生成中的数值漂移”。这清晰地展示了针对长上下文稳定性问题所进行的逐步优化和解决方案的演进。

E. 对比分析:MLA 与 MHA、MQA、GQA 在 DeepSeek 背景下的比较
与 MHA、MQA 和 GQA 相比,MLA 提供了一种独特的 KV 缓存缩减方法 ⁶。

  • MHA (Multi-Head Attention): 为每个头缓存完整的 K 和 V 向量,导致 KV 缓存非常大(例如,DeepSeek-V3 若使用 MHA 处理 128k 词元序列,KV 缓存将需要 213.5 GB ⁶)。
  • MQA (Multi-Query Attention): 所有查询头共享单个 K 和 V 头,极大地减小了缓存大小,但可能限制了表达能力。
  • GQA (Grouped-Query Attention): 一种折衷方案,其中几组查询头共享 K 和 V 头,在 MHA 和 MQA 之间取得了平衡。
  • MLA (Multi-Head Latent Attention): 通过将所有头的 K 和 V 信息压缩到一个共享的低维潜在向量中来减少缓存 ⁶。DeepSeek-V2 的 MLA 使其 KV 缓存相较于其 67B 参数的 MHA 前身减少了 93.3% ⁸。对于 DeepSeek V3,MLA 的 KV 缓存大约为每词元 70 KB (BF16 精度),显著小于使用 GQA 的模型,如 Qwen-2.5 (每词元 327 KB) 和 LLaMA-3.1 405B (每词元 516 KB) ⁴。DataCrunch 的博客分析 ¹⁶ 估计,DeepSeek V3 的 MLA KV 缓存内存占用比等效 MHA 实现小约 60 倍,比等效 GQA 实现小约 12 倍。此外,有观点认为,在相同的 KV 缓存开销下,MLA 比 GQA 具有更强的表达能力 ¹⁷。

核心区别在于 KV 缓存缩减的机制:MQA/GQA 通过减少存储的不同 K/V 头投影的数量来实现,而 MLA 通过潜在压缩来减少每个词元存储的 K/V 信息的维度,同时通过上投影(或吸收投影)在名义上为所有原始查询头保留了独特的信息路径。这种方法的差异解释了为何 MLA 在相似缓存大小下可能具有更高的表达能力 ¹⁷。¹⁷ 将 MLA 的学习型上投影(允许每个 Q 头派生其特定的 K/V)与 GQA 的选择器矩阵(严格共享)进行了对比。¹⁸ 引用了一篇理论证明 MLA 在同等缓存开销下比 GQA 更具表达能力的论文。

MLA 一个重要但常被低估的优势是,在预填充阶段计算 KV 缓存本身(而不仅仅是存储它)所需的 FLOPs 和内存带宽显著减少。在这方面,对于 DeepSeek V3,MLA 比 GQA 效率高约 12 倍,比 MHA 效率高约 64 倍 ¹⁶。这是因为 MLA 为每个词元计算一个小的潜在向量,而不是多个较大的 K 和 V 向量。DataCrunch 的分析 ¹⁶ 明确计算并列出了 KV 缓存计算的这些节省。这种在预填充期间的效率对于减少长提示的首次词元生成时间至关重要。

表1: DeepSeek 背景下注意力机制对比

特性MHA (Multi-Head Attention)MQA (Multi-Query Attention)GQA (Grouped-Query Attention)MLA (DeepSeek V2/V3)
KV 存储机制每头独立的 K, V 向量所有 Q 头共享单 K, V 头Q 头分组共享 K, V 头共享的低维潜在向量 (例如 c t K V c_{t}^{KV} ctKV, k t R k_{t}^{R} ktR)
每词元 KV 缓存大小 (示例)巨大 (例如 DeepSeek V3 MHA 约 4MB @BF16 ⁶)显著减小中等极小 (例如 DeepSeek V3 MLA 约 70KB @BF16 ⁴)
头共享策略无共享完全共享分组共享所有 Q 头通过潜在向量间接共享压缩信息,并通过(吸收的)上投影获得特异性
关键表达能力潜力有限中等高,据称在同等缓存下优于 GQA ¹⁷
RoPE 集成复杂度标准标准标准更复杂,需要解耦 RoPE (例如 k t R k_{t}^{R} ktR) 以适应压缩和长上下文 ⁷
DeepSeek 中的主要优势(基线对比)(理论上更节省)(平衡方案)极低的内存占用,支持超长上下文,预填充阶段 KV 计算高效,同时通过潜在向量和上投影保持高表达能力 ⁶

III. 先进注意力机制与 MLA KV 缓存的集成

A. 借鉴 FlashAttention 原理优化 MLA:FlashMLA
FlashMLA 是一款针对 NVIDIA Hopper GPU 优化的 MLA 解码核心 ²¹。它将 FlashAttention 的核心原理——I/O 感知(通过融合操作和利用 SRAM 减少 HBM 访问)、核心融合以及高效的任务划分——直接应用于 MLA 的压缩潜在向量 ²¹。FlashAttention 通过将注意力计算分块以适应 GPU SRAM 并融合多个核心操作来减少内存 I/O。FlashMLA 旨在最大化内存带宽利用率和计算吞吐量 ²³。

FlashMLA 不仅仅是 MLA 的一种实现,更是一种协同优化的解决方案,它将 FlashAttention 的核心思想应用于 MLA 的特定结构(压缩的 c t K V c_{t}^{KV} ctKV k t R k_{t}^{R} ktR)。这意味着标准的 FlashAttention 可能无法直接在 MLA 上达到最佳效果,需要进行相应调整。²² 指出 FlashMLA “融合了 FlashAttention 的优化技术”。²¹ 讨论了 FlashAttention 如何在批处理大小和查询长度维度上并行化,这在推理(查询长度通常为1)场景中有所不同。与 FlashAttention 相关的 Flash-Decoding 技术增加了对 K/V 序列长度的并行维度。FlashMLA 很可能借鉴了这些思想,以在潜在向量上高效操作,并有效处理特定的上投影/吸收步骤。²¹ 证实了 FlashMLA 直接在压缩向量上操作。

FlashMLA 的开发突显了硬件-软件协同设计的趋势,其中算法创新 (MLA) 与针对特定硬件 (Hopper GPU) 的核心级优化紧密耦合,以实现最佳性能 ⁵。²³ 明确称 FlashMLA 为“专为 NVIDIA Hopper GPU 量身定制的高效解码核心”。²⁵ 强调了其 Hopper 优化。⁵(《DeepSeek-V3 洞察》)通常将硬件感知的模型协同设计作为 DeepSeek 的一项关键原则。

B. MLA Kernel 中大头维度的处理
MLA 的一个特性是其有效头维度较大(例如,查询/键为 576,值 为 512 ¹⁶),这在诸如 FlashMLA 和 TileLang 等核心实现中带来了挑战 ²²。为了高效管理这些大维度,采用了特定的调度策略(例如,将 Q@K 计算分配给单个 warpgroup)和内存优化技术(例如,共享内存置换 (shared memory swizzling) 以避免 bank冲突,以及使用 TMA 进行数据移动的 warp 专业化 (warp specialization))²²。

MLA 中的“大头维度”是 RoPE 组件 ( k t R k_{t}^{R} ktR,维度 64) 与压缩 KV 潜能 ( c t K V c_{t}^{KV} ctKV,维度 512 用于值,用于派生键部分) 连接形成查询所交互的有效键表示 (维度 576) 的结果 ¹⁶。这与传统 MHA 不同,后者的头维度通常更小且统一。²² 指出“查询和键的头维度为 576 (512 + 64),而值的头维度为 512”。这直接关联到前面讨论的 c t K V c_{t}^{KV} ctKV k t R k_{t}^{R} ktR 的结构。

由于这些大的、可能非标准的头维度,共享内存置换和 warp 专业化等技术对于 MLA 变得更加关键,以避免 bank 冲突并在 SM 内最大化数据重用 ²²。²² 在优化 MLA 的背景下解释了这些技术。大的、连续的数据访问(如大头维度所暗示的)是共享内存优化的主要候选对象,以改善局部性并减少全局内存流量。

C. 性能影响:吞吐量与延迟
集成了 MLA 和 FP8 的 vLLM 显示出高达 3 倍的吞吐量提升和 10 倍的显存容量提升 ¹⁹。DataCrunch 的分析 ¹⁶ 表明,MLA 的 KV 缓存计算在 FLOPs 和内存带宽方面比 GQA 快约 12 倍。然而,在低 QPS (每秒查询数) 场景下,与 MHA 相比,MLA 可能具有较高的 TTFT (首个词元生成时间),但在持续负载下具有更好的 TPOT (每个输出词元的时间) ¹⁹。

MLA 在 TTFT 和 TPOT 之间的权衡 ¹⁹ 表明,对于单个短请求,MLA 的投影/吸收的初始开销可能较为明显,但由于其卓越的内存处理能力和持续吞吐量,其效率在批处理或长序列生成中表现突出。这些资料明确指出,在低 QPS 下,MHA 在 TTFT 方面优于 MLA,但 MLA 的 TPOT 更佳。这表明 MLA 存在一个初始设置成本,该成本在较长序列或较大批次中得到摊销。

MLA 的性能可能受到底层硬件 (GPU vs CPU) 的显著影响。虽然在 GPU 上表现优异,但从潜在向量计算 K/V 投影的额外计算会显著减慢 CPU 推理速度 ²⁶。²⁶ 中的用户评论提到:“虽然它使 KV 缓存更小,但在每个推理步骤中,它也为所有先前的词元引入了从缓存的潜在表示中计算 K 和 V 向量的额外开销。虽然这对 GPU 不是问题,但 CPU 无法承受这种额外的负载,并将推理速度降低到爬行状态。”这突显了一种依赖于硬件的性能特征。

IV. 精度工程:DeepSeek KV 缓存的量化

A. DeepSeek 模型量化概述
DeepSeek 广泛采用量化技术,特别是 FP8,不仅用于权重,还用于激活值,并可能直接应用于 KV 缓存本身 ⁴。这是其实现内存效率和利用现代硬件(如 NVIDIA Hopper)能力的关键策略。值得注意的是,DeepSeek-V3 被描述为“原生支持 FP8 (already in FP8)” ²⁸,这意味着 FP8 是其训练和推理的固有精度。

DeepSeek 在训练期间就使用 FP8 ⁴,这是一项重大的创新。这使得模型从一开始就针对 FP8 精度进行了优化,与训练后量化相比,在 KV 缓存和推理中使用 FP8 时可能带来更好的精度。²⁷ 强调了 FP8 训练的新颖性。⁴ 提到 DeepSeek-V3 是首批利用 FP8 进行训练的开源大型模型之一。这意味着模型参数和激活从一开始就具有“FP8 感知”能力。

“DeepSeek V3 原生支持 FP8” ²⁸ 的表述强烈暗示 KV 缓存本身(即存储的潜在向量 c t K V c_{t}^{KV} ctKV k t R k_{t}^{R} ktR)在 V3 中很可能默认以 FP8 格式存储,从而提供最大的内存节省。²⁸ 明确建议在 DeepSeek V3 上不要使用 --kv-cache-dtype fp8 参数,因为它已经是 FP8。⁴ 提到“缓存的激活以…FP8 格式存储”以及“对于推理,KV 缓存…传统上消耗大量内存。DeepSeek-V3 的 MLA 将…压缩成一个较小的潜在向量…只需要缓存这个紧凑的潜在向量。”综合来看,这强烈表明缓存的潜在向量是 FP8 格式。

B. KV 缓存的 FP8 实现
关于具体的 FP8 格式,SGLang 文档 ²⁸ 提到了 W8A8 FP8 和“KV 缓存 FP8 量化”。对于逐块 FP8 (block-wise FP8),激活值使用 E4M3 格式,并采用逐词元、每128通道的子向量尺度进行在线转换;权重则使用逐128x128块的量化 ¹⁴。DeepSeek-V3 对激活值统一使用 E4M3 格式 ¹⁴。缓存的激活值(如果 KV 缓存被视为前一步的激活值,则与之相关)以 FP8 格式存储 ⁴。

DeepSeek 的细粒度量化(激活值为 1x128 切片,权重为 128x128 块 ⁴)对于减轻 FP8 带来的精度损失至关重要。这允许更具适应性的缩放因子,更好地处理异常值,并更充分地利用 FP8 有限的动态范围 ¹⁴。²⁷ 讨论了 FP8 中的分辨率误差和截断误差,以及较小的桶(更细的粒度)如何能带来更好的分辨率,但对异常值的截断更差,而较大的桶则相反。DeepSeek 的切片/块级方法是在两者之间寻求平衡。¹⁴ 明确指出这种粒度允许更好地处理异常值。

“在线量化” ¹⁴(在训练/推理过程中为每个切片/块动态计算缩放因子)比静态量化更具适应性,并简化了框架。这将直接应用于 KV 缓存潜在向量的量化。如果潜在向量是前一层的激活,它们在写入缓存之前会经历这种在线量化。

C. 量化对潜在向量存储和检索的影响
将潜在向量(例如 c t K V c_{t}^{KV} ctKV, k t R k_{t}^{R} ktR)量化到 FP8,会在 MLA 已实现的压缩基础上进一步减少其内存占用。例如,如果 c t K V c_{t}^{KV} ctKV 是 512 维,FP16 精度下每个词元每层需要 1024 字节,而 FP8 则仅需 512 字节。这种减少直接影响了 GPU HBM 中可以存储的词元数量。由于数据移动量减少,检索速度也更快。⁴ 给出 DeepSeek-V3 (MLA) 的 KV 缓存大小为每词元 70.272 KB(推测为 BF16 或混合精度,因为根据 ⁵,输入/输出为 BF16),而 FP8 将使缓存部分的这一数值减半。

MLA 和 FP8 量化的协同作用是实现极致内存压缩的强大组合。MLA 减少了需要存储的值的数量(例如,根据 ⁶,从约 14k 个值/头减少到 512 个潜在向量维度)。然后,与 FP16/BF16 相比,FP8 将这 512 个值的存储空间减半。这种乘数效应是处理极长上下文的关键。

激活值/KV 缓存的 FP8 格式选择(E4M3 vs E5M2)至关重要。根据 ¹⁴,DeepSeek 对激活值使用 E4M3,这种格式在给定的指数位数下提供更宽的动态范围,更适合表示幅度变化的激活值。虽然并非所有来源都明确说明 KV 缓存使用此格式,但 ²⁸ 在逐块 FP8 中提到了激活值的 E4M3 格式。¹⁴ 确认 V3 中激活值统一使用 E4M3。如果潜在向量被视为激活值,则此规则适用。选择 E4M3 而非通常用于权重的 E5M2,反映了激活值与权重的不同统计特性。

表2: DeepSeek 模型中 KV 缓存量化

缓存组件假设基础精度量化后精度 (示例)每词元大小缩减 (示例)KV 缓存总体积影响 (定性/示例)
潜在向量 c t K V c_{t}^{KV} ctKVBF16FP8 (E4M3)约 2 倍 (BF16 -> FP8)显著减少。例如,若 c t K V c_{t}^{KV} ctKV (512维) + k t R k_{t}^{R} ktR (64维) 共 576 维,BF16 需 1152 字节,FP8 需 576 字节。结合 MLA 本身的压缩,整体缓存远小于 MHA/GQA。DeepSeek V3 MLA 每词元缓存约 70KB (BF16) ⁴,FP8 化后此部分可进一步减半。
RoPE 组件 k t R k_{t}^{R} ktRBF16FP8 (E4M3)约 2 倍 (BF16 -> FP8)同上。
整体 KV 缓存MHA (BF16)MLA + FP8>28 倍 (MHA -> MLA FP8, 结合 ¹⁶ 的 MHA vs MLA 约 60 倍,其中一部分是维度减少,另一部分是精度降低;若仅考虑精度,则为 2 倍。若从 213.5GB MHA ⁶ 到 7.6GB MLA ⁶ 再到约 3.8GB MLA FP8,则是约 56 倍)极大减少。从 MHA 的数百 GB (例如 V3@128k 序列 213.5GB ⁶) 降至数 GB (例如 MLA@128k 序列 7.6GB ⁶,FP8 后可能更低至约 3.8GB)。

V. 先进的 KV 缓存管理与调度技术

A. 块级与分页 KV 缓存架构

  1. PagedAttention (例如 vLLM 中) 与 DeepSeek MLA 的结合
    PagedAttention,如 vLLM ²⁹ 中的实现,以非连续内存块(页)的形式管理 KV 缓存。这种机制允许灵活的内存管理,减少碎片并实现高效共享。对于 DeepSeek 的 MLA,压缩后的潜在向量( c t K V c_{t}^{KV} ctKV 以及可能的 k t R k_{t}^{R} ktR 或它们的有效组合)将存储在这些页/块内 ²⁰。vLLM 的发布版本显示已集成 FlashMLA 以及支持分块预填充 (chunked prefill) 的 MLA ³²。

PagedAttention 的块式管理特别适用于 MLA 的压缩潜在向量,因为即使每个词元的向量很小,长序列仍然会累积大量的总缓存。分页允许有效地管理这个大型缓存,而不需要巨大的连续内存区域。MLA 将每个词元的缓存大小减小 ⁶。PagedAttention ²⁹ 以块的形式管理内存,避免了碎片。两者的结合意味着,即使对于非常长的序列,MLA 产生的总缓存(尽管每个词元更小)也可以被处理,而没有严格的连续性要求,否则这可能成为瓶颈。

PagedAttention 中的“块”指的是存储一定数量词元(例如,³¹ 中的 BLOCK_SIZE)的 KV 数据的内存块。对于 MLA,这样一个块将存储 BLOCK_SIZE 个词元的 c t K V c_{t}^{KV} ctKV(以及 k t R k_{t}^{R} ktR 或有效键)。

  1. 理解 FlashMLA 的 “64-block chunks”
    FlashMLA 引入了一种“分页 KV 缓存(64 块组块)(64-block chunks)” ²³。术语“64 块组块”很可能指的是 FlashMLA 核心为处理数据而组织或分组的方式,可能与 GPU 执行配置(例如,线程块或 warp 的数量)有关。此处“块”的确切定义(单个潜在向量、多个向量或元素)以及数字“64”量化的是什么(64 个这样的块,或 64 个元素/词元的块)在现有资料中并未完全阐明,但这暗示了一种结构化的方法来管理 MLA 的潜在向量,以便在 Hopper GPU 上高效执行核心。

FlashMLA 中的“64 块组块” ²³ 很可能指的是一种针对 Hopper 架构优化的内存布局或处理粒度,可能与线程块调度或共享内存容量对齐,以最大化 MLA 操作的吞吐量。这是一种核心级别的内存组织策略。FlashAttention 原则涉及为 SRAM 进行分块。“64 块组块”听起来像是一种这样的分块策略。²³ 提到 FlashMLA 利用 Hopper 的带宽和 TFLOPs 并处理可变长度序列。这种分块将有助于在核心内高效管理此类序列的内存。

FlashMLA 中的这种分页结构,结合 MLA 的压缩,是通过将(已经很小的)潜在向量组织成 GPU 可管理的组块,从而高效处理可变长度序列的关键 ²⁵。²⁵ 指出,分页 KV 缓存(64 块组块)有助于处理可变长度序列并保持数据有组织。这表明“组块”是可以灵活分配/处理的内存单元。

  1. 分块前缀缓存策略
    SGLang 实现了一种“分块前缀缓存 (Chunked Prefix Cache)”优化,通过将前缀缓存切割成块,用 MHA 处理它们,然后合并状态来提高吞吐量。这对于长序列的分块预填充非常有益 ²⁸。vLLM 也支持“带分块预填充的 MLA” ³²。

分块前缀缓存允许在预填充期间更好地利用计算资源,方法是将可能非常长的共享前缀分解为可并行或流水线处理的可管理单元。²⁸ 提到用 MHA 处理块并合并。这暗示着将一个大任务分解为更小的、可能并行的任务。“分块预填充” ³² 表明分段处理初始提示。

这种技术很可能通过将这些块作为页面的集合来管理,与分页 KV 缓存系统交互,从而允许高效存储和检索常见的序列开头。如果前缀是分块的,并且 KV 缓存是分页的,那么前缀缓存的每个块自然会映射到基础 PagedAttention 系统中的一组页面。这似乎是一种合乎逻辑的协同作用。

  1. DeepSeek V3 的 “联合 KV 存储”:概念与集成
    DeepSeek V3 引入了“联合 KV 存储 (Joint KV Storage)”,其中压缩的键和值被合并到一个共享的压缩表示中,这与 V2 将它们分开存储不同 ⁷。这进一步减少了内存流量,尤其是在多节点推理中。

“联合 KV 存储”很可能意味着用于重建 K 和 V(或它们的潜在版本)的信息被更紧密地打包在一起,可能打包到单个潜在向量 c t K V c_{t}^{KV} ctKV 中,有效 K(带 RoPE)和有效 V 都从该向量派生。这比仅仅独立压缩 K 和 V 更进了一步。⁷ 指出 V3“将它们合并到一个共享的压缩表示中”。这暗示了 K 和 V 信息的单一来源向量,而不是两个独立的压缩向量。

与 PagedAttention 的协调:即使在 MLA 的逻辑层面存在“联合 KV 存储”,当与像 vLLM 的 PagedAttention(期望独立的 K 和 V 缓存输入 ³¹)这样的系统接口时,必要的 K 和 V 组件将从这个联合表示中派生出来,然后分别存储到 PagedAttention 的独立 K 块和 V 块中 ³¹。“联合”方面指的是压缩存储格式,而不一定意味着 K 和 V 在注意力计算本身中不再是不同的实体。PagedAttention 核心被构建为消耗独立的 K 和 V 指针 ³¹。为了兼容性,即使 DeepSeek 的 MLA 具有更统一的内部潜在表示,它也需要为这类核心暴露或计算不同的 K 和 V 组件。³¹ 探讨了这种协调。

B. 缓存分层、淘汰与持久化

  1. DeepSeek V3 的 “分层自适应缓存”
    DeepSeek V3 实现了一种“分层自适应缓存 (Layer-Wise Adaptive Cache)”,其中在较深层中会修剪较旧的 KV 条目 ⁷。这有助于管理极长上下文(128K)的内存。

此策略基于这样一种观察:并非所有来自早期词元的信息在深度 Transformer 的所有层中都保持同等重要性。较深的层可能更关注更抽象或更近期的信息。(这是 LLM 研究中的一个常见假设,尽管在资料中没有明确说明)。在“较深层修剪较旧的 KV 条目” ⁷ 暗示了信息重要性的层级结构。如果所有过去的词元在所有层中都同等重要,那么这种修剪将是有害的。这表明对跨层信息流和相关性有隐式理解。

这是一种针对深度维度的“有损”缓存压缩/淘汰形式,与逐词元压缩 (MLA) 或简单的截断/滑动窗口形成对比。它是自适应的,因为修剪发生在较深的层。这种淘汰是层级的,并适应深度。这比全局 FIFO 或截断更为精细。³⁴ (MiniCache) 讨论了类似的跨层 KV 缓存压缩,基于较深层中状态的相似性,尽管它并非 DeepSeek 特有,但表明该领域正在探索这一点。

  1. 基于磁盘的前缀缓存 (DeepSeek API)
    DeepSeek API 默认使用“磁盘上下文缓存技术 (Context Caching on Disk Technology)” ³⁵。如果后续请求与先前请求具有重叠前缀,则重叠部分将从此磁盘缓存中获取(称为“缓存命中”)。该缓存使用 64 个词元作为存储单元;少于 64 个词元的内容不会被缓存。这是一个“尽力而为”的系统。

这种磁盘缓存主要用于请求间的前缀共享,而不是在单个长推理过程中 GPU/CPU 内存已满时用于卸载活动的 KV 缓存 ³⁵。它是为了减少不同 API 调用之间针对常见输入的冗余预填充计算。³⁵ 明确澄清:“在两个请求之间,只有重复的前缀部分才能触发‘缓存命中’”,并且没有提到它用于卸载活动的模型 KV 缓存。

64 词元的粒度 ³⁵ 表明在缓存开销和命中率之间进行了权衡。缓存非常短的前缀可能会导致过多效用较低的小缓存条目。存储和索引非常小的数据块可能效率低下。像 64 词元这样的最小大小确保了缓存的前缀足够大,以便在发生命中时提供有意义的计算节省。

  1. 淘汰策略 (例如截断、滑动窗口)
    KV 缓存管理中的一般挑战包括缓存大小超出内存。诸如截断或滑动窗口之类的技术被提及作为解决方案 ²。DeepSeek V2/V3 的“独特 KV 缓存”也需要诸如淘汰策略之类的缓存管理策略来防止内存溢出 ¹⁰。

尽管 DeepSeek 拥有诸如分层自适应缓存之类的高级技术,但对更基本的淘汰策略(截断、滑动窗口)的需求仍然存在,尤其是在处理极长序列或内存受限的环境中,或者作为后备方案。² 将这些作为缓存大小管理的一般解决方案提及。¹⁰ 明确指出,即使是 DeepSeek 的独特/MLA 缓存也需要淘汰策略。这暗示了一种多层次的缓存控制方法。

C. KV 缓存的异步 I/O 与预取
DeepSeek 的基础设施包括专为异步随机读取设计的 3FS (Fire-Flyer File System),它使用直接 I/O 和 RDMA,对数据加载很有用 ³⁶。虽然 3FS 更侧重于训练数据,但异步 I/O 的原理是相关的。AIBrix 提供了一个具有异步元数据更新的分布式 KV 缓存 ³⁷。最近的研究 ³⁰ 提出了将 KV 缓存异步预取到 GPU L2 缓存中,以隐藏 HBM 延迟,实现计算与加载的重叠,这与 vLLM 的分页 KV 缓存以及 MLA 的潜在向量兼容。

将 KV 缓存块/页(尤其是压缩的 MLA 潜在向量)异步预取到 GPU L2 或 SRAM 中,是通过隐藏 HBM 访问延迟,使内存密集型注意力操作表现得更像计算密集型操作的关键策略 ³⁰。³⁰ 明确指出目标是通过预取到 L2“在计算周期内隐藏 HBM 访问延迟”。这直接解决了推理的内存密集型特性。³⁸ 确认这很可能会为 MLA 预取压缩的潜在向量。

在分布式或分层存储场景中,使用 RDMA(例如,在 3FS ³⁶ 中,或使用 SmartNIC 从存储器传输 KV 缓存 ³)可以显著减少移动 KV 缓存数据的 CPU 开销和延迟。³⁶ 提到 3FS 使用 RDMA。³ 描述了一个工作流程,其中 SmartNIC 使用 RDMA 将 KV 缓存从存储器提取到加速器,从而绕过 CPU 参与数据传输。

D. DeepSeek V3 中的动态缓存优化
DeepSeek V3 引入了几项动态 MLA 改进 ⁷:

  • 动态低秩投影 (Dynamic Low-Rank Projection): 根据序列长度调整 KV 压缩强度(短序列压缩较少,长序列压缩较多)。
  • 自适应查询压缩 (Adaptive Query Compression): 在不同层深度缩放查询维度(早期层使用较高维度,较深层更积极压缩)。

这些动态调整表明对处理不同阶段(序列长度、层深度)信息需求的深入理解。它不是一种“一刀切”的压缩方式,而是适应上下文进行调整。“根据序列长度调整…”和“在不同层深度自适应缩放…” ⁷ 是自适应行为的明确表述。这意味着模型/系统可以动态改变压缩方式,以优化保真度/内存的权衡。

“自适应查询压缩”旨在节省较深层的激活内存 ⁷,虽然不直接作用于 KV 缓存,但通过释放资源或减少带宽争用,可以减少整体内存压力,并间接有益于缓存性能。⁷ 指出它“节省激活内存”。较少的激活内存意味着可能有更多的 HBM 带宽可用于 KV 缓存操作,或者为缓存本身提供更多空间。

E. KV 缓存效率的调度与并行策略
请求调度程序可以通过将具有匹配前缀的请求发送到包含缓存的服务器来促进 KV 复用 ³⁹。SGLang 中用于 MLA 的数据并行 (DP) 注意力消除了跨 TP 设备的 KV 缓存复制,从而减少了内存开销 ²⁸。然而,对于 MLA,由于潜在向量在头部之间共享,TP 无法对其进行分片,因此如果不使用 DP 注意力,KV 缓存会在 TP rank 之间复制 ²⁸。

MLA 和张量并行 (TP) 之间的交互是微妙的。由于 MLA 的潜在向量固有地由所有头共享(对于潜在缓存本身,head_num=1 ⁴⁰),因此标准 TP 沿头维度拆分 KV 缓存是不可行的。这使得 MLA KV 缓存必须在 TP rank 之间复制 ³⁹。³⁹ 明确指出“TP 无法分片潜在向量”并且“每个 TP Rank 存储 KV 缓存的相同副本”。⁴⁰ 解释说 MLA 的 kvcache 的 head_num 为 1,使其无法被 TP 拆分。

因此,DP 注意力对于 TP 设置中的 MLA 至关重要,以避免这种缓存复制并节省内存 ²⁸。它拆分请求,不同请求的潜在缓存存储在不同的 GPU 上。²⁸ 都将 DP 注意力描述为在使用 TP 时减少或消除 MLA KV 缓存复制的一种方法。

表3: DeepSeek V3 中的先进 KV 缓存管理技术

技术简要描述对缓存结构的影响对缓存管理/内存的影响
分层自适应缓存 (Layer-Wise Adaptive Cache) ⁷在较深层修剪较旧的 KV 条目。动态调整不同层缓存内容的保留。优化长上下文内存使用,减少深层不必要缓存。
联合 KV 存储 (Joint KV Storage) ⁷将压缩的 K 和 V 合并为共享的压缩表示。更紧凑的潜在向量表示,可能单个向量包含 K 和 V 的信息。进一步减少 KV 缓存大小和多节点推理时的内存流量。
动态低秩投影 (Dynamic Low-Rank Projection) ⁷根据序列长度动态调整 KV 压缩强度。潜在向量的压缩率可变。平衡短序列的保真度和长序列的内存效率。
自适应查询压缩 (Adaptive Query Compression) ⁷在不同层深度自适应缩放查询维度。不直接影响 KV 缓存结构,但影响查询与缓存的交互。节省激活内存,间接减少整体内存压力。
MLA 的 DP 注意力 (DP Attention for MLA) ²⁸数据并行策略,消除 MLA KV 缓存在 TP 设备间的复制。每个 DP worker 存储不同请求的 KV 缓存。显著减少多 GPU 推理时的总 KV 缓存内存占用。

VI. 在推理服务框架中的实现

A. vLLM 对 DeepSeek MLA 和 KV 缓存的处理方法
vLLM 支持采用 MLA 和 FP8 优化的 DeepSeek 模型 ¹⁹。它使用 PagedAttention 进行 KV 缓存管理(如前所述)。vLLM 针对 DeepSeek 的关键特性包括 FlashMLA 集成、支持分块预填充的 MLA,以及整体内存/性能优化 ²⁰。vLLM 的流水线并行能力允许横向扩展 KV 缓存容量 ¹⁹。

DeepSeek 与 vLLM 社区之间的合作为 MLA 和 FP8 的集成与优化提供了支持 ¹⁹,这表明高效部署这些高级特性具有实际重要性和复杂性。¹⁹ 感谢 Neural Magic (Red Hat)、SGLang、CUTLASS、FlashInfer、Meta、Berkeley 以及 DeepSeek 自身对 vLLM DeepSeek 支持的贡献。这种生态系统级别的努力对于此类复杂模型是必要的。

vLLM 利用流水线并行跨多台机器扩展 KV 缓存容量的能力 ¹⁹,对于启用像 DeepSeek R1 这样的模型极长的上下文能力至关重要,即使在 MLA 压缩之后也是如此。即使 MLA 带来了 9.6 倍的内存容量提升 ¹⁹,128K 或更长的上下文仍然可能耗尽单节点内存。流水线并行分散了这种负载。

B. SGLang 对 DeepSeek 的优化
SGLang 针对 DeepSeek 的 MLA 实现了特定的优化,包括用于减少 KV 缓存复制的 DP Attention、逐块 FP8 量化(激活值为 E4M3,权重为逐 128x128 块)、W8A8 FP8 和 KV 缓存 FP8、分块前缀缓存以及 DeepGEMM 核心集成 ²⁸。其目标是达到与 DeepSeek 官方报告相当的性能 ⁴¹。

SGLang 对 MLA 的 DP Attention 的关注 ²⁸ 突显了该技术对于高效多 GPU 服务 DeepSeek 模型的重要性,它通过解决 TP 中 KV 缓存复制问题来实现。多个资料都强调了这一点。这是针对 MLA 固有结构与 TP 结合时出现的问题的直接解决方案。

SGLang 中对 DeepSeek 的“KV 缓存 FP8 量化”和特定 FP8 格式(激活值为 E4M3)的明确提及 ²⁸,为潜在向量本身在实践中确实被量化为 FP8 提供了有力证据。²⁸ 指出“KV 缓存 FP8 量化可实现高效的 FP8 推理”,并详细说明了逐块 FP8 中激活值的 E4M3 格式。这直接暗示了缓存值是 FP8 格式。

C. Ktransformers 及其他相关框架
Ktransformers 支持采用 int4 和 FP8 量化的 GGUF 格式的 DeepSeek R1/V3 模型。它具有缓存友好的内存布局,针对长上下文(>20K 词元)的“矩阵吸收 MLA”(可减小 KV 缓存大小),以及用于管理共享 KV 缓存空间的 cache_lens 参数 ⁴³。AIBrix 提供了一个具有抗扫描淘汰策略和异步元数据更新的分布式 KV 缓存,并以 DeepSeek Coder 进行了演示 ³⁷。

Ktransformers 针对长上下文的“矩阵吸收 MLA” ⁴³ 表明,即使使用标准的矩阵吸收,对于极长的序列也可能需要进一步的优化或特定的启用,可能是通过更积极地将缓存的多少部分保持在“吸收”状态或如何对其进行分页。如果标准的矩阵吸收足以应对所有上下文长度,则可能不需要针对 >20K 词元的特殊模式。这暗示了针对极长序列的进一步优化层。

AIBrix 的分布式 KV 缓存的“抗扫描淘汰策略” ³⁷ 值得关注。对于 LLM 而言,其访问模式可能有些顺序性,但也涉及重新关注远距离的词元,简单的 LRU 可能不是最佳选择。抗扫描性表明它试图避免仅仅因为一批新数据而淘汰有用的旧数据。标准的 LRU 如果遇到一长串新的、唯一的词元(一次“扫描”),可能会将较旧但仍然相关的前缀信息挤出。抗扫描策略会尝试识别并保留此类“热门”但较旧的数据。

VII. 面向最优 KV 缓存性能的硬件协同设计

A. GPU 架构 (例如 NVIDIA Hopper) 对 MLA 和 FP8 设计的影响
DeepSeek-V3 的设计,包括 MLA 和 FP8 的使用,深受硬件能力的影响,特别是 NVIDIA H800/Hopper GPU ⁴。Hopper 的 FP8 Tensor Core 提供两倍于 FP16 的 FLOPS 和一半的内存占用,这推动了 FP8 的采用 ²⁷。细粒度量化和 CUDA核心中的 MMA 提升等工程手段旨在解决 FP8 较低的精度和累积挑战 ¹⁴。FlashMLA 专为 Hopper 量身定制 ²³。

DeepSeek 在 FP8 上的成功不仅仅在于使用该格式,更在于为克服其在特定硬件上的局限性(数值稳定性、累积精度)而进行的细致协同设计 ⁵。这涉及自定义核心和谨慎的量化策略。²⁷ 详细说明了 FP8 的挑战(较低的精度、错误率)以及 DeepSeek 为减轻这些问题所做的工程努力(细粒度量化、MMA 提升),实现了与 BF16 相比相对损失误差低于 0.25%。这显示了一个深度硬件感知的优化过程。

GPU 上高带宽内存 (HBM) 的可用性虽然可观,但仍然是一个限制因素,推动了对 KV 缓存压缩 (MLA) 和量化 (FP8) 的需求,以便容纳更多/更长的序列 ³。³ 指出 KV 缓存可能超过模型大小,并且 GPU 内存有限。⁴⁸ 注意到 HBM 在密度方面供应不足。³⁰ 强调 HBM 带宽限制是瓶颈。这些内存限制是 DeepSeek 缓存优化策略的主要动因。

B. DeepSeek 中的内存层级考量
DeepSeek 的策略或明或暗地考虑了内存层级(GPU L1/L2 缓存、HBM、CPU RAM、NVM/磁盘)。异步预取旨在在需要 KV 缓存数据之前将其移入更快的 GPU 缓存 (L2) ³⁰。基于磁盘的前缀缓存 ³⁵ 将 NVM 用作较冷的层级。“分层自适应缓存” ⁷ 也可能被视为更有选择性地管理保留在“最热”(GPU HBM)层级的内容。

DeepSeek 中有效的 KV 缓存管理涉及一个多层次策略:通过积极的压缩和量化 (MLA, FP8) 来减少 HBM 占用;智能的 HBM 内管理(PagedAttention,分层自适应缓存);预取到 GPU L2/SRAM 以隐藏 HBM 延迟;以及可能将极冷的前缀卸载到磁盘。这综合了各种技术。MLA/FP8 减少了 HBM 需求 ⁴。PagedAttention 管理 HBM 块 ²⁹。分层缓存修剪 HBM 条目 ⁷。异步预取针对 L2 ³⁸。磁盘缓存用于前缀 ³⁵。这显示了一种针对内存层级的整体方法。

《DeepSeek-V3 洞察》论文 ⁴ 强调了硬件感知的模型协同设计。这强烈表明它们的 KV 缓存策略,包括 MLA 和 FP8 的使用,是在深刻理解 GPU 内存架构(不同级别的带宽、容量、延迟)的基础上设计的,以最大化效率。该论文的摘要和章节标题(例如,“内存效率”、“低精度驱动设计”、“互连驱动设计”、“以内存为中心的创新”)都指向一个深入考虑硬件内存特性的设计过程。

VIII. 结论:DeepSeek KV 缓存创新技术总结

A. 关键策略及其协同效应总结
DeepSeek 在 KV 缓存优化方面采取了一种多方面、深度集成的策略。其核心在于多头潜在注意力 (MLA) 机制,通过低秩压缩将 KV 状态投影到紧凑的潜在向量(如 c t K V c_{t}^{KV} ctKV k t R k_{t}^{R} ktR),从根本上减少了每个词元所需的存储空间。在此基础上,FP8 量化(特别是 E4M3 格式用于激活/潜在向量)进一步将内存占用减半,并利用了现代 GPU 硬件的计算优势。

为了高效管理这些经过压缩和量化的缓存,DeepSeek 采用了先进的缓存管理技术。在 DeepSeek V3 中引入的联合 KV 存储 (Joint KV Storage) 将压缩的键和值信息更紧密地打包。分层自 adaptive 缓存 (Layer-Wise Adaptive Cache) 则根据信息在网络深度的重要性动态修剪旧的缓存条目,特别适用于长上下文场景。像 vLLM 和 SGLang 这样的推理框架通过分页 KV 缓存 (PagedAttention) 和分块前缀缓存 (Chunked Prefix Caching) 等技术,实现了对这些(可能是非连续的)缓存块的灵活高效管理。

调度层面,数据并行注意力 (DP Attention) 对于 MLA 在张量并行环境下的高效部署至关重要,它避免了 KV 缓存在各 TP rank 间的冗余复制。此外,异步 I/O 和预取技术(例如将 KV 块预取到 GPU L2 缓存)旨在通过重叠数据传输与计算来掩盖内存访问延迟。

最后,底层的核心级优化和硬件协同设计,如 FlashMLA,将 FlashAttention 的 I/O 感知和核心融合原理应用于 MLA 的特定结构,最大限度地发挥了 NVIDIA Hopper 等 GPU 架构的性能。DeepSeek V3 中的动态低秩投影和自适应查询压缩等动态优化策略,进一步根据序列长度和层深自适应地调整压缩参数,体现了对资源利用的精细控制。

这些策略并非孤立存在,而是相互协同,形成了一个整体的 KV 缓存优化系统。MLA 实现了基础的压缩,FP8 在此基础上进一步减小了体积,分页和自适应缓存机制高效地管理这些紧凑的缓存条目,而 FlashMLA 等核心则确保了在这些数据结构上的计算效率。从 DeepSeek-V2 到 V3 的演进清晰地展示了在基础 MLA 架构之上,不断叠加更复杂、动态化和硬件感知的优化手段的持续迭代过程。

B. LLM 中 KV 缓存优化的未来展望
展望未来,LLM 中 KV 缓存的优化仍将是提升模型效率和能力的关键领域。当前 HBM 的容量和带宽限制将持续驱动创新,推动技术向更有效地利用较慢/较廉价内存层级(如 CPU RAM 甚至 NVM/磁盘,正如 DeepSeek API 的磁盘前缀缓存和一些关于 NVM 的研究所暗示的 ³)而不显著牺牲性能的方向发展。“内存墙”问题依然存在,随着模型规模的持续增长,即使是高度压缩的 HBM 内缓存也可能不足。因此,分层存储和更智能的缓存卸载策略可能会变得越来越重要。

随着模型复杂度(如 DeepSeek 中的 MoE 架构 ⁷)的增加,对 KV 缓存调度和管理的要求也将更加复杂,尤其是在分布式推理场景中。需要更精密的策略来处理不同专家或模型路径可能产生的不同 KV 缓存生成速率或访问模式。调度器需要考虑到这些因素,以平衡负载并最大化资源利用率。

此外,更深层次的硬件-软件协同设计,例如针对特定内存层级特性定制的缓存算法、内存内计算技术,以及更动态和自适应的缓存管理机制(例如基于实时访问模式预测的预取和淘汰策略),预计将成为未来的研究热点。最终目标是构建一个能够根据模型、硬件和具体工作负载动态调整自身行为,从而在各种约束条件下实现最佳性能的智能 KV 缓存系统。

相关文章:

  • std::is_same
  • 5月18总结
  • leetcode报错原因总结需要背下来的程序片 [更新中]
  • 三:操作系统线程管理之线程概念
  • 2025年全国青少年信息素养大赛C++小学全年级初赛试题
  • 逻辑与非逻辑的弥聚
  • 【Linux】第二十章 管理基本存储
  • 双紫擒龙紫紫红指标源码学习,2025升级版紫紫红指标公式-重点技术
  • 基于单片机路灯自动控制仪仿真设计
  • 创建型:工厂方法模式
  • TASK03【Datawhale 组队学习】搭建向量知识库
  • 10.9 LangChain LCEL革命:43%性能提升+声明式语法,AI开发效率飙升实战指南
  • STM32H562----------启动时钟分析
  • Listener method could not be invoked with the incoming message
  • Linux之基础IO
  • 非线性1无修
  • python + pip 独家秘籍
  • C++ map容器: 插入操作
  • 5.18 day24
  • 新电脑软件配置三 pycharm
  • 网文书单|推荐4本网文,可以当作《绍宋》代餐
  • 上海这个咖啡文化节首次“走出去”,率本土品牌亮相英国伦敦
  • 上海天文馆走进徐家汇书院,XR沉浸式天文科普体验再推力作
  • 天算星座二期首批卫星成功发射,将助力6G空天信息基础设施建设
  • 媒体:“重病老人银行取款身亡”涉事家属称已和解,银行将支付十万
  • 北方产粮大省遭遇气象干旱,夏粮用水如何解决?