【轻量化复刻大模型 / KIMI K3】Serve 模块交互式演示
【轻量化复刻大模型 / KIMI K3】Serve 模块交互式演示
- 【轻量化复刻大模型 / KIMI K3】Serve 模块交互式演示
- 0x00 概述
- 0x01 核心数学
- 0x02 设计思路与实现细节
- 0x03 Tab 功能说明
- 0x04 Tab 1: 投机回放原理
- 0x05 Tab 2: 快照成本分析
- 0x06 Tab 3: 重演一致性
- 0x07 Tab 4: ReplaySSM
- 0x08 Tab 5: 统一页池
- 0x09 Tab 6: MLA 分页
- 0x10 Tab 7: KDA 存储
- 0x11 Tab 8: 前缀缓存命中
- 0x12 Tab 9: 前缀缓存未命中
- 0x13 Tab 10: 引擎 before/after
- 0x14 Tab 11: Fleet 一致哈希
- 0x15 Tab 12: Fleet 最小扰动
- 0x16 Tab 13: Fleet 预算隔离
- 0x17 Tab 14: Fleet 综合仿真
- 0x018 验证策略总览
- 0xFF 参考
0x00 概述
K3 Serve 模块的完整交互式演示,14 个 Tab 覆盖投机回放(投影缓存 vs 快照)、重演一致性验证、ReplaySSM 环形缓冲、统一页池(MLA 分页 + KDA 恒定)、前缀缓存两阶段 lookup + KDA checkpoint 原子性、引擎 before/after、Fleet 一致哈希路由 + 预算隔离。全部 CPU 实时运行,复用 decode.py、replayssm.py、paged_cache.py、prefix_cache.py、engine.py、fleet.py 真实源码算子。
注:
- 项目https://github.com/RossiLH/Model-Viz 和系列博客是我的一个尝试,也是我学习的过程。不确定是否满足读者的需求,我自己会反思改进,也希望大家提出宝贵意见。
- 涉及 KIMI K3,DeepSeek V4,PI0.5,PI0.7 等模型。后续可能会跟踪新模型。
- 全 CPU 复刻,不涉及 GPU,也不涉及大规模训练(这是另外一个庞杂深邃的领域)和硬件。
- 模型的组件尽量是原始大模型的缩小版,如果组件没有开源版本,则用近似组件替代。
- 会解释每个组件在解决一个什么问题、这个问题难在哪、为什么只能这么解、解法的原理是什么,以及组件之间如何咬合成一个整体。重点不是记名词,而是理解一条主线。
- 每个主要组件都有可直接运行的 Gradio demo——无需 GPU。另有若干可视化脚本(
plot_*.py),可生成静态图。 - 所有文件行号基于本地源码快照;源码后续变化时,行号可能移动,但函数名和调用关系仍可作为定位入口。
- 为了保证每个文章可以尽量独立成文,所以有些内容会在不同文章中都存在,可能在系列层面上存在冗余,还请大家理解。
0x01 核心数学
1.1 KDA 投机回放:投影缓存 vs 完整快照
KDA 的递归状态 S 每步就地更新,投机被拒时无法直接回滚。两条策略:
路线 A: 完整快照 (replayssm.py)
每步缓存: S_t ∈ R^{H × dk × dv}
每步字节: H * dk * dv * sizeof (dtype)
回滚: pop 最旧快照 → O (1) 取回,代价是存储翻倍
路线 B: 投影缓存 + 重演 (decode.py)
每步缓存: (q_t, k_t, v_t, g_t, beta_t)
每步字节: H * (3*dk + dv + 1) * sizeof (dtype)
回滚:从 committed 状态用 kda_step 逐位重演 n_accepted 步 → 精确重建
代价比 (draft 长度在分子分母抵消):
snapshot_cost_ratio = (H * dk * dv) / (H * (3*dk + dv + 1))
例: H=16, dk=32, dv=32 → 比值 = 4.0x(投影每步只需快照的 1/4 字节)
-
直觉: 投影只存 "输入"(5 个小向量),快照存 "整个状态矩阵";dk*dv 越大,投影优势越明显
-
关键性质: 比值与 draft 长度无关 —"draft 越长越省" 体现在绝对字节差随 draft 线性增大
1.2 verify_and_replay 重演一致性
输入: committed 状态 S_0, DraftProjections (q,k,v,g,beta)[:n_accepted]
输出: (S_new, output_stacked)
S = S_0.clone()
for i in 0..n_accepted‑1:
out_i, S = kda_step(q[i], k[i], v[i], g[i], beta[i], S)
output_stacked = stack(out_0, ..., out_{n‑1}) # (B, H, n, Dv)
-
一致性保证:
verify_and_replay的输出与kda_recurrent对前 n 个位置的完整递推逐位一致(float64 下 max|diff| < 1e‑12) -
clone 必要性: committed 是 cache 里共享的对象,必须拷贝一份避免重演污染共享状态
1.3 KDA 递推核心 (kda_step /kda_recurrent)
Delta Rule 递推:
delta_t = v_t − S_{t‑1}^T k_t # 纠错项
S_t = Diag(alpha_t) · S_{t‑1} + beta_t · k_t · delta_t^T
读出:
o_t = S_t^T · q_t
-
alpha_t = g_min * sigmoid(...)− 有界衰减,alpha_t ∈ [g_min, 0] -
beta_t = sigmoid(...)− 写入强度,beta_t ∈ [0, 1] -
delta‑rule vs 线性注意力: delta_t 是 "新值减去旧预测" 的纠错,而非直接加 k*v
1.4 ReplaySSM 环形缓冲
push(state):
if len(states) == capacity: states.pop(0) # 满员覆盖最旧
states.append(state)
pop() → states.pop(0) # 始终返回最旧快照
-
FIFO‑overwrite 语义: 满员时新状态覆盖最旧,
pop()无条件返回队首 -
为什么不用纯游标环形: 满→pop 再 push 会导致游标错位,pop 取到较新快照而非最旧(
test_replayssm.py的回归测试覆盖此场景) -
copy_from 深拷贝: 保证两环相互独立,修改一个不影响另一个
1.5 统一页池 (PagedCache)
-
PagePool:单一 free list 管理两种 page kind(MLA_KV / KDA_STATE)
-
MLA 分页:append_mla(n_tokens)
-
tokens_per_page=512,每写满 512 token 分配新页
-
页数 = ceil(n_tokens / tokens_per_page)
-
-
KDA 恒定:store_kda(layer, state)
-
每层 KDA 状态 S (B,H,dk,dv) 固定字节,占一页
-
页数 = n_layers(与序列长度无关)
-
pack_heads: (B,H,dk,dv) → flat # 按 head 连续摊平
unpack_heads: flat → (B,H,dk,dv) # 无损还原
-
统一池的价值: 两种 page 共享同一份 free list,上层只需操作
PagePool一个对象,不必区分 "这是 MLA 页还是 KDA 页" -
pack/unpack 无损: float64 下
max|diff| < 1e‑12
1.6 前缀缓存:两阶段 lookup + chained hash + KDA checkpoint 原子性
chained hash:
H_0 = sha256("", tokens[0:512])
H_1 = sha256(H_0, tokens[512:1024])
...
H_i 认证 "直到该端点的整个前缀" → hit = 内容完全一致
两阶段 lookup:
阶段 1 (MLA 细粒度): 从 t=0 按 hash_block_tokens=512 逐块计算 chained hash,在 index 中命中且 ready → 继续;miss → 停止
阶段 2 (KDA 原子性): 从最深匹配边界往回退,找到 endpoint 处每个 KDA group 都有 checkpoint → 命中,缺一个 group → 不可用
-
原子性: KDA 递推状态必须整组一起恢复,只要有一个 group 缺快照,这个边界就不可复用
-
chained hash vs 独立 hash: chained hash 保证 hit = 内容完全一致,不存在 "高 prefix 撞车" 歧义
-
ready 标志: 异步登记时
ready=False,lookup 只认ready=True的块,避免 false hit
1.7 引擎 before/after
首请求: prefill 512 token → PagedCache 存 KDA page → register + persist checkpoint
第二请求 (命中): prefix lookup → 复用 MLA page + KDA checkpoint → reused_tokens=512
第二请求 (未命中): 全重算 → reused_tokens=0
KCP 通信量:与序列长度无关 O (1)
comm_bytes = KDAContextParallel.communication_volume(B, H, dk, dv, world)
1.8 Fleet 调度:一致哈希 + 预算隔离
一致哈希环:
add_cluster(id, vnodes=8): 把 id 散布 vnodes 个虚拟节点到环上
route(session_id) → (primary, secondary)
* primary: session 的 md5 顺时针落入的集群
* secondary: 顺移下一个不同集群 (primary != secondary) 硬约束
- hopscotch 性质:移除 1 集群只扰动 O (1/N) 的 session
预算准入:
BudgetController:
budgets = {"short": S, "long": L}
weights = {"short": 1, "long": 3}
admit(class, usage) = usage[class] + weight[class] <= budget[class]
- 隔离效果: 长突发只消耗自己的配额,短请求配额不受影响 → 短 P95 TTFT 显著更低
0x02 设计思路与实现细节
2.1 文件
experiments/models/llm/kimi_k3/serve/gradio_serve_demo.py
2.2 覆盖范围
serve 模块全部 7 个源文件、6 个测试文件,共 14 个交互 tab:
| Tab | 函数 | 覆盖源文件 | 覆盖测试 |
|---|---|---|---|
| 1 | fig_replay_principle |
decode.py | test_decode.py |
| 2 | fig_snapshot_cost |
decode.py | test_decode.py |
| 3 | fig_replay_consistency |
decode.py | test_decode.py |
| 4 | fig_replayssm |
replayssm.py | test_replayssm.py |
| 5 | fig_page_pool |
paged_cache.py | test_paged_cache.py |
| 6 | fig_mla_paging |
paged_cache.py | test_paged_cache.py |
| 7 | fig_kda_store |
paged_cache.py | test_paged_cache.py |
| 8 | fig_prefix_hit |
prefix_cache.py | test_prefix_cache.py |
| 9 | fig_prefix_miss |
prefix_cache.py | test_prefix_cache.py |
| 10 | fig_engine_before_after |
engine.py | test_demo_engine.py |
| 11 | fig_fleet_hash_ring |
fleet.py | test_fleet.py |
| 12 | fig_fleet_minimal_perturbation |
fleet.py | test_fleet.py |
| 13 | fig_fleet_budget |
fleet.py | test_fleet.py |
| 14 | fig_fleet_simulation |
fleet.py | test_fleet.py |
2.3 设计决策
- 纯计算可视化:所有 tab 的数据均来自
verify_and_replay、kda_recurrent、PagePool、PrefixCache、FleetSimulator等真实模块,无硬编码数据 - sys.path:5 级上溯至
src/+ 1 级上溯至当前目录(_THIS_DIR) - gr.Plot:Gradio 6 内部处理 Figure -> base64,无需手动转换
- 主题:
gr.themes.Soft()(移到launch()参数,Gradio 6 规范)
2.4 依赖
models.llm.kimi_k3.modules.kda_ref—kda_recurrent,kda_stepmodels.llm.kimi_k3.serve.decode—DraftProjections,verify_and_replay,snapshot_cost_ratiomodels.llm.kimi_k3.serve.replayssm—ReplaySSMmodels.llm.kimi_k3.serve.paged_cache—PageKind,PagePool,PagedCache,pack_heads,unpack_headsmodels.llm.kimi_k3.serve.prefix_cache—PrefixCache,chained_hashmodels.llm.kimi_k3.serve.engine—run_oncemodels.llm.kimi_k3.serve.fleet—ConsistentHashRing,BudgetController,FleetSimulator,Request
2.5 运行方式
运行demo:
python experiments\models\llm\kimi_k3\serve\gradio_serve_demo.py
启动后访问 http://localhost:7860,14 个 tab 垂直排列,点击切换。
运行所有测试:
python -m pytest tests/models/llm/kimi_k3/serve/ tests/models/llm/kimi_k3/parallel/ -q
2.6 依赖
plot_utils.py— 字体配置 + 工具函数plot_decode_replay.py— 快照成本曲线plot_verify_principles.py— 成本对比 + 原理示意图plot_paged_cache.py— 统一页池 MLA vs KDAplot_prefix_cache.py— 前缀缓存命中/未命中plot_fleet.py— 一致哈希 + 预算隔离demo_engine.py— 引擎 before/aftertests/.../test_helpers.py— make_projection, to_batch, make_state
0x03 Tab 功能说明
Tab 1 — 投机回放原理
- 左上:draft 阶段投影缓存 vs 完整状态的内存对比
- 右上:快照 vs 投影每步字节成本(随 dk 变化)
- 中左:verify_and_replay 重演流程图
- 中右:三种接受场景(部分/全部/零接受)的输出对比
- 底部:代价对比公式
Tab 2 — 快照成本分析
- 左:比值随 dk 扩展(dv=32 固定)
- 右:绝对字节差随 draft 线性增大
Tab 3 — 重演一致性
- 三种场景下 verify_and_replay 输出与 kda_recurrent 逐位对比
- 状态最大差显示
Tab 4 — ReplaySSM 环形缓冲
- push/pop 时序、pop 返回最旧、capacity 满覆盖、copy_from 深拷贝独立性
Tab 5 — 统一页池
- 初始空闲、分配 KDA+MLA、释放回收的三阶段可视化
Tab 6 — MLA 分页
- append_mla 跨页、pack/unpack 往返验证
Tab 7 — KDA 存储
- store_kda 流程、load_kda 往返验证
Tab 8 — 前缀缓存命中
- 两阶段 lookup 流程图、chained hash 链式依赖
Tab 9 — 前缀缓存未命中
- 无 checkpoint miss、部分 checkpoint 回退
Tab 10 — 引擎 before/after
- 前缀命中 vs 未命中的复用 token 数、四项指标对比
Tab 11 — Fleet 一致哈希
- 环分布可视化、600 session 路由均匀性
Tab 12 — Fleet 最小扰动
- 移除 1 集群的扰动比例、只有指向失效集群的 session 改绑
Tab 13 — Fleet 预算隔离
- 有/无预算隔离的短请求 P95 TTFT 对比、拒绝数
Tab 14 — Fleet 综合仿真
- 命中率、集群负载、TTFT 分布、汇总指标
0x04 Tab 1: 投机回放原理
4.1 目的
展示投机解码两条回滚策略的核心设计:投影缓存(decode.py) vs 完整快照,以及 verify_and_replay 的重演流程(KDA‑Infra §4)。
4.2 UI 组件与参数影响
无参数,页面加载时自动运行。
4.3 输出图解读

