Commit Graph

272 Commits

Author SHA1 Message Date
7ea77a121f Use cpasync.tma_partition for SMEM->GMEM TMA store (like epilogue_tma_store) 2026-05-27 04:58:47 +00:00
e614d0894c Clean up SMEM acc epilogue: flat indexing sO_acc->sC, TMA store from sC_s0 2026-05-27 04:57:40 +00:00
1724eeb8ec Fix TMA store: use epi_s view of sC for proper layout compatibility 2026-05-27 04:55:18 +00:00
6a621bdf64 D1.5: SMEM accumulator FMHA kernel — one-way TMEM→REGS→SMEM, no round-trip
TMEM round-trip (Ld32x32bOp/St32x32bOp) is FUNDAMENTALLY BROKEN.
Even NO-OP (multiply by 1.0) corrupts data.

New approach:
- PV always ACCUMULATE=False (fresh TMEM each kt)
- After pv_done_bar: one-way Ld32x32bOp load O_kt from TMEM→REGS
- Coordinate-indexed SMEM accumulation: sO_acc = acc_scale * sO_acc + O_kt
- sO_acc: FP32 [128, pv_n_tile] row-major (32KB at hd=64, 64KB at hd=128)
- Final: normalize, cast BF16, write to sC, TMA store to GMEM
2026-05-27 04:53:40 +00:00
81acf1593c Revert "D1.5: WIP SMEM accumulator — framework in place, accumulation logic TODO"
This reverts commit 72d88af400.
2026-05-27 02:17:26 +00:00
72d88af400 D1.5: WIP SMEM accumulator — framework in place, accumulation logic TODO
Added epilogue_tmem_copy_and_partition + epilogue_smem_copy_and_partition
setup for multi-KV-tile O rescale. The one-way TMEM→REGS→SMEM pipeline
is wired up, but the SMEM-level accumulation (load-previous, scale, add,
store-back) needs implementation. Currently falls through to Python KV merge.
2026-05-27 02:15:23 +00:00
a6da93ddfb Revert "D1.5: Try O rescale with tCtO_base layout (epilogue-proven TMEM addressing)"
This reverts commit 79e2eb3b42.
2026-05-27 02:12:20 +00:00
79e2eb3b42 D1.5: Try O rescale with tCtO_base layout (epilogue-proven TMEM addressing)
Previous attempts used tOtO0 (from pv_thr.make_fragment_C) and corrupted data.
This version uses tCtO_base (from pv_mma.make_fragment_C) which is the SAME
tensor the epilogue successfully reads O from. Both load and store atoms built
from same tCtO_i via composition — CUTLASS correction_rescale pattern.
2026-05-27 02:10:39 +00:00
f94978ffa7 D1.5: Prepare for SMEM accumulator implementation
- Added epilogue utility imports (transform_partitioned_tensor_layout, etc.)
- Re-added pv_done_bar for SMEM accumulator synchronization
- Backed up current fmha.py as fmha_backup_v2.py
- SMEM accumulator approach: one-way TMEM→REGS→SMEM per kt, accumulate in FP32 SMEM
2026-05-26 21:00:41 +00:00
afb93eae22 D1.5: Revert broken TMEM round-trip O rescale, document as fundamentally broken
TMEM round-trip via Ld32x32bOp/St32x32bOp corrupts O accumulator data
even with CUTLASS correction_rescale pattern. All variants tested:
- Repetition(16) + composition (CUTLASS exact pattern) — BROKEN
- Repetition(32) + composition — BROKEN
- Repetition(16) raw layout (no composition) — BROKEN
Even NO-OP (multiply by 1.0) produces catastrophically wrong results.

