☰
05.2 · DeepSeek 推理 KV 缓存详解:Entrypoint 前缀匹配、3FS 100 PiB Block KV 与 SWA KV 命中策略
2026/10/29 11:02:22 网站建设 项目流程

📦 GitHub: https://github.com/geekchow/deepseek-v41-flash-inference-guide

背景:本文选自开源学习指南《DeepSeek V4.1 Flash 大规模推理部署实践》。全书用一个贯穿示例串联:编程 Agent 通过 Messages 协议发起第三轮请求,上下文 10 万 token、带一张截图、以edit_file工具调用结束;文中的“第 N 步”即指该示例中的步骤,完整场景见 04 贯穿示例。

你在哪里:第 5 章第 2 篇,贯穿示例的第 ②(前缀命中)、第 ⑤ 的 KV 换入部分、第 ⑨(落盘)以及“SWA 机器宕机”变体。
读完本文你将知道:V4.1 Flash 的 KV 缓存为什么分三层、Block KV 为什么放在独立的 3FS 集群而不是本机内存、SWA KV 如何以 1.35 MiB/序列的代价被保存、命中策略的精确公式,以及缓存开销如何被重叠掉。
开源状态:这部分(kvcache-store、Entrypoint)未开源,以下内容全部来自官方 Q&A 的设计描述。


1. 角色回顾

  • Entrypoint:请求入口;在路由前算出前缀命中长度;维护 SWA KV 的位置目录。
  • KVCache Storage:kvcache-store 服务 + 专用 3FS(Fire-Flyer File System)集群,持久化 Block KV,靠 3FS 自带 GC(Garbage Collection,垃圾回收)回收。
  • 出现在示例:② 命中 96,896;⑤ 换入 KV、拉回 SWA;⑨ decode 结束后落盘;变体中回退到 96,768。

2. 先懂一点模型:为什么会有两种 KV

V4.1 Flash 采用CED(Causal Encoder-Decoder,因果编码器-解码器)结构并结合 CSA2(Compressed Sparse Attention 2,压缩稀疏注意力第二版)的跨层 KV 复用(arXiv 2609.19969)。对推理系统而言,只需记住三点:

  1. Block KV(主 KV + indexer K):长距离稀疏注意力用的压缩 KV,按 128 token 一块分页存储。解码器层的 Block KV 由最后一个编码器层的隐状态投影得到,所以 prefill 只需在编码器层计算(这也是 prefill 每 token 只激活 8B 参数、decode 激活 16B 的原因)。常驻显存的全局 KV 只有890 字节 / token,约为 V4-Flash 的 1/4。
  2. SWA KV:滑动窗口注意力的局部 KV,窗口 128 token。它不能从 Block KV 推出,必须单独保存或重算。
  3. YOCO(You Only Cache Once)consumer 层:部分 SWA 层是“消费者”层,它们的 SWA 不保存,靠 prefill 重算恢复。

FP4 格式:主 KV 为每 16 个元素一组、e4m3 缩放(类似 NVFP4 但没有全局 scale);indexer KV 为 MXFP4(每 32 个一组、ue8m0 缩放);SWA KV 落盘格式为 MXFP8,528 字节 / token。


3. 内部设计

3.1 三层存放

内容介质副本管理者
在途的 Block KV + 状态 KV推理卡显存(HBM)—prefill / decode 实例
SWA KV本机内存单副本,不进 3FSprefill / decode 实例;跨机命中经 400G VLAN(Virtual Local Area Network,虚拟局域网)拉回
分页 Block KV专用 3FS 存储集群应用层不做副本,依赖 3FS 自身冗余kvcache-store

下图回答:三类 KV 分别住在哪里、谁能访问。

专用 3FS 集群

Prefill 机器 P-42

Decode 机器 D-17

只查元数据

记录位置

异步取回

GDR 逐层换入

400G VLAN 拉回

HBM:在途 KV

本机内存
SWA KV 快照

HBM:在途 KV

共享内存
换入缓冲

Block KV 分页
10+2 纠删码

Entrypoint
哈希链元数据
SWA 位置目录

3.2 Block KV:为什么用独立存储集群

官方给出三个理由:

  1. 任意 prefill 机器可以命中任意前缀——缓存不在本机,路由就不必考虑“前缀亲和”,避免它与负载均衡打架;
  2. 存储与计算独立扩缩容;
  3. 缓存不受计算节点故障影响——计算节点故障率比存储节点高一个数量级以上。