3×2 六联图:
左上 (a): Draft 阶段缓存投影而非完整状态
-
柱状图,交替蓝色 (Blue)(状态 S)和绿色 (Green)(投影 q/k/v/g/beta)
-
蓝色柱高 = 1.0(完整状态),绿色柱高 = 0.4(投影更小)
-
你该看什么: 投影每步远小于完整状态
右上 (b): 快照 vs 投影每步字节成本
-
分组柱状图,红色 (Red)= 快照 Hdkdv,绿色 (Green)= 投影 H*(3Dk+Dv+1)
-
X 轴 = dk 值 (16/32/64)
-
你该看什么: dk 越大,快照与投影的字节差距越大
中左 (c): verify_and_replay 重演流程
-
方框箭头示意图:committed → projections [:n] → kda_step × n → 与 kda_recurrent 逐位对比
-
你该看什么: 重演路径与完整递推数值一致
中右 (d): 三种接受场景
-
水平柱状图:部分接受 (n=2) 橙色 (Orange)、全部接受 (n=4) 绿色 (Green)、全部拒绝 (n=0) 红色 (Red)
-
柱旁标注输出步数
-
你该看什么: 接受数决定重演步数
底部 (e): 代价 "代价公式"
-
文字框:快照每步 Hdkdv 字节 | 投影每步 H*(3Dk+Dv+1) 字节 | 比值公式 + 数值示例
-
你该看什么: 比值与 draft 长度无关
4.4 为什么重要
这是理解 K3 投机解码回滚策略的入口图。投影缓存是 K3 的核心设计选择 — 比 SGLang 的快照策略每步节省数倍内存,代价只是一次短重放 O(n_accepted) 步 kda_step。
0x05 Tab 2: 快照成本分析
5.1 目的
画出 draft 长度 vs 投影/快照字节比,验证比值恒定且 >1(投影永远更省)。
5.2 UI 组件与参数影响
无参数,页面加载时自动运行。
5.3 输出图解读