Production path remains Python KV merge (cos 0.999998 for s_k up to 1024).
Next: SMEM accumulator approach (one-way TMEM→REGS→SMEM per kt).
2026-05-26 20:55:16 +00:00
42c5793add D1.5: Add isolated round-trip test comparing s_k=128 vs s_k=256 with NOOP rescale 2026-05-26 20:45:58 +00:00
e35b30dae6 D1.5 debug: try corr_tile_size=32 for O rescale round-trip 2026-05-26 20:43:29 +00:00
20ed6d5114 D1.5: Add TMEM load fence before PV with ACCUMULATE, revert debug rescale factor
The MMA warp needs fence_view_async_tmem_load() before PV[kt>0] to ensure
the rescaled O values are visible. NamedBarrier synchronizes warps but may
not guarantee TMEM visibility without an explicit fence.
2026-05-26 20:31:28 +00:00
34d64137ec D1.5 debug: force rescale_factor=0.5 to test if round-trip code executes 2026-05-26 20:29:34 +00:00
3be708d923 D1.5 debug: add NOOP rescale test (acc_scale=1.0) to isolate TMEM round-trip corruption 2026-05-26 20:28:55 +00:00
bf2c7c8bb8 D1.5: Implement in-kernel O rescale via CUTLASS correction_rescale pattern
- Both load and store atoms built from SAME tOtO_i (composition-tiled)
- Same Repetition(corr_tile_size=16) for both copies
- pv_done_bar synchronization between MMA and softmax warps
- acc_scale computed per kt iteration, used to rescale O in TMEM
- const_expr(n_kv_tiles > 1) guards for zero overhead at s_k=128
- New test: test_d15_in_kernel_rescale.py (s_k=128/256/384)
- Minimal roundtrip test: test_tmem_roundtrip_minimal.py
2026-05-26 20:26:06 +00:00
ffb3e736bb D1.5: Revert broken paired-atom O rescale — TMEM round-trip fundamentally broken
Ld32x32bOp and St32x32bOp have different column mappings at the hardware
level. No layout transformation can fix this — the atoms themselves map
TMEM columns differently.

The MoE correction epilogue avoids the problem by doing a ONE-WAY trip
(TMEM→REGS→SMEM→GMEM, never writes back to TMEM). FMHA needs O in TMEM
for PV accumulation between kt iterations, so one-way doesn't help.

Production path for multi-KV-tile: Python KV merge (already verified,
cos 0.999998 for s_k up to 1024). Run kernel per 128-token segment.

Future: restructure PV to accumulate into REGS/SMEM instead of TMEM,
enabling the one-way correction epilogue pattern.
2026-05-26 19:50:11 +00:00
43f0b5d1e8 D1.5: Fix O rescale with paired atoms (incremental approach)
Keep epilogue_tma_store for final output (proven path).
Only fix the multi-KV-tile O rescale using paired atoms from
epilogue_tmem_copy_and_partition. The paired atoms share addressing,
making the TMEM->REGS->modify->TMEM cycle lossless.

Guarded by const_expr(n_kv_tiles > 1) so single-tile path (n=128)
is completely unaffected — zero regression risk.

Full correction epilogue (one-way TMEM->REGS->SMEM->GMEM) deferred
until we can address the MLIR compilation time issue.
2026-05-26 19:34:26 +00:00
4bb0e063cc D1.5: Replace broken TMEM round-trip with correction epilogue (paired atoms)
Replace hand-constructed Ld32x32bOp/St32x32bOp TMEM round-trip with the
proven correction epilogue pattern from fused_swiglu.py:

1. O rescale (kt>0): TMEM→REGS (paired load), multiply by acc_scale,
   REGS→TMEM (paired store via retile_to_S). No layout mismatch.

2. Final O output: One-way TMEM→REGS→SMEM→GMEM using
   epilogue_tmem_copy_and_partition + epilogue_smem_copy_and_partition
   + TMA partition. Register-level normalization (divide by row_sum)
   or raw BF16 cast for D5a path.

This fixes both D1.5 issues:
- Issue 1: TMEM round-trip corruption (hand-constructed atoms)
- Issue 2: O rescale for multi-KV-tile (kt>0)

