# D→P RDMA Snapshot Push — 实施状态报告

**日期**：2026-05-13
**分支**：`h200-cu130`
**最新 commit**：8a2f72f（E4 protocol 落盘）
**前置文档**：
- `docs/D_TO_P_SYNC_DESIGN_ZH.md`（设计）
- `docs/D_TO_P_PHASE1_LINK_ZH.md`（Phase 1 底层链路验收）
- `docs/E4_PROTOCOL_ZH.md`（实验协议）

---

## 0. 总结

D→P RDMA snapshot push 的 8 phase 工程任务已完成 7 phase（设计、链路验证 host & GPU、SGLang 调度器集成、scheduler RPC handlers、agentic 端 orchestration、CLI flag、smoke test）。剩余的 E4 端到端实验（task #16）已 kick off 跑着。

所有改动都已 commit 并 push 到 `origin/h200-cu130`，**每一步都有对应的 design / acceptance / protocol 文档**。

---

## 1. Commit 序列

| Commit | 描述 | 关键产物 |
|---|---|---|
| `9c35edd` | docs(design): D→P RDMA snapshot push design | `docs/D_TO_P_SYNC_DESIGN_ZH.md` 446 行设计文档 |
| `dc4867c` | feat(snapshot): D→P RDMA link Phase 1 — host mem | `src/agentic_pd_hybrid/snapshot_link.py` + smoke：64 MB 1.7 ms / 316 Gbps |
| `7216507` | feat(snapshot): D→P RDMA Phase 1b — GPU pointer | GPU smoke：256 MB 8.5 ms / 251 Gbps |
| `86412bb` | feat(sglang): D→P snapshot link integration — controller + RPC handlers | SGLang vendored 4 文件改动，3 个新 RPC |
| `b9b0cf0` | feat(agentic): D→P snapshot orchestration in reseed path + CLI flag | agentic-pd-hybrid 4 文件 + smoke script |
| `a369722` | fix(sglang): account snapshot-reserved slots in radix mem leak check | leak check 修正 |
| `8a2f72f` | feat(experiments): E4 protocol + sweep script | `docs/E4_PROTOCOL_ZH.md` + sweep |

---

## 2. 验证状态

### 2.1 Phase 1（底层 RDMA 链路）

✅ **VERIFIED**

- Smoke `scripts/smoke_snapshot_link.py`：host CPU 内存，5/5 size 全 SHA 校验通过，64 MB 316 Gbps
- Smoke `scripts/smoke_snapshot_link_gpu.py`：cuda:0 → cuda:1，5/5 size 通过，256 MB 251 Gbps

### 2.2 Phase 2（SGLang scheduler 集成）

✅ **VERIFIED at RPC level**

Smoke `scripts/smoke_snapshot_sglang_integration.py` 启动 P + D 两个 SGLang worker：

- `POST /_snapshot/prepare_receive` on P → 200 OK，返回 96 layer base ptrs + slot indices + strides
- `POST /_snapshot/dump` on D → 200，返回 `ok=false, reason="session-not-resident"`（正确，session 不存在）
- `POST /_snapshot/finalize_ingest` on P → 200 OK，inserted_prefix_len 字段正确

**Scheduler 不崩**（修了 leak check 后）。证明：
- env-var driven controller startup 工作
- mooncake engine 共存（PD pipeline 用一个，snapshot 用一个独立的）
- 3 个 ReqInput/Output dispatch 全通
- HTTP → tokenizer → ZMQ → scheduler 链路畅通

### 2.3 Phase 3（agentic orchestration + reseed wire-up）

⏳ **IN-FLIGHT**（E4 sweep 跑着）

`_attempt_d_to_p_sync` 在 `_invoke_kvcache_seeded_router` 中被调用，按设计文档 §2 的三阶段协议运行。Phase 3 的端到端验收靠 E4 实验数据。

---

## 3. 未覆盖范围（**重要**）

下面这些场景**还没有验证**，是 E4 实验之外的 follow-up 工作：

