[arctic-rl] align adapter with upcoming zorro_train config grouping - #5
Merged
sfc-gh-kganesan merged 3 commits intoJun 10, 2026
Merged
Conversation
Tracks an upcoming arctic_training API change that regroups
`use_zorro` into a nested `zorro_train` block.
Changes (3 files, +21/-10):
* `verl/trainer/config/remote_backend/arctic.yaml`
- replace flat `use_zorro: False` with nested
`zorro_train: { enable: False, max_rollouts: <rollout.n> }`
* `verl/workers/remote_client/arctic_rl.py`
- rename `self.use_zorro` -> `self.zorro_train_enable`
- rename `meta=dict(use_zorro=...)` -> `meta=dict(zorro_train_enable=...)`
in `_build_log_prob_payload` and `_build_update_actor_payload`
- update `ds_worker_config.update(use_zorro=True)` -> `zorro_train_enable=True`
- update import path: `arctic_training.arctic_rl` -> `arctic_training.rl`
- pass `checkpoint_path=self.config.trainer.default_local_dir`
into `ArcticRLClientConfig` (now required for training jobs)
* `examples/arctic_rl/run_gsm8k_grpo_arl_zorro_yes.sh`
- update Hydra override: `remote_backend.use_zorro=True`
-> `remote_backend.zorro_train.enable=True`
Why now: the upstream server now reads `zorro_train_enable` from
`ds_worker_config` and from per-call request metas. Without this
rename, the adapter silently disables ZoRRO (the missing key defaults
to False) once users upgrade arctic_training.
Validation (local):
* pre-commit (ruff, ruff-format, mypy, autogen-trainer-cfg,
check-docstring-coverage, check-license, compileall) - 7/7 Passed
* import test against post-rename arctic_training - imports succeed
* ArcticRLClientConfig pydantic v2 schema validation - all kwargs accepted
* Ray cluster bootstrap + dataset load + TaskRunner spin-up - OK
* Full 4-step GSM8K E2E - blocked on an unrelated arctic_inference
version skew (ReplicaPool.reset_prefix_cache missing on the
locally installed arctic_inference); will re-validate once a
coordinated arctic_training + arctic_inference release lands.
Targets: this PR is stacked on the public abstract-backend PR
(arctic_rl_share_v0.7.1). When that lands in verl-project/verl,
rebase + open the equivalent upstream follow-up.
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Karthik Ganesan <karthik.ganesan@snowflake.com>
Followup to the zorro_train rename: the yaml exposes
`zorro_train.max_rollouts` but the adapter never forwarded it to
the per-call meta dicts, so users could set it in config and it
would silently have no effect (upstream falls back to `rollout_n`
via `meta_data.get("zorro_train_max_rollouts", meta_data["rollout_n"])`
in `arctic_training/rl/utils/batch.py`).
Add the field on `__init__` and pass it alongside `zorro_train_enable`
in both `_build_log_prob_payload` and `_build_update_actor_payload`.
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Karthik Ganesan <karthik.ganesan@snowflake.com>
Two adapter-side changes needed to E2E-validate against post-rename arctic_training: 1. cuda_ipc / low_memory weight-sync plumbing Adds `cuda_ipc_weight_sync` and `low_memory_weight_sync` keys to `remote_backend/arctic.yaml` (both default False, opt-in) and forwards them on every `update_weights` call to `arctic_training.rl.ray_client.sync_weights(cuda_ipc=, low_memory=)`. With `colocate=True + cuda_ipc_weight_sync=True`, weight sync uses zero-copy CUDA IPC (cudaIpcGet/OpenMemHandle) instead of NCCL all_reduce, bypassing the NCCL bootstrap entirely. Sub-1.3s sync times observed on Qwen3-0.6B vs the previous NCCL-bootstrap hang. 2. async_generate -> generate API rename arctic_training renamed the rollout-side method from `async_generate(...)` to `generate(..., routing_key=None)` (the new kwarg threads through to Mert's FCA group routing). Our wrapper forwards the kwarg as-is; defaulting to None preserves existing behaviour for callers that don't set it. E2E proof: 4-step GSM8K-GRPO smoke completed 4/4 with cuda IPC weight sync confirmed via `[weight-sync names validated] context=cuda_ipc` log line; MFU 211-246, update_weights 0.8-1.2s. Signed-off-by: Karthik Ganesan <karthik.ganesan@snowflake.com> Co-authored-by: Cursor <cursoragent@cursor.com>
sfc-gh-sbekman
approved these changes
Jun 10, 2026
sfc-gh-kganesan
marked this pull request as ready for review
June 10, 2026 23:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Aligns the Arctic remote-backend adapter with the upcoming arctic_training API rename + adds opt-in CUDA IPC weight sync. Two-commit branch; both adapter-internal, both validated end-to-end against the post-rename upstream stack.
Stacked on top of the public abstract-backend PR head (
arctic_rl_share_v0.7.1@cbf9cd5a). This branch is the staging ground for the follow-up upstream PR we'll open againstverl-project/verl:mainonce verl-project#6422 merges there.Commits
21ac6e8d+394e6fb3use_zorro→zorro_train.enablerename; newarctic_training.rlimport path;checkpoint_pathplumbed intoArcticRLClientConfig;zorro_train_max_rolloutsforwarded in per-call metaa5323c9fcuda_ipc_weight_sync+low_memory_weight_syncplumbing;async_generate→generate(..., routing_key=None)to match post-rename arctic_training APIScope
4 files, all adapter-internal. No changes to the
RemoteBackendABC, registry, generic worker/trainer, or any non-Arctic code.verl/trainer/config/remote_backend/arctic.yamluse_zorro: Falsewith nestedzorro_train: { enable, max_rollouts }. (b) Addcuda_ipc_weight_sync: Falseandlow_memory_weight_sync: False(both opt-in, defaults preserve current NCCL path)verl/workers/remote_client/arctic_rl.pyself.use_zorro→self.zorro_train_enable. (b) Update 2meta=dict(...)payloads +ds_worker_config.update(...)kwarg. (c) Update import path toarctic_training.rl. (d) Passcheckpoint_path. (e) Readcuda_ipc_weight_sync/low_memory_weight_syncfrom config and forward to_client.sync_weights(cuda_ipc=, low_memory=). (f) Renameasync_generate→generate(..., routing_key=None)examples/arctic_rl/run_gsm8k_grpo_arl_zorro_yes.shremote_backend.zorro_train.enable=TrueValidation
Local CI (pre-commit, matches verl's CI hooks)
All 7 hooks pass on the modified files:
E2E smoke: 4/4 passed against post-rename stack
4-step GSM8K-GRPO smoke completed end-to-end with
colocate=True+cuda_ipc_weight_sync=True(CUDA IPC weight-sync path; no NCCL handshake required):Training Progress: 100%|██████████| 4/4 [02:21<00:00, 35.37s/it]CUDA IPC path confirmed active via log line:
[weight-sync names validated] context=cuda_ipc sender=310 expected=310Stack used for E2E:
arctic_training@ tunji/verl_integration HEAD (post-rename)arctic_inference@ mert/verl_integration_vllm18 (vLLM 0.18 compatible)vllm==0.18.0,torch==2.10.0+cu129,flashinfer-python==0.5.3flash_attn 2.8.3 + flash_attn_3 3.0.0(H200 wheels for torch 2.10)A longer convergence run is in progress; will attach the log/curve when done.
Why this matters
Without the
cuda_ipc_weight_syncpath the adapter falls back to NCCL all_reduce, which on our reproducer setup hangs indefinitely atstateless_init_ncclduring the firstsync_weights(both ends stuck inncclAllReduceinsidePyNcclCommunicator.__init__). The CUDA IPC path is zero-copy viacudaIpcGet/OpenMemHandleand avoids the NCCL bootstrap entirely — sub-1.3s sync times observed on Qwen3-0.6B vs the previous indefinite hang.Defaults are preserved (
cuda_ipc_weight_sync: False,low_memory_weight_sync: False); existing configs are unaffected.Notes for reviewers
enableas a flatzorro_train_enablekwarg rather than the nested dict — upstream server reads it flat, yaml nesting is for config organization.checkpoint_pathdefaults toself.config.trainer.default_local_dir, which verl always sets — no caller breakage.routing_keydefaults toNone, preserving behaviour for callers that haven't migrated to Mert's FCA group routing.examples/arctic_rl/run_big_bird_grpo_arl_zorro_yes.sh(which uses the samecolocate=True+cuda_ipc_weight_sync=Truecombo).Co-Authored-By: Cursor cursoragent@cursor.com