Supports normalize=True (in-kernel) and normalize=False (D5a external).
Uses epilog_sync_bar + c_pipe for SMEM→GMEM, replacing epilogue_tma_store.
2026-05-26 19:11:19 +00:00
e64392f1ac D5c: add apply_sink_bias flag (independent of n_comp)
For all-SWA segments (n_comp=0), sink bias still needs to be applied
to all positions. The apply_sink_bias flag controls compilation of
the sink bias code path, independent of n_comp offset.
2026-05-26 15:26:52 +00:00
8f7df4d8b5 fix: mRowSums dummy tensor must match mLSE layout (3D, not 1D) 2026-05-26 15:14:35 +00:00
016edbcc97 D5c: add row_sum output for proper external normalization
The kernel's O_unnorm is max-shifted (divided by 2^row_max), so
O_norm != O_unnorm * exp(-LSE). Instead, O_norm = O_unnorm / row_sum.
Added mRowSums output tensor to enable correct normalization.
2026-05-26 15:07:22 +00:00
014d647ba3 fix: sink bias domain correction — add attn_sink/scale to raw logits
The softmax scales by scale_log2 = scale * log2(e). Adding sink_val to
raw logits causes it to be scaled too. Fix: add sink_val/scale instead,
so after scaling: (sink_val/scale) * scale_log2 = sink_val * log2(e).
This correctly multiplies attention weights by exp(sink_val).
2026-05-26 15:03:49 +00:00
dbdbcecadc fix: sink_bias must be pre-converted to CuTe tensor before passing to compile 2026-05-26 15:02:43 +00:00
9d64434954 D5c: add sink bias (attn_sink) logit modification to FMHA kernel
- Add n_comp parameter: compressed KV length, sink bias applies to positions >= n_comp
- Add sink_bias parameter: per-head FP32 logit bias for SWA positions
- D3 mask updated: kv_pos >= n_comp + swa_len (backward compatible when n_comp=0)
- D4 causal mask updated: compare SWA-relative position (kv_pos - n_comp) with m_coord
- Mathematical insight: sink merge = single softmax over [S_comp, S_swa + attn_sink]
- Add test_d5c_fused.py with combined KV + sink bias test
2026-05-26 14:59:52 +00:00
6c73069cb9 D5b: Per-row LSE output + Python KV merge test
- Fix LSE output: all 128 rows now write (mLSE[sfw_idx, 0, 0])
  instead of only row 0 (mLSE[0])
- Each softmax thread (sfw_idx 0..127) independently writes its LSE
- This enables accurate Python-side KV merge for multi-KV-tile
- New test: test_d5b_perrow_lse.py with LSE verification + KV merge
2026-05-26 10:57:54 +00:00
e3e01071f4 fix: swa_len as Int32 scalar instead of CuTe tensor
CuTeDSL @cute.kernel cannot handle dynamic-shape tensors as parameters.
Pass swa_len as Int32 scalar instead of a 1D tensor.
This works for batch_size=1 (current config).
Updated D3 and D4 tests to pass swa_len as int.
2026-05-26 10:54:41 +00:00
df84420414 fix: add is_causal to FmhaKernel __init__ signature 2026-05-26 10:53:14 +00:00
841a3e87b2 D4: Causal mask on SWA branch
- Add is_causal flag to FmhaKernel constructor
- Mask positions where k_coord > m_coord to -inf (causal attention)
- Combined with D3 SWA mask: both conditions use OR logic
- Same tTMEM_LOADcS coordinate mapping as D3
- const_expr guarded: zero overhead when is_causal=False
- New test: test_d4_causal_mask.py with causal + combined masking
2026-05-26 10:52:30 +00:00
b6b581777a D3: In-kernel SWA sequence length masking
- Add apply_swa_mask flag to FmhaKernel constructor
- After TMEM load of S, use tTMEM_LOADcS coordinates to map register
  fragment positions to (row, col) in QK matrix
