You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(sidecar): support data parallelism with the offloading P2P tier (#2075)
* feat(sidecar): support data parallelism with the offloading P2P tier
vLLM binds DP rank r's P2P tier on <p2p-connector-port>+r and gives each
replica a distinct shared-memory offload region (vllm-project/vllm#47636,
vllm-project/vllm#47987), so ranks in one pod no longer collide and the
startup rejection of --kv-connector=offloading with --data-parallel-size > 1
guards a configuration the engine now supports. Lift it and derive the
injected remote_port from the routed endpoint's port: rank r is served on
<base port>+r, so the matching P2P port is <p2p-connector-port>+r. Ports
outside the rank range fall back to rank 0, so a stale or foreign header
degrades to a lookup miss instead of an error. Assumes pods in the pool
share the sidecar port layout and DP size.
Fixes#2074
Signed-off-by: nilig <nili.ifergan@gmail.com>
* fix(sidecar): bound rank ports and accept scheme-prefixed P2P targets
The injected port is p2p-connector-port plus the target's DP rank, so the
highest rank must stay within 65535 - validate the range, not just the
base. Routed endpoint values may carry a http:// prefix (the proxy trims
it when building handlers); trim it in rank derivation and in extractHost
too, so a scheme-prefixed header yields the correct remote_host and
remote_port instead of a garbage host with a rank-0 port.
Signed-off-by: nilig <nili.ifergan@gmail.com>
* docs(sidecar): scope P2P rank derivation to per-pod DP groups
vLLM binds the tier at p2p-connector-port plus the global
data_parallel_index (tiering/p2p/manager.py), while the endpoint-port
offset yields the pod-local rank. The two agree only when each pod is its
own DP group, so state that boundary: multi-pod DP groups (LWS wide-EP)
need the source's global index supplied per request, and this derivation
is the per-pod fallback.
Signed-off-by: nilig <nili.ifergan@gmail.com>
* chore(sidecar): log P2P rank-derivation fallbacks at debug
The fallbacks in p2pPortFor silently return the base P2P port, so a
misrouted or unparsable target is invisible in the logs; a debug line
per fallback explains which guard fired.
Signed-off-by: nilig <nili.ifergan@gmail.com>
* docs(sidecar): restructure the DP section into plain-language bullets
One paragraph carried seven chained clauses; a lead sentence with one
fact per bullet reads without unpacking.
Signed-off-by: nilig <nili.ifergan@gmail.com>
---------
Signed-off-by: nilig <nili.ifergan@gmail.com>
Copy file name to clipboardExpand all lines: docs/disaggregation.md
+23-2Lines changed: 23 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -580,7 +580,28 @@ Both prefill and decode pods require the following `--kv-transfer-config`:
580
580
581
581
`host`must be the pod's own IP at runtime (use the Kubernetes downward API env var `status.podIP`). `port` must match `--p2p-connector-port` (default `7777`). `cpu_bytes_to_use` controls the CPU KV offload buffer size; size it to hold the KV for the expected concurrent in-flight transfers. `OffloadingConnector` is available in vLLM nightly builds from 2026-06-30 onward (commit `bec232a`, [PR #42285](https://github.com/vllm-project/vllm/pull/42285)).
582
582
583
-
**Restriction:** `--kv-connector=offloading` requires `--data-parallel-size=1`. Wide-EP pods (DP > 1) are rejected at startup: every DP rank would bind the same `POD_IP:<p2p-connector-port>`. DP-aware support is not yet implemented.
583
+
**Data parallelism:** the P2P tier supports `--data-parallel-size` N > 1 when
584
+
each pod is a complete DP group (the per-pod DP deployment).
585
+
586
+
- vLLM gives each DP replica its own P2P listener and offload region:
587
+
replica `i` serves on `<p2p-connector-port>+i`, where `i` is the
without those changes bind every replica to the same
592
+
`POD_IP:<p2p-connector-port>`, and DP > 1 fails at engine startup.
593
+
- The sidecar serves rank `r` on its own port + `r`, so the routed
594
+
endpoint's port names the target rank. The sidecar injects
595
+
`remote_port`= `--p2p-connector-port` + `r`; a port outside the rank
596
+
range falls back to rank 0.
597
+
- The endpoint port encodes the pod-local rank, which matches the global
598
+
index only when the pod is a whole DP group. In multi-pod DP groups (for
599
+
example LWS wide-EP, where pod `k`'s replicas hold global indices
600
+
`k*N..k*N+N-1`behind the same serving ports), the global index cannot
601
+
be read from the port and would have to be supplied with the request, so
602
+
those deployments are not covered.
603
+
- Every replica maps its own offload region, so the pod's `/dev/shm` must
604
+
exceed N x `cpu_bytes_to_use`.
584
605
585
606
### General Sidecar Flags
586
607
@@ -597,7 +618,7 @@ Both prefill and decode pods require the following `--kv-transfer-config`:
597
618
|---|---|---|---|---|
598
619
| `mooncake` | `--mooncake-bootstrap-port` | `MOONCAKE_BOOTSTRAP_PORT` | `8998` | Port used to query the Mooncake bootstrap endpoint on prefill pods. Corresponds to vLLM's `VLLM_MOONCAKE_BOOTSTRAP_PORT`. |
599
620
| `sglang` | — | `SGLANG_BOOTSTRAP_PORT` | `8998` | Port used for the SGLang bootstrap endpoint on prefill pods. |
600
-
| `offloading` | `--p2p-connector-port` | `P2P_CONNECTOR_PORT` | `7777` | Prefiller's OffloadingConnector P2P tier listening port, injected as `remote_port` on the decode leg so the decoder can pull KV. |
621
+
| `offloading` | `--p2p-connector-port` | `P2P_CONNECTOR_PORT` | `7777` | Prefiller's OffloadingConnector P2P tier listening port (rank-0 port under data parallelism), injected as `remote_port` on the decode leg so the decoder can pull KV. |
601
622
| `nixlv2` | `--enable-p2p-pull` | — | `false` | Declare the OffloadingConnector P2P tier available for cached-prefix pulls when the PD connector is NIXLv2, i.e. the engines run `MultiConnector(NixlConnector + OffloadingConnector)`. NIXL moves KV prefill to decode while the OffloadingConnector pulls the cached prefix named by `x-kv-cache-source-host-port`. Rejected at startup with any other connector; `offloading` provides the tier natively and needs no flag. |
"the prefiller's OffloadingConnector P2P tier listening port, injected as remote_port on the decode leg (used with --kv-connector=offloading or --enable-p2p-pull)")
255
+
"the prefiller's OffloadingConnector P2P tier listening port, injected as remote_port on the decode leg; with --data-parallel-size > 1 this is the rank-0 port and rank r uses port+r (used with --kv-connector=offloading or --enable-p2p-pull)")
"declare the OffloadingConnector P2P tier available for cached-prefix pulls when the PD connector is NIXL, i.e. engines run MultiConnector(NixlConnector + OffloadingConnector). Rejected with any other --kv-connector; offloading provides the tier natively without this flag.")
258
258
fs.BoolVar(&opts.SecureServing, secureServing, opts.SecureServing, "Enables secure proxy. Defaults to true.")
0 commit comments