Files
agentic-pd-hybrid/docs/KVCACHE_CENTRIC_PROGRESS_ZH.md

264 lines
11 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.

# KV-cache centric P/D routing 当前进展
本文记录当前原型在 SGLang xPyD 上围绕 session-aware / KV-cache-aware P/D routing 的实现、实验结果和阶段性结论。实验日期为 2026-04-24 至 2026-04-25。
## 目标和核心假设
目标是在单机 8 GPU xPyD 环境中验证:针对 agentic coding workloadsession-aware / KV-cache-aware P/D routing 是否能提升端到端延迟。
当前重点假设:
1. 在 PD-disaggregation 下P 节点和 D 节点可能同时保留同一个 session 的 prefix KV形成 P/D duplicate。
2. 如果预测某个 session 后续会 direct-to-D那么 P 侧在 radix/prefix cache eviction 时可以优先淘汰这部分 prefix cache。
3. 这样可以给 P 节点释放 cache 空间,提高 P 侧 prefix cache reuse。
4. 如果 P 侧 reuse 提升后 D 侧开始成为瓶颈,可以通过增加 xPyD 中 D 的配比,也就是增加 y缓解 decode 侧压力。
实验结果表明:第 2、3 点在 P cache 高压 workload 下成立;第 4 点只部分成立,因为瓶颈会从 decode prealloc 转移到 P->D transfer/bootstrap pipeline。
## 已实现机制
### 1. Trace profile 和 paired comparison
新增 `agentic_pd_hybrid profile` 子命令和 `src/agentic_pd_hybrid/profile.py`
能力:
- 统计 trace 的 session 数、turn2+ 数、append tokens、overlap ratio、direct-to-D eligible turn。
- 对比 baseline/candidate metrics输出 paired E2E latency delta。
- 用于解释 micro-benchmark 与 Ali filtered workload 的差异。
### 2. P 侧 priority eviction 支持
修改 SGLang server args允许
```bash
--radix-eviction-policy priority
```
router/replay 支持内部字段:
- `smg_prefill_priority`
- `smg_decode_priority`
router 会将内部字段剥离,只把标准 `priority` 分别传给 P/D backend。这样可以让 direct-to-D predicted session 在 P 侧使用更低优先级,例如 `-100`,普通请求使用 `100`
### 3. Kvcache seed/direct admission 控制
新增多种 seed/reseed 过滤:
- `kvcache_seed_max_resident_tokens`
- `kvcache_seed_max_output_tokens`
- `kvcache_seed_min_turn_id`
- `kvcache_seed_only_multiturn_sessions`
- `kvcache_seed_max_inflight_decode`
新增 P streaming session backup 策略:
- `release-after-transfer`P->D transfer 后释放 P 侧 session backup。
- `capacity-backup`:容量允许时保留 P 侧 backup。
当前主实验使用 `release-after-transfer`
### 4. 稳定性修复
之前 worker-admission 实验会在 replay 尾部卡住,不写出 metrics。原因是 benchmark 的长 `timeout_s=3600` 同时用于:
- SGLang stack 启动等待
- replay client 单请求
- router 到 P/D backend 的单请求
修复后新增:
- `BenchmarkConfig.request_timeout_s`
- CLI `benchmark-live --request-timeout-s`
- launch plan `router_request_timeout_s`
当前做法:
- `timeout_s=3600` 继续用于 SGLang 启动和整体 stack 等待。
- `request_timeout_s=180` 用于 replay client 和 router 到 P/D backend 的单请求。
- control-plane probe/open/close session 使用 2s timeoutfail closed。
修复效果worker-admission 从“尾部卡死不落盘”变为“卡住请求记录为 ReadTimeout整轮实验完成并写 metrics”。
## 关键实验结果
### P cache pressure 下 priority eviction 是否提升 P 侧 reuse
配置2P2DP `--max-total-tokens 90000`micro workload 316 requests / 58 sessions。
| 配置 | ok/total | mean E2E | p99 | request cached tokens | P log cached tokens | P new-token total |
|---|---:|---:|---:|---:|---:|---:|
| LRU | 314/316 | 28.171s | 43.409s | 8.204M | 7.783M | 2.236M |
| Priority | 314/316 | 28.165s | 41.935s | 8.401M | 7.981M | 2.039M |
结论:
- 在 P cache eviction 高频触发时priority eviction 确实提高 P 侧 prefix reuse。
- cached tokens 增加约 197knew prefill tokens 减少约 197k。
- 但 mean E2E 基本不变,说明性能瓶颈转移到 D decode/transfer。
### 增加 D 配比前的 D 侧瓶颈证据
2P2D priority pressure 下:
- decode `#queue-req`max/mean/p90 = 0/0/0
- decode token usagemax 0.98mean 0.842p90 0.96
- decode `#transfer-req`max 7mean 4.61p90 7
- decode `#prealloc-req`max 21mean 11.6p90 21
解释:
- D 侧不是普通 waiting queue 堆积。
- 真正压力在 token usage、transfer queue 和 prealloc queue。
### D scalingrouter admission 旧结果
| 配置 | ok/total | mean | p50 | p90 | p99 | error |
|---|---:|---:|---:|---:|---:|---:|
| 2P2D | 314/316 | 28.165s | 30.576s | 38.267s | 41.935s | 2 |
| 2P3D | 290/316 | 29.915s | 31.428s | 40.856s | 45.964s | 26 |
| 2P4D | 285/316 | 30.566s | 32.823s | 40.566s | 44.838s | 31 |
结论:
- 直接增加 D 不稳定。
- 2P3D/2P4D 的错误主要来自 `kvcache-centric` seed/direct 路径。
- 日志显示 decode 侧出现 `WaitingForInput` timeout 和 `KVTransferError`
### D scalingworker admission + request timeout 修复后
配置P `--max-total-tokens 90000`priority evictionworker admission`request_timeout_s=180`
| 配置 | ok/total | mean | p50 | p90 | p99 | error |
|---|---:|---:|---:|---:|---:|---:|
| 2P2D | 313/316 | 29.838s | 30.742s | 39.641s | 52.506s | 3 |
| 2P3D | 299/316 | 29.349s | 30.569s | 42.161s | 46.113s | 17 |
| 2P4D | 312/316 | 26.442s | 27.759s | 38.197s | 47.970s | 4 |
对应 decode log 摘要:
| 配置 | decode usage mean | decode transfer mean | decode prealloc mean |
|---|---:|---:|---:|
| 2P2D | 0.859 | 4.86 | 11.3 |
| 2P3D | 0.877 | 5.70 | 6.92 |
| 2P4D | 0.809 | 5.31 | 3.46 |
结论:
- 2P4D + worker admission + request timeout 是当前最好的 D scaling 配置。
- 相比旧 2P4D成功率从 285/316 提升到 312/316mean 从 30.566s 降到 26.442s。
- 但 p99 仍未稳定改善tail 仍由 P->D transfer/bootstrap timeout 主导。
- 2P3D 不稳定,错误 17 个,不适合作为当前推荐配置。
### 与默认 PD-disaggregation 的同配置对比
为了避免和旧 2P2D/no-pressure 基线混比,补跑了同一 workload、同一 2P4D、同一 P `--max-total-tokens 90000`、同一 `time_scale=50`、同一 `request_timeout_s=180` 的默认 PD-disaggregation 基线。
| 策略 | ok/total | mean | p50 | p90 | p99 | cached total | direct-to-D |
|---|---:|---:|---:|---:|---:|---:|---:|
| 默认 PD-disaggregation 2P4D | 316/316 | 29.210s | 28.940s | 47.434s | 52.605s | 8.165M | 0 |
| KVC 2P4D latency-best | 312/316 | 26.442s | 27.759s | 38.197s | 47.970s | 7.882M | 11 |
| KVC 2P4D seed-min2 | 316/316 | 26.729s | 25.840s | 43.589s | 50.426s | 8.337M | 3 |
结论:
- 如果只看成功请求延迟KVC 2P4D latency-best 相比默认 PD
- mean 改善约 9.5%
- p50 改善约 4.1%
- p90 改善约 19.5%
- p99 改善约 8.8%。
- 但 latency-best 有 4 个 `ReadTimeout`,全部来自 turn1 大 seed 的 P->D transfer/bootstrap timeout。
- `kvcache_seed_min_turn_id=2` 可以消除这些错误,达到 316/316 成功,同时 mean/p50/p90/p99 仍然优于默认 PD。
- 因此当前推荐分成两档:
- 追求最低 mean/p90使用 KVC 2P4D latency-best。
- 追求稳定性:使用 KVC 2P4D seed-min2。
### 进一步优化尝试
在当前最佳配置基础上尝试了三个优化方向:
| 策略 | ok/total | mean | p50 | p90 | p99 | 结论 |
|---|---:|---:|---:|---:|---:|---|
| KVC 2P4D latency-best | 312/316 | 26.442s | 27.759s | 38.197s | 47.970s | 延迟最优,但有 4 个 turn1 seed timeout |
| transfer-cap4 | 304/316 | 27.961s | 29.785s | 38.730s | 45.192s | 不可取,实时 transfer queue snapshot 滞后,错误更多 |
| disable-failed-session | 285/316 | 29.179s | 30.878s | 42.794s | 46.411s | 不可取,失败 session 降级会放大后端异常状态 |
| seed-min2 | 316/316 | 26.729s | 25.840s | 43.589s | 50.426s | 稳定性最优 |
| inflight0 | 316/316 | 29.497s | 31.186s | 43.498s | 48.022s | 太保守,几乎关闭 KVC 收益 |
从错误明细看latency-best 的 4 个错误全部是 turn1 seed timeout每个都是约 1250 KV blocks 的大 seed。`seed-min2` 跳过 turn1 seed 后,错误全部消失,说明当前主要稳定性问题是启动阶段 seed 风暴,而不是后续 direct append 本身。
transfer-cap4 没有效果,说明仅依赖 D worker 的实时 `decode_transfer_queue_reqs` 不够;并发请求可能同时读取到尚可的 snapshot然后一起进入 P->D transfer导致 backlog 在 admission 后形成。
## Ali filtered 当前状态
Ali filtered small-append trace
- 81 requests
- 28 sessions
- 53 turn2+
- max input 18901
- max output 1925
- span 5414s
PD baseline
- ok 81/81
- mean 9.072s
- p50 7.086s
- p90 21.761s
- p99 26.813s
Kvcache-centric 在 Ali filtered 上曾出现 58-67 个 router 200 后挂住、无 metrics 的问题。当前 request timeout 和 control-plane timeout 修复后,应重新跑 Ali filtered在未重跑前不把 Ali filtered 纳入最终性能结论。
## 当前结论
1. kvcache centric 可以提高 KV reuse但需要满足 workload 条件:
- session 有多 turn
- turn2+ append 较小;
- prefix overlap 高;
- P 侧 cache 有 eviction pressure
- D 侧 seed/direct admission 不把 transfer pipeline 打爆。
2. 不适合的 workload
- 单 turn 或 session 间隔过长;
- turn2+ append 很大direct-to-D 不能省掉多少 prefill
- prefix overlap 低;
- P cache 没有 eviction pressure
- D transfer/prealloc 已经高压。
3. 用户关于 P/D duplicate 的假设部分成立:
- 如果 D session 已经 residentP 侧对应 streaming session backup 可以视为 duplicate。
- `release-after-transfer` 可以避免长期保留 P/D 两份 session KV。
- priority eviction 进一步让 P 在必须 eviction 时优先淘汰 direct-to-D predicted session prefix。
4. 但当前机制还没有完全解决性能问题:
- P 侧 reuse 提升后E2E 不一定改善。
- 主要原因是 D 侧 transfer/bootstrap pipeline 成为瓶颈。
- 增加 D 可以降低 prealloc但不能自动降低 transfer backlog。
- 当前同配置下 KVC 已经可以优于默认 PD但必须在 latency-best 和 stable 两种策略之间取舍。
## 下一步优化方向
1. transfer-aware admission
- seed/direct 不只看 D token capacity也要看 `decode_transfer_queue_reqs``decode_prealloc_queue_reqs``decode_retracted_queue_reqs`
- 当 transfer queue 高时,应该主动走 PD fallback。
- 当前实验显示,单纯使用实时 transfer queue threshold 不够,需要配合本地 reservation。
2. per-D transfer budget
- 对每个 D 设置 seed/reseed 并发上限。
- 不能只按 session residency 或 token headroom 判断。
- 特别要限制 turn1 大 seed 的并发,避免启动阶段 seed 风暴。
3. P/D ratio 联合调度:
- 2P4D 当前最好,但 P queue 也随 D 增加而上升。
- 后续需要测试 3P3D、3P4D、4P4D 等组合,确认 P transfer source 是否成为瓶颈。
4. Ali filtered 重跑:
- 使用 request timeout 修复后的版本重新跑 Ali filtered。
- 如果仍然没有收益,需要按 session gap、append size、overlap ratio 分桶分析。
5. 更严格的成功率指标:
- 当前不能只看成功请求的 mean/p90。
- 必须同时报告 ok/total、timeout/error 类型和 tail latency。