Files
agentic-pd-hybrid/docs/V2_DEEP_ANALYSIS_ZH.md
kzlin 314c4cda0e docs(kvc): redesign gpu_utilization figure to lead with system-total compute
Reviewer feedback: the original gpu_utilization figure was confusing.
"P does prefill" is a trivial restatement of the architecture; the
figure didn't make clear what insight it was supposed to convey.

The non-trivial insight WAS in the figure but buried in per-GPU
breakdown details: KVC v2's total system compute is 3.47M tokens
vs DP's 5.17M -- a 33% reduction for the same 4449-request workload.
That's the result of session affinity actually converting to less
work, not just to better locality.

Redesigned the figure to lead with that finding:

Left panel (NEW): system-wide compute as two stacked bars
  - KVC: P heavy prefill (1.07M) + D append-prefill (1.39M) + decode (1.01M)
  - DP:  full prefill (4.17M) + decode (1.00M)
  - Big "-33% total compute" badge bracketed by an arrow between the
    bar tops makes the headline number unmissable

Right panel (kept, simplified): per-GPU work distribution
  - Same color coding as the left panel, so the architecture story
    flows from "what work the system does" to "where it happens"
  - In-panel annotation boxes describe the two architectural shapes
    (specialized P + light D vs uniform fused workers)
  - Removed the second legend that was overlapping bars

Doc §4.5 rewritten to match:
  - Old title: "[辩驳 critic] Prefill GPU 90%+ 闲置 是设计意图,不是浪费"
    (inside-baseball framing that confused external readers)
  - New title: "KVC 的 compute 经济:session affinity 让系统总 compute 减少 33%"
    (leads with the non-trivial finding)
  - Body presents 3.47M vs 5.17M directly, decomposes into prefill /
    decode segments, shows why session affinity converts to compute
    reduction (mean uncached drops from 952 to 341 on the fast path)
  - Cross-references §3.5 (TPOT) to explain why "unequal GPU load"
    is a design feature, not a bug
  - Drops the audit-rebuttal framing; the rebuttal of "P is idle"
    is now implicit in the system-total comparison

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:39:15 +08:00