单图(折线图):
- X 轴 = draft 长度(1/2/4/8/16/32),Y 轴 = 投影 vs 快照字节比
- 你该看什么:比值是水平线(与 draft 无关),恒 ≈3.94
5.4 为什么重要
量化证明"投影缓存比快照更省"的核心论点。比值与 draft 无关说明优势来自每步字节差,而非 draft 长度。
0x06 Tab 3: 重演一致性
6.1 目的
验证 verify_and_replay 与 kda_recurrent 在三种接受场景下的逐位一致性(float64 精度)。
6.2 UI 组件与参数影响
无参数,页面加载时自动运行。
6.3 输出图解读

1×3 布局,每个子图一种场景:
- 绿色(Green)边框 + "PASS": 输出一致
- 红色(Red)边框 + "FAIL": 输出不一致(不应出现)
- 文字标注:场景名、输出一致判定、状态最大差(应为 ~1e‑15)
- 你该看什么:三种场景全部 PASS,最大差 < 1e‑12。即,三种场景 (部分/全部/零接受) 输出均与 kda_recurrent 逐位一致 最大差: 0.00e+00 (float64 精度)
6.4 三种场景构建方式
verify_and_replay(s0, proj, n) 模拟投机解码的"草稿-验证-回滚"流程。三种场景通过控制 n(实际接受的草稿 token 数)构造:
| 场景 | n | 构建方式 | 验证目标 |
|---|---|---|---|
| 部分接受 | n=2 | 让 4 个草稿 token 中只有前 2 个通过验证(其余 2 个被拒绝)→ 重演时只回滚这 2 个,S 状态也要回滚到接受第 2 个后的位置 | 验证"部分接受时,输出和状态都能精确回滚" |
| 全部接受 | n=4 | 4 个草稿 token 全部通过验证 → 无回滚,输出 = 4 个 token 的完整前向,S 推进到第 4 个后的位置 | 验证"零回滚时输出与 kda_recurrent 完全一致" |
| 全部拒绝 | n=0 | 4 个草稿 token 全部被拒绝 → 完全回滚,输出为空(shape 第 2 维 = 0),S 状态保持为 s0 不变 | 验证"全拒绝时 S 状态完全不变(s_replay == s0)" |
底层机制:投机解码每轮提出 4 个草稿 token,验证后决定接受 0~4 个。kda_recurrent 是"标准答案"(一次性跑完整序列),verify_and_replay 是"工程实现"(按需回滚)。三种场景覆盖全部边界情况:n=0(纯回滚)、n=4(纯前向)、0
6.5 为什么重要
这是重演策略正确性的数值证明。如果 verify_and_replay 与 kda_recurrent 不一致,投机解码的回滚路径会产生错误输出。
0x07 Tab 4: ReplaySSM
7.1 目的
本 Tab 验证 RawInputRing 流式 raw-input 窗口 与 SGLang ReplaySSM fold-every-commit 语义 的一致性(对应 replayssm.py 实现,SGLang server_args.py:2688-2696 与 hybrid_linear_attn_backend.py:1261-1283)。
核心验证逻辑:RawInputRing 与 decode.py 批量构造的 DraftProjections 共享同一个 verify_and_replay 重演引擎,两者在数学上完全等价——缓存内容相同(raw input (q,k,v,g,beta))、回滚结果相同(与 kda_recurrent 参考逐位一致)、差异仅在写入时机(流式 vs 批量)。
7.2 背景知识
SGLang ReplaySSM 不是存快照,而是 fold-every-commit: verify 期间流式存 raw input,commit 时重演 accepted prefix。 与 decode.py 投影重放共享 verify_and_replay,差异只在写入时机。
RawInputRing(raw-input 环形窗口):SGLang ReplaySSM 的真实实现语义——投机验证期间不存完整状态快照,而是把每步 draft 的原始输入投影 (q,k,v,g,beta) 流式写入 per-slot 环形窗口;commit 时取窗口内容,用 kda_step 重演被接受前缀。与 decode.py 的 DraftProjections(批量构造载体)是同一数据的不同封装。
fold-every-commit:SGLang 术语,指"验证期间折叠(不保存中间状态),提交时重演"。这是 KDA 投机回滚的唯一可行方案,因为 KDA 的 delta-rule 状态递推不可加、不可截断(见 kda.py 与 KCP 前缀扫描)。
7.3 设计思路
- 为什么这样设计实验:采用 2×2 四联图布局,分别展示"时序行为→数据结构→正确性→成本"四个维度。左上用水平条形图展示 push/覆盖时序(直观呈现环形语义);右上用热图展示
window()输出的DraftProjections布局(验证数据格式正确性);左下用双柱对比图展示两条路线的数值误差(验证数学等价性);右下用折线图展示带宽账随 draft 长度的增长趋势(验证成本优势)。本 Tab 是 serve 模块的正确性锚点**,与 Tab 3(verify_and_replay 批量重演)形成"流式 vs 批量"的互补对照。 - 想验证什么:
- RawInputRing 的 push/覆盖时序符合环形缓冲语义(capacity=4 时第 4 步起窗口大小恒为 4)
window()输出的DraftProjections布局为(draft, B, H, D),且第 i 行对应第 i 步 push 的数据- RawInputRing 与批量构造的 DraftProjections 经
verify_and_replay后,与kda_recurrent参考的 max err = 0 - raw input 的缓存字节数恒小于假想快照,比值 =
snapshot_cost_ratio
- 希望读者学到什么:
- SGLang ReplaySSM 不是"存快照",而是"存 raw input + commit 时重演"——与 decode.py 投影重放同宗同源
- RawInputRing 与 DraftProjections 是协作关系(流式写入管理器 vs 批量数据载体),不是替代关系
- 希望从图上看到什么:
- 成功信号:左上 push(3) 起窗口大小恒为 4(红色);右上三行色带分明、数值逐行递增;左下两根柱子均标注"误差 = 0.00e+00";右下蓝线(raw input)始终在红线(假想快照)下方,且差距随 draft 长度线性扩大
- 失败信号:左上窗口大小超过 capacity;右上数值错乱或布局维度不对;左下误差非零;右下两线交叉或蓝线在上
7.2 UI 组件与参数影响
无参数,页面加载时自动运行。
7.3 输出图解读