| 范围 | 状态 | 风险 |
|---|---|---|
| **D-side 真实 session KV 字节对齐** | unverified | D 把 SessionSlot 里的 KV slot indices 翻译成 RDMA src 地址，layer-by-layer 排列。逻辑可能有 off-by-one 或 layer 顺序错误。若错，P 端的 radix insert 是正确的 indices 但底下的 KV 内容损坏 → 模型输出乱码。这只能靠端到端测试发现。 |
| **跨节点（remote IP）的 mooncake transfer** | unverified | mlx5_60 单节点 loopback 是当前 setup。跨节点 GID 路径 / route table / firewall 都可能不同。 |
| **多 D → 单 P 的 slot 协调** | unverified | 多个 D worker 同时往同一个 P 推不同 session 的 KV，是否冲突？当前每次 prepare_receive 都从 P 的 kv_pool alloc，应当不冲突，但需 stress test。 |
| **token_id 一致性** | partial | 我们用 `request.input_token_ids` 作为 radix 插入的 key。如果该字段 stale 或 mis-aligned，radix 插入的 key 与真实 KV 不对应。E4 跑出垃圾输出就是这个症状。 |
| **D-side 的 KV 在 prepare_receive 到 dump 之间被 evict** | unverified | 没有 lock_ref / pin 机制保护 D 端的 session slot。在并发负载下 D 可能 LRU 驱逐这个 session，导致 dump 失败或推空数据。fallback 路径会兜底但浪费一次 RPC。 |
| **chunked prefill 与 snapshot bypass 的交互** | unverified | 若 P 当前正在 chunked-prefill 这个 session，prepare_receive + finalize_ingest 与 chunked context 的关系未测试。 |

---

## 4. 端到端实验 E4 当前进展

跑着，结果汇总见 `docs/E4_RESULTS_ZH.md`（实验跑完后写）。

---

## 5. 给下一个接班 agent 的建议

如果你接手时 E4 已跑完且看出问题，按这个排查顺序：

1. **看 D-side dump 的失败原因 top**：grep "d_to_p_sync sid=.*status=" 看 prepare/dump/finalize 哪一步挂得多
2. **如果 dump 大量返回 `session-not-resident`**：说明 reseed 触发时 D-side session 已经被 evict。这是预期的，但需要看占比。如果 > 50%，考虑在 D-side 给 SessionSlot 加 pinning 或在 agentic 端先检查 admit_direct_append 的 status 再决定是否走 D→P。
3. **如果 dump ok 但模型输出乱码**：byte-level KV layout 在 D/P 间有不一致。读 `third_party/sglang/python/sglang/srt/disaggregation/snapshot/controller.py::push_session_kv` 的 (src, dst, len) 三元组计算，按 `kv_pool.get_contiguous_buf_infos()` 的 K-then-V 顺序 cross check。
4. **如果一切 ok 但 TTFT 仍未改善**：D→P 没真触发 fast path。check P-side radix tree 插入后是否真被下一次 prefill 命中。看 `cached_tokens` 字段。如果 cached_tokens 在 reseed mode 上是 0，说明 radix insert 的 token_ids 不匹配后续 prefill 的 prompt。
5. **若你想做 ablation**：保留 `--enable-d-to-p-sync` 但人为在 `_attempt_d_to_p_sync` return None。这把 hot path 关掉但保留控制平面 → 隔离纯 D→P 的边际效益。

---

## 6. 设计文档对照

| 设计 §X | 实现位置 |
|---|---|
| §2.1 Mooncake 双角色 | `third_party/sglang/.../disaggregation/snapshot/controller.py` 用独立 TransferEngine，避免改 MooncakeKVManager |
| §2.2 DecodeKVSnapshotSender | `SnapshotLinkController.push_session_kv` |
| §2.3 PrefillSnapshotStore | `SnapshotLinkController._ingest_records`（dict 形态而非完整 Store class，MVP 化） |
| §2.4 P-side prefill bypass | **未实现**——改用 radix tree insert 让 SGLang 自然 cache hit。比 bypass 更保守、更简单。 |
| §2.5 D-side commit hook | **延迟实现**——E4 试用 reseed-triggered（被动）模式而非 per-append push（主动）。等数据后看是否值得做主动模式。 |
| §2.6 HTTP endpoints | `entrypoints/http_server.py:_snapshot/{prepare_receive,dump,finalize_ingest}` |
| §2.7 agentic-pd-hybrid hook | `replay.py::_attempt_d_to_p_sync` + 调用点在 `_invoke_kvcache_seeded_router` |
| §2.8 CLI flag | `cli.py --enable-d-to-p-sync` |

---

**核心句**：D→P RDMA snapshot push 的 7/8 phase 已落地、commit、push。Phase 1 底层链路通过 host + GPU smoke 验证。Phase 2 的 SGLang scheduler 集成通过 RPC-level smoke 验证。Phase 3 的端到端 reseed orchestration 通过 E4 实验验证（跑着）。