其他要点:prefill 侧也用分页 KV;decode 不做 KV offload(decode 不受缓存容量约束,因此也不用 Hi-Sparse),但decode 产生的 KV 仍会写盘以提高命中率。

3FS 的可靠性设计:

  • 数据以10+2 纠删码(EC,Erasure Coding)存储,每个 EC 组可容忍两个节点同时故障;
  • 读请求同时发往组内 11 个存储节点,任意 10 个返回即可解码(用冗余读消除长尾抖动);
  • 每个存储节点部署一个GC Worker,按 LRU(Least Recently Used,最近最少使用)定期淘汰,使磁盘占用低于水位线;kvcache-store 本身没有过期逻辑。

容量与保留期:

参数数值
KV 缓存总容量约 100 PiB SSD
TTLAgent 流量 3 天;对话(chatbot)流量 7 天
为什么对话流量更长对话流量命中长尾更重:少量 KV 被读非常多次。经验上 TTL 约 3 天会让对话流量损失 0.5%–1% 命中率
存储与在线 GPU 配比约 14.4 TB / GPU(逻辑容量,物理容量更大)
推荐存储服务器20 × 30.73 TB SSD;每台至少 40 GB/s 读、5 GB/s 写;总容量至少能保留 24 小时数据

3.3 缓存开销如何被重叠

下图回答:匹配、取回、换入三步分别由谁执行、哪一步藏不住。

引擎进程3FSFetch 进程kvcache-store(CHECK)Entrypoint引擎进程3FSFetch 进程kvcache-store(CHECK)Entrypoint路由前必须知道命中长度,藏不住loop[每一层]哈希链前缀匹配(只看元数据)命中长度路由到 prefill异步读 Block KV任意 10/11 返回写入主机共享内存换入线程 GDRH2D 第 i+1 层前向计算第 i 层
  • 匹配:Entrypoint 对本地 CHECK 角色的 kvcache-store 做哈希链前缀匹配,只查元数据。因为路由前要用到命中长度,这一步无法隐藏。
  • 取回:独立进程异步把 KV 从 3FS 搬到主机共享内存。
  • 换入(swap-in):引擎进程内的线程把共享内存搬到 HBM,目标是让逐层 H2D(Host to Device)与前向计算重叠。由于 CUDA copy engine 处理细粒度 KV 块拷贝性能差,换入改用GDR(GPUDirect RDMA):用 RDMA 网卡打满 PCIe 带宽,且不占用 GPU 的 SM。

3.4 SWA KV:每条序列只存 1.35 MiB

存放结构:SWA KV 不进分页块,而是放在状态缓存(state cache)里,每条序列占一个固定大小的槽位StateBlock,分两个区:

StateBlock = [ 存储区:SWA(前 20 层) | 丢弃区:YOCO consumer 层 SWA + C2 压缩边界累加器 ca_state / ica_state ]

丢弃区靠 prefill 重算恢复;C2 压缩窗口边界天然对齐 128 的倍数,没有跨边界依赖。

存多少:

state_size_to_disk = 20 层 × 134 token × 528 B/token = 1,415,040 B ≈ 1.35 MiB / 序列 └ 128 窗口 + 6 个投机回退余量

只在 128 的倍数位置存:

  • prefill 结束后:序列末尾预留 1 个 token,向下取整到 128 的倍数作为存储位置;不足一个 128 单元则本轮不存。分块 prefill 中途不存,只有最后一块存。
  • decode 期间:在显存里另分一个副本区,请求每跨过一个 128 边界,就把当前窗口在显存内拷贝到副本区;请求结束时,从最近一次完成的拷贝落存,挂载点向下取整到 128 边界。拷贝位置最多越过边界 5 个 token,由槽位环形缓冲比窗口多出的 6 个位置吸收。

存在哪:不进持久化缓存,留在产生它的机器内存里。Entrypoint 维护一个逻辑统一、物理上按 key 分片到各 Entrypoint 机器的内存目录,记录它在哪台机器;命中时若不在本机,从远端经 400G VLAN 拉回。SWA KV 与 Block KV 共用同一条 P→D 传输路径。

3.5 命中策略(精确版)

