对比不同 Connector 的状态一致性层数差异根因
四个 KV offloading scheduler 的状态一致性层数从 3 层到 1 层不等。根本原因是每个 scheduler 要维护的独立关注点数量不同——每个正交的功能需求贡献一层状态。
层数拆解
| 关注点 | OCS | SCOS | LMCache | Tiering | 说明 |
|---|---|---|---|---|---|
| 异步传输追踪 | ✅ _jobs |
✅ _store_event_to_blocks |
❌ | ✅ _transfer_jobs |
所有异步 scheduler 都需要追踪 job/event 的 pending_count、keys、is_store 等 |
| per-request job 索引 | ✅ transfer_jobs |
❌ 用 _store_event_to_reqs 反向映射 |
❌ | ✅ pending_primary_stores 计数 |
per-request job 模型需要正向索引;per-batch event 模型用反向映射代替 |
| sliding window block 保护 | ✅ _block_id_to_pending_jobs |
❌ 复用 BlockPool | ❌ | ❌ | OCS 自己管理 sliding window;SCOS 复用 GPU 侧 BlockPool |
| 总层数 | 3 | 2 | 1 | 2 |
每一层存在/不存在的原因
第 1 层:异步传输追踪(OCS / SCOS / Tiering 共有)
异步传输需要记录每个 job/event 的 pending_count、keys、is_store、block IDs,等待 worker 完成报告后递减/累加计数。LMCache 不需要——同步提交给 LMCache session,无 in-flight job。
第 2 层:per-request job 索引(OCS / Tiering 有,SCOS 用反向映射代替)
需要知道一个请求有哪些 in-flight job,用于:get_num_new_matched_tokens 检查是否有 pending job → 延迟调度;request_finished 遍历 in-flight jobs 注册 non-sw blocks;_build_store_jobs 检查已有 job 是否都是 store。
SCOS 用 per-batch event 模型,通过 _store_event_to_reqs[event] = list[ReqId] 反向映射(event → reqs),不需要 per-request 的正向索引。LMCache 同步完成,没有 in-flight job 概念。
第 3 层:sliding window block 保护(仅 OCS 有)
Sliding window blocks 可以在请求运行期间被 GPU 调度器回收并重新分配给其他请求。需要追踪哪些 blocks 有 pending store job,在重分配时 flush 这些 job。
SCOS 复用了 GPU 侧的 BlockPool 和 KVCacheCoordinator——sliding window 的 block 回收由 BlockPool 自己管理,scheduler 不需要额外追踪。LMCache 不支持 sliding window。Tiering 是后端 manager,不管 GPU block 分配。
结论
OCS 的 3 层不是设计缺陷,而是三个正交关注点的自然产物:
| 关注点 | 贡献的层数 | 能否消除 |
|---|---|---|
| 异步传输 | +1 层(_jobs) |
否——性能需求决定必须异步 |
| per-request job 模型 | +1 层(transfer_jobs) |
理论可以——改用 per-batch event,但失去精确追踪 |
| sliding window block 保护 | +1 层(_block_id_to_pending_jobs) |
理论可以——复用 BlockPool,但需重构 block 管理交互 |
| 合计 | 3 层 |
SCOS 少一层是因为用了 per-batch event + BlockPool 复用替代其中两层。LMCache 少两层是因为同步传输 + 不支持 sliding window。Tiering 少一层是因为不管 GPU block 分配。