Skip to content

[ckpt, ray, trainer] feat: add opt-in sub-second fault tolerance with dynamic NCCL re-rendezvous and in-memory failover - #7910

Open
sunnylovestiramisu wants to merge 1 commit into
verl-project:mainfrom
sunnylovestiramisu:fault-tolerance
Open

sunnylovestiramisu wants to merge 1 commit into
verl-project:mainfrom
sunnylovestiramisu:fault-tolerance

Conversation

@sunnylovestiramisu

@sunnylovestiramisu sunnylovestiramisu commented Sep 17, 2026 •

Copy link
Copy Markdown

What does this PR do?

This PR introduces an opt-in fault tolerance architecture for disaggregated RL training (Trainer & Rollout separated across GPU nodes) that prevents pipeline collapse and long restarts when GPU workers or nodes abruptly fail (e.g., hard process crashes, CUDA uncorrectable ECC errors, or cloud provider maintenance notices like rack switch events).

Currently, VeRL's NCCL checkpoint engine requires static communicators; a worker crash causes socket timeout and terminates the distributed Ray job. With this PR, when fault_tolerance.enable=True, VeRL:

  1. Replaces dead actor handles on the fly via RayWorkerGroup.replace_worker() using prewarmed standby actors.
  2. Dynamically re-rendezvous NCCL communication groups (re_rendezvous()) on a versioned group name without restarting the Ray cluster.
  3. Supports bidirectional in-memory VRAM weight recovery (recover_weights_from_rollout()), allowing promoted standby trainers to recover the latest parameters directly from rollout GPU memory in < 0.5s instead of reloading multi-gigabyte checkpoints from disk/object storage.

Default Behavior: Gated behind fault_tolerance.enable=False (default), ensuring 100% backward compatibility and zero overhead for standard runs.

Checklist Before Starting

  • Search for similar PRs. Paste at least one query link here: ...
  • Format the PR title as [{modules}] {type}: {description} (This will be checked by the CI)
    • {modules} include fsdp, megatron, veomni, sglang, vllm, rollout, trainer, ci, training_utils, recipe, hardware, deployment, ray, worker, single_controller, misc, perf, model, algo, env, tool, ckpt, doc, data, cfg, reward, fully_async, one_step_off
    • If this PR involves multiple modules, separate them with , like [megatron, fsdp, doc]
    • {type} is in feat, fix, refactor, chore, test
    • If this PR breaks any API (CLI arguments, config, function signature, etc.), add [BREAKING] to the beginning of the title.
    • Example: [BREAKING][fsdp, megatron] feat: dynamic batching

Test

Validated on a 3-node Google Cloud A3 HighGPU cluster (24x NVIDIA H100 80GB GPUs, GPUDirect-TCPX) running disaggregated RL training with Qwen/Qwen2.5-0.5B (942.3 MB parameters in VRAM):

  1. Sampler Failover Benchmark (--fail-target sampler)
  • Steps 1–4: Normal training & rollout generation (~500ms/step).
  • Step 5: Hard SIGKILL injected into Active Sampler actor (os._exit(1)).
  • Failover: Prewarmed Standby Sampler promoted, dynamic NCCL group v1 re-rendezvoused in ~1.5s, 942.3 MB parameters synced over TCPX in ~0.4s.
  • Total End-to-End Failover Latency: 3.386 seconds (Zero cluster restart, zero dropped training steps).
  • Steps 6–10: Resumed training seamlessly with matching checksums across all steps.
  1. Trainer Failover Benchmark (--fail-target trainer)
  • Step 5: Active Trainer killed right before computing gradient step.
  • Reverse Recovery: Standby Trainer promoted to Rank 0 and recovered $W_4$ directly from Sampler VRAM over NCCL (src=1) in ~0.4s.
  • Execution: Promoted Trainer executed Step 5 gradient update ($W_5$), streamed forward to Sampler, and completed iteration with zero pipeline collapse (2.147 seconds total failover latency).

Test Logs

