Skip to content

[Serve] [SGLang] [Draft] POC PD disaggregation - #63741

Open
limarkdcunha wants to merge 23 commits into
ray-project:masterfrom
limarkdcunha:feature/ray-serve-sglang-pd-disaggregation
Open

[Serve] [SGLang] [Draft] POC PD disaggregation#63741
limarkdcunha wants to merge 23 commits into
ray-project:masterfrom
limarkdcunha:feature/ray-serve-sglang-pd-disaggregation

Conversation

@limarkdcunha

Copy link
Copy Markdown
Contributor

Description

A POC PR for the my proposal (#63257) related to Ray Serve SGLang PD disaggregation support.

Related issues - #62792 #63257

@limarkdcunha limarkdcunha changed the title [Serve] POC ready for PD dissaggregation [Serve] [SGLang] POC PD disaggregation May 30, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces SGLang Prefill-Decode (PD) disaggregated LLM serving by adding SGLangPDPrefillServer and SGLangPDDecodeServer deployments, and updating the SGLang engine to pass bootstrap coordination fields. Feedback on these changes highlights critical issues: first, setting attributes directly on Pydantic v2 models will raise runtime errors, so object.__setattr__ should be used instead; second, the prefill generator must be consumed in a background task to prevent premature garbage collection and engine hangs; third, asyncio needs to be imported to support this background task; and finally, the new servers should be added to the __all__ list in deployment.py to be properly exposed in the public API.

Comment thread python/ray/serve/llm/deployment.py Outdated
@jeffreywang88

jeffreywang88 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

can you add a target in release_tests.yaml? example: https://github.com/ray-project/ray/blob/master/release/release_tests.yaml#L4643-L4661

@limarkdcunha

Copy link
Copy Markdown
Contributor Author

Added the target in release_tests.yaml. Thanks

@jeffreywang88 jeffreywang88 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some design questions for you to consider while revising the RFC.

Comment on lines +12 to +14
to the right place. The decode server generates the bootstrap_room upfront and
dispatches both sides simultaneously — it does not wait for a prefill response
before starting decode.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks similar to the parallel handoff pattern (https://github.com/ray-project/ray/pull/63950/changes#diff-ccc2365e3ea6c5f4fd309223ecbaaa15d44deb1d510f0acf985604060a7f1747R56). Could you assess the feasibility of leveraging the established concurrent handoff mechanism?

Comment on lines +144 to +145
# LLMServer.get_deployment_options calls get_engine_config(), which
# unconditionally imports vLLM. The SGLang byod image uninstalls vLLM,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to somehow decouple vLLM from the common paths. It might require a refactor. Could you explore some options?

carrying the same prefill bootstrap host/port/room — the decode
KVReceiver connects to that prefill bootstrap server and blocks
internally waiting for the KV cache to arrive.
5. Streams the decode response back to the client.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exactly what we need, nice!

For each chat/completions request it:
1. Reads the PREFILL node's bootstrap_host and bootstrap_port, fetched
from the prefill deployment at init (the bootstrap server lives there).
2. Generates a unique bootstrap_room integer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the design doc, it'd be great to clarify what bootstrap_room does and where it lives.

Comment on lines +185 to +187
# TODO: Users currently need to set disaggregation_mode manually in engine_kwargs.
# The builder should set this automatically since it already knows which
# config is prefill and which is decode.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should emulate ray serve LLM's PD API for vLLM here. The user API should be similar.


Unlike the vLLM flow, we do not wait for a prefill response before
starting decode — the bootstrap_room is established upfront and both
sides coordinate directly via SGLang's bootstrap server.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this bootstrap server strictly required?

Comment thread python/ray/serve/llm/deployment.py Outdated
pass


@PublicAPI(stability="beta")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should start from alpha.

Comment on lines +4674 to +4675
- UCX_TLS=all
- UCX_NET_DEVICES=all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you help me understand why we need these?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we use SGLang with NIXL, it uses a networking library called UCX to move data directly from one GPU to another.

By default, our testing environment (the CI box) has strict or limited network paths. Without these two settings, UCX gets confused, picks a network path that doesn't actually have access to the GPUs, and the data transfer crashes.

Here is what these two lines specifically tell UCX to do:

  • UCX_TLS=all: Tells it, 'You are allowed to use any available transport method (like shared memory, TCP, or CUDA-IPC) to move this data.'

  • UCX_NET_DEVICES=all: Tells it, 'You are allowed to look at all network devices on this machine to find a working path.'

Basically, it forces UCX to stop being picky and use whatever path works on our test machines so the test doesn't fail. Once we know the absolute bare minimum network settings needed for this specific CI box, we can narrow this down."

Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
@eicherseiji
eicherseiji removed the request for review from alimaazamat July 13, 2026 23:41
@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had
any activity for 14 days. It will be closed in another 14 days if no further activity occurs.
Thank you for your contributions.

You can always ask for help on our discussion forum or Ray's public slack channel.

If you'd like to keep this open, just leave any comment, and the stale label will be removed.

@github-actions github-actions Bot added the stale The issue is stale. It will be closed within 7 days unless there are further conversation label Jul 28, 2026
@limarkdcunha

Copy link
Copy Markdown
Contributor Author

The work on this PR has been paused due to unavailability of GPU's I am working on getting access to some resources, commenting it here so this PR is not marked as stale.

@github-actions github-actions Bot added unstale A PR that has been marked unstale. It will not get marked stale again if this label is on it. and removed stale The issue is stale. It will be closed within 7 days unless there are further conversation labels Jul 29, 2026
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread bench/launch_ray_pd.py
Comment thread bench/ray_pd_ttft.job
Comment thread bench/ray_pd_ttft.job
Comment thread bench/ray_pd_ttft.job Outdated
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread python/ray/llm/_internal/serve/engines/sglang/kv_transfer/pd_connector.py Outdated
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread python/ray/llm/_internal/serve/engines/sglang/kv_transfer/pd_connector.py Outdated
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread release/llm_tests/serve/test_llm_serve_sglang_pd.py
Comment thread bench/launch_native_pd.sh
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread python/ray/llm/_internal/serve/engines/sglang/sglang_engine.py
Comment thread bench/sweep.py Outdated
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Comment thread python/ray/llm/_internal/serve/engines/sglang/kv_transfer/pd_connector.py Outdated
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 9cc692b. Configure here.

limarkdcunha and others added 3 commits August 1, 2026 18:18
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Launching 8 SGLang processes simultaneously spikes the container's
cgroup PID/thread count past its limit for a moment (each process
spins up its own tokenizer thread pool, scheduler, detokenizer),
crashing whichever process happens to hit the ceiling with a
rayon ThreadPoolBuildError. A few seconds between launches avoids it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
@limarkdcunha limarkdcunha changed the title [Serve] [SGLang] POC PD disaggregation [Serve] [SGLang] [Draft] POC PD disaggregation Aug 4, 2026
Signed-off-by: Limark Dcunha <limarkdcunha@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution Contributed by the community llm serve Ray Serve Related Issue unstale A PR that has been marked unstale. It will not get marked stale again if this label is on it.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants