Skip to content

Fix FSDP double-buffer overflow in lazy main_grad_getter during backward#146

Open
sudhu2k wants to merge 1 commit into
rocm_devfrom
sudhu/megatron_fsdp_dbuf_fix
Open

Fix FSDP double-buffer overflow in lazy main_grad_getter during backward#146
sudhu2k wants to merge 1 commit into
rocm_devfrom
sudhu/megatron_fsdp_dbuf_fix

Conversation

@sudhu2k

@sudhu2k sudhu2k commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Fixes an assertion failure (No buffer found for bucket_id) when training with fsdp_double_buffer=True. During backward, TE calls get_main_grad() lazily via main_grad_getter, which could allocate a grad bucket before draining the fixed double-buffer pool (size 2). Once two FSDP units' buckets were live, a third allocation would assert in FixedPoolAllocator.allocate.
This PR adds double-buffer back-pressure in the lazy allocation path: expose grad_reduce_pipeline on ParamAndGradBuffer, call _enforce_double_buffer_limit before fetch_bucket() in main_grad_getter, and run the drain on the reduce-scatter stream so buffer frees order correctly against in-flight reduce-scatters.
Ports the fix from NVIDIA/Megatron-LM#5222 (commit 55638bc4), adapted for this fork's FSDP layout.

Changes

  • megatron_fsdp.py: Set param_and_grad_buffer.grad_reduce_pipeline so main_grad_getter can reach the reduce-scatter pipeline.
  • param_and_grad_buffer.pymain_grad_getter: Enforce the double-buffer limit before allocating; remove the premature fetch_bucket() call.
  • param_and_grad_buffer.py_enforce_double_buffer_limit: Issue wait_for_previous_grad_reduce on rs_stream instead of the caller's compute stream.

Test plan

  • Reproduce with Llama3 8B, fsdp_double_buffer=True, TE fused wgrad — training completes past first backward step (previously failed at bucket_id: 31 with using_buffer: {33, 32}).
  • Confirm no regression with fsdp_double_buffer=False.
  • Multi-GPU run (8 ranks) completes at least one full iteration without FSDP buffer assert.

- Expose the reduce-scatter pipeline on the param_and_grad_buffer to enable back-pressure management, preventing overflow in the double-buffer pool during gradient allocation.
- Implement a mechanism in main_grad_getter to drain the oldest pending reduce-scatter before allocating new grad buckets, ensuring efficient memory usage.
- Adjust the wait_for_previous_grad_reduce method to operate on the reduce-scatter stream, improving synchronization during backward passes.
@cspades

cspades commented Jul 14, 2026

Copy link
Copy Markdown

Oh, I just noticed this PR while looking at a PR that fixes this double buffer leak while working on an issue. It was an insanely lousy bug that survived for a long time untested. Sorry for the inconvenience! 🙏🏻

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