Repository navigation
fix(sc): pass refit_payload_mode when recovery regenerates refit info - #4233
Merged
Merged
Conversation
Policy.prepare_refit_info has taken a keyword-only refit_payload_mode since #3739 (5d49fbf, 2026-09-11), which updated the one caller that existed at the time: CollectiveWeightSynchronizer.init_communicator. #3592 (53bce05, 2026-09-14) then added a second caller in reconcile_communicator -- the fleet-health recovery that rebuilds the communicator over the surviving shards and redistributes refit metadata to them -- written against the pre-#3739 signature. The merge was clean textually and wrong semantically: every collective-transport recovery raised TypeError: Policy.prepare_refit_info() missing 1 required keyword-only argument: 'refit_payload_mode' before touching NCCL, so a run that lost a generation shard died in the rebuild that was meant to keep it alive. nccl_reshard is unaffected: its rebuild does not re-prepare refit info. Nothing was red. The unit fake for the policy accepted a bare call, every fleet-health recovery variant self-skips on CI's 2-GPU runners, and the last cluster runs of those variants predate the sync that brought #3739 in. Found by the fault-injection validation on #3929 (CW-DFW job 18689836): #3929 (comment) Mirror init_communicator's call, asking the backend for its payload mode. Make the test fake keyword-only so the signature is pinned -- against the old call 14 of the 38 reconcile tests now fail with the production error -- and add a test that the rebuild asks for the backend's mode and pushes the metadata once. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: asolergibert <asolergibert@nvidia.com>
|
Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
Contributor
Author
|
/ok to test 3d4701f |
terrykong
reviewed
Sep 22, 2026
terrykong
left a comment
Collaborator
There was a problem hiding this comment.
@youngeunkwon0405 to review (this pr should target yours)
youngeunkwon0405
approved these changes
Sep 22, 2026
Contributor
Hi @terrykong, why does this PR have to target #3929? This is just fixing the previous implementation. Shouldn't it be more natural to go right into main? |
Collaborator
|
@youngeunkwon0405 sorry, it was my confusion. i thought it was tied |
terrykong
approved these changes
Sep 22, 2026
yfw
added a commit
that referenced
this pull request
Sep 23, 2026
Brings #4198 (remove the DTensor v1 policy worker), #4207, #4196, #4143 (MiniMax-M3 GRPO support), #4233, #4232 and #3408 (flow_grpo research). Conflicts and resolution: - pyproject.toml: main removed the `fsdp` extra together with the v1 worker; this branch had given that extra its own torch 2.13 pin. The extra is dropped here as well (with its `[tool.uv] conflicts` entries), and the per-extra torch comment no longer lists it. - uv.lock: regenerated from this branch's lock; the only change is the addition of #3408's flow-grpo research dependencies (albumentations, paddleocr, scikit-image, ...). No existing package moved, and nothing resolves below main except the deliberate numpy / llguidance / flash-attn pins. Also removed, not conflicting: `_patch_vllm_minimax_m3_topk_buffer_layout` (#4143) and its tests. It backported vllm-project/vllm@d1a8ba63 (token-major vs head-major `topk_indices_buffer`) onto vLLM 0.26.0 and its docstring asks for removal at vLLM >= 0.27; vLLM 0.29.0's `minimax_m3/common/indexer.py` already carries the head-major `buf_htk` layout, so on this branch the patch could only ever log "source shape not found" and its installed-vLLM anchor tests would fail. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yi-Fu Wu <yifu.wu@gmail.com>
cspades
pushed a commit
that referenced
this pull request
Sep 24, 2026
…#4233) Signed-off-by: asolergibert <asolergibert@nvidia.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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.
What does this PR do ?
Fixes the fleet-health recovery on the collective (
nccl) refit transport:reconcile_communicator()calledPolicy.prepare_refit_info()without therefit_payload_modethat #3739 made mandatory, so every recovery died with aTypeErrorbefore touching NCCL.Why it happened
5d49fbf4e, Sept 11) maderefit_payload_modea required keyword-only argument ofPolicy.prepare_refit_infoand updated the one caller that existed at the time,CollectiveWeightSynchronizer.init_communicator(collective_weight_synchronizer.py:213).53bce0568, Sept 14) added a second caller inCollectiveWeightSynchronizer.reconcile_communicator— the recovery that rebuilds the communicator over the surviving shards and redistributes refit metadata to them (a restarted engine has none). It was written against the pre-feat(megatron): add nccl_reshard M-to-N refit for Megatron generation #3739 signature, and the merge was textually clean and semantically wrong.test_reconcile_communicator.pyaccepted a bare call; every fleet-health recovery variant inL1_Functional_Tests_SingleController.shself-skips on CI's 2-GPU runners; and the last multi-GPU runs of those variants predate themainsync that brought feat(megatron): add nccl_reshard M-to-N refit for Megatron generation #3739 in.It surfaced in the fault-injection validation of #3929 — see #3929 (comment) (attribution to #3739/#3592) and the run details in #3929 (comment) (CW-DFW job 18689836: step 3/24, one generation shard killed, then):
Effect on
mainsince Sept 14: on the default transport, a run that loses a generation shard ends in the rebuild that was meant to keep it alive (#3591's contract).nccl_reshardis unaffected — its rebuild does not re-prepare refit info — which is why the reshard step-kill scenario in that validation passed while thencclone and the Gym quarantine one failed.The fix
nemo_rl/weight_sync/collective_weight_synchronizer.py: the rebuild now mirrorsinit_communicator—self._policy.prepare_refit_info(refit_payload_mode=self._generation.get_refit_payload_mode()).get_refit_payload_modeis onGenerationInterface(default"hf_export", overridden byMegatronGeneration), so this is valid for every backend the collective synchronizer can hold.tests/unit/weight_sync/test_reconcile_communicator.py: the fake policy is now keyword-only, exactly likePolicy.prepare_refit_info, so the signature is pinned — against the old call, 14 of the 38 tests in the file fail with the production error. The fake generation answersget_refit_payload_mode, and a newtest_refit_info_is_regenerated_in_the_backend_s_payload_modeasserts the rebuild asked for the backend's mode and pushed the metadata to the fleet once.Issues
No standalone issue; raised in #3929 (comment). #3929 should re-merge
mainafter this lands and re-run its collective-transport scenarios.Usage
Not applicable — no user-facing change. To exercise the fixed path end to end on a node with ≥ 3 GPUs:
Before your PR is "Ready for review"
Pre checks:
tests/unit/weight_sync,tests/unit/single_controller,tests/unit/models/generation/test_fleet_health.py,tests/unit/models/policy/test_worker_refit_signatures.py,tests/unit/models/policy/test_lm_policy_collective.py. Functional: the recovery variant above needs ≥ 3 GPUs and was not run locally; it is the run that found the bug.Additional Information
nccl_reshardmid-refit stall reported in the same validation (reshard-refit-kill/reshard-refit-freeze) is a different problem — a timing race between the controller's refit bound and the synchronizer's straggler settle — and is not addressed here.🤖 Generated with Claude Code