布局:2×2 四联图。
左上 (a):push/窗口溢出时序(capacity=4)
- 图类型:水平条形图
- X/Y 轴:X 轴为"窗口中投影组数"(线性刻度,0-4);Y 轴为操作步骤(push(0) 到 push(6),自下而上)
- 颜色含义:蓝色 = 窗口未满(大小 < 4);红色 = 窗口已满(大小 = 4),表示最旧投影被覆盖
- 你该看什么:push(0) 到 push(2) 窗口大小从 1 增至 3(蓝色);push(3) 起窗口大小恒为 4(红色),且后续 push 不再增加——直观展示环形缓冲"满则覆盖最旧"的语义
- 理想情况:前 3 根蓝色条形高度递增,第 4 根起转为红色且高度恒为 4
- 异常指示:若窗口大小超过 4,或红色条形高度不恒定,说明 capacity 控制逻辑有 bug
右上 (b):window() → DraftProjections 布局
- 图类型:热图(heatmap)
- X/Y 轴:X 轴为"H × D 展平"(0-5,对应 H=2 × D=3);Y 轴为"draft 步"(第 0 步、第 1 步、第 2 步)
- 颜色/数值含义:viridis 色阶,单元格内白色数字为实际值。第 0 步全为 0,第 1 步全为 1,第 2 步全为 2(代码中刻意用
torch.full(..., float(i))填充,便于验证布局) - 你该看什么:三行色带分明(紫→青→黄),数值严格逐行递增;每行 6 个单元格(H=2 × D=3 = 6),验证
DraftProjections.q的形状为(draft=3, B=1, H=2, D=3) - 理想情况:色带整齐、数值与步数一一对应、X 轴单元格数 = H × D
- 异常指示:若色带混杂、数值跳跃、或单元格数不对,说明
window()的torch.stack布局有 bug
左下 (c):RawInputRing vs 投影重放:共享重演引擎
- 图类型:双柱对比图(占位柱,因误差为 0 无法显示高度)
- X/Y 轴:X 轴为两条路线("批量构造 (decode.py)" vs "RawInputRing (replayssm.py)");Y 轴为占位(误差为 0,无实际刻度)
- 颜色含义:浅蓝柱 = decode.py 批量构造;浅红柱 = RawInputRing 流式写入。柱内绿色文字标注"误差 = 0.00e+00"
- 你该看什么:两根柱子内均显示"误差 = 0.00e+00"——这是最关键的正确性信号,证明两条路线经
verify_and_replay后与kda_recurrent参考逐位一致 - 理想情况:两柱等高(占位),内部文字均为绿色"误差 = 0.00e+00"
- 异常指示:若任一柱内文字非零、或显示红色/警告色,说明重演逻辑或数据传递有 bug
右下 (d):带宽账:raw input vs 假想快照
- 图类型:双折线对比图(带填充区域)
- X/Y 轴:X 轴为"draft 长度"(1-8,线性刻度);Y 轴为"缓存字节数 (B)"(0-8000+,线性刻度)
- 颜色/线型含义:蓝色圆点线 = raw input
(q,k,v,g,beta);红色方块线 = 假想快照(完整状态 S)。两线之间粉色填充区域表示成本差距 - 你该看什么:蓝线始终在红线下方,且差距随 draft 长度线性扩大;右下角注释框标注"快照是 raw input 的 1.94 倍"(H=2, dk=8, dv=8, fp64)及"KDA 的 per-channel gate 让差距更大"
- 理想情况:蓝线斜率 < 红线斜率,两线间距随 X 增大而扩大,填充区域清晰可见
- 异常指示:若两线交叉、或蓝线在上、或比值注释与
snapshot_cost_ratio计算结果不符,说明成本模型有 bug
7.6 调节建议
- 想看环形覆盖的临界行为 → 调 capacity 到更小值(如 2),观察 push(1) 起即出现红色
- 想看不同 H/D 下的布局 → 调
_make_projections的 h/dk 参数,观察右上热图 X 轴单元格数变化 - 想看更大 draft 下的带宽差距 → 调 draft_lens 范围到 16 或 32,观察右下两线分离程度
7.7 为什么重要
本 Tab 是 KDA 投机解码正确性的主锚点。它验证了 RawInputRing 与 decode.py 批量构造在数学上的完全等价性——如果左下误差非零,说明 verify_and_replay 的重演逻辑或 RawInputRing 的数据封装有 bug,将直接导致在线投机解码产生错误输出。同时,右下的带宽账从工程角度论证了"为什么必须走 raw-input 路线而非快照路线":KDA 的 per-channel gate 让完整状态矩阵的存储成本随 dk·dv 乘积膨胀,而 raw input 仅随 3dk+dv+1 线性增长。若错误地采用快照方案,在大 batch、长 draft 的生产环境中,状态深拷贝的带宽开销将抵消投机解码的全部收益。
0x08 Tab 5: 统一页池
8.1 目的
展示统一页池中 MLA 页随序列长度线性增长 vs KDA 恒定一页(KDA‑Infra §2)。
8.2 UI 组件与参数影响
无参数,页面加载时自动运行。
8.3 输出图解读

单图(log‑log 折线图):
- 蓝色(Blue)折线:MLA 占用 page 数 vs 序列长度(512/1024/4096/16384/65536)
- 橙色(Orange)虚线:KDA 一层固定 1 page(水平线 y=1)
- X 轴 = 序列长度(tokens),Y 轴 = 页池 page 数,双对数刻度
- 你该看什么:MLA 是斜率=1 的直线(线性增长),KDA 是水平线(恒定)
8.4 为什么重要
量化展示混合架构下两种注意力的内存增长行为差异。统一页池让两种 page 共享同一份 free list,上层不必区分类型。
0x09 Tab 6: MLA 分页
9.1 目的
展示 MLA 按 token 分页跨页 + pack_heads/unpack_heads 无损往返。
9.2 UI 组件与参数影响
无参数,页面加载时自动运行。
9.3 输出图解读

1×2 布局:
左图:append_mla(600), tokens_per_page=512
- 柱状图,X 轴 =Page #id,Y 轴 =filled(token 数)
- 红色(Red)虚线:页容量 512
- 柱旁标注 "512/512" 和 "88/512"
- 你该看什么:600 token 跨 2 页,第一页满 512,第二页 88
右图:pack_heads / unpack_heads 无损往返
- 文字标注:原始形状 → pack → flat 形状 → unpack → 还原形状
- 最大差 + PASS/FAIL 判定
- 你该看什么:往返最大差 < 1e‑12,PASS
9.4 为什么重要
MLA 分页是 PagedAttention 语义的基础。pack/unpack 无损是跨节点传输和页池存储正确性的前提。
0x10 Tab 7: KDA 存储
10.1 目的
展示 KDA 状态 store_kda / load_kda 的无损往返。
10.2 UI 组件与参数影响
无参数,页面加载时自动运行。
10.3 输出图解读

