跳转到主要内容

CSA/HCA 注意力:DeepSeek-V4 的混合压缩稀疏机制

· 约 3 分钟阅读

1. Attention 技术全景

技术核心思想KV cache 影响
PagedAttentionKV 按 block 分页管理减少碎片,不减总量
FlashAttentionfused kernel, O(1) 额外显存不影响 KV 大小
MLA (Multi-head Latent Attention)低秩 latent 代替多 KV headKV dim << n_heads x head_dim
GQA/MQA多 query head 共享少量 KV headKV 缩小到 1/n_groups
Sliding Window只保留最近 W 个 tokenKV 上界 = W x kv_dim
CSA/HCA压缩 + 稀疏索引 + 混合比例~10% KV of dense

DeepSeek-V4 的 attention 是 MLA + 混合压缩稀疏 的组合,在 V3 的 MLA 基础上进一步引入逐层异构压缩。

2. 三种 Layer 类型

V4 的 61 层由 compress_ratios 数组逐层指定类型:

类型compress_ratio行为KV cache 大小
Sliding Window Only (SWA)0 (最后 1 层)只保留最近 128 token128 x head_dim
CSA (Compressed Sparse Attention)44
压缩 + top-1024 稀疏索引
win(128) + seq/4 + indexer_cache
HCA (Heavily Compressed Attention)128128
极度压缩,无索引
win(128) + seq/128

V4-Pro 的 61 层分布[128, 128, 4, 128, 4, 128, 4, ..., 4, 0]

  • 约 29 个 CSA 层 (ratio=4)
  • 约 31 个 HCA 层 (ratio=128)
  • 1 个纯 SWA 层 (ratio=0)

3. CSA 工作流 (ratio=4)

Input KV stream
    |
    v
[Compressor] -- 每 4 个 token 的 KV 通过 learned gate + softmax 加权池化为 1 个压缩 entry
    |
    v
[Indexer] -- 轻量级 attention head 对所有压缩 KV 打分,选 top-1024 最相关位置
    |          (64 heads, head_dim=128, FP4 量化存储)
    v
[Sparse Attention] -- 只对 window(128) + selected(1024) 个位置做 full attention

Indexer 是 CSA 的核心创新:通过独立的轻量 attention 模块筛选出与当前 query 最相关的压缩 KV,避免对全部压缩历史做 full attention。

4. HCA 工作流 (ratio=128)

Input KV stream
    |
    v
[Compressor] -- 每 128 个 token 池化为 1 个压缩 entry
    |
    v
[Full Attention] -- window(128) + 所有压缩 KV (seq/128 个)
                    (无 Indexer,因压缩后数量已足够小)

HCA 层的压缩更激进,但因压缩后 KV 数量极少(1M token 仅 ~7812 个 entry),直接全量 attend 即可。

5. KV Cache 精度与量化

V4-Pro 的 KV cache 采用异构精度存储:

维度精度大小原因
非 RoPE 维度 (448 dims)FP8 (per-64 block scale)448 x 1 = 448 bytes位置无关,可压缩
RoPE 维度 (64 dims)BF1664 x 2 = 128 bytes保持位置编码精度
Indexer cacheFP4 (Hadamard rotation)更小只用于粗筛选

有效 KV bytes per entry = 448 + 128 = 576 bytes

对比纯 BF16 (512 x 2 = 1024 bytes),额外获得 ~44% 压缩。

6. 1M Token KV Cache 计算

For seq_len = 1,000,000:

CSA layer (29 layers):
  entries = (128 + 1000000/4) = 250,128 per layer
  subtotal = 29 x 250,128 x 576 bytes = ~4.18 GB

HCA layer (31 layers):
  entries = (128 + 1000000/128) = 7,940 per layer
  subtotal = 31 x 7,940 x 576 bytes = ~0.14 GB

SWA layer (1 layer):
  entries = 128
  subtotal = 1 x 128 x 576 bytes = ~0.00007 GB

Indexer (29 CSA layers):
  entries = 29 x 250,000 x 128 x 0.5 bytes (FP4) = ~0.47 GB

Total per-request (no CP) = ~4.79 GB

对比 Dense MLA (V3.2):61 x 1,000,000 entries = 61M entries => 压缩比 7.75M / 61M = ~12.7%,与官方声称 “10% KV” 吻合。

7. 1M 上下文的真实瓶颈

  1. KV cache 总量:即使压缩后,单请求 ~4.79 GB。并发 10 请求 = 48 GB KV alone。
  2. Prefill 计算量:稀疏后仍为 O(N x topk) = O(N x 1024) per CSA layer。
  3. Indexer 开销:每个 CSA layer 每个 decode step 需全量扫描 N/4 个压缩 KV 来选 top-1024。
  4. CP 通信:Context Parallel 需 all-gather compressed KV across CP ranks。
  5. Disk prefix caching 带宽:从 NVMe 加载 4.79GB KV 约 0.7s (7 GB/s SSD)。

8. 模拟器建模建议

def kv_cache_per_request(config, seq_len, cp=1):
    head_dim = config['head_dim']        # 512
    rope_dim = config['rope_head_dim']   # 64
    nope_dim = head_dim - rope_dim       # 448

    bytes_per_entry = nope_dim * 1 + rope_dim * 2  # FP8 + BF16 = 576

    total_entries = 0
    for layer_id in range(config['n_layers']):
        ratio = config['compress_ratios'][layer_id]
        win = config['window_size']  # 128

        if ratio == 0:    # SWA
            total_entries += win
        elif ratio == 4:  # CSA
            total_entries += win + seq_len // ratio
        else:             # HCA (ratio=128)
            total_entries += win + seq_len // ratio

    kv_bytes = total_entries * bytes_per_entry // cp

    # Indexer cache (FP4, separate)
    n_csa = sum(1 for r in config['compress_ratios'] if r == 4)
    indexer_bytes = n_csa * (seq_len // 4) * config['index_head_dim'] * 0.5

    return kv_bytes + indexer_bytes

关键建模要点:

  • 必须分 CSA/HCA/SWA 三种 layer 分别计算 KV
  • 必须建模 Indexer 的额外 FLOPs:seq/ratio x index_head_dim x index_n_heads per decode step
  • Activation peak 受 chunk_size 限制,不是 seq_len

9. 与其他主题的关联

修改历史
修改历史1 次提交