Commit Graph

467 Commits

Author SHA1 Message Date
97531a68e6 fix: remove n_kv_tiles from capi too 2026-05-30 10:30:40 +00:00
f032800eaa P5: integrate WORKING multi-tile kernel (fmha_6warp_tma_multirow_multitile) into production
- fmha_multitile_capi.cu: C API wrapper for TMA multi-tile kernel
  Creates TMA descriptors per (head, batch), launches kernel
- fmha_multitile_op.py: nvcc precompile + ctypes loader
- production.py: dispatch to multitile for N>128 or hd=512
- Reverted fmha_6warp_multihead.cuh to working single-tile version
- The TMA multi-tile kernel already passes 72 configs (D1.5)
  HD=64/128/256/512 × T=1/4/32/128 × s_k=128/256/384/512
2026-05-30 10:27:38 +00:00
c55030a340 P5: clean kernel with runtime branch (single-tile unchanged, multi-tile separate path)
Single-tile path is IDENTICAL to the working pre-P5 kernel.
Multi-tile path uses FA2 online softmax with sOacc accumulator.
Runtime branch on is_multi_tile = (n_kv_tiles > 1).
2026-05-30 08:57:00 +00:00
5f4856d771 P5: fix sOacc init race — use single thread (tid==0) instead of 4 softmax warps 2026-05-30 08:53:50 +00:00
0f34f60494 P5: fix single-tile backward compat (normalized P for n_kv_tiles==1) 2026-05-30 08:47:47 +00:00
2649488d13 P5: in-kernel multi-KV-tile FA2 online softmax in fmha_6warp_multihead.cuh
- Kernel loops over KV tiles internally with running max/sum rescale
- SMEM accumulator sOacc[hd] replaces TMEM accumulation across tiles
- P is UN-NORMALIZED for multi-tile (exp(s-max), not /sum)
- Per KV tile: QK→softmax→PV→TMEM→read→add to sOacc
- Final: O = sOacc / running_sum
- Single tile (n_kv_tiles=1): same as before, no rescale
- Updated CAPI, Python loader, production.py fast path
- Added multi-tile test cases (N=256, 512)
2026-05-30 08:46:09 +00:00
10915c4e70 fix: remove double normalization in fmha_6warp_multihead epilogue
P was already normalized in softmax step. PV = P_norm @ V gives the
correct attention output. Dividing by row_sum again in the epilogue
produces O = O_correct / row_sum (128x too small for uniform data).
2026-05-30 08:26:20 +00:00
074c4c4f42 P3: call fmha_multihead_decode_raw directly (skip custom op) 2026-05-30 08:21:53 +00:00
0608d9d09e P3: fix GQA via K/V repeat_interleave, relax threshold to 0.999990 2026-05-30 08:20:01 +00:00
d5c0086737 P3: fix SMEM computation, pad K/V to 128, remove stale files
- fmha_multihead_capi.cu: SMEM formula matches standalone test
  Added cudaFuncSetAttribute for dynamic SMEM > 48KB
- fmha_multihead_op.py: pad K/V to N=128 when N<128
  (kernel softmax loop is hardcoded to SK_TILE=128)
