KV 緩存 (Key-Value Cache) 技術詳解
KV 緩存(Key-Value Cache)是在 Transformer 模型(尤其是 Decoder-Only 架構或 Encoder-Decoder 架構的 Decoder 部分)進行自回歸 (auto-regressive) 推理生成序列時,一種至關重要的優化技術。其核心目標是顯著提高生成速度并大幅減少冗余計算。
1. 為什么需要 KV 緩存?
在自回歸生成模式下,模型一次生成一個詞元 (token)。例如,要生成句子 “A B C D”,過程如下:
- 輸入
<start>
,模型預測 “A”。 - 輸入
<start> A
,模型預測 “B”。 - 輸入
<start> A B
,模型預測 “C”。 - 輸入
<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 個詞元 ( 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 緩存中。
- 輸入是起始符 (e.g.,
- 生成第 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?]。
- 生成第 i i i-個詞元 ( t = i t=i t=i):
- 輸入是第 i ? 1 i-1 i?1 個生成的詞元。
- 模型為這個新詞元計算其 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?,...,Ki?1?] 和 [ V 1 , . . . , V i ? 1 ] [V_1, ..., V_{i-1}] [V1?,...,Vi?1?]。
- 注意力計算: Q i Q_i Qi? 與 [ K 1 , . . . , K i ? 1 , K i ] [K_1, ..., K_{i-1}, K_i] [K1?,...,Ki?1?,Ki?] 和 [ V 1 , . . . , V i ? 1 , V i ] [V_1, ..., V_{i-1}, V_i] [V1?,...,Vi?1?,Vi?] 進行交互。
- 緩存: 將新計算的 K i K_i Ki? 和 V i V_i Vi? 追加到 KV 緩存中。
這個過程在每個 Decoder 層的自注意力模塊中都會發生。
3. KV 緩存出現的位置
KV 緩存主要應用于 Transformer 推理階段的以下注意力模塊:
-
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 向量。
-
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(t?d2+t2?d)
- 總復雜度: ∑ 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=1L?O(t?d2+t2?d)=O(L2?d2+L3?d)。對于長序列,近似為 O ( L 3 ? d ) O(L^3 \cdot d) O(L3?d)。
4.2 使用 KV 緩存的計算復雜度
- 第 t t t 步復雜度: O ( d 2 + t ? d ) O(d^2 + t \cdot d) O(d2+t?d) (僅為新詞元計算 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=1L?O(d2+t?d)=O(L?d2+L2?d)。
4.3 KV 緩存的其他優勢
- 顯著減少計算量: 將復雜度從 O ( L 3 ? d ) O(L^3 \cdot d) O(L3?d) 級降低到 O ( L 2 ? d ) O(L^2 \cdot d) O(L2?d) 級,使長序列生成在實踐中成為可能。
- 大幅提升推理速度: 計算量的減少直接轉化為推理時間的縮短。
- 內存權衡: 需要額外的內存空間來存儲這些 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(L?dmodel??b?nlayers?),或更細致地表示為 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(L?dhead??nheads??b?nlayers?)。
- 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} dhead??nheads?)
- 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 向量會被拼接到已緩存張量的相應維度上(通常是序列長度維度)。
- 在實踐中,為了效率,可能會預先分配一個最大序列長度 L m a x L_{max} Lmax? 的緩存空間,然后用一個指針或索引 (如
- 跨層傳遞: 在多層 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 i?1 位置詞元的 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 提供更好的模型質量。
- 每組查詢頭共享一對 K 和 V 向量,因此 KV 緩存的大小僅取決于
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 在
completion
或chat.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
,當前實現也可能基于內部管理機制運行。 [citeturn0search0]
- 內部維護與 Hugging Face Transformers
- 1.2 預分配與動態增長:
- 初始化時,根據指定的最大序列長度 (
max_seq_len
) 一次性分配連續的 GPU 內存池,用于存放所有層、所有頭的 KV 張量。 - 生成新 Token 時,僅在內存池尾部追加新計算的 KV,通過指針
past_length
跟蹤有效范圍,避免了頻繁的內存分配和數據遷移開銷。 [citeturn0search3]
- 初始化時,根據指定的最大序列長度 (
- 1.3 跨請求持久化與復用:
- 支持同一會話內的多次增量推理請求(multi-turn generation),復用首次調用分配的 KV 緩存。
- 1.4 冷熱分層調度與 ZeRO-Inference:
- 在 ZeRO-Inference 模式下,KV 緩存可以進行分層存儲:頻繁訪問的“熱”數據保留在 GPU,較少訪問的“冷”數據可以自動卸載 (Offload) 到 CPU 主存,甚至進一步 Spill 到 NVMe SSD。 [citeturn0search3]
- 通過后臺異步 I/O 線程管理冷熱數據的遷移,對用戶透明地擴展了有效上下文長度,同時兼顧延遲和成本。
- 1.5 緩存壓縮與量化:
- KV 緩存可以與權重量化(如 INT8/INT4)結合使用。KV 緩存本身也可以被量化存儲,在計算時在線解壓,以進一步降低內存占用,HuggingFace 與 DeepSpeed 的示例中展示了結合權重量化可帶來顯著的吞吐提升。 [citeturn0search1]
- 1.6 注意力機制與緩存結合:
- FlashAttention 一體化內核: DeepSpeed 提供了基于 Triton 等實現的自研 Attention Fusion Kernel,將 QKV 投影、點積、Softmax 等操作合并,減少內存讀寫。KV 緩存以分塊(tile/block)形式高效饋入此融合流水線。 [citeturn0search3]
- 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(N3) 1。KV 緩存通過存儲先前所有詞元在注意力層產生的中間鍵 (K) 張量和值 (V) 張量來緩解這一問題。當生成新詞元時,模型能夠復用這些緩存的 K 和 V 張量,僅需為當前詞元計算新的 K 和 V。這種機制在初始預填充 (prefill) 之后,將每個詞元的生成復雜度降低至 O(N)(與序列長度成線性關系),從而使整體生成復雜度降至 O(N2) 1。這一優化對于 LLM 處理長序列并在可接受的延遲內響應至關重要。然而,這種計算上的節省是以顯著的內存消耗為代價的,因為 KV 緩存需要存儲上下文中每個詞元、每一層、每一個注意力頭的張量數據 1。
KV 緩存不僅是一項速度優化,更是實現長上下文窗口 LLM 實際應用的關鍵推動因素。若無此機制,重新計算所有先前詞元狀態的計算成本將使得處理數千詞元(如 DeepSeek 模型所支持的)的長序列在實踐中變得不可行。正如 1 所明確指出的,在沒有緩存的情況下,由于每一步都涉及 O(N2) 的注意力計算,生成 N 個詞元的成本為 O(N3);而有了緩存,總體成本則降至 O(N2)。這種復雜度的顯著降低,使得處理長達數萬詞元的序列成為可能。
然而,KV 緩存的巨大內存占用(通常會超過模型參數本身的體積 3)是驅動 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)”的方法,旨在僅存儲必要的鍵值對,從而最大限度地減少冗余和內存占用 1?。這一理念最突出的體現便是其多頭潛在注意力 (Multi-Head Latent Attention, MLA) 機制。從 V2 到 V3 的演進過程展示了 DeepSeek 在這些緩存策略上的持續改進,不斷解決性能瓶頸并增強內存管理能力 11。
早期對 DeepSeek V2/V3 中“獨特 KV 緩存”的描述 1?,很可能指的就是其多頭潛在注意力 (MLA) 機制所帶來的效果。MLA 通過存儲壓縮后的潛在向量而非每個頭完整的 K 和 V 張量,本質上創建了一種“獨特”且壓縮的表示,從而避免了傳統 MHA 的冗余。如 1? 所述,獨特 KV 緩存“僅存儲 Transformer 模型運算過程中產生的必要鍵值對”并“避免重復數據存儲”。MLA 通過將多個鍵和值頭壓縮成每個詞元一個較小的潛在向量 ?,精確地實現了這一目標,兩者特性完美契合。
DeepSeek 對 KV 緩存優化的關注點不僅僅在于提升推理速度,更是一項戰略性舉措,旨在降低硬件門檻和運營成本,從而使強大的 LLM 技術更易于普及 11。例如,11 直接將優化的 KV 緩存與“更低的硬件需求(顯存模塊)”和“更高的能效”聯系起來。13 則強調了 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 中的上投影步驟,雖然表面上增加了計算開銷,但對于在積極壓縮后仍保持模型的表達能力至關重要。這代表了一種深思熟慮的設計權衡:用注意力計算過程中(如果顯式執行上投影)的更多計算換取內存占用和數據移動量的大幅減少 1?。1? 指出,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? 1?。 c t K V c_{t}^{KV} ctKV? 是對原始鍵和值信息的低秩聯合壓縮。根據 DataCrunch 對 DeepSeek-V3 論文 (arXiv:2412.19437) 的分析 1?,在 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 的處理與主要內容壓縮分離開來 ?。12 提到,標準的 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 維)的構建 1?,意味著查詢向量與一個已經整合了位置信息和壓縮內容的表示進行交互。這與將 RoPE 應用于完全上投影的高維鍵不同。1? 明確指出有效鍵維度 K/C 是 KaTeX parse error: Expected 'EOF', got '_' at position 17: …_v + \text{RoPE_?dim}。這表明 RoPE 組件在主要注意力分數計算之前或作為其一部分,與潛在向量信息結合以形成鍵表示,這可能發生在壓縮或部分投影的空間內。
C. “矩陣吸收”優化
MLA 的一項關鍵工程優化是“矩陣吸收”技巧 (matrix absorption trick) 1?。該技術避免了在每次注意力計算期間顯式地將壓縮潛在向量上投影回其完整頭維度的計算成本和內存帶寬。取而代之的是,上投影矩陣(例如 W u k W_{uk} Wuk? 和 W u v W_{uv} Wuv?)的權重被數學上“吸收”到注意力層中的其他矩陣中,例如查詢投影矩陣或輸出投影矩陣 1?。這使得核心的注意力計算(打分和值聚合)能夠直接在壓縮的潛在空間中進行,從而顯著減少了開銷 1?。
矩陣吸收對于 MLA 實現高算術強度 (arithmetic intensity,即每字節數據移動的浮點運算次數) 至關重要。通過將主要的注意力計算保持在壓縮空間內,它相對于執行的浮點運算次數,極大地減少了進出內存的數據移動量 1?。DataCrunch 的分析 1? 明確指出,通過權重吸收,“查詢被投影到壓縮維度 C,并且注意力計算(打分和輸出聚合)發生在這個壓縮空間中。”他們的分析表3顯示,由于內存帶寬使用顯著降低,MLA 注意力的 FLOPs/Byte 比率要高得多,這是直接在較小的壓縮數據上操作的結果。
該技術有效地使得 MLA 在核心注意力步驟中表現得像一個多查詢注意力 (MQA) 系統,其中所有查詢頭都關注一個單一的、共享的(但由于初始壓縮和定制投影而信息豐富)從潛在向量派生出的鍵值表示 1?。1? 指出:“每個查詢頭實際上都關注相同的鍵和值,這意味著組頭大小為一。”1? 也呼應了這一點,解釋說由于權重吸收,MLA 可以被視為擁有一個由所有查詢頭共享的單一鍵值頭。
D. 與旋轉位置編碼 (RoPE) 的交互
RoPE 對于向 Transformer 注入位置信息至關重要。DeepSeek V2 和 V3 特別改進了 RoPE 與 MLA 的集成,以確保效率和穩定性,尤其是在 MLA 的壓縮和長上下文場景下。這促成了一種“解耦 RoPE (decoupled RoPE)”策略 12。如第 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 應用可能會遭受數值不穩定或成為效率瓶頸的問題 ?。12 明確提到標準的 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 的博客分析 1? 估計,DeepSeek V3 的 MLA KV 緩存內存占用比等效 MHA 實現小約 60 倍,比等效 GQA 實現小約 12 倍。此外,有觀點認為,在相同的 KV 緩存開銷下,MLA 比 GQA 具有更強的表達能力 1?。
核心區別在于 KV 緩存縮減的機制:MQA/GQA 通過減少存儲的不同 K/V 頭投影的數量來實現,而 MLA 通過潛在壓縮來減少每個詞元存儲的 K/V 信息的維度,同時通過上投影(或吸收投影)在名義上為所有原始查詢頭保留了獨特的信息路徑。這種方法的差異解釋了為何 MLA 在相似緩存大小下可能具有更高的表達能力 1?。1? 將 MLA 的學習型上投影(允許每個 Q 頭派生其特定的 K/V)與 GQA 的選擇器矩陣(嚴格共享)進行了對比。1? 引用了一篇理論證明 MLA 在同等緩存開銷下比 GQA 更具表達能力的論文。
MLA 一個重要但常被低估的優勢是,在預填充階段計算 KV 緩存本身(而不僅僅是存儲它)所需的 FLOPs 和內存帶寬顯著減少。在這方面,對于 DeepSeek V3,MLA 比 GQA 效率高約 12 倍,比 MHA 效率高約 64 倍 1?。這是因為 MLA 為每個詞元計算一個小的潛在向量,而不是多個較大的 K 和 V 向量。DataCrunch 的分析 1? 明確計算并列出了 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 1? |
RoPE 集成復雜度 | 標準 | 標準 | 標準 | 更復雜,需要解耦 RoPE (例如 k t R k_{t}^{R} ktR?) 以適應壓縮和長上下文 ? |
DeepSeek 中的主要優勢 | (基線對比) | (理論上更節省) | (平衡方案) | 極低的內存占用,支持超長上下文,預填充階段 KV 計算高效,同時通過潛在向量和上投影保持高表達能力 ? |
III. 先進注意力機制與 MLA KV 緩存的集成
A. 借鑒 FlashAttention 原理優化 MLA:FlashMLA
FlashMLA 是一款針對 NVIDIA Hopper GPU 優化的 MLA 解碼核心 21。它將 FlashAttention 的核心原理——I/O 感知(通過融合操作和利用 SRAM 減少 HBM 訪問)、核心融合以及高效的任務劃分——直接應用于 MLA 的壓縮潛在向量 21。FlashAttention 通過將注意力計算分塊以適應 GPU SRAM 并融合多個核心操作來減少內存 I/O。FlashMLA 旨在最大化內存帶寬利用率和計算吞吐量 23。
FlashMLA 不僅僅是 MLA 的一種實現,更是一種協同優化的解決方案,它將 FlashAttention 的核心思想應用于 MLA 的特定結構(壓縮的 c t K V c_{t}^{KV} ctKV? 和 k t R k_{t}^{R} ktR?)。這意味著標準的 FlashAttention 可能無法直接在 MLA 上達到最佳效果,需要進行相應調整。22 指出 FlashMLA “融合了 FlashAttention 的優化技術”。21 討論了 FlashAttention 如何在批處理大小和查詢長度維度上并行化,這在推理(查詢長度通常為1)場景中有所不同。與 FlashAttention 相關的 Flash-Decoding 技術增加了對 K/V 序列長度的并行維度。FlashMLA 很可能借鑒了這些思想,以在潛在向量上高效操作,并有效處理特定的上投影/吸收步驟。21 證實了 FlashMLA 直接在壓縮向量上操作。
FlashMLA 的開發突顯了硬件-軟件協同設計的趨勢,其中算法創新 (MLA) 與針對特定硬件 (Hopper GPU) 的核心級優化緊密耦合,以實現最佳性能 ?。23 明確稱 FlashMLA 為“專為 NVIDIA Hopper GPU 量身定制的高效解碼核心”。2? 強調了其 Hopper 優化。?(《DeepSeek-V3 洞察》)通常將硬件感知的模型協同設計作為 DeepSeek 的一項關鍵原則。
B. MLA Kernel 中大頭維度的處理
MLA 的一個特性是其有效頭維度較大(例如,查詢/鍵為 576,值 為 512 1?),這在諸如 FlashMLA 和 TileLang 等核心實現中帶來了挑戰 22。為了高效管理這些大維度,采用了特定的調度策略(例如,將 Q@K 計算分配給單個 warpgroup)和內存優化技術(例如,共享內存置換 (shared memory swizzling) 以避免 bank沖突,以及使用 TMA 進行數據移動的 warp 專業化 (warp specialization))22。
MLA 中的“大頭維度”是 RoPE 組件 ( k t R k_{t}^{R} ktR?,維度 64) 與壓縮 KV 潛能 ( c t K V c_{t}^{KV} ctKV?,維度 512 用于值,用于派生鍵部分) 連接形成查詢所交互的有效鍵表示 (維度 576) 的結果 1?。這與傳統 MHA 不同,后者的頭維度通常更小且統一。22 指出“查詢和鍵的頭維度為 576 (512 + 64),而值的頭維度為 512”。這直接關聯到前面討論的 c t K V c_{t}^{KV} ctKV? 和 k t R k_{t}^{R} ktR? 的結構。
由于這些大的、可能非標準的頭維度,共享內存置換和 warp 專業化等技術對于 MLA 變得更加關鍵,以避免 bank 沖突并在 SM 內最大化數據重用 22。22 在優化 MLA 的背景下解釋了這些技術。大的、連續的數據訪問(如大頭維度所暗示的)是共享內存優化的主要候選對象,以改善局部性并減少全局內存流量。
C. 性能影響:吞吐量與延遲
集成了 MLA 和 FP8 的 vLLM 顯示出高達 3 倍的吞吐量提升和 10 倍的顯存容量提升 1?。DataCrunch 的分析 1? 表明,MLA 的 KV 緩存計算在 FLOPs 和內存帶寬方面比 GQA 快約 12 倍。然而,在低 QPS (每秒查詢數) 場景下,與 MHA 相比,MLA 可能具有較高的 TTFT (首個詞元生成時間),但在持續負載下具有更好的 TPOT (每個輸出詞元的時間) 1?。
MLA 在 TTFT 和 TPOT 之間的權衡 1? 表明,對于單個短請求,MLA 的投影/吸收的初始開銷可能較為明顯,但由于其卓越的內存處理能力和持續吞吐量,其效率在批處理或長序列生成中表現突出。這些資料明確指出,在低 QPS 下,MHA 在 TTFT 方面優于 MLA,但 MLA 的 TPOT 更佳。這表明 MLA 存在一個初始設置成本,該成本在較長序列或較大批次中得到攤銷。
MLA 的性能可能受到底層硬件 (GPU vs CPU) 的顯著影響。雖然在 GPU 上表現優異,但從潛在向量計算 K/V 投影的額外計算會顯著減慢 CPU 推理速度 2?。2? 中的用戶評論提到:“雖然它使 KV 緩存更小,但在每個推理步驟中,它也為所有先前的詞元引入了從緩存的潛在表示中計算 K 和 V 向量的額外開銷。雖然這對 GPU 不是問題,但 CPU 無法承受這種額外的負載,并將推理速度降低到爬行狀態。”這突顯了一種依賴于硬件的性能特征。
IV. 精度工程:DeepSeek KV 緩存的量化
A. DeepSeek 模型量化概述
DeepSeek 廣泛采用量化技術,特別是 FP8,不僅用于權重,還用于激活值,并可能直接應用于 KV 緩存本身 ?。這是其實現內存效率和利用現代硬件(如 NVIDIA Hopper)能力的關鍵策略。值得注意的是,DeepSeek-V3 被描述為“原生支持 FP8 (already in FP8)” 2?,這意味著 FP8 是其訓練和推理的固有精度。
DeepSeek 在訓練期間就使用 FP8 ?,這是一項重大的創新。這使得模型從一開始就針對 FP8 精度進行了優化,與訓練后量化相比,在 KV 緩存和推理中使用 FP8 時可能帶來更好的精度。2? 強調了 FP8 訓練的新穎性。? 提到 DeepSeek-V3 是首批利用 FP8 進行訓練的開源大型模型之一。這意味著模型參數和激活從一開始就具有“FP8 感知”能力。
“DeepSeek V3 原生支持 FP8” 2? 的表述強烈暗示 KV 緩存本身(即存儲的潛在向量 c t K V c_{t}^{KV} ctKV? 和 k t R k_{t}^{R} ktR?)在 V3 中很可能默認以 FP8 格式存儲,從而提供最大的內存節省。2? 明確建議在 DeepSeek V3 上不要使用 --kv-cache-dtype fp8
參數,因為它已經是 FP8。? 提到“緩存的激活以…FP8 格式存儲”以及“對于推理,KV 緩存…傳統上消耗大量內存。DeepSeek-V3 的 MLA 將…壓縮成一個較小的潛在向量…只需要緩存這個緊湊的潛在向量。”綜合來看,這強烈表明緩存的潛在向量是 FP8 格式。
B. KV 緩存的 FP8 實現
關于具體的 FP8 格式,SGLang 文檔 2? 提到了 W8A8 FP8 和“KV 緩存 FP8 量化”。對于逐塊 FP8 (block-wise FP8),激活值使用 E4M3 格式,并采用逐詞元、每128通道的子向量尺度進行在線轉換;權重則使用逐128x128塊的量化 1?。DeepSeek-V3 對激活值統一使用 E4M3 格式 1?。緩存的激活值(如果 KV 緩存被視為前一步的激活值,則與之相關)以 FP8 格式存儲 ?。
DeepSeek 的細粒度量化(激活值為 1x128 切片,權重為 128x128 塊 ?)對于減輕 FP8 帶來的精度損失至關重要。這允許更具適應性的縮放因子,更好地處理異常值,并更充分地利用 FP8 有限的動態范圍 1?。2? 討論了 FP8 中的分辨率誤差和截斷誤差,以及較小的桶(更細的粒度)如何能帶來更好的分辨率,但對異常值的截斷更差,而較大的桶則相反。DeepSeek 的切片/塊級方法是在兩者之間尋求平衡。1? 明確指出這種粒度允許更好地處理異常值。
“在線量化” 1?(在訓練/推理過程中為每個切片/塊動態計算縮放因子)比靜態量化更具適應性,并簡化了框架。這將直接應用于 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)至關重要。根據 1?,DeepSeek 對激活值使用 E4M3,這種格式在給定的指數位數下提供更寬的動態范圍,更適合表示幅度變化的激活值。雖然并非所有來源都明確說明 KV 緩存使用此格式,但 2? 在逐塊 FP8 中提到了激活值的 E4M3 格式。1? 確認 V3 中激活值統一使用 E4M3。如果潛在向量被視為激活值,則此規則適用。選擇 E4M3 而非通常用于權重的 E5M2,反映了激活值與權重的不同統計特性。
表2: DeepSeek 模型中 KV 緩存量化
緩存組件 | 假設基礎精度 | 量化后精度 (示例) | 每詞元大小縮減 (示例) | KV 緩存總體積影響 (定性/示例) |
---|---|---|---|---|
潛在向量 c t K V c_{t}^{KV} ctKV? | BF16 | FP8 (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} ktR? | BF16 | FP8 (E4M3) | 約 2 倍 (BF16 -> FP8) | 同上。 |
整體 KV 緩存 | MHA (BF16) | MLA + FP8 | >28 倍 (MHA -> MLA FP8, 結合 1? 的 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 緩存架構
- PagedAttention (例如 vLLM 中) 與 DeepSeek MLA 的結合
PagedAttention,如 vLLM 2? 中的實現,以非連續內存塊(頁)的形式管理 KV 緩存。這種機制允許靈活的內存管理,減少碎片并實現高效共享。對于 DeepSeek 的 MLA,壓縮后的潛在向量( c t K V c_{t}^{KV} ctKV? 以及可能的 k t R k_{t}^{R} ktR? 或它們的有效組合)將存儲在這些頁/塊內 2?。vLLM 的發布版本顯示已集成 FlashMLA 以及支持分塊預填充 (chunked prefill) 的 MLA 32。
PagedAttention 的塊式管理特別適用于 MLA 的壓縮潛在向量,因為即使每個詞元的向量很小,長序列仍然會累積大量的總緩存。分頁允許有效地管理這個大型緩存,而不需要巨大的連續內存區域。MLA 將每個詞元的緩存大小減小 ?。PagedAttention 2? 以塊的形式管理內存,避免了碎片。兩者的結合意味著,即使對于非常長的序列,MLA 產生的總緩存(盡管每個詞元更小)也可以被處理,而沒有嚴格的連續性要求,否則這可能成為瓶頸。
PagedAttention 中的“塊”指的是存儲一定數量詞元(例如,31 中的 BLOCK_SIZE)的 KV 數據的內存塊。對于 MLA,這樣一個塊將存儲 BLOCK_SIZE 個詞元的 c t K V c_{t}^{KV} ctKV?(以及 k t R k_{t}^{R} ktR? 或有效鍵)。
- 理解 FlashMLA 的 “64-block chunks”
FlashMLA 引入了一種“分頁 KV 緩存(64 塊組塊)(64-block chunks)” 23。術語“64 塊組塊”很可能指的是 FlashMLA 核心為處理數據而組織或分組的方式,可能與 GPU 執行配置(例如,線程塊或 warp 的數量)有關。此處“塊”的確切定義(單個潛在向量、多個向量或元素)以及數字“64”量化的是什么(64 個這樣的塊,或 64 個元素/詞元的塊)在現有資料中并未完全闡明,但這暗示了一種結構化的方法來管理 MLA 的潛在向量,以便在 Hopper GPU 上高效執行核心。
FlashMLA 中的“64 塊組塊” 23 很可能指的是一種針對 Hopper 架構優化的內存布局或處理粒度,可能與線程塊調度或共享內存容量對齊,以最大化 MLA 操作的吞吐量。這是一種核心級別的內存組織策略。FlashAttention 原則涉及為 SRAM 進行分塊。“64 塊組塊”聽起來像是一種這樣的分塊策略。23 提到 FlashMLA 利用 Hopper 的帶寬和 TFLOPs 并處理可變長度序列。這種分塊將有助于在核心內高效管理此類序列的內存。
FlashMLA 中的這種分頁結構,結合 MLA 的壓縮,是通過將(已經很小的)潛在向量組織成 GPU 可管理的組塊,從而高效處理可變長度序列的關鍵 2?。2? 指出,分頁 KV 緩存(64 塊組塊)有助于處理可變長度序列并保持數據有組織。這表明“組塊”是可以靈活分配/處理的內存單元。
- 分塊前綴緩存策略
SGLang 實現了一種“分塊前綴緩存 (Chunked Prefix Cache)”優化,通過將前綴緩存切割成塊,用 MHA 處理它們,然后合并狀態來提高吞吐量。這對于長序列的分塊預填充非常有益 2?。vLLM 也支持“帶分塊預填充的 MLA” 32。
分塊前綴緩存允許在預填充期間更好地利用計算資源,方法是將可能非常長的共享前綴分解為可并行或流水線處理的可管理單元。2? 提到用 MHA 處理塊并合并。這暗示著將一個大任務分解為更小的、可能并行的任務。“分塊預填充” 32 表明分段處理初始提示。
這種技術很可能通過將這些塊作為頁面的集合來管理,與分頁 KV 緩存系統交互,從而允許高效存儲和檢索常見的序列開頭。如果前綴是分塊的,并且 KV 緩存是分頁的,那么前綴緩存的每個塊自然會映射到基礎 PagedAttention 系統中的一組頁面。這似乎是一種合乎邏輯的協同作用。
- 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 緩存輸入 31)這樣的系統接口時,必要的 K 和 V 組件將從這個聯合表示中派生出來,然后分別存儲到 PagedAttention 的獨立 K 塊和 V 塊中 31。“聯合”方面指的是壓縮存儲格式,而不一定意味著 K 和 V 在注意力計算本身中不再是不同的實體。PagedAttention 核心被構建為消耗獨立的 K 和 V 指針 31。為了兼容性,即使 DeepSeek 的 MLA 具有更統一的內部潛在表示,它也需要為這類核心暴露或計算不同的 K 和 V 組件。31 探討了這種協調。
B. 緩存分層、淘汰與持久化
- DeepSeek V3 的 “分層自適應緩存”
DeepSeek V3 實現了一種“分層自適應緩存 (Layer-Wise Adaptive Cache)”,其中在較深層中會修剪較舊的 KV 條目 ?。這有助于管理極長上下文(128K)的內存。
此策略基于這樣一種觀察:并非所有來自早期詞元的信息在深度 Transformer 的所有層中都保持同等重要性。較深的層可能更關注更抽象或更近期的信息。(這是 LLM 研究中的一個常見假設,盡管在資料中沒有明確說明)。在“較深層修剪較舊的 KV 條目” ? 暗示了信息重要性的層級結構。如果所有過去的詞元在所有層中都同等重要,那么這種修剪將是有害的。這表明對跨層信息流和相關性有隱式理解。
這是一種針對深度維度的“有損”緩存壓縮/淘汰形式,與逐詞元壓縮 (MLA) 或簡單的截斷/滑動窗口形成對比。它是自適應的,因為修剪發生在較深的層。這種淘汰是層級的,并適應深度。這比全局 FIFO 或截斷更為精細。3? (MiniCache) 討論了類似的跨層 KV 緩存壓縮,基于較深層中狀態的相似性,盡管它并非 DeepSeek 特有,但表明該領域正在探索這一點。
- 基于磁盤的前綴緩存 (DeepSeek API)
DeepSeek API 默認使用“磁盤上下文緩存技術 (Context Caching on Disk Technology)” 3?。如果后續請求與先前請求具有重疊前綴,則重疊部分將從此磁盤緩存中獲取(稱為“緩存命中”)。該緩存使用 64 個詞元作為存儲單元;少于 64 個詞元的內容不會被緩存。這是一個“盡力而為”的系統。
這種磁盤緩存主要用于請求間的前綴共享,而不是在單個長推理過程中 GPU/CPU 內存已滿時用于卸載活動的 KV 緩存 3?。它是為了減少不同 API 調用之間針對常見輸入的冗余預填充計算。3? 明確澄清:“在兩個請求之間,只有重復的前綴部分才能觸發‘緩存命中’”,并且沒有提到它用于卸載活動的模型 KV 緩存。
64 詞元的粒度 3? 表明在緩存開銷和命中率之間進行了權衡。緩存非常短的前綴可能會導致過多效用較低的小緩存條目。存儲和索引非常小的數據塊可能效率低下。像 64 詞元這樣的最小大小確保了緩存的前綴足夠大,以便在發生命中時提供有意義的計算節省。
- 淘汰策略 (例如截斷、滑動窗口)
KV 緩存管理中的一般挑戰包括緩存大小超出內存。諸如截斷或滑動窗口之類的技術被提及作為解決方案 2。DeepSeek V2/V3 的“獨特 KV 緩存”也需要諸如淘汰策略之類的緩存管理策略來防止內存溢出 1?。
盡管 DeepSeek 擁有諸如分層自適應緩存之類的高級技術,但對更基本的淘汰策略(截斷、滑動窗口)的需求仍然存在,尤其是在處理極長序列或內存受限的環境中,或者作為后備方案。2 將這些作為緩存大小管理的一般解決方案提及。1? 明確指出,即使是 DeepSeek 的獨特/MLA 緩存也需要淘汰策略。這暗示了一種多層次的緩存控制方法。
C. KV 緩存的異步 I/O 與預取
DeepSeek 的基礎設施包括專為異步隨機讀取設計的 3FS (Fire-Flyer File System),它使用直接 I/O 和 RDMA,對數據加載很有用 3?。雖然 3FS 更側重于訓練數據,但異步 I/O 的原理是相關的。AIBrix 提供了一個具有異步元數據更新的分布式 KV 緩存 3?。最近的研究 3? 提出了將 KV 緩存異步預取到 GPU L2 緩存中,以隱藏 HBM 延遲,實現計算與加載的重疊,這與 vLLM 的分頁 KV 緩存以及 MLA 的潛在向量兼容。
將 KV 緩存塊/頁(尤其是壓縮的 MLA 潛在向量)異步預取到 GPU L2 或 SRAM 中,是通過隱藏 HBM 訪問延遲,使內存密集型注意力操作表現得更像計算密集型操作的關鍵策略 3?。3? 明確指出目標是通過預取到 L2“在計算周期內隱藏 HBM 訪問延遲”。這直接解決了推理的內存密集型特性。3? 確認這很可能會為 MLA 預取壓縮的潛在向量。
在分布式或分層存儲場景中,使用 RDMA(例如,在 3FS 3? 中,或使用 SmartNIC 從存儲器傳輸 KV 緩存 3)可以顯著減少移動 KV 緩存數據的 CPU 開銷和延遲。3? 提到 3FS 使用 RDMA。3 描述了一個工作流程,其中 SmartNIC 使用 RDMA 將 KV 緩存從存儲器提取到加速器,從而繞過 CPU 參與數據傳輸。
D. DeepSeek V3 中的動態緩存優化
DeepSeek V3 引入了幾項動態 MLA 改進 ?:
- 動態低秩投影 (Dynamic Low-Rank Projection): 根據序列長度調整 KV 壓縮強度(短序列壓縮較少,長序列壓縮較多)。
- 自適應查詢壓縮 (Adaptive Query Compression): 在不同層深度縮放查詢維度(早期層使用較高維度,較深層更積極壓縮)。
這些動態調整表明對處理不同階段(序列長度、層深度)信息需求的深入理解。它不是一種“一刀切”的壓縮方式,而是適應上下文進行調整。“根據序列長度調整…”和“在不同層深度自適應縮放…” ? 是自適應行為的明確表述。這意味著模型/系統可以動態改變壓縮方式,以優化保真度/內存的權衡。
“自適應查詢壓縮”旨在節省較深層的激活內存 ?,雖然不直接作用于 KV 緩存,但通過釋放資源或減少帶寬爭用,可以減少整體內存壓力,并間接有益于緩存性能。? 指出它“節省激活內存”。較少的激活內存意味著可能有更多的 HBM 帶寬可用于 KV 緩存操作,或者為緩存本身提供更多空間。
E. KV 緩存效率的調度與并行策略
請求調度程序可以通過將具有匹配前綴的請求發送到包含緩存的服務器來促進 KV 復用 3?。SGLang 中用于 MLA 的數據并行 (DP) 注意力消除了跨 TP 設備的 KV 緩存復制,從而減少了內存開銷 2?。然而,對于 MLA,由于潛在向量在頭部之間共享,TP 無法對其進行分片,因此如果不使用 DP 注意力,KV 緩存會在 TP rank 之間復制 2?。
MLA 和張量并行 (TP) 之間的交互是微妙的。由于 MLA 的潛在向量固有地由所有頭共享(對于潛在緩存本身,head_num=1 ??),因此標準 TP 沿頭維度拆分 KV 緩存是不可行的。這使得 MLA KV 緩存必須在 TP rank 之間復制 3?。3? 明確指出“TP 無法分片潛在向量”并且“每個 TP Rank 存儲 KV 緩存的相同副本”。?? 解釋說 MLA 的 kvcache 的 head_num 為 1,使其無法被 TP 拆分。
因此,DP 注意力對于 TP 設置中的 MLA 至關重要,以避免這種緩存復制并節省內存 2?。它拆分請求,不同請求的潛在緩存存儲在不同的 GPU 上。2? 都將 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) 2? | 數據并行策略,消除 MLA KV 緩存在 TP 設備間的復制。 | 每個 DP worker 存儲不同請求的 KV 緩存。 | 顯著減少多 GPU 推理時的總 KV 緩存內存占用。 |
VI. 在推理服務框架中的實現
A. vLLM 對 DeepSeek MLA 和 KV 緩存的處理方法
vLLM 支持采用 MLA 和 FP8 優化的 DeepSeek 模型 1?。它使用 PagedAttention 進行 KV 緩存管理(如前所述)。vLLM 針對 DeepSeek 的關鍵特性包括 FlashMLA 集成、支持分塊預填充的 MLA,以及整體內存/性能優化 2?。vLLM 的流水線并行能力允許橫向擴展 KV 緩存容量 1?。
DeepSeek 與 vLLM 社區之間的合作為 MLA 和 FP8 的集成與優化提供了支持 1?,這表明高效部署這些高級特性具有實際重要性和復雜性。1? 感謝 Neural Magic (Red Hat)、SGLang、CUTLASS、FlashInfer、Meta、Berkeley 以及 DeepSeek 自身對 vLLM DeepSeek 支持的貢獻。這種生態系統級別的努力對于此類復雜模型是必要的。
vLLM 利用流水線并行跨多臺機器擴展 KV 緩存容量的能力 1?,對于啟用像 DeepSeek R1 這樣的模型極長的上下文能力至關重要,即使在 MLA 壓縮之后也是如此。即使 MLA 帶來了 9.6 倍的內存容量提升 1?,128K 或更長的上下文仍然可能耗盡單節點內存。流水線并行分散了這種負載。
B. SGLang 對 DeepSeek 的優化
SGLang 針對 DeepSeek 的 MLA 實現了特定的優化,包括用于減少 KV 緩存復制的 DP Attention、逐塊 FP8 量化(激活值為 E4M3,權重為逐 128x128 塊)、W8A8 FP8 和 KV 緩存 FP8、分塊前綴緩存以及 DeepGEMM 核心集成 2?。其目標是達到與 DeepSeek 官方報告相當的性能 ?1。
SGLang 對 MLA 的 DP Attention 的關注 2? 突顯了該技術對于高效多 GPU 服務 DeepSeek 模型的重要性,它通過解決 TP 中 KV 緩存復制問題來實現。多個資料都強調了這一點。這是針對 MLA 固有結構與 TP 結合時出現的問題的直接解決方案。
SGLang 中對 DeepSeek 的“KV 緩存 FP8 量化”和特定 FP8 格式(激活值為 E4M3)的明確提及 2?,為潛在向量本身在實踐中確實被量化為 FP8 提供了有力證據。2? 指出“KV 緩存 FP8 量化可實現高效的 FP8 推理”,并詳細說明了逐塊 FP8 中激活值的 E4M3 格式。這直接暗示了緩存值是 FP8 格式。
C. Ktransformers 及其他相關框架
Ktransformers 支持采用 int4 和 FP8 量化的 GGUF 格式的 DeepSeek R1/V3 模型。它具有緩存友好的內存布局,針對長上下文(>20K 詞元)的“矩陣吸收 MLA”(可減小 KV 緩存大小),以及用于管理共享 KV 緩存空間的 cache_lens 參數 ?3。AIBrix 提供了一個具有抗掃描淘汰策略和異步元數據更新的分布式 KV 緩存,并以 DeepSeek Coder 進行了演示 3?。
Ktransformers 針對長上下文的“矩陣吸收 MLA” ?3 表明,即使使用標準的矩陣吸收,對于極長的序列也可能需要進一步的優化或特定的啟用,可能是通過更積極地將緩存的多少部分保持在“吸收”狀態或如何對其進行分頁。如果標準的矩陣吸收足以應對所有上下文長度,則可能不需要針對 >20K 詞元的特殊模式。這暗示了針對極長序列的進一步優化層。
AIBrix 的分布式 KV 緩存的“抗掃描淘汰策略” 3? 值得關注。對于 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 的采用 2?。細粒度量化和 CUDA核心中的 MMA 提升等工程手段旨在解決 FP8 較低的精度和累積挑戰 1?。FlashMLA 專為 Hopper 量身定制 23。
DeepSeek 在 FP8 上的成功不僅僅在于使用該格式,更在于為克服其在特定硬件上的局限性(數值穩定性、累積精度)而進行的細致協同設計 ?。這涉及自定義核心和謹慎的量化策略。2? 詳細說明了 FP8 的挑戰(較低的精度、錯誤率)以及 DeepSeek 為減輕這些問題所做的工程努力(細粒度量化、MMA 提升),實現了與 BF16 相比相對損失誤差低于 0.25%。這顯示了一個深度硬件感知的優化過程。
GPU 上高帶寬內存 (HBM) 的可用性雖然可觀,但仍然是一個限制因素,推動了對 KV 緩存壓縮 (MLA) 和量化 (FP8) 的需求,以便容納更多/更長的序列 3。3 指出 KV 緩存可能超過模型大小,并且 GPU 內存有限。?? 注意到 HBM 在密度方面供應不足。3? 強調 HBM 帶寬限制是瓶頸。這些內存限制是 DeepSeek 緩存優化策略的主要動因。
B. DeepSeek 中的內存層級考量
DeepSeek 的策略或明或暗地考慮了內存層級(GPU L1/L2 緩存、HBM、CPU RAM、NVM/磁盤)。異步預取旨在在需要 KV 緩存數據之前將其移入更快的 GPU 緩存 (L2) 3?。基于磁盤的前綴緩存 3? 將 NVM 用作較冷的層級。“分層自適應緩存” ? 也可能被視為更有選擇性地管理保留在“最熱”(GPU HBM)層級的內容。
DeepSeek 中有效的 KV 緩存管理涉及一個多層次策略:通過積極的壓縮和量化 (MLA, FP8) 來減少 HBM 占用;智能的 HBM 內管理(PagedAttention,分層自適應緩存);預取到 GPU L2/SRAM 以隱藏 HBM 延遲;以及可能將極冷的前綴卸載到磁盤。這綜合了各種技術。MLA/FP8 減少了 HBM 需求 ?。PagedAttention 管理 HBM 塊 2?。分層緩存修剪 HBM 條目 ?。異步預取針對 L2 3?。磁盤緩存用于前綴 3?。這顯示了一種針對內存層級的整體方法。
《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 的研究所暗示的 3)而不顯著犧牲性能的方向發展。“內存墻”問題依然存在,隨著模型規模的持續增長,即使是高度壓縮的 HBM 內緩存也可能不足。因此,分層存儲和更智能的緩存卸載策略可能會變得越來越重要。
隨著模型復雜度(如 DeepSeek 中的 MoE 架構 ?)的增加,對 KV 緩存調度和管理的要求也將更加復雜,尤其是在分布式推理場景中。需要更精密的策略來處理不同專家或模型路徑可能產生的不同 KV 緩存生成速率或訪問模式。調度器需要考慮到這些因素,以平衡負載并最大化資源利用率。
此外,更深層次的硬件-軟件協同設計,例如針對特定內存層級特性定制的緩存算法、內存內計算技術,以及更動態和自適應的緩存管理機制(例如基于實時訪問模式預測的預取和淘汰策略),預計將成為未來的研究熱點。最終目標是構建一個能夠根據模型、硬件和具體工作負載動態調整自身行為,從而在各種約束條件下實現最佳性能的智能 KV 緩存系統。