1×2 布局:
左图:store_kda: (B,H,dk,dv) → flat → page.data
- 文字标注:state 形状 → pack → flat 形状 → 写入 page.data
- 底部灰色文字:后续为 pad 零
右图:load_kda 往返验证
- 蓝色(Blue)文字:load_kda → 还原形状
- 绿色(Green)/红色(Red)文字:最大差 + PASS/FAIL
- 你该看什么:往返最大差 < 1e‑12,PASS
10.4 为什么重要
KDA 状态的 store/load 是投机解码回滚和前缀缓存 checkpoint 持久化的基础。如果往返有损,恢复出的状态会偏离正确值。
0x11 Tab 8: 前缀缓存命中
11.1 目的
展示前缀缓存两阶段 lookup 流程 + chained hash 链式依赖(KDA‑Infra §2 双粒度)。
11.2 UI 组件与参数影响
无参数,页面加载时自动运行。
11.3 输出图解读

1×2 布局:
左图:两阶段 lookup 流程
- 方框箭头示意图:
- 蓝色(Blue): 阶段 1 MLA chained hash 逐块匹配
- 橙色(Orange): 候选边界 [512, 1024, ...]
- 紫色(Purple): 阶段 2 KDA 从最深回退找 checkpoint
- 红色(Red): MLA miss → break
- 黄色(Yellow): checkpoint 原子性检查
- 绿色(Green): hit! matched_tokens
- 你该看什么: 两阶段串行,阶段 2 从阶段 1 的最深匹配往回退
右图:chained hash 链式依赖
- 文字标注:H1 = sha256("", [0..511]), H2 = sha256(H1, [512..1023])
- "H2 depends on H1 → entire prefix"
- 底部:H1 前 12 位 hex
- 你该看什么: chained hash 保证 hit = 内容完全一致
11.4 为什么重要
前缀缓存是 K3 服务层的关键优化—1M 上下文下 prefix 400K,命中一次避免重算整个前缀,比 miss 便宜几个数量级。两阶段 lookup 是混合架构(KDA+MLA)的必然选择。
0x12 Tab 9: 前缀缓存未命中
12.1 目的
展示前缀缓存两种未命中场景:无 KDA checkpoint → miss,部分 checkpoint → 回退到最近可用边界。
12.2 UI 组件与参数影响
无参数,页面加载时自动运行。
12.3 输出图解读

1×2 布局:
左图:场景 1 * 无 KDA checkpoint → miss
- 红色(Red)边框
- 文字: matched: 0, checkpoint: None
- "hit: False → 必须从头重算"
- 你该看什么: 没有 checkpoint 时即使 MLA hash 匹配也无法复用
右图:场景 2 * checkpoint 仅在 512 → 回退到 512
- 橙色(Orange)边框
- 文字: matched: 512, checkpoint: 512
- "阶段 1 匹配到 1024,但 1024 无 checkpoint → 回退到 512"
- 你该看什么: 原子性约束导致回退—1024 处缺 checkpoint 则不可用
12.4 为什么重要
理解未命中场景是调试前缀缓存命中率的关键。无 checkpoint 和部分 checkpoint 是生产环境最常见的两种 miss 原因。
0x13 Tab 10: 引擎 before/after
13.1 目的
收官汇总:多请求共享前缀时,前缀缓存到底省了什么—reused_tokens、MLA KV 线性 vs KDA 恒定、KCP 通信量 O(1)。
13.2 UI 组件与参数影响
无参数,页面加载时自动运行。
13.3 输出图解读

1×3 布局:
左图 (a): prefix‑cache reuse of 2nd request
- 柱状图: without_prefix (reused=0) vs with_prefix (reused=512)
- 柱旁标注数值
- 你该看什么: 命中时第二请求免重算 512 token
中图 (b): KV cache vs KCP comm
- 双折线(semilogx): MLA KV (linear) 随序列增长,KDA KCP (constant) 水平
- 你该看什么: KCP 通信量与序列长度无关
右图 (c): KCP comm is O(1) in length
- 单折线(semilogx): KCP 通信量水平线
- 你该看什么: KCP 通信量恒定
13.4 为什么重要
这是前 4 个子系统的收官汇总—量化回答"第二个请求复用前缀时到底省了什么"。reused_tokens=512 vs 0 是前缀缓存收益的直接度量。
0x14 Tab 11: Fleet 一致哈希
14.1 目的
展示一致哈希环的虚拟节点分布 + 600 session 路由分布均匀性(K3 报告 §5.4.3)。
14.2 UI 组件与参数影响
无参数,页面加载时自动运行。
14.3 输出图解读

1×2 布局:
左图:一致哈希环分布(8 集群 × 8 vnodes)
- 圆环散点图,8 种颜色对应 8 个集群
- 每个集群 8 个虚拟节点均匀散布在环上
- 你该看什么: 虚拟节点在环上分布均匀
右图:600 session 路由分布
- 柱状图,8 根柱对应 8 个集群,Y 轴=session 数
- 灰色虚线:均匀线 (75)
- 你该看什么: 各集群 session 数接近 75,分布均匀
14.4 为什么重要
一致哈希是 cache‑aware affinity scheduling 的基础—session 稳定路由到持有其 prefix cache 的集群。均匀分布保证负载均衡。
0x15 Tab 12: Fleet 最小扰动
15.1 目的
验证一致哈希的 hopscotch 性质:移除 1 集群只扰动 O(1/N) 的 session。
15.2 UI 组件与参数影响
无参数,页面加载时自动运行。
15.3 输出图解读

1×2 布局:
左图:移除 c3 后扰动
- 柱状图:绿色(Green)=未扰动,红色(Red)=扰动
- 柱旁标注数值
- 你该看什么: 扰动数 ≈ 600/8 = 75(理论 12.5%),远小于总数
右图:移除 c3 后无 session 指向 c3
- 绿色(Green)文字:指向 c3 的 session: 0
- 蓝色(Blue)文字:改绑比例 = X%(理论 ~1/8 = 12.5%)
- 你该看什么: 失效集群不再接收任何 session
15.4 为什么重要
最小扰动是 failover 可预期性的基础—集群故障时只有绑定到该集群的 session 需要改绑,re‑prefill 工作量被均匀分散到全 fleet。
0x16 Tab 13: Fleet 预算隔离
16.1 目的
展示预算隔离前后短请求 P95 TTFT 的差异(K3 报告 §5.4.3)。
16.2 UI 组件与参数影响
无参数,页面加载时自动运行。
16.3 输出图解读

