Commit 6c32c0c
[CuTe,Bwd,Sm100] Support head_dim not a multiple of 32 in backward
Backward on SM100 (B200/B300) crashed or silently produced wrong dK/dV
when head_dim was not a multiple of 32 (e.g. ViT head_dim=72, 104).
Fixes #2492. Three independent root causes:
1. flash_bwd_preprocess.py: the O/dO load predicate (predicate_k) carries a
CPY_M mode broadcast over m, but the copy source is sliced per-m
(tOgO[None, m, None]) without slicing the predicate. The vectorized
128-bit copy atom's predicate-shape verifier then rejects the extra mode
("expects (1,(k)) but got (1,(cpy_m,k))"). Slice the predicate per-m to
match, as flash_fwd.py / flash_bwd.py already do.
2. flash_bwd_sm100.py: tile_hdim padded head_dim to a multiple of 16, but the
dQ accumulator reduce requires a multiple of 32 (assert tile_hdim %
dQ_reduce_ncol == 0) and both the preprocess kernel and interface already
round to 32. head_dim=72 -> 80 tripped the assert. Pad to 32 so all three
agree (96); this reuses the already-working head_dim=96 path.
3. interface.py: varlen MHA uses the non-TMA dK/dV epilogue store, which
writes tile_hdim (mult of 32) columns per row with no head-dim OOB
predication (its 16-wide vectorization cannot mask a 72 boundary). It
therefore spilled past the real head_dim and corrupted neighboring dK/dV.
Route that store through a head-dim-padded scratch buffer, then slice back.
Validated on B300 (SM103) against torch.nn.functional.scaled_dot_product_attention
(fp32 reference): dense + varlen, causal + non-causal, head_dim in
{64, 72, 80, 104, 128}, MHA and GQA(hd=128). dq/dk/dv max relative error
2e-3..7e-3 (bf16 precision), matching the multiple-of-32 baselines. No
regression on aligned head dims. End-to-end Qwen3.5-VL training (ViT
head_dim=72, varlen) trains with a decreasing loss and finite grad norm.
Note: this is an alternative to #2633. #2633 keeps V padding at a multiple of
16 and predicates the non-TMA store via a reduced tmem Repetition, which is
neater for varlen; however in our testing that leaves the dense (TMA-store)
dV path numerically wrong for head_dim % 32 != 0 (large relative error),
whereas padding V to 32 keeps both the dense and varlen paths correct.
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>1 parent 5835c73 commit 6c32c0c
3 files changed
Lines changed: 43 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
17 | 16 | | |
18 | 17 | | |
19 | 18 | | |
| |||
365 | 364 | | |
366 | 365 | | |
367 | 366 | | |
368 | | - | |
369 | | - | |
| 367 | + | |
| 368 | + | |
370 | 369 | | |
371 | 370 | | |
372 | 371 | | |
| |||
378 | 377 | | |
379 | 378 | | |
380 | 379 | | |
381 | | - | |
382 | | - | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
383 | 387 | | |
384 | 388 | | |
385 | 389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
72 | | - | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
73 | 75 | | |
74 | 76 | | |
75 | 77 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1611 | 1611 | | |
1612 | 1612 | | |
1613 | 1613 | | |
| 1614 | + | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
1614 | 1636 | | |
1615 | 1637 | | |
1616 | 1638 | | |
| |||
1998 | 2020 | | |
1999 | 2021 | | |
2000 | 2022 | | |
| 2023 | + | |
| 2024 | + | |
| 2025 | + | |
| 2026 | + | |
| 2027 | + | |
| 2028 | + | |
| 2029 | + | |
| 2030 | + | |
2001 | 2031 | | |
2002 | 2032 | | |
2003 | 2033 | | |
| |||
0 commit comments