原则:命中长度由 Block KV 决定;最后一块要不要重算由 SWA KV 决定。

下图回答:给定输入长度 L,最终命中长度如何算出。

有

无

输入长度 L

命中上限
L − 134

查 Block KV
得 L1,128 的倍数

区间 L1−128 到 L1
有 SWA 快照?

命中 = L1

命中 = L1 − 128
回退一块重放

  • 上限L − 134来自 YOCO 截断要求:128 窗口 + 6 个投机回退 token。
  • 回退的 128 个 token 由SWA Bounded Replay在 prefill 中重放(机制见 DeepInfer · Prefill 篇)。

4. 交互契约

对端输入输出
deepseek-recipe → Entrypointtoken 列表 + 采样参数—
Entrypoint → Prefill LB请求 +命中长度(决定未命中 token 数,也就是计算配额)—
kvcache-store ↔ Prefill 引擎命中块的位置KV 块(3FS → 共享内存 → HBM)
Prefill / Decode → 3FS新的完整 128-token 块—
Prefill / Decode → 本机内存 + 目录SWA 快照(20 层 × 134 token)目录项

5. ⚓ 回到示例

第 ②步:算出命中 96,896

  1. 第 2 轮结束时序列长 97,000。它的 decode 实例在请求结束时:把 Block KV 写到 3FS,⌊97,000 / 128⌋ = 757个完整块 → 覆盖前96,896个 token;SWA 快照的位置 =⌊(97,000 − 1) / 128⌋ × 128 = 96,896,存在这台 decode 机器(我们称为 D-17)的内存里,目录记录 “key → D-17”。
  2. 第 3 轮L = 100,000。上限L − 134 = 99,866。
  3. Entrypoint 查哈希链:前 757 块全部命中,L1 = 96,896 ≤ 99,866。
  4. 查 SWA 目录:区间[96,768, 96,896]内有快照(恰在 96,896)→命中 = 96,896。
  5. 未命中后缀 = 100,000 − 96,896 =3,104 token,连同命中长度一起交给 Prefill LB。

第 ⑤步(缓存部分):把 96,896 token 的 KV 搬进显存

  • 分配到的 prefill 机器(P-42)的 Fetch 进程从 3FS 读 757 个块(每块同时发往 11 个节点、收齐 10 个即解码),写入主机共享内存。
  • 引擎的换入线程用 GDR 逐层把 KV 搬进 HBM,与前向计算重叠。按 890 B/token 估算,96,896 token 的全局 KV 约86 MB——这就是“1/4 体积”在 I/O 上的意义:长上下文命中的搬运量很小。
  • SWA 快照不在 P-42 本机 → 按目录从 D-17 经 400G VLAN 拉回 1,415,040 字节。

第 ⑨步:为第 4 轮做准备

decode 期间每跨过一个 128 边界就在显存里拷贝一次 SWA 窗口;本轮输出约 700 token 后结束(序列总长约 100,700),最近一次拷贝位于⌊100,699 / 128⌋ × 128 = 100,608,落存到 decode 机器内存;新增的完整块写入 3FS。第 4 轮来时,命中长度最多可达 100,608。

变体:D-17 宕机

第 ② 步查 SWA 目录:D-17 不可达,区间[96,768, 96,896]内没有可用快照→ 命中 =L1 − 128 = 96,768。未命中后缀变为 3,232 token;其中最后 128 个“命中但需重放”的 token 只用来重建 SWA KV,它们的 Block KV 仍直接复用、不重算也不覆写。代价:多算 128 个 token,结果正确。


6. 故障行为

故障影响设计如何应对
计算节点宕机其上的在途请求、本机 SWA 快照丢失Block KV 在独立 3FS,不受影响;SWA 缺失只导致回退一块重放
3FS 存储节点宕机—10+2 EC,每组可同时坏 2 个;读任意 10/11 即可
网络抖动、慢节点读尾延迟冗余读,先到先得
存储写满—每节点 GC Worker 按 LRU 淘汰到水位线以下
跨数据中心部署光纤被施工挖断等可靠性风险技术上可行(KV 已大幅压缩),按每 8 卡约 400 Gbps 预留互联;DeepSeek 实际部署在不同但相邻的数据中心

上一篇:05.1 deepseek-recipe | 下一篇:05.3 负载均衡器 | 返回:概念地图


📚 返回专栏目录

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询