1×2 布局:
左图:长突发混流 − 隔离后 P95 反而更糟
- 分组柱状图:红色(Red)=无预算(全通),绿色(Green)=预算隔离
- X 轴 = 请求类(short/long),Y 轴 = P95 TTFT
- 你该看什么: 隔离后 short 的 P95 ≈ 2,001,000,反而高于无隔离时的 ~6.0
- 原因: 预算隔离把大量请求拒绝了(short 拒绝 52 个,long 拒绝 14 个),被拒绝的请求 P95 TTFT 被计为无穷大(或极大值),拉高了整体 P95
右图:预算隔离 − 短请求被拒绝更多
- 柱状图:rejected(long)=14 和 rejected(short)=52
- 你该看什么: 短请求被拒绝 52 个,远多于长请求的 14 个——这与"短请求零拒绝"的宣称完全相反
- 原因:
short_budget=8意味着同时只能有 8 个 short 请求在飞,而场景提交了 60 个 short 请求,超额的 52 个全部被拒绝;long_budget=8只提交了 20 个 long,所以只拒绝 14 个
真正的预算隔离机制:
short_budget/long_budget是并发上限,不是"保护短请求"的配额- 当某类请求超过并发上限时,超额部分直接被拒绝(不是排队等待)
- 这个 demo 的参数设置(short_budget=8 vs 60 个 short 请求)故意制造了大量拒绝,用来演示"限流"行为,而不是"保护短请求"
实际行为是:预算隔离通过拒绝超额请求来保护系统容量,而不是通过"优先服务短请求"来降低短请求延迟。
16.4 为什么重要
生产流量混着短请求和超长请求,长度横跨 3 个数量级。预算隔离保证长突发不拖累短请求的 TTFT。
0x17 Tab 14: Fleet 综合仿真
17.1 目的
Fleet 综合仿真:8 集群、20 long + 50 short 请求,产出命中率/代价/P95 TTFT/负载均衡/failover 汇总指标。
17.2 UI 组件与参数影响
无参数,页面加载时自动运行。
17.3 输出图解读

1×3 布局:
左图:命中率 + 集群负载分布
- 柱状图,X 轴=集群 id,Y 轴=累计负载
- 标题显示命中率
- 你该看什么: 各集群负载接近均匀
中图:TTFT 分布(short)
- 直方图,X 轴=TTFT,Y 轴=频次
- 红色(Red)虚线:P95 TTFT
- 你该看什么: P95 TTFT 越低越好
右图:汇总指标
- 文字列表:命中率、总代价、短/长 P95 TTFT、拒绝数、Failover 数、负载标准差
- 你该看什么: 命中率 > 0、负载标准差小(均衡)
17.4 为什么重要
这是 Fleet 层的端到端验证—命中率、P95 TTFT、负载均衡、failover 四个维度的汇总指标直接反映服务层质量。
0x018 验证策略总览
| Tab | 测试函数 | 验证点 | 通过标准 |
|---|---|---|---|
| 1 | 投机回放原理 | test_verify_replay_partial_matches_full_recurrence |
verify_and_replay 部分接受与 kda_recurrent 一致 |
| 2 | 快照成本 | test_snapshot_cost_ratio_exceeds_one_and_grows_with_state |
比值 >1 且随 dk*dv 增大 |
| 3 | 重演一致性 | test_verify_replay_accept_all_matches_full |
全部接受与完整递推一致 |
| 3 | 重演一致性 | test_verify_replay_reject_zero_is_identity |
零接受 = 原状态不变 |
| 4 | ReplaySSM | test_ring_evicts_oldest_at_capacity |
满员覆盖最旧 |
| 4 | ReplaySSM | test_pop_after_refill_returns_oldest |
满pop→push→pop仍返回最旧 |
| 4 | ReplaySSM | test_copy_from_is_deep_and_independent |
深拷贝独立 |
| 5 | 统一页池 | test_append_mla_increments_pages_across_boundary |
600 token 跨 2 页 |
| 6 | MLA 分页 | test_pack_unpack_roundtrip |
pack→unpack 无损 |
| 7 | KDA 存储 | test_store_and_load_roundtrip |
store→load 无损 |
| 8 | 前缀命中 | test_register_then_lookup_at_same_prefix_hits |
同前缀命中 |
| 8 | 前缀命中 | test_two_stage_uses_longest_checkpoint_boundary |
两阶段回退到有 checkpoint 的边界 |
| 9 | 前缀未命中 | test_lookup_without_checkpoint_misses |
无 checkpoint → miss |
| 9 | 前缀未命中 | test_checkpoint_atomic_across_groups |
原子性:缺一个 group → 不可用 |
| 10 | 引擎 | test_engine_returns_hit_stats |
命中时 reused=512 |
| 10 | 引擎 | test_engine_miss_returns_zero |
未命中时 reused=0 |
| 11 | Fleet 哈希 | test_ring_distributes_sessions_uniformly |
路由分布均匀 |
| 12 | Fleet 扰动 | test_remove_cluster_only_affects_few_sessions |
移除 1 集群扰动 < 60% |
| 13 | Fleet 预算 | test_budget_isolates_long_burst_from_short |
长满不影响短准入 |
| 14 | Fleet 仿真 | test_simulator_routes_to_primary_on_hit |
同 session 第二请求命中 |

0xFF 参考
原文地址: https://www.cveoy.top/t/topic/qHUG 著作权归作者所有。请勿转载和采集!