Repository navigation
Add GDN input-projection and conv/QKV selective recompute and offload - #7852
Draft
Aravind-11 wants to merge 2 commits into
Draft
Aravind-11 wants to merge 2 commits into
Aravind-11 wants to merge 2 commits into
Conversation
GatedDeltaProduct supports gdp_in_proj / gdp_qkv recompute and gdp_qkv offloading, but GatedDeltaNet and GatedDeltaNet2 could only recompute the output norm. Add the same options for the GDN family: - gdn_in_proj: recompute the input projection and CP-to-HP all-to-all. - gdn_qkv: recompute the causal conv and q/k/v preparation. - gdn_qkv offload: offload the causal-conv input. Move the conv and q/k/v preparation shared by GDN and GDN2 into _GDNBase, split kernel-input preparation into q/k/v and gate parts, and register the recompute hooks on the gated-delta-rule output so the layer stays two-stage-attention compatible. Without the new options the forward and backward are bit-identical to before. Reject gdn_qkv with gdn_pre_gated_delta_rule_fusion, gdn_qkv offload with gdn_in_proj recompute, and the new options on non-GDN models. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015GWnUwTNXQ9MTA4dw8gT2Q Signed-off-by: Aravindhan <arvindhant01@gmail.com>
The fused pre-GDR path gives the output norm a strided view of the input projection. Freeing that projection before the norm reads it corrupts the forward. When the norm output is recomputed as well, its hook is on the output projection and runs before a restore hook that lives only on the norm output. Discard the projection once, after the norm has read it, and register that same restore on the output projection first. Cover the strided gate, including the norm-recompute combination, and cover gdn_qkv offload with the recompute combinations that are allowed beside it. Signed-off-by: ARAVINDHAN T <arvindhant01@gmail.com>
6 of 7 tasks
6 of 7 tasks
This branch has not been deployed
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?
Adds fine-grained selective recompute and activation offloading to Gated DeltaNet (
gdn) and Gated DeltaNet 2 (gdn2), matching what GatedDeltaProduct already supports withgdp_in_proj/gdp_qkv. Today the GDN family can only recompute its output norm (gdn_norm_out).Roadmap: #5676, "GDN memory optimization" (fine-grained activation offloading and selective recompute for in-projection, conv1d, and gated delta rule logic).
New options
gdn_in_proj--recompute-moduleshidden_statesis kept.gdn_qkv--recompute-modulesgdn_qkv--offload-modulesRejected with a clear error:
gdn_qkv(recompute or offload) withgdn_pre_gated_delta_rule_fusion, which fuses the conv and q/k/v prep with the gates.gdn_qkvoffload together withgdn_in_projrecompute. The same rule exists forgdp_qkv/gdp_in_proj.Implementation
gdn.pyandgdn2.py, moves into_GDNBase._causal_conv_qkv._prepare_input_for_gated_delta_ruleis split into_prepare_qkv_for_gated_delta_ruleand_prepare_gates_for_gated_delta_rule. The original method keeps its signature and behaviour, andpre_gated_delta_ruleis unchanged for callers._project_inputwraps in_proj + all-to-all and_conv_and_prepare_qkv_maybe_recomputewraps conv + q/k/v prep, each in aCheckpointWithoutOutput(and thegdn_qkvoffload group). This followsGatedDeltaProductMixer._gdp_chunk_forward..contiguous(), which is why a CPU replay of the unfused module still matched.gdn_in_projwith fusion stays allowed;gdn_qkvwith fusion stays rejected.gdn_qkvrecompute is hooked on the raw gated-delta-rule output, and thegdn_qkvoffload group is committed on that same tensor.gdn_in_projis discarded on the norm output, after the gated norm has read its gate.forward_post_core_attnalso registers that same restore on the output projection, before thegdn_norm_outhook and without a second discard. Hooks on one tensor run FIFO, and hooks on the output projection run before hooks on the norm output, so the projection (and a fused gate view into it) is restored before either consumer reads it. The new discards stay insideforward_pre_attn_and_core_attn, so these options keep two-stage attention working.gdn_norm_outstill does not, because its checkpoint is discarded on the output projection.Testing
Earlier CPU checks:
gdn/gdn2× fp32/bf16 × batch 1/2 × {gdn_in_proj,gdn_qkv, both, both +gdn_norm_out}: 32/32 cases. Each requested checkpoint released its outputs in forward. Runs the deterministic torch-native kernels, with CUDA RNG / TE hooks stubbed.mainforgdn/gdn2× fp32/bf16.gdn_in_projgdn_qkvgdn_in_proj+gdn_qkv+gdn_norm_outUnit tests in
tests/unit_tests/ssm/test_gated_delta_net_recompute.py:test_in_proj_recompute_with_strided_gate_viewbuilds the fused pre-GDR gate layout (a strided view ofqkvzba, shared storage with the real gate) and checksgdn_in_projalone and together withgdn_norm_out. GDN2 skips it. The real fused kernel is covered bytest_in_proj_recompute_with_real_pre_gated_delta_rule_fusion, which skips unlesscausal_conv1dbackward is installed.gdn_qkvoffload: warmup offload bytes are non-zero, and a second forward/backward afterPipelineOffloadManager.reset()stays bit-identical. Combinations are offload alone, withgdn_qkv, withgdn_norm_out, and with both.gdn_in_projstays rejected next to offload.GPU run of that file, commit
732159d2154c242ee812d00213bd764013c25acc, on one NVIDIA A100-SXM4-40GB (torch 2.11.0+cu130, CUDA 13.0, Transformer Engine 2.20.0, flash-linear-attention 0.5.1, world size 1):The 30 passes are the tp=1 / sequence-parallel off / cp=1 slice: 10 selective-recompute cases, 2 strided-gate cases, 8 offload cases, and the 10 CPU config tests. Outputs and grads matched with
torch.equal. The 4 skips are the two GDN2 strided-gate cases, the GDN2 real-fusion case, and the GDN1 real-fusion case (causal_conv1dbackward is not installed). The 120 deselected cases are the same matrix at tp=2 or cp=2.The Colab process disabled
torch.compileand kept a single Triton autotune config so the first-shape compile fit in the assignment. The commit leaves both enabled. The comparison is eager against eager on the same kernels.Still pending:
causal_conv1dbackward)gdn_qkvoffloadContribution process
Pre-checks
transformer_config.pydocstrings, fine-grained offloading guide)BASE_REF=main CHECK_ONLY=true; black, isort, pylint, and ruff clean on the changed Python)