feat: support heterogeneous qwen3.5 PD disaggregation#1995
Draft
Vectorwh wants to merge 1 commit into
Draft
Conversation
- transfer target, draft, convolution, and SSM state across heterogeneous TP layouts\n- propagate per-rank cache metadata and synchronize staged prefill pushes\n- parallelize Decode shard pulls with a safe serial fallback and request-level staging protection\n- add topology and push-route coverage plus request-level performance instrumentation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
中文说明
概述
本 PR 为昇腾 NPU 上的 Qwen3.5 推测解码增加异构 TP 的 PD 分离能力。当前支持 Prefill TP2、Decode TP1,并传输 Target KV Cache、MTP Draft KV Cache、Causal Conv State 和 SSM State。
Decode 收到 Prefill 生成的首 token 后,可直接接管请求并继续生成,不再重复执行 Prefill。
本 PR 还将 Decode 对两个 Prefill 分片的拉取改为并行执行。并行路径默认开启,同时保留运行时回退开关。
背景与问题
原有 PD 路径默认 Prefill 和 Decode 的 Cache 布局兼容。Qwen3.5 同时包含 Attention KV Cache、MTP Draft Cache、Causal Conv State 和 SSM Recurrent State。
当 Prefill TP 与 Decode TP 不一致时,两侧的 Cache ID、Tensor Shape、分片归属以及 Decode 最终布局均不同。
因此,只向 Decode 传递首 token 并不足以完成请求接管。Decode 要么得到不完整的状态,要么只能重新执行 Prefill。
本 PR 增加按 rank 传递的 Cache 元数据以及异构分片合并逻辑,使 Decode 能够直接使用 Prefill 产生的状态。
实现方案
拓扑检查与路由
按 rank 传递 Cache 元数据
Decode Cache 分配与 Staging Cache
Cache 传输与合并
[Q, K, V]重排为 Decode 侧的[Q0, Q1, K0, K1, V0, V1]。并行分片拉取与并发安全
XLLM_PD_PARALLEL_SHARD_PULL=0,无需重新编译即可回退到串行拉取。代码修改要点与分布
本 PR 共修改 33 个文件,代码量为
+1538/-93。改动集中在 KV 传输层,同时补齐元数据在 Distributed Runtime、Worker、Scheduler 和 Protobuf 之间的传递链路。xllm/core/framework/kv_cache_transfer/+1025/-19xllm/core/distributed_runtime/+223/-38xllm/core/runtime/+124/-2xllm/core/scheduler/+111/-29xllm/models/与xllm/proto/+10/-0tests/+45/-5关键代码入口:
LlmDataDistTransfer::pull_and_merge_sharded_caches():并行拉取 Prefill 分片,并按 Cache Role 合并到 Decode 最终布局。LlmDataDistTransfer::push_layer_registered_caches_to_staging():等待 Prefill 各层完成后,将 Target KEY/VALUE 逐层推送到 Decode Staging Cache。SpecKVCacheTransfer::register_kv_cache_spec()与pull_kv_blocks():注册并恢复 Target/Draft/Linear-State Cache。LLMEngine::pull_kv_blocks()、link_cluster()和unlink_cluster():将多源 Cluster 连接和分片 Cache ID 传递到具体传输实现。DisaggPDScheduler::dispatch_requests():在 Prefill 开始前创建 Decode 请求,并返回目标 Cache 元数据。DisaggPDScheduler::prefill_send_first_generation():发送首 token、MTP Bootstrap 信息和源端 Cache ID。DisaggPDScheduler::decode_recv_first_generation():恢复 KV/Linear State,完成首个 Decode Step 前的状态接管。按单文件代码量看,核心实现主要位于:
llm_data_dist_transfer.cpp:+637/-2。spec_kv_cache_transfer.cpp:+261/-10。disagg_pd_scheduler.cpp:+92/-29。llm_engine.cpp:+91/-30。使能方式
部署需要先启动
etcd和xllm-service,随后分别启动 Prefill 和 Decode xLLM 实例。Prefill 和 Decode 共同使用以下参数:
角色参数如下:
两侧必须使用相同的模型、Draft Model、Block Size、MTP 深度和 etcd 地址,并配置兼容的 DataDist 传输端口。
当前异构 Staging 布局支持 MTP3,本 PR 暂不使能 MTP5。
性能现状
测试合同:
ignore_eos=true。并行拉取相对串行 PD Control 的收益
当前性能基线对比
当前异构 PD 的 E2E 比干净的混部 TP2 基线慢
30.509 ms。TTFT 仅慢1.914 ms,剩余差距主要来自 Decode 状态接管以及 TP1 Decode 的稳态生成开销。由于混部使用 MTP5,而异构 PD 当前使用 MTP3,上表属于工程性能基线,不是相同 MTP 深度下的严格 A/B。
功能验证结论
Warning
精度尚未验证。 当前仅完成异构 KV 传输路径、输出非空和并发安全 smoke 验证。由于测试时没有空闲 NPU,
pd_launch/test_accuracy.py尚未执行,因此本 PR 当前没有可发布的精度分数,也不能声明模型精度通过。clang-formatpre-commit 检查通过。运行与性能证据采集自最终 PD 实现,随后公开分支被整理到最新 upstream
main。本 PR 不修改任何第三方 submodule 指针;根据项目要求,本次发布未追加三方件编译验证。已知限制与后续工作
10.2 ms/request,是最大的 PD 专属优化方向。提交范围
公开分支只有一个 commit,并直接基于最新 upstream
main。机器专用的 Weight-Loading commit
c4e88dc6f6a52f1ddfd4a6bd09cfe6725b41c3dd、本地启动脚本、Core Dump 和 Dirty Submodule 均未包含在 PR 中。English Description
Summary
This PR adds heterogeneous tensor-parallel PD disaggregation for Qwen3.5 speculative decoding on NPU. It supports a Prefill instance running with TP2 and a Decode instance running with TP1, transfers the target KV cache, MTP draft KV cache, causal-convolution state, and SSM state, and lets Decode continue from the first generated token without replaying Prefill.
The implementation also makes the two Prefill-shard pulls concurrent on Decode. The parallel path is enabled by default and has a runtime fallback switch.
Motivation
The existing PD path assumes compatible cache layouts between Prefill and Decode. Qwen3.5 contains attention KV cache, MTP draft cache, causal-convolution state, and SSM recurrent state. When Prefill TP and Decode TP differ, their cache IDs, tensor shapes, shard ownership, and final Decode layouts are different.
Passing only the first token is therefore insufficient: Decode either receives incomplete state or has to execute Prefill again. This PR introduces explicit per-rank cache metadata and heterogeneous merge logic so that Decode can directly take over the request.
Implementation
Topology validation and routing
Per-rank cache metadata propagation
Decode cache allocation and staging
Cache transfer and merge
[Q, K, V]shards to[Q0, Q1, K0, K1, V0, V1].Parallel shard pull and safety
XLLM_PD_PARALLEL_SHARD_PULL=0as an immediate serial fallback without rebuilding.Code change highlights and distribution
This PR changes 33 files with
+1538/-93. Most of the implementation is in the KV-transfer layer, with supporting metadata plumbing across the distributed runtime, workers, scheduler, and protobuf interfaces.xllm/core/framework/kv_cache_transfer/+1025/-19xllm/core/distributed_runtime/+223/-38xllm/core/runtime/+124/-2xllm/core/scheduler/+111/-29xllm/models/andxllm/proto/+10/-0tests/+45/-5Key code entry points:
LlmDataDistTransfer::pull_and_merge_sharded_caches()pulls Prefill shards concurrently and merges each cache role into the final Decode layout.LlmDataDistTransfer::push_layer_registered_caches_to_staging()waits for each Prefill layer and pushes target KEY/VALUE into Decode staging.SpecKVCacheTransfer::register_kv_cache_spec()andpull_kv_blocks()register and restore target, draft, and linear-state caches.LLMEngine::pull_kv_blocks(),link_cluster(), andunlink_cluster()propagate multi-source cluster links and sharded cache IDs to the transfer implementation.DisaggPDScheduler::dispatch_requests()creates the Decode request before Prefill and returns destination cache metadata.DisaggPDScheduler::prefill_send_first_generation()sends the first token, MTP bootstrap data, and source cache IDs.DisaggPDScheduler::decode_recv_first_generation()restores KV/linear state and completes takeover before the first Decode step.The largest implementation files are:
llm_data_dist_transfer.cpp:+637/-2.spec_kv_cache_transfer.cpp:+261/-10.disagg_pd_scheduler.cpp:+92/-29.llm_engine.cpp:+91/-30.Enablement
The deployment requires
etcdandxllm-service, followed by separate Prefill and Decode xLLM instances.Both xLLM roles use:
Role-specific settings:
Both roles must use the same model, draft model, block size, speculative depth, etcd endpoint, and compatible DataDist transfer ports. The current heterogeneous staging layout supports MTP depth 3. MTP5 is not enabled by this PR.
Performance status
Test contract:
ignore_eos=trueParallel pull improvement over serial PD control
Current baseline comparison
The heterogeneous PD path is currently 30.509 ms slower in E2E than the clean mixed-TP2 reference. TTFT differs by only 1.914 ms; most of the remaining gap is Decode handoff plus TP1 Decode steady-state cost. These rows are engineering baselines rather than a strict same-depth A/B because mixed mode uses MTP5 while heterogeneous PD currently uses MTP3.
Functional validation
Warning
Model accuracy has not been validated yet. The current evidence only covers heterogeneous KV-transfer routing, non-empty outputs, and concurrency-safety smoke tests.
pd_launch/test_accuracy.pyhas not been executed because no NPU was available, so this PR has no publishable accuracy score and does not claim an accuracy PASS.clang-formatpre-commit validation passed for the public commit.The runtime and performance evidence was collected with the final PD implementation before the public branch was rebased onto the latest upstream
main. This PR does not modify third-party submodule pointers; per project instruction, no additional third-party build validation was required for publication.Known limitations and follow-up work
Commit hygiene
The public branch contains one commit based directly on the latest upstream
main. The local-only weight-loading commitc4e88dc6f6a52f1ddfd4a6bd09cfe6725b41c3dd, local launch scripts, core dumps, and dirty submodule worktrees are not included.