Repository navigation
Add opt-in BF16/FLA GDN recurrence activation offloading - #7908
WEIXILIN0307 wants to merge 16 commits into
Conversation
…t copy `ChunkOffloadHandler.reload()` enqueues its host-to-device copy on the caller's current stream -- which on the `tensor_pop` path is the compute stream -- with no ordering edge on the group's `_offload_event`, recorded on `d2h_stream`. Only `bulk_reload_group` waits on that event; `tensor_pop` calls `reload()` inline and bypasses the wait. A backward that reaches a group before any prefetch ran can therefore read the pinned staging buffer while the device-to-host copy that fills it is still in flight. The saved activation silently becomes stale buffer contents and the gradients computed from it are wrong. Nothing raises, and the loss curve still descends. This contradicts the feature's own documented design: "Before the group's backward, tensors are reloaded from CPU to GPU on `h2d_stream`, and the compute stream waits for the transfer to complete." The inline path is not rare. The prefetch trigger `on_group_start_backward` is the backward of the group-start marker, which autograd runs at the end of that group's backward, after every `tensor_pop` in it, so the reload LIFO has to be primed one group ahead by `pre_reload_last_layer`. During warmup nothing primes it: `should_bulk_offload` returns True unconditionally while `is_warmup`, and `tensor_pop` drained a group's tensors while leaving the group object on `_groups_to_reload`, so every `bulk_reload_group` re-targeted an already-drained tail and the priming branch was never reached. Measured on a 4-layer GPTModel with `--offload-modules core_attn`, the warmup iteration took the unordered inline path for all 24 of its reloads, with 0 prefetched. Add a `reload_pending` latch to `OffloadTensorGroup`, set when the group's device-to-host copy is enqueued and cleared by whichever reload consumes it. On the inline path, `tensor_pop` waits on the group's offload event on the compute stream and drops the group from the LIFO so the next prefetch advances. Keying the latch on group identity is necessary rather than waiting unconditionally: `_offload_event` is a single event per group, reused every iteration, so a group that was not offloaded this iteration would otherwise wait on a stale edge. `reset()` clears the latch for groups offloaded but never reloaded, and `bulk_reload_group` clears it too so a prefetched group never re-serializes compute behind the device-to-host copy. With no artificial stall at all -- a 256 MiB device-to-host copy and nothing else -- 20 trials per arm corrupted 19/20 on B300 and 20/20 on A40 before this change, and 0/20 on both after it. Add a regression test that stalls `d2h_stream` with `torch.cuda._sleep` before the commit to make the race deterministic, asserts the stall took effect, and then checks both the ordering and the reloaded values. Reverting the latch turns it red. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: GarlGuo <wg247@cornell.edu>
The single-group test stayed green when `_groups_to_reload.remove(group)` was dropped from `tensor_pop`. Use two forward-ordered groups, so the inline pop of the second must release the LIFO and let the next prefetch advance to the first. Raised in review on NVIDIA#7399. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: GarlGuo <wg247@cornell.edu>
b343409 to
8e8c43c
Compare
|
/ok to test b22c9f7 |
|
Thank you for contributing GDN recurrence activation offloading and for the extensive testing and validation work behind it. To make this easier to review and merge, I suggest splitting it into three PRs:
Please also consider moving the raw CSV measurements and detailed historical experiment logs into the pinned evidence repository/artifacts already linked here. The in-tree documentation can retain the design and usage guidance, reproducible commands, a concise results summary, and known limitations, with links to the full evidence. Tests and validation should move with the corresponding changes: each PR should include its relevant regression tests and evidence tied to that PR's code revision, while the final GDN feature PR should validate the combined end-to-end training path. This would preserve the useful validation work while making each change easier to assess independently. |
Thanks @lhb8125, that split makes sense, especially reviewing the pre-GDR backward change separately since it also affects the offload-disabled path. |
b22c9f7 to
8d13882
Compare
ee2e6c1 to
8a2d198
Compare
67fb40d to
b113b63
Compare
NVIDIA#7908: a 1-layer VPP chunk kept on GPU advanced the chunk early -> 'Chunk mismatch')
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
ff3994e to
1adb1f6
Compare
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
1adb1f6 to
e96793f
Compare
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
…PT training Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
e96793f to
ef43183
Compare
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
Signed-off-by: Pinoeer-kingxi <13022943007@163.com>
What does this PR do?
Add opt-in
gdn_core_attnactivation offloading for BF16/FLA GDN training, using the existing manager, transfer streams and pinned-memory pool.Enable with
--fine-grained-activation-offloading --offload-modules gdn_core_attn. With TE 2.10 or newer, setNVTE_CPU_OFFLOAD_V1=1before launch. The scope wraps the FLA recurrence and commits before output normalization. A differentiable recurrence input anchors backward prefetch; shared inputs are not force-released. No-grad and fully frozen recurrence execution bypass the GDN scope.Selective
gdn_norm_outrecomputation and existing pre-GDR fusion are supported. GDN2, FP8/FP4, non-BF16 execution, other recurrence backends, full recomputation and CUDA graphs are rejected. GDN2/TE graph support is proposed separately in #8308. Native pre-GDR kernels and autotuning are unchanged.FP8/NVFP4 support for TE projections and MLPs is proposed separately in #8543, after #8308. It is not included in this PR.
Includes a saved-tensor profiler/benchmark and a local-Qwen training tool with native checkpoint save/load. Megatron Bridge is required only by the Qwen tool. See usage and reproduction commands.
Dependencies and scope
Requires #8243 at
5bc9e72bda70129f088dd78328d4064f1d838c62and its #7399 prerequisite. The diff againstmainincludes those dependencies; the GDN-only diff isolates this feature.Projection/convolution/QKV recomputation and convolution-input offloading belong to #7852; combined use is not validated.
Validation
Head:
b6fa63ab8c2cb855f0368cd8455245c295cde234, including the #8243 prerequisite and a merge frommainat3ddfe0fe07efc73dbdc40d4a02acbc1c1f8a9f08.Commands, source import paths, original rank logs and checksums identify the executed head. The current stability and checkpoint evidence includes per-step pool and state checks.
Validation covers fixed-length training initialized by a training step; evaluation-first initialization and tensor-size changes after warmup are not qualified.
The earlier four-rank matrix and TP2+SP+PP2 Qwen runs ran at
e96793feecb0fdd54ce00ef09a67e28fce940d06and were not repeated at this head. Native fused decoder comparisons usertol=1e-5,atol=1e-8for atomic gate-gradient variability; unfused comparisons are exact. Upstream GPU CI is pending.Recorded memory and runtime
At the current head
b6fa63ab8c2cb855f0368cd8455245c295cde234, complete Qwen3.5-0.8B language-model training on one RTX PRO 6000 used BF16, sequence 4096, four microbatches, fraction 1, the default threshold and no norm recomputation. Each row uses three fresh-process pairs, three warmup steps and ten measured optimizer steps. Peak values are medians of the per-arm peaks; step changes are paired medians and ranges.The fused result does not establish a speedup. No other compute process was observed on the measured GPU, but other GPUs were shared; host and PCIe isolation are not established. The timed runs compare loss and gradient norm; the full-state correctness runs are described above. Commands, rank logs, samples, telemetry and audit.
Earlier performance and checkpoint and stability results used different revisions and configurations; they do not qualify the current head.
Issue tracking
Related to #6757.
Code provenance
No code copied or adapted from external repositories.
Contribution process
Pre-checks