PD Disaggregation#
PD Disaggregation separates Prefill and Decode workers in vLLM rollout. This is especially useful for multi-turn, long-context, and agentic RL workloads where prompt processing and token generation have very different compute and memory profiles.
When to Use#
Use PD Disaggregation when:
rollout contexts are long or grow across turns;
decode dominates rollout time;
prefix-cache locality matters for multi-turn sessions;
prefill and decode need different TP, memory, or runtime settings;
you want a vLLM serving topology that is closer to production serving rather than a single uniform inference group.
For short single-turn tasks, the default regular vLLM engine layout is usually simpler.
Configuration Paths#
vime supports two ways to configure PD.
Simple Path: --prefill-num-servers#
For a single actor model with a simple PD layout, set:
--prefill-num-servers 1
This is the lightweight path used by simple scripts. It is convenient when you only need to split prefill/decode without tuning each group separately.
Advanced Path: --vllm-config#
For production rollout topologies, use vLLM Config. It lets you configure prefill and decode groups independently, and can also express EPD layouts, heterogeneous server groups, multi-model serving, and per-group vLLM overrides.
Example:
vllm:
- name: actor
update_weights: true
server_groups:
- worker_type: prefill
num_gpus: 4
num_gpus_per_engine: 2
overrides:
chunked_prefill_size: 8192
- worker_type: decode
num_gpus: 12
num_gpus_per_engine: 4
overrides:
mem_fraction_static: 0.88
Launch with:
python train.py \
--vllm-config vllm_pd.yaml \
--rollout-num-gpus 16 \
...
EPD: Splitting the Vision Encoder#
For vision-language models, the vision tower is a third workload with its own profile — bursty, image-count-driven, and idle whenever a sample is text-only. Adding a worker_type: encoder group moves it onto dedicated engines that publish image embeddings to an encoder cache, which the language engines consume instead of running the vision tower themselves.
EPD is orthogonal to PD, so the two compose:
vllm:
- name: actor
update_weights: true
server_groups:
- worker_type: encoder
num_gpus: 2
- worker_type: prefill
num_gpus: 6
- worker_type: decode
num_gpus: 8
vime starts the encoder group first, then launches the prefill/decode groups with language_only: true and the encoder URLs injected. Encoder engines stay out of the router’s worker registry — only prefill and decode serve routed traffic.
Dropping the decode group gives you encoder + regular, which splits the vision tower without PD.
See EPD Disaggregation for the full role matrix, the prime_encoder requirement for custom rollout functions, how to swap the encoder-cache connector, and current limitations.
Why This Matters for RL#
RL rollout is often not a uniform batch of short completions. Agentic and verifier-based workloads commonly have:
long prompts from tool/environment history;
multiple turns per sample;
long-tail decode latency;
session-local prefix cache opportunities;
different resource needs for actor, reference, reward, or judge models.
PD lets vime keep the training loop unchanged while using a rollout topology that matches the actual serving workload.
Operational Notes#
For new complex deployments, prefer
--vllm-configover--prefill-num-servers.Use router session affinity for multi-turn agents so turns from the same sample can reuse prefix cache. See Session-Affinity Routing.
Keep
--rollout-num-gpusequal to the total GPUs described by the vLLM config.Do not mix
regularworkers withprefill/decodeworkers inside the same model entry.encoderis the exception — it composes with either layout.Tune prefill and decode TP separately when prompt processing and token generation have different bottlenecks.