Repository navigation
[Dev] Add output gating to absorbed MLA - #8006
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/review model=claude mode=strict |
svcnvidia-nemo-ci
left a comment
There was a problem hiding this comment.
Strict review summary
Findings: CRITICAL: 0, IMPORTANT: 1, SUGGESTION: 0. No tests were run; everything below comes from reading the source.
Most impactful finding
[IMPORTANT Compatibility] The new test test_hy4_attention_shape_cudnn_gated_dsa_matches_native always builds a config with dsa_kernel_backend="cudnn". It does not first check that the GPU and kernel dependencies are present, which every other real-kernel cuDNN DSA test does.
- The config check at transformer_config.py L1992-L1993 raises a
ValueErrorwhenflash_mlaor cuDNN-frontend DSA is missing. - The LTS image installs neither of them.
- The
tests/unit_tests/transformer/**/*.pybucket runs in theltsenvironment. - Result: the LTS unit-test lane always errors on this test instead of skipping it.
Details and the exact fix are in the inline comment. Proposed replacement for lines 471-472 of that test file (written to match the existing guards; not run):
def test_hy4_attention_shape_cudnn_gated_dsa_matches_native():
if torch.cuda.get_device_capability()[0] < 9:
pytest.skip("cuDNN fused DSA path requires SM90+")
missing = _missing_cudnn_dsa_kernel_dependencies()
if missing:
pytest.skip(f"cuDNN fused DSA dependencies are unavailable: {', '.join(missing)}")
_run_native_parity("elementwise", production_shape=True, kernel_backend="cudnn")This also needs from megatron.core.utils import _missing_cudnn_dsa_kernel_dependencies added to the test's imports.
What was checked and found sound
Shared gate helper (attention_output_gate.py). Every caller keeps its previous precision and compile behaviour:
- Attention, scalar per-head gate: still eager, still casts the scale to the input dtype before multiplying.
- Attention
_apply_output_gate: still compiled withjit_fuser, still multiplies by the FP32 scale and casts afterwards. - MLA per-head gate: still compiled, casts before multiplying.
- MLA per-element gate: still eager, casts before multiplying.
- KDA: compiled, leaves the product in its natural dtype, and the caller applies the final
.to(x_dtype). - Shape checks match what the old inline MLA checks enforced.
Absorbed MLA / DSA gate (absorbed_mla.py):
- Gate input: the post-LayerNorm
hidden_states. The spec setsfuse_input_layernorm: False, and gating combined withmla_down_proj_fusionis already rejected in the config. - Projection: a column-parallel linear produces the TP-local head slice and gathers the sequence-parallel input, which matches the existing assert
core_attn_out.shape[0] == hidden_states.shape[0]*TP. - Placement: applied after the V up-projection and the recompute discard, before
linear_proj. - Deferred weight gradients: included in
backward_dw, which the EP-overlap scheduler reaches throughlayer.self_attention.backward_dw. - LayerNorm recompute: included in
set_for_recompute_input_layernorm.
Checkpoints: the key linear_gate.weight and its row sharding are the same in the training AbsorbedMLASelfAttention spec and the inference MLASelfAttention DSA spec in hybrid_layer_specs.py.
Unused-identifier check (mandatory): the new linear_gate field, gate_projection_size, and the helper's granularity and cast_mode arguments all have real uses at runtime.
Overall risk
- Production code: low risk. The gate math is behaviour-preserving for existing callers, and the new absorbed-MLA path matches ordinary MLA's TP/SP/CP, recompute and deferred-gradient handling.
- Remaining risk: the CI-environment issue above.
Limitation: the style-guide.md that the skill references is not in the base tree, so style was not checked beyond the configured linters.
Review generated by claude
2bd5e1f to
af5d982
Compare
Support headwise and elementwise output-gate projections in absorbed MLA and the default DSA module specifications, including recomputation and deferred weight gradients. Share FP32 sigmoid gating across Attention, MLA, and KDA while preserving each caller's cast and compilation policy. Use one headwise layout flow. Add independent numerical and distributed regression coverage. Signed-off-by: Robin Zhang <robinz@nvidia.com>
af5d982 to
b9c36e0
Compare
|
/ok to test b9c36e0 |
…, restore CP-convert imports
More defects surfaced by the AttnRes/Kimi-K3 UT:
- transformer_config.py still raised NotImplementedError("Output gate is not supported
for MLA yet.") — a main placeholder guard. NVIDIA#8006's MLA output gate is now implemented
(MultiLatentAttention.linear_gate + _project_and_apply_mla_output_gate), so remove it.
- attention.py (SelfAttention) and gdn.py reference convert_module_input_tensors_cp_partition_mode
(the NVIDIA#7545 CP-layout input conversion) but lost the import in the merge; restore it
(kda.py / multi_latent_attention.py already import it).
- test_kimi_k3_attnres_mtp.py configured Kimi-K3 with dev's situlu activation; adapt to
main's silu + activation_func_tanh_clamp_scale(=4.0)/_linear(=25.0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…VIDIA#6877 Refresh the squashed PR integration, including input layernorm recompute support for GDN and KDA under FP8/FP4. Source-PR: NVIDIA#6877 Source-head: 4a335ed Source-base: 0c59fc6 Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com> Rebase (2026-10-21, dev ff4fbc9): squash of fork branch yuzhongw/kimi-k3-kda @ 0af9035 (PR NVIDIA#6877, 15 commits) rebased onto dev. The jit-fused MLA elementwise output gate commit was dropped in favour of dev's eager apply_attention_output_gate (NVIDIA#8006); _use_fused_q_uproj now also requires use_rope so NoPE layers never take the RoPE-applying kernel; dev's NVIDIA#8203 te_checkpoint recompute wrap is kept with the active pg_collection; in_proj_dim is resolved through the variant hook next to dev's in_proj_qkvg_dim. Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com> (cherry picked from commit 8fccd77) Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…ntAttention Port dev NVIDIA#8006 (2cc4b6f) output gating onto main's MultiLatentAttention: build an optional linear_gate projection (gate_projection_size = query_projection_size for elementwise, num_attention_heads for headwise), capture the layer input as the gate source, and apply the gate to the core-attention output before the output projection. The gate math reuses the already-carried apply_attention_output_gate helper (FP32 sigmoid, cast-before multiply) and flushes its delayed weight grad in backward_dw. Add the gated_attention_proj_granularity config field. Kimi-K3's no-RoPE MLA layers use attention_output_gate=True. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…, restore CP-convert imports
More defects surfaced by the AttnRes/Kimi-K3 UT:
- transformer_config.py still raised NotImplementedError("Output gate is not supported
for MLA yet.") — a main placeholder guard. NVIDIA#8006's MLA output gate is now implemented
(MultiLatentAttention.linear_gate + _project_and_apply_mla_output_gate), so remove it.
- attention.py (SelfAttention) and gdn.py reference convert_module_input_tensors_cp_partition_mode
(the NVIDIA#7545 CP-layout input conversion) but lost the import in the merge; restore it
(kda.py / multi_latent_attention.py already import it).
- test_kimi_k3_attnres_mtp.py configured Kimi-K3 with dev's situlu activation; adapt to
main's silu + activation_func_tanh_clamp_scale(=4.0)/_linear(=25.0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…ntAttention Port dev NVIDIA#8006 (2cc4b6f) output gating onto main's MultiLatentAttention: build an optional linear_gate projection (gate_projection_size = query_projection_size for elementwise, num_attention_heads for headwise), capture the layer input as the gate source, and apply the gate to the core-attention output before the output projection. The gate math reuses the already-carried apply_attention_output_gate helper (FP32 sigmoid, cast-before multiply) and flushes its delayed weight grad in backward_dw. Add the gated_attention_proj_granularity config field. Kimi-K3's no-RoPE MLA layers use attention_output_gate=True. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…, restore CP-convert imports
More defects surfaced by the AttnRes/Kimi-K3 UT:
- transformer_config.py still raised NotImplementedError("Output gate is not supported
for MLA yet.") — a main placeholder guard. NVIDIA#8006's MLA output gate is now implemented
(MultiLatentAttention.linear_gate + _project_and_apply_mla_output_gate), so remove it.
- attention.py (SelfAttention) and gdn.py reference convert_module_input_tensors_cp_partition_mode
(the NVIDIA#7545 CP-layout input conversion) but lost the import in the merge; restore it
(kda.py / multi_latent_attention.py already import it).
- test_kimi_k3_attnres_mtp.py configured Kimi-K3 with dev's situlu activation; adapt to
main's silu + activation_func_tanh_clamp_scale(=4.0)/_linear(=25.0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…, restore CP-convert imports
More defects surfaced by the AttnRes/Kimi-K3 UT:
- transformer_config.py still raised NotImplementedError("Output gate is not supported
for MLA yet.") — a main placeholder guard. NVIDIA#8006's MLA output gate is now implemented
(MultiLatentAttention.linear_gate + _project_and_apply_mla_output_gate), so remove it.
- attention.py (SelfAttention) and gdn.py reference convert_module_input_tensors_cp_partition_mode
(the NVIDIA#7545 CP-layout input conversion) but lost the import in the merge; restore it
(kda.py / multi_latent_attention.py already import it).
- test_kimi_k3_attnres_mtp.py configured Kimi-K3 with dev's situlu activation; adapt to
main's silu + activation_func_tanh_clamp_scale(=4.0)/_linear(=25.0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…VIDIA#6877 Refresh the squashed PR integration, including input layernorm recompute support for GDN and KDA under FP8/FP4. Source-PR: NVIDIA#6877 Source-head: 4a335ed Source-base: 0c59fc6 Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com> Rebase (2026-10-21, dev ff4fbc9): squash of fork branch yuzhongw/kimi-k3-kda @ 0af9035 (PR NVIDIA#6877, 15 commits) rebased onto dev. The jit-fused MLA elementwise output gate commit was dropped in favour of dev's eager apply_attention_output_gate (NVIDIA#8006); _use_fused_q_uproj now also requires use_rope so NoPE layers never take the RoPE-applying kernel; dev's NVIDIA#8203 te_checkpoint recompute wrap is kept with the active pg_collection; in_proj_dim is resolved through the variant hook next to dev's in_proj_qkvg_dim. Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
… latent up-projection (port dev PR NVIDIA#6804) MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Port: dev PR NVIDIA#6804; integrates PR NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
… latent up-projection (NVIDIA#8633) MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Main PR: NVIDIA#8633. Integrates PR NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
… latent up-projection (NVIDIA#8633) MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Main PR: NVIDIA#8633. Integrates PR NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
NVIDIA#8006 ("[Dev] Add output gating to absorbed MLA") replaced MLA's jit-fused elementwise output gate with the eager apply_attention_output_gate() so that the released model's cast-before-multiply rounding and VJP are reproduced exactly. Run eagerly, that composition keeps three gate-sized tensors alive from a layer's forward to its backward: the FP32 sigmoid output (SigmoidBackward), the BF16 scale and the core-attention output (MulBackward). The compiled version saved only the two BF16 inputs. With pipeline parallelism every in-flight microbatch pins them: at 32K tokens x 3072 local channels that is 384 MiB per MLA layer, 6 MLA layers per stage (7 on the last stage with MTP) = 2.25 GiB per microbatch and stage, which the memory probe measured exactly on the full-model 64K TP4 PP4 EP64 CP2 recipe (memory_allocated +2.25 GiB after each warm-up forward on every stage, released at that microbatch's backward): +8.6 GiB device peak on stage 0 with four in-flight microbatches, +3.7 GiB on stage 1. Add an autograd Function that computes the same eager forward, saves only core_attn_out and gate, and replays MulBackward, the cast's backward and SigmoidBackward with the same ATen ops in backward, so outputs and gradients stay bit-identical while the footprint returns to that of the fused gate. The headwise MLA gate (still jit-fused), the regular-attention gate and KDA's gated norm (inside its recompute checkpoint) are unchanged. Tests check bit-equality against the eager helper for every dtype pairing and that only the two inputs are saved. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…Norm latent up-projection MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Integrates NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
NVIDIA#8006 ("[Dev] Add output gating to absorbed MLA") replaced MLA's jit-fused elementwise output gate with the eager apply_attention_output_gate() so that the released model's cast-before-multiply rounding and VJP are reproduced exactly. Run eagerly, that composition keeps three gate-sized tensors alive from a layer's forward to its backward: the FP32 sigmoid output (SigmoidBackward), the BF16 scale and the core-attention output (MulBackward). The compiled version saved only the two BF16 inputs. With pipeline parallelism every in-flight microbatch pins them: at 32K tokens x 3072 local channels that is 384 MiB per MLA layer, 6 MLA layers per stage (7 on the last stage with MTP) = 2.25 GiB per microbatch and stage, which the memory probe measured exactly on the full-model 64K TP4 PP4 EP64 CP2 recipe (memory_allocated +2.25 GiB after each warm-up forward on every stage, released at that microbatch's backward): +8.6 GiB device peak on stage 0 with four in-flight microbatches, +3.7 GiB on stage 1. Add an autograd Function that computes the same eager forward, saves only core_attn_out and gate, and replays MulBackward, the cast's backward and SigmoidBackward with the same ATen ops in backward, so outputs and gradients stay bit-identical while the footprint returns to that of the fused gate. The headwise MLA gate (still jit-fused), the regular-attention gate and KDA's gated norm (inside its recompute checkpoint) are unchanged. Tests check bit-equality against the eager helper for every dtype pairing and that only the two inputs are saved. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
NVIDIA#8006 ("[Dev] Add output gating to absorbed MLA") replaced MLA's jit-fused elementwise output gate with the eager apply_attention_output_gate() so that the released model's cast-before-multiply rounding and VJP are reproduced exactly. Run eagerly, that composition keeps three gate-sized tensors alive from a layer's forward to its backward: the FP32 sigmoid output (SigmoidBackward), the BF16 scale and the core-attention output (MulBackward). The compiled version saved only the two BF16 inputs. With pipeline parallelism every in-flight microbatch pins them: at 32K tokens x 3072 local channels that is 384 MiB per MLA layer, 6 MLA layers per stage (7 on the last stage with MTP) = 2.25 GiB per microbatch and stage, which the memory probe measured exactly on the full-model 64K TP4 PP4 EP64 CP2 recipe (memory_allocated +2.25 GiB after each warm-up forward on every stage, released at that microbatch's backward): +8.6 GiB device peak on stage 0 with four in-flight microbatches, +3.7 GiB on stage 1. Add an autograd Function that computes the same eager forward, saves only core_attn_out and gate, and replays MulBackward, the cast's backward and SigmoidBackward with the same ATen ops in backward, so outputs and gradients stay bit-identical while the footprint returns to that of the fused gate. The headwise MLA gate (still jit-fused), the regular-attention gate and KDA's gated norm (inside its recompute checkpoint) are unchanged. Tests check bit-equality against the eager helper for every dtype pairing and that only the two inputs are saved. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…Norm latent up-projection MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Integrates NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…Norm latent up-projection MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Integrates NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
…Norm latent up-projection MultiLatentAttention output gate (integrates PR NVIDIA#8006, with the standalone attention_output_gate helper) and the RMSNorm latent up-projection (dev PR NVIDIA#6804), plus wiring the MLA linear_gate into the hybrid specs. Architectural MLA features. Category: functionality (new model features; directly submittable to main). Integrates NVIDIA#8006. Depends-on: none (upstream only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Yuzhong Wang <yuzhongw@nvidia.com>
Single repair commit for the main slice 5812485 -> dev merge. - ssm/kda: restore dev's `False` distribute_saved_activations argument in both KDA recompute checkpoints. The kda.py conflict resolution had taken main NVIDIA#7054's config read; dev's recompute contract (NVIDIA#8203, test_gdn_quantized_recompute) passes False, as dev's GDN does. - tests/models/test_hybrid_mhc: main NVIDIA#7555 replaced mtp_layer_pattern with mtp_layer_config_list; assert the new attributes instead. - tests/transformer/moe/test_route_metadata_cpu: the dispatcher test double accepts packed_seq_params, which main NVIDIA#8458 now passes. - tests/transformer/test_attention_output_gate: the KDA test double sets two_stage_gates=False, read by main NVIDIA#7054's _apply_gated_norm. - tests/data/test_get_batch: stub dev's prepare_packed_seq_params hook in main NVIDIA#8525's config-cache test; all main assertions are kept. - ssm/kda: keep dev's direct-gate op order in _apply_gated_norm (norm, then gate reshape). main NVIDIA#7054 reshaped the gate first, which changed the compiled rounding that dev NVIDIA#8006's test_kda_gated_norm_preserves_upstream_ rounding pins; main's two-stage branch is unchanged. - tests/data/test_pretrain_gpt_dataset_config: main NVIDIA#8391 replaced pretrain_gpt's build_tokenizer(args) with get_tokenizer(); the dev test now patches get_tokenizer. Its assertion is unchanged. - ssm/kda_layer_config: run validate_kda() before TransformerConfig's __post_init__ as well as after it. Dev NVIDIA#6556's shared GDN-family assertions ran first and preempted the KDA ValueErrors that main NVIDIA#7054's test_kda config tests expect. Dev's plain TransformerConfig checks are unchanged. - tests/transformer/test_thd_cuda_graph: the dev HybridModel test double sets hybrid_layer_config_list=None, which main NVIDIA#7555 reads in HybridModel.forward. Main NVIDIA#7555 made the same change to its own hybrid test doubles. The test assertions are unchanged. - functional goldens: refresh dev_dgx_h100 golden values for the four gpt3_mcore_te_tp2_pp2 mHC cases after main NVIDIA#7521 changed their numerics (local H100 runs on merge 44a8771). - tests/unit_tests/ssm/test_kda.py: keep dev NVIDIA#6556 kda_safe_gate/kda_lower_bound on TransformerConfig (CLI flags); main NVIDIA#7054 placement check now excludes only those two fields and asserts they stay on the stack config. - tests/unit_tests/ssm/test_kda.py: main NVIDIA#7054's recompute-acceptance test builds a non-hybrid experimental_attention_variant="kda" config. Dev NVIDIA#6556 registers kda as a GDN-family variant, and dev requires linear_attention_freq for every standalone GDN-family model, so the kda case now passes linear_attention_freq=[1]. Dev's validation and the test assertion are unchanged. - docker: pin the ARM64 MoK build to main NVIDIA#8210's 7a8cfb7f. The merged MoK backend passes shared_output_gate_weight to mok.functional.forward, and main's test_mok_numerics runs that path on GB200. Dev's a2ad2d0c pin does not accept the argument (GB200 CI TypeError in test_real_mok_ddp_numerics). 7a8cfb7f is a fast-forward of a2ad2d0c (2 commits) that already contains both hunks of dev's docker/patches/mok.patch, so the patch, its bind mount and the install_mok.sh patch argument are removed as on main, and the MoE README names the new snapshot. The AMD64 (H100) image still skips MoK; the rest of dev's Dockerfile.ci.dev is unchanged. - .github/workflows/cicd-main.yml: NVIDIA-NeMo/RL 4aaa48fa (NVIDIA#4253) renamed tests/functional/L1_Functional_Tests_Megatron_4.sh to L1_Functional_Tests_Megatron_Generation.sh, so the NeMo RL dispatch pattern matched no script and the downstream pre-flight failed with "No test scripts match the requested selection". Point the pattern at the renamed script. Dev and main carry the same stale pattern. Signed-off-by: svcnemo-autobot <svcnemo-autobot@nvidia.com>
Summary
Enable
attention_output_gatein absorbed MLA, including the default DSA path, with headwise and elementwise gates applied before the output projection.Main counterpart: #8008.
Changes
Test plan
CHECK_ONLY=true BASE_REF=dev bash tools/autoformat.shpassed (Black, isort, Pylint, and Ruff).The full GPU suite ran in the pinned CI-derived container on dev
b4407209. Production source is unchanged on this PR's devf11f03405base. This is not validation of a fresh install from the current dev lockfile. The PR contains one signed commit.