658 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# KVC v2 深度分析:相对 TEAM_REPORT 基线的改进、性能、新暴露的问题
**日期**2026-05-11
**对象**:项目团队同学
**基线**`docs/TEAM_REPORT_AGENTIC_PD_HYBRID_ZH.md`v3-v6 ts=10 调优 sweep 的状态报告)
**新数据**
- `docs/REFACTOR_PLAN_V1_ZH.md`ts=1 4-run validation 结果)
- `docs/MIGRATION_V1_FINDINGS_ZH.md`v1 thrashing 诊断)
- `docs/V2_RESULTS_ZH.md`v2 reset-on-success + threshold tuning 结果)
- Critic agent 的对等性审查(本文 §4
**目的**:把"TEAM_REPORT 之后的实验产物"按改进 / 性能 / 新问题三段重新审视,明确哪些原结构性问题被消解、哪些被掩盖、哪些是新引入的。
---
## 0. TL;DR
1. **TEAM_REPORT 头条结论"真实 agentic workload 上 KVC 无配置能赢 naive DP"在 ts=1 下被推翻**——KVC v2 在 lat mean / p50 / p90、TTFT mean / p50 / p90 上全面优于 4DP CA。
2. **生产决策结论online coding agent serving 应选 KVC 1P3D**。KVC 的设计 motifsession affinity + 集中 cache + direct-to-D 快路径)正是 multi-turn 长上下文 agent workload 的 sweet spotfast path 减少 prefill 工作量 6.9× 是机制目标实现,不是 measurement artifact。
3. **真实代价只有一项TTFT p99 = 1.29s vs DP 0.43sKVC 3× 差)**——来自 8.3% 非 direct-to-D 路径的 mooncake reseed 长尾。生产部署要么用真 RDMA 把这条压下来,要么靠容量规划让 reseed 极少发生。
4. **TEAM_REPORT §1session pin 饿死)已被 v2 修好**——direct-to-D 从 42.8% 涨到 91.6%severe thrashing 清零。但 reset-on-success 是事后补的——v1 直接加 migration 制造了更严重的 thrashing 失效模式,记入设计经验。
5. **TEAM_REPORT §2/§3/§4/§5LRU / backpressure / P-side imbalance / admission RPC 干扰)在 ts=1 下消失**,但是被 ts=1 的"低压自然 drain time"吸收,不是机制层面修好。一旦回到 ts=10 / 更长 trace / 更紧容量,会全部复现——属于潜在的,不是消除的。
6. **方法学待办**(不影响产品决策):(a) 补 naive 1P3D 对照分离"KVC 层贡献"vs"1P3D 拓扑贡献"(b) 补 v2 N=2/3 验证 ts=1 确定性;(c) 拉齐两个 server 的 `max-input-len`(当前 KVC=92098 vs DP=87811 是 SGLang 自动算的差异,详见 §4.3)。
---
## 1. 三组新实验与 TEAM_REPORT 的关系
### 1.1 时间线和因果链
```
TEAM_REPORT (2026-05-06)
├─ §1-§7 列出 ts=10 数据下的 7 类结构性问题
├─ 头条结论KVC 全配置输 DP需要重构
└─ 提出 backpressure 作为最小代码修复点
↓ 2 天
ts=1 validation (2026-05-07)
4 个 runKVC 1P3D N=3 + 4DP CA × 1全部 ts=1
├─ 发现 1ts=1 下 errors 从 372-912 跌到 5DP 也 5 个,是 trace input-超限 artifact
├─ 发现 2ts=1 下 KVC 在 categorical 层面完全确定0/4449 records 跨 run 不同)
├─ 发现 3KVC 整体仍然慢 DP 9% / TTFT 慢 47%
└─ 结论TEAM_REPORT §2/§3/§4/§5 是 ts=10 高压 artifact§1 仍然是真问题(被 ts=1 衰减但不消失)
↓ 1 天
v1 migration (2026-05-08)
KVC 1P3D + rejection blacklistpolicies.py 加 session_d_rejects Counter
├─ 修复 §1session pin——18/52 starved 降到 0
├─ 但引入新失效模式6 个 session 跨 3 D 严重 thrashmax 116 次切换)
├─ Lat mean 反退化到 1.758sTTFT mean 涨到 0.419s
└─ 中期诊断blacklist 永久累积 + degenerate fallback 形成 self-amplifying 死循环
↓ 1 天
v2 migration (2026-05-09)
v1 + reset-on-success + --kvcache-direct-max-uncached-tokens 2048→8192
├─ Thrashing 消除max D-changes 116→45severe thrashing 0
├─ direct-to-D 53.3%→91.6%threshold 拉高让大 append 也走快路径)
├─ Lat / TTFT 全面赢 baseline且 7/8 头部指标赢 4DP
└─ 但 N=1 + critic 发现的对等性问题(见 §4
↓ 2 天
本文 (2026-05-11)
把上述 5 天的数据放回 TEAM_REPORT 的结构性问题清单上做审计
```
### 1.2 同 trace 全部数字总表(按时间)
来源:`outputs/qwen3-30b-tp1-*` 系列各 summary.json。**4449 reqs / 52 sessions / Qwen3-30B-A3B (TP1) / 4×H100 80GB**。
| 阶段 | 时间尺度 | 配置 | Errors | Lat mean | Lat P50 | Lat P99 | TTFT mean | TTFT P50 | direct-to-D% |
|---|---|---|---:|---:|---:|---:|---:|---:|---:|
| **TEAM_REPORT baseline 区间(全部 ts=10** | | | | | | | | | |
| v5 1P7D Option D | 10 | KVC | 9 | 5.18s | 1.59s | 26.09s | 0.207s | | 45% |
| v5 2P6D Option D | 10 | KVC | 9 | 3.49s | 1.31s | 24.92s | 0.244s | | 41% |
| v5 rerun1 (重测) | 10 | KVC | **372** | 3.50s | 1.11s | 19.49s | 0.147s | | ~40% |
| v5 rerun2 | 10 | KVC | **912** | 3.00s | 0.94s | 20.37s | 0.071s | | ~40% |
| v5 rerun3 | 10 | KVC | **396** | 3.42s | 1.22s | 18.97s | 0.183s | | ~40% |
| 8-way DP CA | 10 | DP-colo | **0** | **1.43s** | **0.65s** | **8.37s** | **** | **0.093s** | |
| **ts=1 validation 区间** | | | | | | | | | |
| v0 baseline run1 | 1 | KVC 1P3D | 5 | 1.574s | 0.811s | 8.70s | 0.245s | 0.124s | **42.8%** |
| v0 baseline run2 | 1 | KVC 1P3D | 5 | 1.573s | 0.809s | 8.74s | 0.243s | 0.120s | 42.8% |
| v0 baseline run3 | 1 | KVC 1P3D | 5 | 1.574s | 0.812s | 8.76s | 0.243s | 0.123s | 42.8% |
| 4-way DP CA | 1 | DP-colo | 0 | 1.443s | 0.659s | 8.43s | 0.129s | **0.090s** | |
| **Migration 区间** | | | | | | | | | |
| v1 migration | 1 | KVC 1P3D | 6 | 1.758s | 0.773s | 9.92s | 0.419s | 0.057s | 53.3% |
| **v2 migration (头条)** | 1 | KVC 1P3D | 5 | **1.432s** | **0.576s** | **8.69s** | **0.098s** | **0.042s** | **91.6%** |
**两组关键对比**
1. **ts=10 → ts=1同 KVC 配置)**Lat mean 5.18s → 1.574s**3.3× 改善**errors 9-912 → 5**~100× 改善**direct-to-D 41% → 42.8%(持平,机制不变)
2. **v0 → v2同 ts=1机制改进**Lat mean 1.574s → 1.432s**9% 改善**TTFT mean 0.245s → 0.098s**60% 改善**direct-to-D 42.8% → 91.6%**+48.8 pp**
**TEAM_REPORT 时代被认为"机制不可用"的 KVC把 trace 时序还原到 ts=1 + 修两个旋钮后,赢了同 scale 下的 4DP。**
---
## 2. TEAM_REPORT §1-§9 的逐项更新
按原始优先级排序,每条标注"是否仍是问题 / 被什么消解 / 残留风险"。
### 2.1 §1KvAwarePolicy 不感知 D 容量 + Session 永久 pin — **被 v2 修好**
| 维度 | TEAM_REPORT 状态 | v2 状态 | 修复机制 |
|---|---|---|---|
| 跨 run 一致饿死 session 数 | 13/5225% | 0 | `policies.py: session_d_rejects` + `replay.py: reset-on-success`:每次 direct-to-D 成功清零 reject 计数,连续失败累积到阈值 3 才迁移 |
| Avg distinct-D / session | 1.00 | <2v2 实测 mean=0.6 D-changes/session | 同上 |
| direct-to-D % | 41% | 91.6% | 同上 + threshold 20488192 |
| 饿死 session turn 6× | | 饿死消失 | |
**残留风险**reset-on-success reactive 修复——session 必须先经历 N 次失败才迁移并且第一次失败的那个 turn 仍然慢在严苛容量下如把 trace 改成 ts=2 sess 数翻倍迁移阈值可能频繁触发重新逼近 v1 thrashing 区域。**未在更紧 workload 上验证。**
### 2.2 §2D 端 LRU 跟不上 → 8% errors — **被 ts=1 自然吸收**
| 维度 | TEAM_REPORT 状态 | v2 状态 | 原因 |
|---|---|---|---|
| run KVTransferError | 369 | 0 mooncake timeout | ts=1 inter-turn gap p50 = 2.5s D 充分 drain 时间 |
| D 峰值 token_usage | 6 D 全顶到 0.97-1.00 | 偶发 0.97-1.00burst常态 0.4-0.85 | 同上 |
| LRU trim 触发次数 | 9-43远不够 | 不需要——D 自然回落 | ts=1 工作流 |
**残留风险**这条**没有机制层面修好**。 ts 调回 10或者 session 数从 52 增到 100+、或者 model 切到更大都会立刻让 D 容量重新顶死LRU 再次跟不上。**TEAM_REPORT §2 是潜在的不是消失的。**
### 2.3 §3无 D→Replay backpressure — **代码已写但冷藏**
| 维度 | TEAM_REPORT 状态 | v2 状态 |
|---|---|---|
| 代码实现 | 提议 | 已合入`--enable-backpressure` flag`recommended_pause_ms` 字段`_compute_backpressure_pause_hint` |
| 是否启用 | | 默认 **off** |
| 启用后效果 | 预期 errors 370→<50 | 未验证ts=1 下无作用对象 |
**残留风险**代码冷藏意味着发生在生产 RDMA / 更大 trace 上的回归不会触发保护。**如果团队决定项目要支持 ts=10 / 更大 sessions需要把 backpressure 默认 on 并补 smoke 验证。**
### 2.4 §4P-side round-robin 不感知 D 健康 — **1P 配置不可测**
v2 1P3D P无从测试 P-side 调度TEAM_REPORT 数据来自 2P6D 配置
**残留风险**未来如果扩到 2P+ 必须重新审查 P 侧调度。**当前数据无法支持也无法反驳。**
### 2.5 §5Admission RPC 与 scheduler 互相干扰 — **ts=1 下不显著**
TEAM_REPORT 现象1Hz polling errors 46×来自 ts=10 高压时的 scheduler 主循环争抢ts=1 D scheduler 大部分时间空闲RPC 进来不阻塞 batched prefill
**残留风险** §2 同源——属于 ts=10 高压 artifact
### 2.6 §6time-scale=10 失真 — **DONE作为前置条件锁定**
| 现象 | ts=10 | ts=1 | 比例 |
|---|---:|---:|---:|
| Errors | 372-912 | 5trace input-超限 artifact | **74×↓** |
| TTFT P50 | 0.07-0.18s | 0.04s | 4.5×↓ |
| Per-D spread | ±26% | ±3.8% | 7×↓ |
| Lat P99 | 18-29s | 8.7s | 2-3×↓ |
**REFACTOR_PLAN_V1 把这条当作所有后续讨论的前置条件——ts=10 数据从此不参与 KVC vs DP 比较。**
### 2.7 §7execution_mode 标签错位 — **部分修复**
`pd-router-fallback-large-append-*` v1+ 被细分成
- `pd-router-fallback-real-large-append-session-cap`实际 append > 阈值)
- `pd-router-fallback-session-not-resident-session-cap`session 在该 D 上没住过)
- `pd-router-fallback-no-d-capacity`D 全满)
- `pd-router-fallback-session-not-resident-seed-filter-early-turn`
**残留**error_count 在 KVC vs DP 之间口径不一致(见 §4.3),未统一。
### 2.8 §8N=1 不可信 — **ts=1 下规则改写**
| Trace 区间 | N 要求 |
|---|---|
| ts=10 高压 | N≥3v5 rerun 显示 errors 漂移 2.5× |
| ts=1 常规 | N=1 可信baseline N=3 显示 0/4449 records 跨 run 不同) |
**残留**v2 引入了新代码路径reset-on-success + threshold=8192但仅 N=1。新分支是否仍保持 categorical 确定性**未验证**。这是 critic 标 MINOR 但未关闭的点。
### 2.9 §9microbench 把 KVC 失效条件全规避 — **保留为方法学原则**
v2 的胜利证明 microbench 的"赢 PD disagg"在 SWE-Bench 上也能复现,但 TEAM_REPORT §2.9 的方法学原则仍然成立——micro-benchmark 应该主动构造能触发 fallback 的 workload。
---
## 3. v2 的真实性能拆解path-level
v2 整体跑得快不仅因为 "KVC 机制好",更因为 **91.6% 请求被路由到了几乎免费的 fast path**。需要看路径级细节才能理解胜利的来源。
### 3.1 v2 内部 execution_mode 分布
![KVC v2 execution_mode 分布](figures/v2_execution_mode_distribution.png)
数据来源:`outputs/qwen3-30b-tp1-ts1-migration-v2/kvc_1p3d_migration_v2_run1_metrics.jsonl`n = 4449全部请求含失败。绿色 = direct-to-D 快路径 = 91.6%;其余红色 = 慢路径 / fallback / 失败。绘图脚本:`scripts/analysis/plot_v2_path_breakdown.py`
### 3.2 path-level 延迟 vs DP
![Path-level latency: KVC v2 各路径 vs DP](figures/v2_path_level_latency.png)
数据来源:同上 + `outputs/qwen3-30b-tp1-ts1-validation/dp4_metrics.jsonl`。Y 轴 log 刻度latency 跨度 41ms ~ 7.71s)。已过滤 abort / error 请求,所有数字按对等口径计算。
**关键事实**
- KVC 的 91.6% **fast path** 在 TTFT p50 上是 **41ms vs DP 92ms**——压制 DP 2.2×TTFT p99 150ms vs DP 428ms 仍优 2.9×
- KVC 的 **3.4% reseed 慢路径** TTFT p99 = **5.12s**,是 DP 单一路径 p99428ms**12×**
- KVC 的 **0.7% no-d-capacity fallback** 是最坏情况TTFT p99 = 7.65smooncake 大 transfer + 重试链)
- DP **没有 slow path**——单一 `dp-colo-router` mode最坏 TTFT p99 0.43s,全程稳定
- 整体 latency p50 上 KVC fast path552ms仍比 DP 全量668ms快 17%;这是 v2 整体 lat p50 -13% 的来源
### 3.3 Fast path 的工作量比 DP 少 6.9× —— 不是 mechanism 更快
| 路径 | Mean uncached tokens |
|---|---:|
| KVC direct-to-D | **341** |
| DP dp-colo-router | **2355** |
**KVC 之所以快**,是因为 91.6% 请求的 prefix KV **已经在目标 D 上**,本次只需 append 平均 341 tokenDP 同样请求要 prefill 平均 2355 token**6.9× 工作量**)。
这是结构性的 KVC vs DP 差异——**KVC 的设计就是利用 session 间 KV 复用**,所以"工作量少"本身就是机制核心目标。但在比较时必须诚实:
> KVC 的 TTFT 优势 = **session-aware 路由减少了 prefill 工作量****不是** D 端硬件层面更快。
如果工作量做归一化(比如限定都做 2000 token 以上 uncached prefillKVC 应该和 DP 在同一速度量级。
### 3.4 TTFT 概率密度对比bimodal vs unimodal
把 path-level 数据投影到 TTFT 的分布维度,可以更直观看出 KVC 与 DP 是**本质不同的两种分布形状**
![TTFT probability density: KVC v2 vs 4-way DP](figures/ttft_pdf_comparison.png)
左图(线性 x ∈ [0, 0.6s])看 body
- **KVC 的 PDF 在 ~40ms 有一个尖锐峰值**(来自 91.6% direct-to-D fast path
- **DP 的 PDF 是宽峰,集中在 50-200ms**(每个请求都要做完整 prefill 的固有时间)
- 在 body 区间KVC 把 50% 请求压在 41msDP 的 50% 在 92ms
右图log x ∈ [10ms, 10s])看全范围:
- **KVC 是 bimodal 分布**fast path 主峰(~40-50ms+ slow path reseed 尾峰(~1-5s
- **DP 是 unimodal 分布**:单一宽峰,从 ~50ms 拖到 ~500ms 截止
- KVC p99 = 1.28s 来自小尾峰DP p99 = 0.43s 来自主峰宽尾
**论文意义**:这两种分布形状的本质差异比单个 percentile 数字更说明问题——KVC 的 TTFT 不是"DP 整体快"或"DP 整体慢",而是"绝大多数极快 + 少数比 DP 慢得多"。生产决策的判据应该是 **fast path 集中度 vs slow path tail 长度**的权衡,而不是单个 mean 或 p50 数字。
绘图脚本:`scripts/analysis/plot_ttft_pdf.py`(用 `scipy.stats.gaussian_kde`body 用 Scott bandwidth 0.15full range 用 log10 域 KDE
### 3.5 TPOT 概率密度对比KVC 不牺牲 decode 速度
为防止 reviewer 质疑"KVC 的 TTFT 优势是否以牺牲 decode 速度TPOT换来的",我们对 token 间延迟也做了概率密度对比:
![TPOT probability density: KVC v2 vs 4-way DP](figures/tpot_pdf_comparison.png)
实测 TPOT 分位数:
| 指标 | KVC v2 | DP 4w | Δ |
|---|---:|---:|---:|
| min | 4.432ms | 4.420ms | +0.012ms |
| p50 | 5.561ms | 5.525ms | **+0.035ms (+0.6%)** |
| p90 | 6.644ms | 6.694ms | **0.050ms (0.7%)** |
| p99 | 7.568ms | 7.543ms | +0.026ms |
| mean | 5.680ms | 5.661ms | **+0.019ms (+0.34%)** |
| std | 0.711ms | 0.720ms | 0.009ms |
| max | 11.315ms | 9.531ms | +1.78ms |
**核心事实**在主体分布p99 以下,覆盖 99% 请求)上,**KVC 与 DP 的 TPOT 差异在 0.05ms 以内(< 1%**。两条 KDE 曲线视觉上几乎完全重合左面板)。这是预期行为——decode 阶段在同样模型 (Qwen3-30B-A3B) 和同样 GPU (H100) per-token 延迟由硬件 + 模型架构决定与路由策略无关
**唯一可见差异在 max 处**KVC 11.3ms vs DP 9.5ms**KVC 尾部多了 ~1.8ms outlier**。来源推测reseed 后的 cold start decodeKV 刚到 D warm-up 的第一个 decode step 略慢于 steady state)。这影响 0.1% 的请求可忽略
**论文意义(重要)**这张图防的是 reviewer "KVC 是不是用 decode 慢换 TTFT "质疑答案是**没有**——KVC 的胜利**完全发生在 prefill 路径**直接 append-prefill in D, vs DP 的全 prefill on workerdecode 路径两边都是直接 batched generation速度相同
**对照 §3.2 path-level latency**那张图的"Lat p50"列里 KVC fast path 0.55s vs DP 0.67s 的差距**几乎全部来自 TTFT **KVC 41ms vs DP 92ms = 51msdecode 段双方都消耗 mean output_tokens × TPOT 227 × 5.7ms 1.3s一致)。这一致性是 TPOT 图的直接体现
绘图脚本`scripts/analysis/plot_tpot_pdf.py` `scipy.stats.gaussian_kde`body bandwidth 0.15full range log10 KDE)。
---
## 4. 需要诚实交代的 caveats不是 KVC 的设计缺陷)
Critic agent v2 vs 4DP 的对等性做了 10 项审查下面分两类
- **真实代价**(§4.1-§4.3)— KVC 机制本身的开销无法回避论文里必须讲清楚
- **辩驳 critic**(§4.4-§4.5)— critic KVC **设计意图**误标为"对比不公平"本节澄清
- **方法学待办**(§4.6-§4.7)— 实验对照层面的事需要补但不影响产品决策
### 4.1 TTFT p99 长尾 — **真实代价,必须显式报告**
实测 TTFT 全分位数
| 指标 | KVC v2 | DP | Ratio |
|---|---:|---:|---:|
| TTFT p50 | 0.042s | 0.090s | 0.47× (KVC ) |
| TTFT p90 | 0.091s | 0.252s | 0.36× (KVC ) |
| **TTFT p99** | **1.285s** | **0.427s** | **3.01× (DP 劣)** |
| **TTFT p99.5** | **2.65s** | **0.485s** | **5.47× (DP 劣)** |
| **TTFT > 1s 计数** | **59** | **9** | **6.5× (DP 劣)** |
之前 `V2_RESULTS_ZH.md §2` headline 表省略了 TTFT p99是错的。**论文里 headline 必须包含 p99**——KVC mean/p50/p90 全胜但 p99 3×要诚实摆出来这不是赢负翻盘p99 之外都赢 p99 长尾是真实代价
### 4.2 TTFT p99 恶化的根因8.3% 非 direct 路径的 mooncake reseed
59 TTFT > 1s 请求的 mode 分布:
```
49 个 pd-router-d-session-reseed (83%) ← session 被驱逐/迁移后重新拉 KV
5 个 pd-router-fallback-no-d-capacity (8%)
4 个 pd-router-fallback-session-not-resident-session-cap (7%)
1 个 pd-router-fallback-real-large-append-session-cap (2%)
```
按 session 分布88% (52/59) 集中在 5 个超大输入 session22080 / 44800 / 22400 / 58080 / 45280input 60-90K
**机理拆分**reseed 路径的延迟由两段组成——
1. **P 端 re-prefill 段**:用 trace 中带的完整 prompt 在 P 上重新算 prefill。**典型场景**session 在 P 上 seed 完turn 0~1K tokens之后turn 1-50 全走 direct-to-D appendturn 51 D 端 LRU 驱逐 / 容量拒绝触发 reseed。此时 P 端的 backup若开 `capacity-backup`)仍是 turn-0 的 ~1K 状态turn 1-50 的 ~49K append 内容**从未流过 P**。SGLang 的 radix prefix cache 在 P 上只能匹配 turn 0 的 1K剩余 ~49K 必须由 P 重新跑 prefill kernel——这一步占 reseed 总时间的大头(约 1.5-3s @ 1×H10030B 模型)。
2. **P→D mooncake transfer 段**:把整段 KV50-90K tokens 对应的 KV 张量,~5-9 GB通过 mooncake 推到目标 D。本次 benchmark 用的是 TCP loopback实测 1.5-4s取决于 session 大小)。生产用 IB RDMA节点实际有 mlx5_0/_1 @ 200 Gb/s × 2 active应可压到 200-400ms。
**两段相加**:当前 reseed 中位 ~2.5s、p99 ~7.7s。
### 缓解策略的真实效果
- (a) **真 RDMA 替换 mooncake TCP loopback**——救的是 transfer 段(~1.5-4s → ~200-400ms不动 re-prefill 段。预期 reseed 总延迟从 3-7s 压到 **1.7-3.2s**TTFT p99 从 1.28s 降到 ~0.7s 量级(**仍输 DP 0.43s**)。**当前 sweep 未启用**(缺 `--force-rdma --ib-device mlx5_0`)。
- (b) **容量规划**sessions × peak context ≤ 总 D KV pool × 0.7,让 LRU/reseed 几乎不触发。对生产部署而言最可靠,但对本 trace 不适用——sessions 已固定。
- (c) **D→P 增量同步**——**整个项目最大的工程缺口**:要消灭 re-prefill 段,必须让 P 端的 backup 在 direct-to-D append 完之后同步追上 D 的当前 KV 状态。这样 reseed 时 P 端已经有最新整段 KV可以直接 P→D transfer无需 re-prefill。**经独立 Opus agent forensic 审查(见 commit 信息),当前框架代码层 / vendored SGLang 层 / mooncake 层均没有任何 D→P KV transfer 实现**
- mooncake `MooncakeKVManager``DisaggregationMode` 强角色分支PREFILL 模式拥有 senderDECODE 模式纯 receiver-only loop`assert disaggregation_mode == PREFILL``add_transfer_request` 上是硬约束
- `BaseKVSender` / `BaseKVReceiver` 是双角色抽象,**没有任何 bidirectional slot**
- D 端 `session_aware_cache.release_session` 只调 `kv_pool_allocator.free()`,无序列化、无出站网络调用
- `_commit_prefill_backup_residency` 唯一 caller 是 `_invoke_kvcache_seeded_router`seed/reseed 路径direct-to-D 路径从不更新 P 端 backup
- `capacity-backup` policy 的真实语义只是"reseed 完不关 P streaming session"——P 端 KV 是 seed-time 的**静态快照**,不随 D 的 append 而增长
- **实现 D→P 同步的工程量评估**~1-2 周。最难的不是网络层mooncake 加 D-sender + P-receiver 角色 ~400 LOC 改动),而是 **SGLang radix tree 改成允许从外部 worker 喂数据**——radix cache 当前假设单一生产者(本 worker model 输出)。这是论文里 §future-work 的核心 contribution 缺口。
### 4.3 Error 统计口径已修复abort 数双方都比之前发现的多
之前 V2_RESULTS_ZH.md 说"DP 同样有 5 个 input-too-long abort"。实测纠正:
| Run | error_count | abort_count | failure_count |
|---|---:|---:|---:|
| KVC v2 | 5 (ReadTimeout) | **40** | **45** |
| DP 4w | 0 | **67** | **67** |
两边都有大量 abort**不是只有 DP 有**。原因SGLang 服务器启动时自动算 `max-input-len`
- KVC decode-only worker → `max_total_tokens=92104` → max-input=92098可用 GPU 内存 10.85 GB
- DP fused worker → `max_total_tokens=87817` → max-input=87811可用 GPU 内存 8.93 GB因为还要给 chunked-prefill workspace ~2 GB
DP 限制更紧,所以 abort 多 27 个。**这是 SGLang 自动 mem 分配的产物,不是机制差异。**
**已修代码**`src/agentic_pd_hybrid/metrics.py` 加了 `_is_failed_request` 过滤 + `abort_count`/`failure_count` 字段abort 行不再算"快请求"被计入 lat stats。重算后
```
修复前 修复后(排除 abort
KVC v2 lat_mean 1.4323 1.4441
DP 4w lat_mean 1.4435 1.4642
delta (KVC vs DP) -0.8% -1.4% ← KVC 优势略放大
```
**论文里要拉齐两个 server 的 `--max-input-len`**(都设到较小的 87811重跑一次消除这层 confound。
### 4.4 [辩驳 critic] "Cache 集中是架构差异,不是策略胜利" ≠ KVC 不该赢
Critic 的 framing
> KVC 之所以赢,是因为它把 cache 集中到 3 个 D每个 ~43M tokenDP fragment 到 4 个 worker每个 ~30M token。两边 policy 都是 `kv-aware`,差异来自架构而非策略。
**反驳**KVC 整套机制的**核心设计就是主动选择 affinity 集中而非 fragment**。"差异来自架构"等价于"差异来自 KVC 是 KVC"——这正是要论证的设计点。更重要的:**KVC 的总 KV pool 实际上比 DP 少 27%**KVC 3×92K=276K vs DP 4×87K=351K tokens但 cache 命中率仍然更高98.1% vs 96.8%)。
![Cache efficiency paradox: KVC 用更少的总池子缓存更多](figures/cache_efficiency.png)
**左图 — 命中率随 turn 的演化**揭示了 cache 效率不是"总池子大小"决定的,是"留什么"的策略决定的:
- KVC 的 session affinity → cache 在被钉定的 D 上**随 turn 累积**hit rate 单调上升
- DP 的 hash 路由 + radix LRU → 跨 session 共享 87K poolhit rate 在 turn 8-25 区间KVC 97.0% vs DP 95.8%,差 **1.24pp**)出现"中段 drift"
- 后期两边都稳定在 ~98-99%session 长时间没换cache 反复命中),但 DP 的 IQR band 更宽 → 不同请求 / 不同 session 之间命中波动更大
**右图 — uncached tokens 的 ECDF** 量化了 per-request 影响:
- KVC 50% 请求 uncached ≤ **187 tokens**DP 50% 请求 uncached ≤ **781 tokens**4× 差距)
- 在 uncached = 500 tokens 阈值上:**KVC 74% 请求落在该阈值以下DP 只有 31%**
- KVC 的曲线 "撞墙" 在 ~200 token 处快速爬到 0.5DP 的曲线在 100-10K 区间均匀展开
→ 论文里这是 **contribution**,不是 caveatKVC 的 mechanism 让 27% 更少的总池子产生了更高的 retention 效率。
### 4.5 KVC 的 compute 经济session affinity 让系统总 compute 减少 33%
**头条事实**:在同样 4449 个请求的 workload 上KVC v2 整个系统消耗的 compute tokens 比 4DP CA 少 33%。
![System-wide compute economy + per-GPU work distribution](figures/gpu_utilization.png)
**左图 — 系统总 compute堆叠条形图**
- KVC 1P3D v2 总 compute = **3.47M tokens**
- P-side 重 prefillreseed/seed 路径8.3% 请求1.07M
- D-side append-prefill91.6% direct-to-D 路径,每个请求平均仅 341 token1.39M
- Decode1.01M
- DP 4-way CA 总 compute = **5.17M tokens**
- Full prefill每个请求都是 mean 952 uncached token4.17M
- Decode1.00M
差异的根因**完全在 prefill 段**DP 每个请求做 mean 952 token 的 uncached prefillKVC 91.6% 请求只做 mean 341 token 的 append-prefill剩 8.3% 走 P 做平均 5455 token 的重 prefill。session affinity 让 91.6% 请求的 prefix KV **已经在目标 D 上 resident**,下次 turn 只需算 append delta——**这就是 cache 复用直接折算成 compute 减少的过程**。
**右图 — per-GPU 工作分布(同样 8 个 GPU**
- KVC 把 compute **不均匀分配**P 专门承担 1.07M 的重 prefill不做 decode3 个 D 各自只承担 ~0.80M 的轻 append + decode 混合。
- DP 把 compute **均匀分配**:每个 fused worker ~1.25Mfull prefill + decode 必须在同 GPU 上交替)。
这种"不均匀分配"是 KVC 的设计意图,不是 load imbalance bug
1. **重 prefill 被隔离**——P 的 prefill kernel 不会插队进 D 的 decode batchdecode 端 batching 几乎无 jitter详见 §3.5 TPOT 双方完全重合)
2. **D 端只做小 append**mean 341 token vs DP 的 952 tokenprefill kernel 占的 GPU 时间从 ~10ms 降到 ~1ms对 decode batching 的干扰从主导变为可忽略
3. **总 compute 不依赖每个 GPU 满载** —— "P 闲着但当它工作时承担全部重活" 是合理的分工
**Paper 论述角度**:这张图证明 session affinity 不是只产生 locality 收益,而是直接把 locality **折算成系统层面的 compute 减少**。具体地:
- 91.6% 请求的 uncached_tokens 从 mean 952DP降到 mean 341KVC direct-to-D= 工作量减少 64%
- 8.3% 请求的 uncached_tokens 在 KVC 里上升mean 5455 reseed vs DP 全部 mean 952但请求数小
- 加权平均后 KVC 系统总 prefill compute 减少 67%1.07M+1.39M vs 4.17M),加上不变的 decode 后总 compute 减少 33%
历史尝试佐证KVC 4D0P取消 P 角色,所有 GPU 都做 P+D类似 DP已经实验过——整体性能下降因为 prefill 与 decode 争 GPU 资源时 decode latency 抖动放大。这反过来印证 "P 专门化" 的设计价值:它让 D 的 decode 路径**永不与重 prefill 在同 GPU 上争资源**。
### 4.6 v2 N=1 + 新代码路径未验证确定性 — **MINOR方法学待办**
TEAM_REPORT §2.8 改写规则后允许 ts=1 N=1理由是 baseline N=3 显示 0/4449 records 跨 run 不同。
但 v2 新增了两条状态可变路径:
- `policies.py: session_d_rejects` Counter每次失败累积、每次 direct 成功清零)
- `replay.py` 内 reject 触发 condition 改写
**新代码引入的非确定性未单独测过。** v2 当前结论严格说基于 N=1。
### 4.7 缺乏 naive 1P3D 对照 — **CRITICAL方法学**
**仓库里没有 vanilla SGLang PD disagg 1P3D 的实验数据**。所有 `pd-disaggregation-default` 都是 **1P1D**2 GPU全部 ts=10。
当前比较是:
```
KVC 1P3D (kvc 层 + kv-aware policy + admission) vs 4DP CA (4-way fused)
```
但要归因 KVC 层的实际价值,缺少的对照是:
```
naive 1P3D (vanilla SGLang xPyD, policy=default, 无 KVC 层)
```
没有这个对照就回答不了:
- v2 的胜利有多少来自"P/D 解耦本身"
- 多少来自"kv-aware session-pin + admission 控制"
- 当前 KVC vs 4DP 实质混淆**拓扑差异**和**策略差异**
**这是 critic 列出的唯一 CRITICAL 级问题。**
---
## 5. Fast path / Slow path 的本质KVC 是 bimodal 系统
把 §3 / §4 综合起来,可以把 v2 看作两个不同性质的系统叠加:
### 5.1 Fast path (91.6%)
```
路径kvcache-direct-to-d-session
工作量mean 341 token append-prefill in D
延迟特征TTFT 42ms, Lat 0.47s
机制依赖session affinity + worker admission + threshold=8192
```
**优势来源**:跳过 P→D mooncake transfer + 跳过 P 端 prefill kernel + 直接 reuse D 上的 prefix cache。
### 5.2 Slow path (8.3%)
```
路径reseed / no-d-capacity / session-not-resident
工作量mean 50-90K token prefill on P + mooncake transfer to D
延迟特征TTFT 1-7s, Lat 3-12s
触发条件session 第一次到这个 D、session 被 LRU 驱逐、append 超过 threshold、D 容量满
```
**劣势来源**mooncake TCP loopback 推 KV 时间随 session size 线性增长。
### 5.3 整体表现 = 加权平均
```
v2 mean = 0.916 × 0.47s + 0.084 × ~3.5s = 0.43 + 0.29 = 0.72s (但实测 lat mean 1.43s,差异来自长尾)
v2 p50 = fast path 主导 → 0.576s
v2 p99 = slow path 主导 → 8.69s (KVC) vs 8.43s (DP) 接近
```
**对比 DP**DP 是 unimodal 系统,每个请求做完整 prefill。TTFT 分布更紧,没有 slow path 长尾。
### 5.4 工程含义
- **要让 v2 的胜利更扎实**:把 8.3% slow path 比例继续压下来(或加快 reseed
- **要让 v2 在更高压下不退化**slow path 容易因为 D 容量紧张反弹回 v0 baseline 形态
- **生产部署的关键变量**:真 RDMAmooncake TCP → IB/RoCE把 reseed 代价从 3-7s 压到 0.3-0.7s 后slow path 长尾消失bimodal 系统坍缩成 quasi-unimodal
---
## 6. 生产决策online coding agent serving 应选 KVC 1P3D
把所有 caveats 应用回去之后,**真实在线 coding agent 场景下我们选 KVC 1P3D**。理由:
### 6.1 修复后的 headline 表(对等口径 + 含 TTFT p99
| 指标 | KVC v2 | 4DP CA | Delta | 评价 |
|---|---:|---:|---:|---|
| Lat mean | 1.444s | 1.464s | **KVC -1.4%** | 微胜,机制无显著差异 |
| Lat p50 | 0.581s | 0.668s | **KVC -13.0%** | 显著优势91.6% direct-to-D 路径) |
| Lat p90 | 3.638s | 3.680s | **KVC -1.1%** | 平 |
| Lat p99 | 8.687s | 8.433s | DP -3.0% | 量级内,平 |
| TTFT mean | 0.097s | 0.130s | **KVC -25.0%** | 用户体感优势明显 |
| TTFT p50 | 0.042s | 0.092s | **KVC -54.8%** | 大幅优势 |
| TTFT p90 | 0.085s | 0.254s | **KVC -66.7%** | 大幅优势 |
| **TTFT p99** | **1.285s** | **0.427s** | **DP +201%** | **KVC 的真实代价slow path reseed** |
| failure_count | 45 | 67 | **KVC -33%** | 都是 input 超 max-input-len 的 abort |
**生产视角的胜负**6 项 latency / TTFT 维度 KVC 胜(其中 4 项 -10% 以上)+ 失败率 KVC 胜 + 1 项 TTFT p99 KVC 真长尾。**这不是"5 胜 1 负 3 平"的均势,是 KVC 在 latency/TTFT 主战场全胜,付出 p99 长尾的代价。**
### 6.2 为什么 KVC 1P3D 是 coding agent serving 的正确架构选择
1. **Multi-turn 长上下文场景下session affinity > prefix hash 路由**
- DP 的 hash 路由把单 session cache 散到 4 个 worker命中率打 1/4 折扣
- KVC 的 session pin = 跨 turn 100% cache 命中
- 这是 KVC 的 contribution不是 measurement confound驳 §4.4 critic
2. **Direct-to-D 在 91.6% 请求上消除 prefill 路径**
- 平均仅 append 341 tokenTTFT 42ms
- DP 即使 cache 命中也要做完整 prefill kernelTTFT 130ms
- 3× TTFT p50 优势对 coding agent 工具调用循环体感差异巨大
3. **Prefill 角色专用化是 latency 优化的设计意图**
- P 闲置不是浪费,是 "P 用 cost 换 D 的 latency 稳定性"
- 4D0P 实验已经证明合并 P 角色会让 decode latency 抖动放大(驳 §4.5 critic
4. **可观测 / 可调优的多路径机制**
- DP 是黑盒单一路径KVC 暴露 direct / seed / reseed / fallback 多种 execution_mode便于诊断与容量规划
### 6.3 真实代价(论文里必须诚实写)
- **TTFT p99 = 1.29s vs DP 0.43s**KVC 3× 差)
- 来自 8.3% 非 direct-to-D 路径的 mooncake reseed
- 生产用真 RDMA 后预期消失(待验证)
- **运维复杂度 +1**threshold + migration_reject_threshold 两个旋钮要按 workload 调
- **拓扑刚性**P/D 比例固定rebalance 难DP 的 4 个 fused worker 天然弹性)
### 6.4 哪种 workload 会反悔选 DP
| 触发条件 | 原因 |
|---|---|
| Session 短 (<5 turns) | direct-to-D 摊销不开KVC 拓扑成本回不来 |
| Cache hit rate < 60% | KVC affinity 优势消失 |
| Session 总量 >> D KV pool | reseed 占比飙升slow path 主导 |
| TTFT p99 SLO < 200ms | KVC reseed 长尾过不了 |
| 运维带宽紧没人调参 | DP 开箱即用更稳 |
### 6.5 v2 真正解决了 / 缓解了 / 没触及 TEAM_REPORT 的哪些问题
| 项目 | 状态 |
|---|---|
| TEAM_REPORT §1 session pin 饿死 | 机制修复reset-on-success migration |
| TEAM_REPORT §6 ts=10 失真 | 切到 ts=1作为前置条件 |
| TEAM_REPORT §7 metric 标签错位 | KVC 端细分KVC vs DP error 口径已修(§4.3 |
| TEAM_REPORT §8 N=1 不可信 | 规则改写ts=1 categorical 确定 |
| TEAM_REPORT §2 D LRU 跟不上 | 🟠 ts=1 自然 drain 掩盖ts=10 / 更紧容量下仍存在 |
| TEAM_REPORT §3 backpressure | 🟠 代码已实现但默认 off高压时需要启用 |
| TEAM_REPORT §4 P-side 调度 | 1P 配置无从测试扩到 2P+ 后需重新审查 |
| TEAM_REPORT §5 admission RPC 干扰 | 🟠 ts=1 下不显著高压时复现 |
| **新真实代价TTFT p99 reseed** | 🟡 已识别生产用 RDMA 缓解 |
| **方法学待办naive 1P3D 对照** | 待补但不阻塞产品决策 |
| **方法学待办v2 N≥2 确定性** | 待补 |
---
## 7. 推荐补做的实验
ROI 排序
### 7.1 必做(验证当前结论的鲁棒性)
1. **naive 1P3D ts=1 N=1**vanilla SGLang xPyDpolicy=default policy=kv-aware 各一次
- 用途隔离 KVC 层贡献 vs 1P3D 拓扑贡献
- 工程~6h GPU × 2 run
- 这是 critic 标的唯一 CRITICAL**最高 ROI**
2. **v2 N=2 或 N=3**
- 用途验证新代码路径reset-on-success + threshold=8192 ts=1 categorical 确定
- 工程~11h GPU × 2 run同时跑双独立 GPU group 也行
### 7.2 强烈推荐(清理对等性)
3. **对等口径重算**无需新 run纯分析脚本
- DP 67 abort `finish_reason='abort'` 过滤
- KVC 5 ReadTimeout 300s timeout 计入 lat
- 两套口径并列展示 v2 是否仍胜
4. **DP `max-input-len` 调到 92098** KVC 一致重跑 N=1
- 用途消除 abort 数量不对等
- 工程~5.5h GPU
5. **headline 表加 TTFT p99**更新 `V2_RESULTS_ZH.md`
### 7.3 看团队带宽(探索 v2 边界)
6. **threshold sweep**2048 / 4096 / 8192 / 16384 / 32768 trace-specific 最优
7. **更长 trace>200 sessions**验证 §2.1 残留风险下 v2 的容量边界
8. **8 GPU 重测**2P6D KVC v2 vs 8DP CA ts=1 下验证 4 GPU 结论可外推
9. **真 RDMA**mooncake TCP loopback RDMA slow path 代价能否压下来
### 7.4 不要做的事
- **回到 ts=10**:那是 benchmark artifact 主导区间不代表真实部署
- ** §2 D LRU 分层 eviction** ts=1 自然吸收超出 KISS 边界
- ** §3 backpressure 默认 on**除非要支持 ts=10 / 更紧 workload
---
## 8. 决策点
| # | 决策 | 推荐 |
|---|---|---|
| D1 | 接受 v2 作为项目 milestone + KVC 1P3D coding agent serving 的推荐架构 | **Yes** |
| D2 | 论文 headline 表加 TTFT p99 + abort_count + failure_count | **Yes**已修复 metrics.py |
| D3 | 拉齐 `--max-input-len` 87811 重跑一次 N=1 消除 SGLang 自动 mem 分配的 confound | **Yes** |
| D4 | naive 1P3D 对照实验policy=default kv-aware分离拓扑贡献 vs KVC 层贡献 | **Yes**学术对照不影响产品决策 |
| D5 | v2 N=2/3 验证新代码路径 ts=1 categorical 确定 | **Yes**学术鲁棒性 |
| D6 | 启用 backpressure 默认值 | Off + 写明触发条件 |
| D7 | 项目目标是否扩展到 ts=10 / 更长 trace | 暂不扩先把 ts=1 配置稳定 |
| D8 | 论文 motif 论述:「KVC P 闲置换 TTFT 稳定性」? | **Yes**(§4.5 |
**作者建议总结**D1/D2/D3/D4/D5/D8 Yes 3 项是论文必须做的对等性修复 + 修辞调整D4/D5 是学术鲁棒性的对照实验D8 是把 critic 误标的"缺陷"翻译成 paper-friendly contribution 语言
---
## 9. 局限与未验证(本文自身)
1. **4 GPU 缩配**所有 ts=1 数据都是 4 GPU8 GPU KVC 2P6D vs 8DP CA 的对比是否同样 KVC 胜未知
2. **N=1 for v2**上文 §4.6 已述
3. **单 trace**所有结论建立在 SWE-Bench 50sess trace 其他 agentic workload写作研究多模态行为未验证
4. **Mooncake TCP loopback**单机环境模拟生产 RDMA生产环境 transfer 开销显著降低slow path 占比可能变小KVC 优势可能放大也可能引入其他 artifact
5. **Critic 审查 N=1**用了 opus agent 单次审查完全可能漏掉其他对等性问题
6. **§5 bimodal 模型是描述而非证明**尚未做工作量归一化的对照实验来证明"KVC D 端速度本身 DP"。
---
## 附录 A本文数据来源
| 章节 | 数据源 |
|---|---|
| §1.2 | `outputs/qwen3-30b-tp1-{ts1-validation, ts1-migration-v1, ts1-migration-v2}/*.json` |
| §2 | TEAM_REPORT §1-§9 原数据 + ts=1 新数据交叉 |
| §3 | v2 metrics.jsonl execution_mode 聚合直接计算 |
| §4 | Critic agent ID `a34c7673fc5a3fa76` 审查结果 + 本文直接验证 |
| §5 | v2 + DP metrics.jsonl 路径级延迟统计 |
| §6 | 重算自上述数据 |
## 附录 B相关文档
- `docs/TEAM_REPORT_AGENTIC_PD_HYBRID_ZH.md` 本文基线v3-v6 ts=10 状态
- `docs/REFACTOR_PLAN_V1_ZH.md` ts=1 验证后的方向决策
- `docs/MIGRATION_V1_FINDINGS_ZH.md` v1 thrashing 诊断
- `docs/V2_RESULTS_ZH.md` v2 结果原始报告本文是对它的 critique
- `docs/archive/AGENTIC_FIT_ANALYSIS_ZH.md` 早期 fit 分析(§1-§7 来源
- `docs/archive/STRUCTURAL_VALIDATION_REPORT_ZH.md` ts=10 结构性 claim 验证
## 附录 C相关代码
- `src/agentic_pd_hybrid/policies.py` `RoutingState.session_d_rejects` + `KvAwarePolicy.migration_reject_threshold`
- `src/agentic_pd_hybrid/replay.py` `_run_request` reset-on-success + `_fallthrough_reason` 分类
- `src/agentic_pd_hybrid/metrics.py:124,170` latency/truncation 过滤逻辑
- CLI flags: `--kvcache-migration-reject-threshold` / `--kvcache-direct-max-uncached-tokens` / `--enable-backpressure`
---
**核心句**v2 KVC SWE-Bench 真实 agentic workload 上成为 coding agent serving 的正确架构选择——latency mean/p50/p90 + TTFT mean/p50/p90 全胜付出 TTFT p99 长尾的真实代价论文需要的不是" critic 找的对等性问题道歉"而是把"session affinity + direct-to-D + P 闲置换稳定性"作为 contribution 写清楚 TTFT p99 长尾作为已知代价诚实交代并补 2 个学术对照naive 1P3D / v2 N2 1 max-input-len 拉齐重跑