- Mask positions >= swa_lens[batch_idx] to -inf before softmax
- Supports multi-KV-tile (kt*128 + k_coord for absolute position)
- swa_lens parameter passed as CuTe tensor, indexed by block_idx_z
- Dummy tensor (max int) when swa_lens=None (no masking)
- New test: test_d3_inkernel_mask.py with proper in-kernel masking
- Replaces pre-masking approach (BF16 min on K) which can't produce -inf
2026-05-26 10:51:23 +00:00
d6a56342cc D3: add swa_lens parameter to FmhaKernel (in-kernel masking TBD) 2026-05-25 17:31:01 +00:00
f278348f44 D3: SWA mask with BF16 min pre-masking approach (K[invalid]=BF16_MIN → scores≈-inf) 2026-05-25 17:27:35 +00:00
dbe2ecbd41 D2: add num_query_heads/batch_size params + batch grid dimension
- Head-packed approach: Q is (n_h*T, hd, 1), kernel treats each row independently
- Grid: (1, 1, batch) — M dimension handled by head packing
- n_h=128, T=1 → M=128, one MMA tile, all heads in single CTA
- Tested: cos 0.999995 for both n_h=1 and n_h=128
2026-05-25 17:15:08 +00:00
13b5afc471 fully revert FmhaKernel changes to debug regression 2026-05-25 17:04:31 +00:00
0b9f9da2f7 revert grid change to debug regression 2026-05-25 17:03:19 +00:00
4826fa6afb D2: add num_query_heads/batch_size params + head-packed test
- FmhaKernel.__init__: add num_query_heads=1, batch_size=1
- Grid: (ceil_div(n_h*T, 128), 1, batch) for multi-CTA
- Test: head-packed multi-head (Q reshaped to (n_h*T, hd))
- n_h=1 regression, n_h=128 Pro decode, n_h=64 Flash, hd=128
2026-05-25 16:50:49 +00:00
d53e0a33a9 NVFP4-3: add use_2cta_instrs conditional to gemm_runner
- run_nvfp4_grouped_gemm: use_2cta = tokens_sum >= 256 and cluster_m even
- run_fused_swiglu_grouped_gemm: same conditional
- Auto-warms up on first use via lazy compilation cache
- 1.7-1.9× throughput at prefill shapes (M>=256)
- Decode (M<256) stays 1-CTA (correct, no waste)
2026-05-25 16:42:02 +00:00
5290c91c35 fix quantize_nvfp4 kernel: use proven single-thread-per-CTA pattern from deinterleave_quantize.cu
The warp shuffle approach failed because __shfl_down_sync with 16 threads
has undefined behavior for the odd nibble. Use the same pattern as the
working deinterleave_quantize.cu: 1 CTA per 16-element block, 16 threads
per CTA, each thread reads all 16 elements sequentially and computes
amax + quantize + pack.
2026-05-25 16:21:44 +00:00
c2e3d15633 NVFP4-1.1 integration: GPU-only quantize kernel + MoE pipeline wiring
- Add quantize_nvfp4.cu: BF16→FP4 GPU kernel (no CPU sync, warp shuffle amax)
- Add quantize_nvfp4_gpu() bridge in ops/quantize.py
- Fix deinterleave_quantize kernel path (dsv4/ops/kernels → dsv4/kernels/cuda)
- Wire GPU quantize into Nvfp4MoE._run_impl():
  - L1 input: quantize_nvfp4_gpu (replaces quantize_activation_nvfp4)
  - Fused SwiGLU L2: deinterleave_quantize_nvfp4_cuda (single kernel)
  - Non-fused L2: quantize_nvfp4_gpu
- Add test_nvfp4_gpu_quantize.py for both kernels
2026-05-25 16:19:07 +00:00
6cc151097e Revert D2 multi-CTA attempts - keeping per-head launch approach (works correctly) 2026-05-25 01:08:38 +00:00
34f5beb767 D2: fix gC coordinate to match 5-mode flat_divide result 2026-05-24 23:44:39 +00:00
a3559538cf D2: try 6-mode coordinate for flat_divide result 2026-05-24 23:43:23 +00:00
6f371d6b31 D2: add flat_divide shape print, try different coordinate order 2026-05-24 23:42:04 +00:00
7007a9db79 D2: use flat_divide for runtime coordinate indexing (like CUTLASS) 2026-05-24 23:40:37 +00:00
3e340a0eee D2: fix local_tile coordinate for 4D Q (2 rest modes, not 3) 2026-05-24 23:38:48 +00:00
b5cd1b88c9 D2: add shape debug print for mQ/mK 2026-05-24 23:37:10 +00:00
df3146eb53 D2: hardcode a_major=MN for multi-CTA (Q is always MN-major in FMHA) 2026-05-24 23:35:49 +00:00
e809e71253 D2: use tensor indexing q[0] instead of local_tile for layout extraction 2026-05-24 23:34:38 +00:00
49c4189195 D2: fix LayoutEnum for multi-dim Q (use head-0 view for layout) 2026-05-24 23:33:27 +00:00
2b76b691cb fix: block_idx() returns tuple, use [1] for y 2026-05-24 23:29:59 +00:00