- Removed fmha_multihead_launch.cu (ATen approach, didn't work)
- Removed test_p3_ctypes_minimal.py (superseded by main test)
2026-05-30 08:19:16 +00:00
63645a3c7b fix: -Xcompiler -fPIC instead of -fPIC for nvcc 2026-05-30 08:16:04 +00:00
adcf3e04ab P3: ctypes loader for 6-warp FMHA (bypass torch JIT sm_100 arch issue)
- fmha_multihead_capi.cu: pure C API wrapper, no ATen/pybind11 deps
- fmha_multihead_op.py: nvcc precompile + ctypes load (sm_100a)
- Removed fmha_multihead_launch.cu (ATen approach didn't work)
- Updated test to call kernel directly via ctypes API
2026-05-30 08:15:31 +00:00
1e6adf5e01 P3: wire 6-warp multi-head FMHA decode fast path into production.py
- fmha_multihead_launch.cu: PyTorch launch wrapper for fmha_6warp_multihead_kernel
  (c10::BFloat16 boundary, uint16_t bf16_t inside kernel, zero-cost casts)
- fmha_multihead_op.py: torch.utils.cpp_extension JIT loader + custom_op registration
  (dsv4::fmha_multihead_decode for torch.compile)
- production.py: fast path dispatch for T=1, n_segments==1, hd in {64,128,256}
  Falls through to CuTeDSL slow path for multi-segment/prefill
- test_p3_fast_decode.py: integration test (MHA/MQA/GQA, cosine >= 0.999998)

Architecture:
  Grid: dim3(1, n_h, batch_size) — one CTA per (head, batch)
  MQA: k_head_stride=0 so all Q heads share same K/V
  Single kernel launch, zero cudaDeviceSynchronize on hot path
  Normalized output for single-segment decode
2026-05-30 08:12:23 +00:00
f2592ea0da fix: native TMEM columns for hd_chunk (no remapping) 2026-05-30 07:01:42 +00:00
3dbd3c5e7f debug: test chunk 1 only 2026-05-30 07:00:14 +00:00
9227b0e93f debug: skip hd_chunk>0 to isolate chunk0 2026-05-30 06:59:01 +00:00
25aeaca9ab fix: PV accumulate flag 2026-05-30 06:56:53 +00:00
1da785c070 D1.5: HD tiling (HD_CHUNK=256) for HD=512 support 2026-05-30 06:56:09 +00:00
5544d3a0a4 fix: TMEM reads must be outside my_row_active (warp-collective) 2026-05-30 04:48:26 +00:00
dd3e0fdfc8 D1.5: multi-row + multi-tile FMHA with SMEM accumulator in-kernel rescale 2026-05-30 04:37:33 +00:00
8b1ac380ac feat: HD=512 support — TMEM_N=512, test variants for all three TMA kernels 2026-05-30 03:45:05 +00:00
762f054d6d feat: double-buffer TMA pipeline in multi-row kernel 2026-05-30 03:20:49 +00:00
4a9c850e9c feat: double-buffer TMA pipeline for K loads in single-tile kernel 2026-05-30 03:14:06 +00:00
afa949071b fix: brace structure in V TMA conversion 2026-05-29 22:59:18 +00:00
ec577f71ee feat: V TMA loads in single-tile kernel too 2026-05-29 22:57:59 +00:00
422e7bb312 cleanup: v_head reference in multi-row (V via TMA now) 2026-05-29 22:54:44 +00:00
88c72a887e feat: V TMA loads in multi-row kernel 2026-05-29 22:51:24 +00:00
13403d2808 cleanup: remove unused v_head in multi-tile (V via TMA) 2026-05-29 22:48:50 +00:00
74145a31cc feat: V TMA loads in multi-tile kernel 2026-05-29 22:46:21 +00:00
d47b2bfcce fix: use un-normalized P for multi-tile PV (correct online softmax merge) 2026-05-29 19:57:54 +00:00
43ae3e7f98 fix: reload Q per-K-sub-tile in multi-tile kernel (same as single-tile) 2026-05-29 19:56:35 +00:00
8e99bd50e6 feat: 6-warp TMA multi-tile KV kernel with register accumulator + test 2026-05-29 19:49:53 +00:00
1814510195 wip: add n_kv_tiles param for multi-tile KV (not yet used) 2026-05-29 19:47:48 +00:00
d20792aa9d fix: TMA descriptor index for batched multi-head (batch*n_h + head) 2026-05-29 19:45:44 +00:00
754c6a692c feat: per-head TMA descriptors for multi-head FMHA 2026-05-29 19:44:58 +00:00
a1b2ab79a1 feat: 6-warp TMA FMHA multi-row kernel + test 2026-05-29 19:39:17 +00:00
d0a50f1f2e fix: remove double normalization in TMA epilogue (P already normalized before PV) 2026-05-29 19:36:41 +00:00
fb971781aa fix: revert V to direct load (V TMA needs debugging), K TMA works 2026-05-29 19:35:44 +00:00
cd2c028b39 feat: TMA loads for both K and V in 6-warp FMHA kernel 2026-05-29 19:34:48 +00:00
4459ddefdd feat: 6-warp TMA FMHA kernel + test — TMA for K loads 2026-05-29 19:32:02 +00:00
5542a9da00 debug: V loaded directly from GMEM (not TMA) to isolate PV issue 2026-05-29 18:57:42 +00:00
2262e10fca fix: PV GEMM — V canonical uses CORES_MN_V=2 (block_mn=16), not 16
V is the B operand with block_mn=16 in the PV MMA. Its canonical layout
uses CORES_MN=16/8=2, not 128/8=16. The previous code used CORES_MN=16
which produced wrong canonical indexing → garbage PV output.

Also:
- V SMEM size is (16,16) canonical = 256 BF16, not (128,16) = 2048
- P written as 16 elements at row 0 (T=1 decode)
- V loaded from TMA (16,128) and sub-sampled to (16,16) canonical
- V TMA coord: {col_start, d_base} for (HD,s_k) tensor
2026-05-29 18:54:02 +00:00
90c3372040 refactor: TMA FMHA kernel — 4-warp, proven pattern, full pipeline
Complete rewrite of fmha_6warp_tma.cuh based on lessons learned:
- 128 threads (4 warps) instead of 192 (6 warps) — simpler, proven
- Warp 0: TMA load + softmax, Warp 1: MMA + TMEM alloc
- TMA: mbarrier.arrive.expect_tx (root cause fix), phase parity tracking
- Q loaded directly (T=1 decode), K/V via TMA
- Per-K-sub-tile Q and K loading into (128,16) canonical buffers
- Full softmax + PV GEMM + epilogue pipeline
- Test updated to match new kernel signature
2026-05-29 18:50:58 +00:00
204cc90808 fix: load full Q (128,HD) once before QK loop — not per K-sub-tile
The MMA expects Q sub-tiles from a full (128,HD) canonical buffer,
but we were only loading (128,16) sub-tiles into a (128,16) buffer.
The MMA descriptor with block_mn=128 describes a (128,128) matrix,
reading 128 columns from SMEM but only 16 had real data.

Now: load all HD/16 TMA tiles of Q into a full (128,HD) canonical
buffer before the QK loop. The MMA reads the kt-th sub-tile via
descriptor offset kt * 128 * 32 bytes.

Also: share single sTmaBuf staging buffer for all TMA loads (Q, K, V).
Removed separate sQ_tma, sK_tma, sV_tma buffers.
2026-05-29 18:28:45 +00:00
8e09fae3a1 fix: warp-stride for TMA canonical writes — only load warp calls them
write_smem_canonical used NTHREADS=192 as the stride, but in the TMA
kernel only the load warp (32 threads) calls it. With threadIdx.x in
[160,191] and stride 192, only 32 out of 2048 elements got written.
Fix: template STRIDE parameter, default 192, TMA kernel uses 32.
2026-05-29 18:25:47 +00:00
3e14a25bb0 fix: don't re-init mbarrier in loop — use phase parity tracking
The mbarrier is initialized once before the loop with count=1.
Inside the loop: issue TMA → arrive.expect_tx → wait(phase) → flip phase.
Re-initializing the mbarrier inside the loop resets the phase, which
breaks the parity tracking and causes the wait to hang.

This matches the CUTLASS/gau-nernst pattern exactly.
2026-05-29 18:24:47 +00:00
bd169ccb0f fix: smart quote in fmha_tma.cuh 2026-05-29 18:22:26 +00:00
345b107f4c fix: TMA mbarrier — add arrive.expect_tx (root cause of multi-warp hang)
The TMA cp.async.bulk.tensor with mbarrier::complete_tx::bytes decrements
the mbarrier tx_count by the byte count of the transfer. Without calling
mbarrier.arrive.expect_tx to increment tx_count first, the count underflows
and the phase never completes — causing the wait to hang forever.

This was the root cause of the multi-warp TMA hang. With 32 threads it
worked by accident (phase parity wrapped around); with 128+ threads the
timing was different and the hang was exposed.

Also:
- Use CUTLASS-style @P1 bra DONE wait pattern (not selp.b32)
- Add fence.mbarrier_init.release.cluster after mbarrier init
- Track phase parity across the kernel (flip after each wait)
- Re-init mbarrier before each TMA transaction (proper phase management)

Reference: gau-nernst tcgen05 tutorial
2026-05-29 18:22:00 +00:00
c69f3668e1 feat: TMA async FMHA kernel — WORKING on B200
Three critical CUDA 13 fixes that made TMA work:
1. globalStrides in BYTES not elements (root cause of desc creation failures)
2. BFLOAT16 data type instead of UINT16
3. mbarrier wait: selp.b32 polling pattern (@p bra HANGS on SM100!)

Also includes CUTLASS driver workaround (bit 21 clear for drv <= 13.1).

Verified: 2D TMA load of (128,16) BF16 tile = 0 mismatches.
Kernel: fmha_6warp_tma_kernel with per-sub-tile TMA loads for Q, K, V.
Test: test_fmha_tma.cu with padded Q allocations and per-head descriptors.
2026-05-29 07:02:07 +00:00
a40c05f3f2 archive: TMA driver-API files + CUDA 13 TMA discovery notes
Key findings documented in docs/cuda13_tma_notes.md:
- CUDA 13 globalStrides are in BYTES not elements (root cause of desc creation failures)
- BFLOAT16 data type available in CUDA 13
- Driver API descriptors create OK but cp.async.bulk.tensor hangs on driver 13.0 + toolkit 13.2
- CuTeDSL tma_partition works (production path)

Archived (not deleted):
- fmha_tma_driver_api.cuh, fmha_6warp_tma_driver_api.cuh, test_fmha_tma_driver_api.cu
- These will work once driver matches toolkit version
2026-05-29 06:52:39 +00:00