2026-09-17 15:28:22 [INFO] VeRL NCCL Communicator v0 initialized in 9.21s.
2026-09-17 15:28:23 [INFO] [VeRL Step 1] Status: Rollout #1 generated in 1385.6ms | Checksum: 77412.17
...
2026-09-17 15:28:25 [WARNING] !!! INJECTING SUDDEN SAMPLER FAILURE AT STEP 5 (VeRL Fault Tolerance ON) !!!
(SamplerActor pid=4450) !!! SIMULATING TRUE HARD NODE CRASH (SIGKILL) !!!
(raylet) A worker died or was killed while executing a task by an unexpected system error.
2026-09-17 15:28:25 [INFO] [VeRL Framework] Engaging dynamic re-rendezvous on port 29501 (Group v1)...
2026-09-17 15:28:27 [INFO] [VeRL Framework] Resyncing parameters to promoted Standby Sampler and resuming rollout...
2026-09-17 15:28:28 [INFO] *** VeRL Sampler Failover Succeeded in 3.386s! ***
2026-09-17 15:28:28 [INFO] [VeRL Step 5] Promoted Standby Rollout: "Question: How does VeRL fault tolerance prevent pipeline collapse in distributed RL? Answer: VeRL is a machine learning-..."
2026-09-17 15:28:29 [INFO] [VeRL Step 6] Status: Rollout #2 generated in 569.8ms | Checksum: 77412.58
...
2026-09-17 15:28:31 [INFO] VeRL Reliability Execution Finished Successfully: 10/10 steps completed.
2026-09-17 15:28:31 [INFO] VeRL Measured Failover Latency: 3.386 seconds.

API and Usage Example

Demonstrate how the API changes if any, and provide usage example(s) if possible.

  1. Default (Unchanged)
    Standard execution remains completely untouched:
python3 -m verl.trainer.main_ppo
  1. Enabling Sub-Second Fault Tolerance via CLI
python3 -m verl.trainer.main_ppo fault_tolerance.enable=True
  1. Enabling via YAML Configuration
fault_tolerance:
  enable: True                          # Default: False
  mode: "standby"                       # "standby" (prewarmed VRAM) or "cold"
  standby_resource_pool: "standby_pool" # Dedicated resource pool for standby actors
  detect_node_maintenance: True         # Auto-detect cloud maintenance notices (e.g. 600s GCE notice)
  maintenance_check_interval: 10        # Seconds between polling checks
  reverse_weight_sync: True             # Allow promoted trainer to recover weights from rollout VRAM
  max_failovers: 5                      # Maximum allowed failover recovery events

Design & Code Changes

Detailed File Changes:

  1. verl/trainer/config/config.py & verl/trainer/config/ppo_trainer.yaml:
  • Added FaultToleranceConfig dataclass and YAML block with enable: False default.
  1. verl/single_controller/ray/base.py:
  • Added replace_worker(rank, new_worker_handle) to RayWorkerGroup to allow hot-swapping failed Ray actors within existing placement groups.
  1. verl/checkpoint_engine/nccl_checkpoint_engine.py:
  • Added re_rendezvous(...): Safely destroys stale NCCL communicator and rejoins a new versioned group (group_name_v{version}) on dynamic port.

  • Added recover_weights_from_rollout(): Enables promoted trainer to pull weights directly from rollout VRAM over NCCL (src=num_senders).

  1. verl/checkpoint_engine/base.py:
  • Added handle_failover() to CheckpointEngineManager to coordinate process group reconstruction across surviving and standby replicas.
  1. verl/trainer/ppo/ray_trainer.py:
  • Wrapped update_weights in an exception boundary that intercepts actor/comm failures and triggers handle_failover() when fault_tolerance.enable: True.

Checklist Before Submitting

Important

Please check all the following items before requesting a review, otherwise the reviewer might deprioritize this PR for review.

…ynamic NCCL re-rendezvous and in-memory failover
@CLAassistant

CLAassistant commented Sep 17, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants