Skip to content

Scope hybrid pre-collective failure sync over both children's meshes - #74

Merged
thad0ctor merged 2 commits into
mainfrom
fix/hybrid-backup-failure-sync
Jul 15, 2026
Merged

Scope hybrid pre-collective failure sync over both children's meshes#74
thad0ctor merged 2 commits into
mainfrom
fix/hybrid-backup-failure-sync

Conversation

@thad0ctor

@thad0ctor thad0ctor commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Fixes a cross-rank correctness bug in GefenMuonHybrid's pre-collective failure synchronization, surfaced by a CodeRabbit review on the convention PR (#67) but rooted in the Tier-2 code already on main.

The bug — silent cross-rank state divergence (not a hang)

GefenMuonHybrid derived its failure-sync process-group scope from the Muon child only (hybrid.py self.muon._step_failure_process_groups()), while its composite step preflight validates both children. When the backup child owns a sharded mesh that the Muon child does not participate in, a preflight/closure failure on one rank of that backup-only mesh is not all-reduced across it — so ranks disagree on whether the step failed.

The original review framed this as a deadlock. Adversarial verification showed a hang is not reachable: the backup child is only ever Gefen or torch.optim.AdamW, and neither performs a post-preflight sharded collective that a stranded peer would block on. What actually happens is worse in a quieter way — reproduced on a 2-rank gloo hybrid (non-sharded Muon weight + sharded backup, rank-0 closure failure): rank 0 raises and rolls back while rank 1 sees no error and mutates its backup shard, leaving the two ranks with divergent optimizer state and no error surfaced.

The fix

  • gefen_muon.py: extracted the sharded-mesh dedup/order logic into a reusable _collect_sharded_failure_groups(param_groups) staticmethod (byte-identical to the previous _step_failure_process_groups body; keyed on group.get("sharded_mode") so a foreign backup's groups are handled). _step_failure_process_groups now delegates to it; the Muon path is unchanged.
  • hybrid.py: GefenMuonHybrid._step_failure_process_groups now derives the scope from the union of both children's param-groups through a single deduped, deterministically-ordered scan — a shared mesh yields one collective, a backup-only mesh is included, and there is exactly one cross-rank ordering (no per-child concatenation that could break 2D-mesh row/column lock order). @torch._dynamo.disable and the capture guard mirror the Muon path.

Under standard fully_shard (both halves shard on the same mesh) the dedup collapses to the Muon-only scope, so this is a verified no-op in the common topology; it only changes behavior in the asymmetric-mesh case that was previously unsynchronized.

Test

tests/test_precollective_failure_sync.py: new test_backup_only_mesh_preflight_failure_is_synchronized (backup owns the sharded mesh, Muon non-sharded, rank-0 closure fails) asserts both ranks fail fast and neither mutates, with bounded no-hang deadlines. Verified it fails without the fix (rank 1 reports no error and mutates state) and passes with it.

Validation (CPU / gloo)

  • test_precollective_failure_sync.py: 4 passed
  • Hybrid + distributed suite (7 files): 89 passed, 2 skipped
  • Step-preflight / grad-presence / FSDP2 / AMP-scope suite (7 files): 61 passed, 67 skipped (GPU-only skips)

No failures.

Known limitation (out of scope)

A degenerate backup-only hybrid (muon=None) still does not synchronize this path — the sync helpers are GefenMuon-instance-bound, so covering it would require promoting them to module-level functions. That single-child case is outside the composite-hybrid scenario this fixes and is left as a follow-up.

Summary by CodeRabbit

  • Bug Fixes

    • Improved distributed failure synchronization for hybrid optimizers when sharded parameters are managed by the backup optimizer.
    • Ensured failure checks consistently cover all participating sharded parameter groups.
  • Tests

    • Added coverage for backup-only sharded configurations.
    • Verified synchronized early failures without parameter, state, or gradient mutations.

GefenMuonHybrid.step derived its pre-collective failure-sync scope from the
Muon child alone, while the composite preflight (closure + structural grad
validation + AMP controls) validates BOTH children. When the backup half owns
a sharded mesh the Muon half does not touch (a sharded backup weight with a
non-sharded or absent Muon half), a one-rank preflight failure on that
backup-only mesh was never all-reduced across it: the failing rank raised while
its mesh peers stepped and mutated their backup shard, diverging cross-rank
state.

Derive the scope from the UNION of both children's sharded meshes. Extract the
dedup/order logic into GefenMuon._collect_sharded_failure_groups and fold both
children's param_groups through one deduped, sorted scan, so the standard
fully_shard case (both halves on the same mesh) collapses to exactly the
Muon-only scope with no extra collective, while a backup-only mesh is folded in
with one deterministic cross-rank order. A plain-torch backup (AdamW) with no
sharded_mode groups contributes only its DTensor params, if any.

Add a Gloo CPU regression test: a hybrid whose backup owns the sharded mesh and
whose Muon half is non-sharded; a rank-0 closure failure must fan out so all
ranks fail fast with no mutation and no hang. Fails before this change (peer
rank steps and mutates), passes after.
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: effc4d39-fa73-420d-bd10-2647c1183e93

📥 Commits

Reviewing files that changed from the base of the PR and between cbe2681 and 5a1e9b1.

📒 Files selected for processing (3)
  • src/gefen/gefen_muon.py
  • src/gefen/hybrid.py
  • tests/test_precollective_failure_sync.py
📝 Walkthrough

Walkthrough

GefenMuon centralizes sharded failure-group discovery. GefenMuonHybrid now collects groups from both Muon and backup optimizers, and tests cover synchronization when only the backup optimizer owns a sharded mesh.

Changes

Hybrid sharded failure synchronization

Layer / File(s) Summary
Centralized sharded group collection
src/gefen/gefen_muon.py
Adds deterministic, deduplicated collection of valid multi-process sharded failure groups and delegates the existing method to it.
Hybrid failure-scope integration
src/gefen/hybrid.py
Computes the preflight synchronization scope from both child optimizers, with distributed-support and CUDA-graph guards.
Backup-owned mesh validation
tests/test_precollective_failure_sync.py
Adds a hybrid configuration and distributed test covering synchronized closure failure when only the backup side is sharded.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

  • thad0ctor/Gefen-X#4 — Introduced the related GefenMuonHybrid.step() implementation.
  • thad0ctor/Gefen-X#71 — Builds the pre-collective synchronization protocol around the sharded process-group scope.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: expanding hybrid pre-collective failure sync to both child optimizers' meshes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hybrid-backup-failure-sync

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbe2681f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gefen/hybrid.py
@thad0ctor

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

A backup-only GefenMuonHybrid (self.muon is None) whose backup owns a sharded
mesh skipped the pre-collective failure sync entirely: step() gated both the
error sync and the AMP agreement on self.muon being present, so a one-rank
preflight/closure failure raised only on the failing rank while its mesh peer
stepped and mutated its backup shard (cross-rank state divergence).

_synchronize_sharded_step_error and _prepare_synchronized_amp_step touch no
GefenMuon instance state (they only reach already-static helpers), so make both
@staticmethod and call them unconditionally from the hybrid over the union
scope. When the scope is empty the static error sync just re-raises any local
error and the AMP agreement returns True / falls back to
_amp_prepare_optimizer_step -- identical to the previous muon-absent branches,
which are removed. Drop the now-unused _amp_prepare_optimizer_step import.

Add a Gloo CPU regression test: a hybrid with every param routed to a sharded
backup (muon is None); a rank-0 closure failure must fan out so all ranks fail
fast with no mutation and no hang. Fails before this change (peer steps and
mutates), passes after.
@thad0ctor
thad0ctor merged commit fca6744 into main Jul 15, 2026
15 checks passed
@thad0ctor
thad0ctor deleted the fix/hybrid-backup-failure-sync branch July 15, 2026 20:30
thad0ctor added a commit that referenced this pull request Jul 15, 2026
Reconcile the hybrid pre-collective failure sync with #74 (merged to main):
gefen_muon.py auto-merges (the sync helpers are now @staticmethod and the
mesh scope is collected via _collect_sharded_failure_groups). In
GefenMuonHybrid.step, keep the convention's codebook-scope binding branch
(_synchronize_prevalidated_codebook_scope_failure) unchanged, and in the
no-binding branch adopt #74's static UNION-scope sync
(GefenMuon._synchronize_sharded_step_error / _prepare_synchronized_amp_step
over self._step_failure_process_groups()), which also covers the muon=None
backup-only case. Also picks up the v0.4.1 release bump.
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.

1 participant