Captures the current state of the D→P RDMA snapshot push work for the next agent (or future me): which commits land which phase, which phases are verified vs in-flight, and the known unverified surfaces (byte-level KV layout, cross-node, multi-D contention, token_id consistency, D-side evict races, chunked-prefill interactions). Also maps the §2 design points to their implementation locations so the doc-to-code traceability is explicit.
7.2 KiB
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_receiveon P → 200 OK,返回 96 layer base ptrs + slot indices + stridesPOST /_snapshot/dumpon D → 200,返回ok=false, reason="session-not-resident"(正确,session 不存在)POST /_snapshot/finalize_ingeston 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 已跑完且看出问题,按这个排查顺序:
- 看 D-side dump 的失败原因 top:grep "d_to_p_sync sid=.*status=" 看 prepare/dump/finalize 哪一步挂得多
- 如果 dump 大量返回
session-not-resident:说明 reseed 触发时 D-side session 已经被 evict。这是预期的,但需要看占比。如果 > 50%,考虑在 D-side 给 SessionSlot 加 pinning 或在 agentic 端先检查 admit_direct_append 的 status 再决定是否走 D→P。 - 如果 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。 - 如果一切 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。 - 若你想做 ablation:保留
--enable-d-to-p-sync但人为在_attempt_d_to_p_syncreturn 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 实验验证(跑着)。