[Dev] Allow FP8/FP4 with AbsorbedMLA up-projection recompute - #6178
Conversation
AbsorbedMLASelfAttention asserted that quantization was unsupported whenever "mla_up_proj" selective recompute was enabled, blocking FP8 and FP4 training for any model that needs that recompute to fit in memory. The assertion arrived with the initial absorbed-MLA implementation as a not-yet-validated placeholder rather than a guard for a known failure. The quantized replay is safe for the same reason it is in MLASelfAttention, which runs the identical CheckpointWithoutOutput pattern with no such assertion: the checkpoint records the forward recipe and amax state and replays under the recorded fp8_autocast, and the only quantized operation inside qkv_up_proj_and_rope_apply is the Q up projection. The absorption einsum reads the K up-projection weight directly, and that weight is a persistent parameter -- under fp8_param_gather it is remapped to TE quantized storage that outlives the backward pass -- so the forward and the replay observe the same values. Add test_fp8_up_proj_recompute_parity, which drives two identically-initialized modules, one recomputing the up projection and one not, and requires bitwise-identical outputs and parameter gradients. Recompute is meant to be an exact replay, so any drift would indicate a different quantization scale or a stale weight. The test covers the tensorwise, delayed and mxfp8 recipes across sbhd and thd layouts and both the combined and split K/V up-projection module specs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
|
/ok to test 510d14c |
|
/claude strict-review |
There was a problem hiding this comment.
Strict review passed — no significant issues found. LGTM
Findings: CRITICAL: 0, IMPORTANT: 0, SUGGESTION: 1 (non-blocking)
Verified the change is safe:
- The removed assertion was a not-yet-validated placeholder, not a guard for a known failure.
- The new comment's two load-bearing claims check out against the source: the only quantized op inside
qkv_up_proj_and_rope_applyis the Q up projection (linear_q_up_proj/linear_q_proj), and the K up-projection weight is read directly via_get_kv_up_weights()(a persistent parameter), not through the checkpoint context — so the forward and the recompute replay observe identical values. - The identical
CheckpointWithoutOutput(fp8=quantization)pattern already ships inMLASelfAttention(multi_latent_attention.py:981) with no assertion — and there it quantizes both the Q and KV up-projection GEMMs, making the absorbed path a strict subset of an already-validated one. - The
atol=0, rtol=0bitwise-parity test is the appropriate contract: recompute is meant to be an exact replay, so any quantization-scale or stale-weight drift would fail it. Coverage spans tensorwise/delayed/mxfp8 × sbhd/thd × combined/split KV up-proj.
Non-blocking suggestion (test coverage): The code path also enables FP4 (self.config.fp8 or self.config.fp4) and the PR title says "FP8/FP4," but the test only exercises FP8 recipes; the test's guarantee is effectively FP8-scoped. FP4 shares the exact same code path and requires TE ≥2.7 + capable hardware, so deferring it is reasonable — worth a note in the test docstring or a follow-up.
Risk: Low. A single-line assertion removal plus an accurate explanatory comment, mirroring an existing validated path and backed by a strong bitwise-parity test.
Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
713ecc0 to
7efcb52
Compare
Good catch — I will add |
Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
|
/ok to test 713fcab |
|
/ok to test c5d3cdd |
Importing tests.unit_tests.determinism.utils pulls in torch.testing._internal.common_utils, which calls torch.backends.disable_global_flags() at import time and makes test_te_layers_batch_invariant.py fail later in the same pytest session with 'not allowed to set torch.backends.cudnn flags'. Inline capture_rng_state/restore_rng_state instead of importing them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
|
/ok to test 6648492 |
@buptzyb CI is green now. Root cause was an import side effect: the test imported helpers from |
Summary
AbsorbedMLASelfAttentionasserted that quantization was unsupported whenever"mla_up_proj"selective recompute was enabled, blocking FP8 and FP4 training for any model that needs that recompute to fit in memory. The assertion arrived with the initial absorbed-MLA implementation (#3193 / #3198) as a not-yet-validated placeholder rather than a guard for a known failure.The quantized replay is safe for the same reason it is in
MLASelfAttention, which runs the identicalCheckpointWithoutOutputpattern with no such assertion (multi_latent_attention.py):ctx.fp8/ctx.fp8_recipeunderactivation_recompute_forward(recompute_phase=False)) and replays under the recordedfp8_autocastwithrecompute_phase=True.qkv_up_proj_and_rope_applyis the Q up projection — the same module set MLA already replays.fp8_param_gatherit is remapped to TE quantized storage that outlives the backward pass (param_and_grad_buffer.py), and the only path that frees param storage is explicit weight CPU offload. So the forward and the replay observe the same values.DeepSeekV4HybridAttentionalready runs the same pattern without the assertion.Test plan
Added
test_fp8_up_proj_recompute_parity, which drives two identically-initialized modules — one recomputing the up projection, one not — over the same inputs underget_fp8_context, and requires bitwise-identical (atol=0, rtol=0) outputs and per-parameter gradients. Recompute is meant to be an exact replay, so any drift would indicate a different quantization scale or a stale weight; a tolerance-based comparison would hide exactly the failures this guards against.A bf16 reference run guards the parity check against passing vacuously: the same weights go through an
fp8=Falsemodule, and the FP8 output must track it closely and differ from it bitwise — which is only possible if quantization actually engaged.Coverage:
tensorwise/mxfp8/blockwiserecipes xsbhd/thdlayouts x combined / split K-V up-projection module specs.Run on GB200 (mxfp8 needs Blackwell, so nothing is capability-skipped there):
76 = 64 pre-existing
test_functionalitycases (unchanged, no BF16 regression) + 12 new FP8 cases, 0 skipped.