Configuration#
PSRL uses Hydra with OmegaConf for hierarchical, composable configuration management.
Configuration System#
All configuration lives under psrl/trainer/config/. Hydra composes a single merged
config from multiple YAML files at runtime, allowing you to:
Override individual parameters from the command line
Swap entire config groups (e.g., switch from FSDP to Megatron backend)
Use variable interpolation (e.g.,
${psrl.staleness}) across config files
File Layout of the psrl Group#
psrl/psrl.yaml is a Hydra defaults list that composes one file per feature. All of
them live in psrl/trainer/config/psrl/:
File |
Merged at |
Covers |
|---|---|---|
|
|
Core settings and the defaults list |
|
|
Cluster sizing, heterogeneous rollout, elastic RM |
|
|
Rollout/training compute overlap |
|
|
Multi-turn agent loop toggles |
|
|
Optional external HTTP rollout service |
|
|
Profiling/analysis switches |
|
|
Rollout-engine log-prob toggle |
|
|
Engine status telemetry |
|
|
Periodic GPU memory logging |
|
|
RDMA weight-sync transport |
|
|
Rank-0 checkpoint broadcast |
|
|
Megatron save/load strategy |
|
|
Streaming group post-processing |
|
|
Batch buffer post-processing |
|
|
torch_memory_saver scope |
|
|
KV offloading and P2P transfer |
|
|
SMG gateway process |
|
|
Online generation coordination (six files) |
Each file is merged into the node shown above, so a field’s key path is that node
plus the field name. For example, enable in lmcache.yaml is addressed as
psrl.lmcache.enable.
Top-Level Config#
The entry point is psrl/trainer/config/ppo_trainer.yaml, which composes the following
groups via Hydra defaults:
Group |
Config Key |
Config Path |
Description |
|---|---|---|---|
|
|
|
PSRL-specific settings (staleness, deployment, routing) |
|
Hydra selection |
|
Selects DP/FSDP-compatible or Megatron component groups |
|
|
|
Actor model training config |
|
|
|
PSRL-extended validation/training-side rollout config |
|
|
|
PSRL-extended generation-cluster rollout config |
|
|
|
Dataset and dataloader config |
|
|
|
Reference model config |
|
|
|
HuggingFace model loading config |
|
|
|
Critic model config. Its |
|
|
|
Reward model and reward-manager config |
|
|
(inline in ppo_trainer.yaml) |
Algorithm hyperparameters (PPO/GRPO/DAPO) |
|
|
|
Rollout importance-sampling correction |
|
|
|
On-policy distillation config |
|
|
(inline in ppo_trainer.yaml) |
Training loop settings (epochs, logging, checkpoints) |
|
|
(inline in ppo_trainer.yaml) |
Sample storage and transport backend |
The generation cluster does not load its own model group: gen_actor_rollout_ref.model
is an interpolation of train_actor_rollout_ref.model, so both clusters always agree on
the HuggingFace model definition.
Groups marked (veRL) are not duplicated in this repository. A Hydra search-path
plugin appends pkg://verl.trainer.config as a fallback, so any group PSRL does not
define locally resolves against the installed veRL package. Dropping a same-named
YAML into PSRL’s own config/ directory overrides the veRL version. For Megatron
training, use ppo_megatron_trainer.yaml.
Note
The rollout (train) group, train_actor_rollout_ref.rollout, exists only to
stay aligned with veRL’s config layout. Except for the handful of parameters that
affect validation and recompute log-prob on the training cluster, its fields
are unused and act as a placeholder. In practice, keep it aligned with
gen_actor_rollout_ref.rollout (the generation-cluster rollout config that actually
drives online generation). This config split is a known rough edge that we plan to
streamline in a future release.
veRL-Managed Configuration#
Most of the config groups above (train_actor_rollout_ref, data, algorithm,
trainer, rollout, critic, reward_model, etc.) are inherited directly from
veRL with minimal changes.
Tip
For the full reference of veRL-managed config groups, including actor training hyperparameters, optimizer settings, rollout sampling parameters, data loading, algorithm coefficients, and trainer loop settings, refer to the official veRL configuration documentation:
Given the note above, the PSRL-introduced surface is small: only two parts of the
tree are genuinely new. The psrl config group (described below) and the
gen_actor_rollout_ref sub-tree that configures the decoupled generation cluster
separately from the training cluster. Everything else mirrors veRL.
PSRL Config Reference#
The primary PSRL configuration file is psrl/trainer/config/psrl/psrl.yaml. Below is a
categorized reference of all parameter groups.
Core Settings#
ps_manager_ipIP address of the Parameter Server Manager process. All inter-component communication (NIXL, LMCache Controller, reward service) defaults to this address. Default:
127.0.0.1reward_service_ipIP address of the reward scoring service. Default:
${psrl.ps_manager_ip}logging_pathBase directory for all PSRL log outputs (trajectory dumps, profiling files, etc.). Default:
~/psrl_logsstalenessMaximum version gap between generation and training.
0= fully synchronous (generation blocks until training consumes). Values>0allow that many rollout buffers to be generated ahead of training consumption. Default:0staleness_buffer_entriesNumber of prompts in each staleness buffer (effective training batch size). Each buffer must be fully filled before it can be consumed by training. Default:
512rollout_nNumber of responses generated per prompt. Set
>1for GRPO/DAPO group sampling (e.g., 8). Default:1ps_modeParameter server weight synchronization mode.
cpu_ref: CPU-based reference model (simpler setup, no NIXL required)nixl_cpu: GPU-direct RDMA via NIXL (recommended for production)
Default:
cpu_refretry_boundBuffer bound for the retry mechanism.
-1means unbounded. Default:-1retry_ratioRatio applied on top of
retry_bound. Default:1.0
Note
retry_bound and retry_ratio are declared placeholders: no code path reads them
today. They are reserved for the buffer retry mechanism and setting them has no
effect on the current training loop.
Fine-Grain Overlap#
Overlaps training-side compute with ongoing rollout generation by releasing training buffers in smaller chunks instead of waiting for a full global batch to accumulate. When enabled, the trainer starts running per-sample forward passes (old log-prob, reference log-prob, values, reward) on completed prompt groups as they arrive, so the per-sample GPU work for chunk N runs while rollout continues generating chunk N+1.
fine_grain_overlap.granularityGranularity of each training chunk.
none: disabled. The trainer waits for the full global batch before starting any work.mini_batch: each chunk contains one PPO mini-batch worth of prompt groups (ppo_mini_batch_sizeprompts, timesrollout_ntrajectories each). Setmultiplierto combine multiple mini-batches into one chunk.micro_batch: each chunk is derived fromppo_micro_batch_size_per_gpu * dp_sizesamples. Onlyoverlap_scope: recomputeis supported at this granularity. Thepre_stepscope for micro-batch overlap is not yet implemented.
When
multipliercauses the computed chunk size to exceed the next level (a micro-batch chunk exceeding one mini-batch, or a mini-batch chunk exceeding the full batch), the granularity is automatically clamped to that level.Default:
nonefine_grain_overlap.multiplierMultiplier applied to the base chunk size. The effective chunk is
base_unit_samples * multiplier, clamped at the full global batch. Default:1fine_grain_overlap.overlap_scopeWhat computation runs inside each chunk.
recompute: only the per-sample forward stages (old log-prob, reference log-prob, values, reward) run per chunk. Advantage computation and the optimizer update run once on the full concatenated batch after all chunks arrive. The training math is numerically identical togranularity: nonefor all advantage estimators.pre_step: in addition to per-sample stages, advantage and one optimizer step also run per chunk. Each chunk withgranularity: mini_batchbecomes a complete PPO mini-batch update. This scope requiresppo_epochs: 1. Withadv_estimator: grpo, results are exact because GRPO normalizes per prompt group. Withadv_estimator: gaeorreinforce_plus_plus, the per-chunk whitening scope differs from the full-batch scope and results are approximate.
Default:
recompute
Note
overlap_scope: pre_step is only supported with granularity: mini_batch.
Combining pre_step with granularity: micro_batch raises a ValueError at startup.
Compatibility constraints enforced at startup:
overlap_scope: pre_steprequiresppo_epochs: 1.granularity: micro_batchwithuse_dynamic_bsz: Trueraises an error because the chunk size cannot be determined without a staticppo_micro_batch_size_per_gpu.granularity: micro_batchwithoverlap_scope: pre_stepandactor.strategy: megatronis not supported.
Example: recompute scope (safe starting point)
fine_grain_overlap:
granularity: mini_batch
multiplier: 1
overlap_scope: recompute
Example: pre_step scope with GRPO (maximum overlap)
fine_grain_overlap:
granularity: mini_batch
multiplier: 1
overlap_scope: pre_step
# also set:
# train_actor_rollout_ref.actor.ppo_epochs: 1
# algorithm.adv_estimator: grpo
Deployment#
Resource allocation for training and rollout clusters.
deployment.n_rollout_instancesNumber of independent rollout (generation) vLLM instances. Default:
1deployment.n_validate_instancesNumber of validation rollout instances (typically colocated with training). Default:
1deployment.rollout_nnodes_per_instanceNodes allocated to each rollout instance. Default:
1deployment.rollout_ngpus_per_node_per_instanceGPUs per node for each rollout instance. Default:
1deployment.validate_nnodes_per_instanceNodes allocated to each validation instance. Default:
1deployment.validate_ngpus_per_node_per_instanceGPUs per node for each validation instance. Default:
1deployment.train_nnodesNodes allocated to the training cluster. Default:
1deployment.train_ngpus_per_nodeGPUs per node in the training cluster. Default:
1deployment.total_nnodesTotal nodes in the job. When set, excess nodes are blocked from scheduling to prevent colocated validate workers from spilling onto idle nodes. Set to match
NNODESin your launch script. Default:nulldeployment.heterogeneous_rolloutEnable per-instance configuration of rollout resources. When
enable: True, each rollout instance can be individually configured:Sub-field
Description
enableMaster switch. Default:
Falsen_rollout_instancesMirrors
psrl.deployment.n_rollout_instancesrollout_nnodes_per_instanceList of per-instance node counts (length =
n_rollout_instances)rollout_ngpus_per_node_per_instanceList of per-instance GPU counts
tensor_model_parallel_size_per_instanceList of per-instance TP sizes
pipeline_model_parallel_size_per_instanceList of per-instance PP sizes
deployment.elastic_rmPolicy-driven resource sharing between rollout and named generative reward-model instances. The
ElasticExecutormonitor loop samples per-instance KV-cache utilization and queue depth, then sleeps and wakes whole inference instances through their coordinators so the two roles can trade GPUs at runtime.Resource pool and monitor loop
Sub-field
Description
Default
enableMaster switch for rollout/reward auto-scaling.
Falseshared_nnodesNodes in the shared resource pool.
1shared_ngpus_per_nodeGPUs per node in the shared pool.
8enable_policyLet the monitor loop make policy-driven scaling decisions. With
Falsethe executor only reports state.Truemonitor_interval_msMonitor loop tick interval.
1000coordinator_sync_timeout_sPer-tick cap on coordinator Ray RPCs (engine snapshot + router backlog), so a blocked coordinator cannot silently hang the monitor.
<= 0disables the cap.10coordinator_command_timeout_sPer-command cap on each
SLEEP/WAKE_UP/ABORTsent to a coordinator.0waits indefinitely.300decision_execution_abandon_stall_ticksConsecutive ticks blocked on an unfinished scale decision before the in-flight state is cleared so new decisions can run.
0never abandons. Wall time is roughlyticks * monitor_interval_ms / 1000.180Scaling policy
Sub-field
Description
Default
theta_lowKV-cache utilization below which an instance may cede its GPUs.
0.1theta_maxKV-cache utilization above which an instance counts as full-load.
0.8full_load_modeWhether
allinstances of a role must be full-load before scaling up, oranysingle one suffices.anycooldown_msCooldown after each scaling action, to damp oscillation.
10000hysteresisMinimum bottleneck-throughput gain required to justify a one-step transfer.
0.05min_awake_per_roleInstances each role always keeps awake.
0lets one side sleep entirely.1max_waiting_queue_for_scale_downScale-down guard: even below
theta_low, do not shrink a candidate whose local waiting queue exceeds this.0requires an empty queue.64post_scale_up_abort_waiting_ratioFraction
[0, 1]of each instance’s waiting queue aborted after a scale-up so the freshly woken instance can pick the work up. Aborts are FIFO.0disables and1aborts all.0.8lambda_ewma_alphaEWMA smoothing factor for the arrival-rate estimate.
0.2Throughput model
Sub-field
Description
Default
throughput_model_dirDirectory holding
{model_name}_token.jsonfitted throughput formulas.psrl/config/throughput_modelthroughput_model_output_lenOutput-length bucket to read from the token-throughput fit.
1024profile_pathsOptional
{model_name: profile_json_path}map using the newer profile schema.{}The policy resolves throughput in priority order: fitted formula file, then
profile_pathsentry, then the measured runtimegeneration_throughput.
Colocate & Fuse Settings#
colocate_validate_and_trainWhether to colocate validation and training workers on the same nodes. Default:
Truefuse_rollout_with_validateWhether to dispatch validation requests to the rollout instance pool as well, effectively using the rollout instances as extra validation capacity (validation and rollout share one instance pool instead of validation having a dedicated pool). Must be
Truewhencolocate_validate_and_train=False. Default:True
Status Collection#
The rollout coordinator collects real-time engine statistics to enable smart routing and sync decisions.
status_collection.enableWhether to enable engine status collection. Default:
Truestatus_collection.engine_sync_interval_in_msHow often each vLLM engine pushes its status to the rollout coordinator (ms). Default:
100status_collection.coordinator_sync_interval_in_msHow often the coordinator aggregates engine statuses and pushes to the router (ms). Default:
100status_collection.dump_logging_to_file_levelGranularity of status logs written to disk. Options:
none,partial_rollout,prompt,generation,all. Default:allstatus_collection.dump_logging_to_file_interval_in_msFile logging flush interval (ms). Default:
500status_collection.stats_recorder.enablePeriodically write per-replica JSONL snapshots to
psrl.logging_path, one file per(replica_id, dp_rank)pair. Default:Truestatus_collection.stats_recorder.interval_in_sSnapshot interval (seconds). Default:
1.0
Rollout Coordination#
psrl.rollout_coordination.* groups all the online generation-coordination
strategies together. It is composed from six Hydra sub-groups (partial rollout,
redundant rollout, routing strategy, sync & migration, proactive
filter, and session strategy), each documented below. Together they decide how
requests are dispatched, when weights are synced, how stragglers and over-capacity
sessions are handled, and how much work is over-provisioned.
See also
Flexible Rollout Coordination covers the design of partial rollout, redundant rollout, intelligent routing, and migration, and how they interact with the staleness system.
Partial Rollout#
Allows generation to be interrupted and resumed, preventing long sequences from blocking the training pipeline.
rollout_coordination.partial_rollout.enableWhether to enable partial rollout interruption. Default:
Truerollout_coordination.partial_rollout.interrupt_as_promptIf
True, interrupted trajectories are treated as new prompts (the partial generation becomes part of the next prompt). IfFalse, the SMG path keeps the request active and continues it through partial-rollout routing loopback. Default:False
Redundant Rollout#
Generates more trajectories than needed for training, allowing the system to select the best subset and discard redundant or slow samples.
rollout_coordination.redundant_rollout.enableWhether to enable redundant rollout generation. Default:
Falserollout_coordination.redundant_rollout.alg_global_batch_sizeRequired batch size for the algorithm (buffers are considered ready at this size). Default:
${psrl.staleness_buffer_entries}rollout_coordination.redundant_rollout.alg_rollout_nNumber of responses required by the algorithm per prompt. Default:
${psrl.rollout_n}rollout_coordination.redundant_rollout.redundant_global_batch_sizeActual number of trajectory prompts generated (must be ≥
alg_global_batch_size). Default:${psrl.staleness_buffer_entries}rollout_coordination.redundant_rollout.redundant_rollout_nActual number of responses generated per prompt (must be ≥
alg_rollout_n). Default:${psrl.rollout_n}
Routing Strategy#
Controls how generation requests are dispatched across rollout instances.
rollout_coordination.routing_strategy.methodRouting algorithm. Options:
random: uniform random assignmentround_robin: cyclic assignmentrequest_num_balance: route to the instance with fewest active requeststhroughput_optimal: maximize global throughput using a cost modelthroughput_optimal_with_budget: throughput-optimal with per-request token budgetcache_aware: SMG’s native prefix-cache-aware routing (single-tier: GPU-resident prefix hits, plus shortest-queue load balancing)cache_aware_v1: PSRL’s optimized, multi-tier cache-aware variant. On top of SMG’s native behaviour it also scores off-GPU (LMCache CPU-tier) prefix hits, using thecache_aware_policyweights below. Prefer this when LMCache offload is enabled.
Default:
request_num_balancerollout_coordination.routing_strategy.cache_aware_policyHyperparameters for the SMG cache-aware router. Only used when
methodiscache_awareorcache_aware_v1. The multi-tier fields (lmcache_overlap_weight) only take effect undercache_aware_v1.Sub-field
Description
Default
cache_thresholdMin cache-hit ratio for the approximate radix-tree fallback path (used only when KV events are unavailable, since event-driven scoring ignores it). Ranges from 0.0 to 1.0.
0.0gpu_overlap_weightWeight for GPU-resident prefix hits in the multi-tier overlap score. A GPU hit costs ~zero reload.
1.0lmcache_overlap_weightWeight for off-GPU (LMCache) prefix hits (
cache_aware_v1only). Cheaper than re-prefill but not free, so keepgpu >= lmcache.0scores GPU hits only, so raise it once LMCache offload is enabled.0balance_abs_thresholdShortest-queue load balancing triggers when BOTH the absolute and relative request-count thresholds are met.
16balance_rel_thresholdRelative request-count spread threshold for the load-balancing trigger.
1.5balance_token_usage_thresholdKV-utilization (token usage) level that triggers load balancing (
>= 1.0disables).0.75overload_token_usage_thresholdKV-utilization level above which an instance is treated as overloaded (
>= 1.0disables, which is the default).1.0eviction_interval_secsApproximate radix-tree maintenance interval (fallback when KV events are unavailable).
60max_tree_sizeMax size of the approximate prefix tree.
67108864(2^26)block_sizeKV block size used for event-driven routing.
16kv_capacity_thresholdcache_aware_v1only. Admission gate rejects an instance wheneffective_kv_used + new_tokens > kv_capacity_threshold * max_model_len. Values below1.0reserve headroom for decode-time growth (0.85leaves 15%). The shipped default of2.0is permissive and effectively disables the check.2.0The request-count spread (
balance_abs_threshold/balance_rel_threshold) is computed from in-flight worker load, whereas the two token-usage triggers read the backend engine’stoken_usagesnapshot.rollout_coordination.routing_strategy.kv_transferWhen re-routing a request to a different instance, optionally transfer its accumulated KV cache via LMCache P2P to avoid re-prefill. Requires
lmcache.enableandlmcache.enable_p2p.Sub-field
Description
enableMaster switch. Default:
Falsetransfer_modeasync(fire-and-forget),sync(await, no pin),pin_sync(pin→await→unpin). Default:asynctransfer_timeout_msTimeout for
sync/pin_syncmodes before falling back to re-prefill. Default:5000stats_log_interval_sInterval (s) between periodic KV-transfer stats log lines on each source instance.
0suppresses stats even when transfer is enabled. Default:30rollout_coordination.routing_strategy.cost_model_pathPath to a JSON cost model file (required for
throughput_optimalmethods). Default:nullrollout_coordination.routing_strategy.request_sort_indicatorHow to prioritize requests within a routing cycle. Options:
short_length,long_length,small_id. Default:small_idrollout_coordination.routing_strategy.candidate_sort_indicatorHow to sort candidate instances. Options:
version,reserve_capability. Default:versionrollout_coordination.routing_strategy.enable_multi_priority_queueUse separate queues for different request priorities. Default:
Falserollout_coordination.routing_strategy.enable_group_stickyPin all rollout requests sharing a
prompt_idto the same rollout instance so their KV-cache prefixes are reused. Default:Falserollout_coordination.routing_strategy.enable_trajectory_stickyPin all generation calls within a single trajectory (subsequent turns) to the same rollout instance that served the first turn, reusing the per-trajectory KV-cache prefix. This is the trajectory-affinity knob for multi-turn agentic RL. Default:
Falserollout_coordination.routing_strategy.logging_interval_in_msInterval for routing-loop log lines (ms). Currently a declared placeholder that no code path reads. Default:
2000rollout_coordination.routing_strategy.delta_throughput_thresholdStop routing new requests to an instance when its marginal throughput contribution drops below this fraction. Default:
0.5rollout_coordination.routing_strategy.request_budgetEstimated token budget per request, used by
throughput_optimal_with_budgetto predict response length. Default:1024rollout_coordination.routing_strategy.snapshot_staleness_threshold_in_msAge limit for an engine-status snapshot before it is considered stale, measured as the gap between the last recorded timestamp and the snapshot time. Currently a declared placeholder that no code path reads. Default:
1000rollout_coordination.routing_strategy.max_concurrent_seqs_per_instanceCap on concurrent sequences per instance. This value serves double duty: it is the admission gate’s in-flight request cap and it is forwarded to vLLM as
max_num_seqs. Lower it to bound per-instance concurrency.0means no cap. Default:1024rollout_coordination.routing_strategy.check_interval_in_msPolling interval for the routing loop (ms). Default:
500
Admission control
The admission gate is always on and has no master switch. It decides whether a
selected instance may accept a request based on in-flight count, KV capacity
(cache_aware_policy.kv_capacity_threshold), and the waiting-queue rule below.
rollout_coordination.routing_strategy.admission_reject_on_waitingWhen
True, the gate only admits a request to an instance whose engine waiting queue is empty, which is the strict setting that keeps queueing at the router rather than inside the engine. Default:Truerollout_coordination.routing_strategy.max_num_waiting_reqs_after_preemptionForwarded to vLLM as
preemption_notification_threshold. The engine notifies the gateway once its waiting queue exceeds this many requests after a preemption, and those preempted requests are then looped back to the SMG router for global re-scheduling instead of staying queued on the local instance. This is a notification threshold, unrelated to admission despite the similar name. Default:1024
Important
With the default SMG gateway, set rollout_coordination.routing_strategy.method to
cache_aware or cache_aware_v1 to enable PSRL’s vLLM KV-event publisher and prefix
reuse. Use cache_aware_v1 when LMCache offload is enabled so off-GPU prefix hits are
scored too.
Sync & Migration#
Controls when model weights are synchronized and when rollout requests are migrated between instances for load balancing.
rollout_coordination.sync_and_mig_strategy.methodStrategy for deciding sync/migration timing.
status_based: use instance status indicators to decide when to syncgreedy: sync as soon as a new version is available
Default:
greedyrollout_coordination.sync_and_mig_strategy.check_interval_in_msPolling interval for the sync/migration loop (ms). Default:
100rollout_coordination.sync_and_mig_strategy.sync.indicatorMetric that triggers weight sync. Options:
request_num,throughput,kv_cache,hypothesis_test. Default:request_numrollout_coordination.sync_and_mig_strategy.sync.thresholdWorkload threshold below which model sync is triggered. Interpretation depends on the
indicator(count, tokens/s, or utilization fraction). Default:nullrollout_coordination.sync_and_mig_strategy.sync.check_req_before_syncBefore syncing, verify that no routeable requests are pending for this instance. Default:
Truerollout_coordination.sync_and_mig_strategy.sync.seamless_train_versionAll model versions ≤ this value are guaranteed to have a ready buffer waiting, so training can proceed immediately after weight pull without stalling. Default:
0rollout_coordination.sync_and_mig_strategy.mig.enableWhether to enable coordinator-side request migration between rollout instances. When enabled, the coordinator aborts requests on overloaded instances so they loop back to the router. Default:
Falserollout_coordination.sync_and_mig_strategy.mig.indicatorMetric used to identify imbalanced instances for migration. Options:
request_num,throughput,kv_cache. Default:request_numrollout_coordination.sync_and_mig_strategy.mig.thresholdRelative imbalance ratio (
max_indicator / min_indicator) that triggers migration. Default:nullrollout_coordination.sync_and_mig_strategy.mig.stop_indicatorMetric used to decide when to stop migrating. Default:
request_numrollout_coordination.sync_and_mig_strategy.mig.stop_thresholdThreshold on
stop_indicatorbelow which migration halts. Default:null
Proactive Filter#
Handles situations where a buffer is nearly ready but a few remaining requests are straggling.
rollout_coordination.proactive_filter_strategy.methodStrategy for handling straggling requests.
null: disabled (wait indefinitely)retry: abort and re-dispatch straggling requeststruncate: mark buffer as ready with fewer entries
Default:
nullrollout_coordination.proactive_filter_strategy.thresholdNumber of remaining reserved entries below which the filter strategy activates. Default:
0
See also
Fine-Grained Staleness Control, How proactive filtering integrates with the Reserve/Occupy/Consume staleness protocol.
Session Strategy#
Session hang/continue scheduling for multi-turn TITO sessions, ported from ThunderAgent. When enabled, the RolloutCoordinator periodically hangs whole sessions pinned to over-KV-capacity instances (blocking their next turn at the SessionRouter without aborting in-flight work) and continues them once the pinned instance frees capacity. This subsystem is under active development. ThunderAgent is the currently integrated strategy, adapted from the original capacity-based pause/resume design in the ThunderAgent project.
rollout_coordination.session_strategy.thunder_agent.enableMaster switch for session hang/continue scheduling. Default:
Falserollout_coordination.session_strategy.thunder_agent.check_interval_in_msScheduler tick interval (ms). Default:
1000rollout_coordination.session_strategy.thunder_agent.env_token_weightReservation coefficient for env-status (between-turns) session tokens. Such a session’s KV has already been freed from the engine pool, so it is absent from the measured
used_tokens, so this coefficient adds it back as a predictive reservation for when the session returns from the environment. Values below1.0assume not all env sessions come back at once. Default:1.0rollout_coordination.session_strategy.thunder_agent.buffer_per_sessionDecode headroom (tokens) reserved per running session. Default:
100rollout_coordination.session_strategy.thunder_agent.continue_scopeWhich instance a hung session is readmitted on.
bucketed: readmit the session on the instance it already occupies. This is the only valid choice under trajectory sticky routing, whichvalidate_configenforces.global: run a global Best-Fit-Decreasing pass across all instances, which may relocate the session onto an emptier one, matching ThunderAgent’s_greedy_resume.
Default:
bucketedrollout_coordination.session_strategy.thunder_agent.continue_force_pinWhether to force-pin the chosen continue instance for the readmitted session’s next turn, sent as a one-shot pin that SMG clears on the first loopback. When
False, only the session id is sent on continue and SMG routes the next turn normally. Default:False
continue_scope and continue_force_pin are independent, giving four combinations.
See also
Router, SessionRouter, and TITO, SessionRouter, TITO session capture, and how hang/continue interacts with sticky routing.
NIXL#
Configuration for RDMA-based weight synchronization via NIXL (used when
ps_mode: nixl_cpu).
nixl.server_ipNIXL server IP address. Default:
${psrl.ps_manager_ip}nixl.server_portNIXL server port. Default:
23456nixl.max_pinned_temp_memory_slotsNumber of pinned temporary memory slots for non-contiguous tensor transfers. Increase if you hit registration contention with many concurrent PS workers. Default:
16nixl.enable_tms_for_temp_buffersManage NIXL temporary buffers with TMS, simplifying re-registration after memory is resumed. Default:
${psrl.tms.enable_nixl}
Checkpoint#
Controls the Megatron checkpoint save/load strategy. Relevant only when using the Megatron training backend.
checkpoint.use_dcp_saveWhether to use verl’s default DCP (Distributed Checkpointing) for save/load.
False: Use PSRL’s per-ranktorch.save(savesrank_N.pt+parallel_config.jsonper rank). This path is UCX-safe: it avoids DCP’sFullyParallelSaveStrategyWrapperwhich callsall_gather_objecton all shard metadata, causing a large temporary allocation that can corrupt NIXL’s UCX endpoint memory under high memory pressure (manifests asaddr_version assertionSIGABRT). The NIXL background UCX progress thread (enable_prog_thread) is kept enabled in this mode.True(default): Use verl’s DCP path. Two patches are applied automatically:NCCL no-fork patch: DCP’s async writer normally forks child processes that inherit NCCL communicators. When the child exits,
ncclCommAbortcorrupts the parent’s NCCL state, causing a 600-second timeout then SIGABRT. The patch replaces the forking multiproc writer with a sequential in-process version.NIXL prog_thread disabled:
enable_prog_thread=Falseis passed to the NIXL agent to prevent the UCX background thread from racing with DCP’sall_gather_objectmemory activity.
Default:
True
LMCache#
KV cache offloading and cross-instance P2P transfer for reducing re-prefill overhead in multi-turn workloads.
lmcache.enableMaster switch for LMCache KV offloading in vLLM. Default:
Falselmcache.backendStorage backend for offloaded KV blocks.
cpu: host memory (fast, limited by DRAM)disk: filesystem-backed (large capacity, slower)remote: reserved for a remote KV server, not yet implemented
Default:
cpulmcache.offload_size_gbTotal offload budget in GiB, divided automatically across TP ranks. Do not set
LMCACHE_MAX_LOCAL_CPU_SIZEas an env var, that would apply the full budget to every rank. Default:100.0lmcache.chunk_sizeToken chunk size for hash-based KV indexing (must divide the block size). Default:
256lmcache.clear_on_weight_updateEvict all cached KV entries after each model weight pull from the PS. This prevents stale-weight KV from being reused in the next generation round, but it is a blunt instrument, it discards every reusable prefix in the offload backend once per weight update. The default is
Falsebecause the shipped configuration relies onmulti_version_kvinstead, which is the finer-grained mechanism and the one P2P requires. Default:Falselmcache.multi_version_kvTag cached KV entries with the model version that produced them, so a request running under version N can never structurally hit an entry produced under version M, instead of clearing the whole cache on every update. Stale entries then age out naturally through ordinary LRU eviction as new-version entries fill the cache. This is the shipped default because under
psrl.staleness > 0different rollout instances can legitimately sit at different model versions at the same time, so clearing the whole cache on every pull would throw away prefixes that a still-behind instance could still use. Required whenenable_p2p: True(the shared P2P backend has no clear operation and relies entirely on version tags), in which caseclear_on_weight_updatemust beFalse. Default:Truelmcache.reserve_local_cpu_sizeGiB of CPU memory to keep free and never use for KV offloading (headroom for other processes on the same node). Default:
0.0lmcache.save_decode_cacheAlso cache KV from decode steps (not just prefill). Increases memory usage but improves multi-turn prefix reuse. Default:
Truelmcache.save_unfull_chunkPersist a chunk even when it is not completely filled, which helps prompts shorter than
chunk_size. Default:False. Currently has a known bug, do not enable.lmcache.cache_policyEviction policy:
LRUorFIFO. Default:LRUlmcache.enable_async_loadingOverlap KV cache retrieval with prefill computation to reduce time-to-first-token. Default:
False. Currently has a known bug, do not enable.lmcache.config_filePath to a full LMCache YAML config. When set, overrides all individual fields above. Default:
null
Disk backend (when backend: disk)
lmcache.disk_pathFilesystem path for disk-backed KV storage. Required when
backend: disk. Default:nulllmcache.max_disk_size_gbMaximum disk usage for KV storage (GiB). Default:
1000.0
Remote backend (when backend: remote)
lmcache.remote_urlURL of the remote LMCache server, for example
redis://host:6379. The remote backend is not implemented yet. Default:null
P2P cross-instance transfer
lmcache.enable_p2pEnable cross-instance KV cache transfer via a shared LMCache Controller process. Required when
routing_strategy.kv_transfer.enable: True. Default:Falselmcache.p2p_transfer_channelTransport for P2P KV transfer.
nixl: UCX-based (RDMA on multi-node, shared memory on same node). Recommended.tcp: fallback when UCX is unavailable.
Default:
nixllmcache.controller_hostHost where the LMCache Controller runs. Default:
${psrl.ps_manager_ip}lmcache.controller_base_portBase HTTP port for the LMCache Controller’s REST API (
/move,/lookup, etc.). The actual port is selected viafind_available_port()starting here. Default:9000lmcache.controller_pull_portZMQ PULL port where the Controller listens for worker registrations and heartbeats. Default:
8300lmcache.controller_reply_portZMQ REPLY port for Controller → worker task dispatch. Default:
8400lmcache.controller_health_timeout_sSeconds to wait for the Controller’s HTTP API to become healthy before failing init. The Controller imports torch and vLLM at startup and runs on the busy
ps_managernode, so under cluster CPU or filesystem contention it can take considerably longer than a standalone launch. Default:3000lmcache.gpu_pin_block_budgetMax number of GPU KV blocks PSRL may hold pinned simultaneously, used by
routing_strategy.kv_transfer.transfer_mode == "pin_sync". When exceeded, the oldest-pinned trajectory is unpinned (PSRL-side LRU).0means no limit. Default:0
See also
KV Cache Management, KV cache management architecture, LMCache Controller process, and cache eviction behavior.
TMS (torch_memory_saver)#
GPU memory management that transparently swaps idle tensors to CPU, enabling colocated workloads to share GPU memory.
tms.rangeScope of TMS management.
null: disabledtrain: manage training worker memory onlyall: manage both rollout and training worker memory
Default:
nulltms.enable_cuda_graphRelease CUDA graphs via TMS when not in use. Requires
range: all. Default:Falsetms.enable_nixlManage NIXL temporary buffers with TMS (simplifies re-registration after resume). Default:
False
Agentic RL#
Settings for multi-turn agent training loops (tool-use, code generation, SWE-agent).
agentic_rl.manager_retry_on_errorOn rollout errors, retry via the manager instead of crashing the worker. On validation failure, manager shrinks
val_buffer_sizeso the waiter is unblocked. Applies to terminations whereTerminateReason.needs_manager_retry()isTrue(rollout errors and unclassified failures). WhenFalse, the worker raisesRuntimeErrorimmediately so the failure is visible instead of silently stalling. Default:Trueagentic_rl.trajectory_output.enableWhether every agent loop writes a per-trajectory text dump via
TrajectoryWriter. Files land at<dir>/v{version}/{uid}.txt, one per rollout trajectory. Default:Trueagentic_rl.trajectory_output.dirOutput directory for the per-trajectory dumps. Empty string falls back to
<psrl.logging_path>/trajectories. Default:""
Broadcast Init#
When loading a large model checkpoint, each PS worker normally reads from disk
independently. broadcast_init instead has rank-0 read the checkpoint and broadcast
weights to other PS workers via NIXL, reducing filesystem load at scale.
broadcast_init.enabledEnable rank-0 broadcast initialization. Default:
Falsebroadcast_init.algorithmBroadcast algorithm. Currently only
binary_treeis supported. Default:binary_tree
Group & Buffer Post-Processing#
Post-processors can filter, re-weight, or transform trajectory groups before they are submitted to the staleness buffer.
group_post_process.enableEnable streaming group-level post-processing. Default:
Falsegroup_post_process.nameRegistered post-processor name. Options:
dynamic_sampling_filter,no_filter. When usingdynamic_sampling_filter, requiresalgorithm.filter_groups.metricto be set. Default:nullbuffer_post_process.enableEnable batch-level buffer post-processing (applied when a full buffer is ready). Default:
Falsebuffer_post_process.nameSame options as
group_post_process.name. Default:null
Log Probability#
log_prob.enable_rollout_engine_log_probWhether to request token log-probabilities from the vLLM rollout engine (used for importance sampling corrections). Disable to reduce generation overhead when log-probs are not needed. Default:
True
Server Rollout#
An optional HTTP gateway that exposes PSRL’s rollout service externally (useful for serving agent loops from non-PSRL clients).
server_rollout.enableEnable the server rollout HTTP gateway. Default:
Falseserver_rollout.gateway.router_ipBind address for the gateway process. Default:
${psrl.ps_manager_ip}server_rollout.gateway.router_portHTTP port for the gateway. Default:
18080server_rollout.server_concurrencyMax concurrent HTTP connections per rollout server. Default:
64
Rollout Gateway (SMG)#
The rollout gateway is the mandatory online request path. A Ray RolloutGateway actor
starts SMG and SessionRouter subprocesses, and rollout replicas register as gRPC workers.
rollout_gateway.server_max_concurrencyMaximum HTTP generation concurrency per active rollout server. The shared client budget is this value multiplied by active rollout and colocated validation instances. Default:
256rollout_gateway.use_distributed_postRoute AgentLoopWorker POST requests through a round-robin Ray actor pool to spread HTTP client work across nodes. Default:
Falserollout_gateway.post_actor_num_per_nodeNumber of distributed POST actors placed on each alive Ray node when the pool is enabled. Default:
8rollout_gateway.rust_log_filterPer-module Rust log filter for the SMG gateway process, in
RUST_LOGtracing directive syntax. Overrides the gateway’s defaultwarnlevel. An empty string means no override. The shipped value keeps SMG quiet while leaving PSRL’sroute_traceandscore_tracetargets atinfoso routing decisions stay visible. Default:"warn,smg::routers::grpc::kv_transfer=warn,smg::routers::grpc::common::stages::worker_selector::psrl=warn,route_trace=info,score_trace=info"rollout_gateway.grpc_registration_health_timeout_sTotal seconds a replica waits for its local
VllmEngine.HealthCheckto pass before registering itself with the SMG gateway. Default:300rollout_gateway.grpc_registration_health_poll_interval_sInterval between those health-check polls (seconds). Default:
1.0rollout_gateway.grpc_registration_health_rpc_timeout_sPer-RPC timeout for a single health-check call (seconds). Default:
5.0rollout_gateway.enable_kv_event_replayServe
SubscribeKvEventsthrough a bufferingKvEventReplayHubthat can replay missed sequence numbers after a gap, instead of the inline per-subscription ZMQ loop. Default:False. Keep it disabled: the gateway’s KV-event monitor accepts sequence gaps monotonically, so it does not depend on the hub’s replay guarantee, and the inline path is simpler with no ingester thread and measures at roughly 100% cache-overlap routing. The hub path is opt-in and currently exhibits a zero-overlap indexing bug under investigation.
SMG uses worker_selection_strategy=psrl, gRPC worker connections, the
routing loop, and TITO. See Router, SessionRouter, and TITO.
TransferQueue#
TransferQueue configuration is a top-level block in ppo_trainer.yaml.
transfer_queue.enableRuntime integration flag.
main_ppo.pyenables it for the current PSRL training flow. Default in YAML:Falsetransfer_queue.metrics.enabledExpose Prometheus-style metrics on an HTTP
/metricsendpoint. WhenFalse, metrics are reported through the logger only. Default:Falsetransfer_queue.metrics.portPort for that endpoint.
0auto-assigns a free port. Default:0transfer_queue.controller.samplerMetadata sampling strategy. Default:
SequentialSamplertransfer_queue.controller.polling_modeEnable polling-mode controller behavior. Default:
Falsetransfer_queue.backend.storage_backendStorage implementation:
SimpleStorageor experimentalMooncakeStore. Default:SimpleStoragetransfer_queue.backend.SimpleStorage.total_storage_sizeMaximum number of experience samples across storage units. Default:
100000transfer_queue.backend.SimpleStorage.num_data_storage_unitsDistributed storage-unit count. Use at least twice the node count for larger deployments. Default:
8transfer_queue.backend.MooncakeStore.*Experimental Mooncake metadata/master addresses, local host, TCP/RDMA protocol, memory sizes, and NIC selection. See TransferQueue Integration.
Memory Logger#
memory_logger.enableEnable periodic GPU memory logging for debugging memory pressure. Default:
Falsememory_logger.interval_secondsLogging interval (seconds). Default:
30
Profile#
Analysis-only switches that deliberately break training correctness. Keep both at their defaults for real runs.
profile.disable_attnDisable attention in the rollout engine, propagated to vLLM as
VLLM_DISABLE_ATTNand torollout.disable_attn. Useful for isolating attention cost when profiling. Default:Falseprofile.fix_weightSkip the weight-load step after a parameter pull, so rollout instances keep serving their initial weights. Useful for measuring sync overhead without the load cost. Default:
False
Overrides#
Override any parameter from the command line using Hydra syntax:
python -m psrl.trainer.main_ppo \
+psrl.staleness=3 \
psrl.rollout_coordination.routing_strategy.method=throughput_optimal \
psrl.deployment.n_rollout_instances=4 \
psrl.lmcache.enable=True \
transfer_queue.backend.storage_backend=SimpleStorage
Key syntax rules:
key=value: Override an existing key+key=value: Add a new key not present in the default config~key: Remove a key from the configUse dot notation for nested keys:
psrl.rollout_coordination.routing_strategy.method=...
Tip
For complex experiments, create a separate YAML file with your overrides and pass it
with --config-path:
python -m psrl.trainer.main_ppo \
--config-path=/path/to/my_overrides \
--config-name=my_experiment
Example: Advanced 7B FSDP Config#
Here is a representative override pattern for 4-node DAPO training from
examples/dapo_trainer/advanced_qwen2.5_7b_fsdp.sh:
python -m psrl.trainer.main_ppo \
--config-path=./config --config-name='ppo_trainer' \
psrl.staleness=2 \
psrl.staleness_buffer_entries=64 \
psrl.ps_mode=nixl_cpu \
psrl.rollout_n=8 \
psrl.deployment.n_rollout_instances=16 \
psrl.deployment.train_nnodes=2 \
psrl.deployment.total_nnodes=4 \
psrl.rollout_coordination.partial_rollout.enable=True \
psrl.rollout_coordination.redundant_rollout.enable=True \
psrl.rollout_coordination.routing_strategy.method=throughput_optimal \
psrl.rollout_coordination.routing_strategy.enable_multi_priority_queue=True \
psrl.rollout_coordination.sync_and_mig_strategy.method=status_based \
psrl.rollout_coordination.sync_and_mig_strategy.sync.indicator=kv_cache \
psrl.rollout_coordination.sync_and_mig_strategy.mig.enable=True \
psrl.rollout_coordination.proactive_filter_strategy.method=retry \
psrl.rollout_coordination.proactive_filter_strategy.threshold=4
See also
Quick Start: Minimal working example with DAPO
Fine-Grained Staleness Control: Staleness control design
Flexible Rollout Coordination: Routing and rollout coordination
KV Cache Management: KV cache management
Router, SessionRouter, and TITO: SMG, SessionRouter, and TITO
TransferQueue Integration: sample data plane