""" FMHA D2: Multi-CTA grid with flat_divide + tma_partition inside kernel. Proper Blackwell approach following CUTLASS reference pattern: - Q/K/V/O tensors with embedded head dimensions: (s, d, ((h_r, h_k), batch)) - flat_divide + tma_partition inside warp blocks (runtime block_idx) - Direct TMA bulk copy for O output (not epilogue_tma_store) - Grid: (M_tiles, h_q, batch) — one CTA per (M-tile, head, batch) triple DSV4 is MQA: h_r = num_query_heads, h_k = 1, K/V shared. """ import torch, math import cutlass.cute as cute import cutlass.torch as ct import cuda.bindings.driver as cuda from dsv4.kernels.attention.fmha import FmhaKernel def reference_attention(q, k, v, scale): """FP32 reference attention. q: (batch, n_h, T, hd), k/v: (batch, s_k, hd)""" qf = q.float() kf = k.float() vf = v.float() batch, n_h, T, hd = q.shape s_k = k.shape[1] ref = torch.zeros_like(qf) for b in range(batch): for h in range(n_h): attn = qf[b, h] @ kf[b].T * scale attn_max = attn.max(dim=-1, keepdim=True)[0] attn_exp = torch.exp(attn - attn_max) attn_sum = attn_exp.sum(dim=-1, keepdim=True) ref[b, h] = (attn_exp / attn_sum) @ vf[b] return ref def test_multicta(hd=64, n_h=1, batch=1, T=128, s_k=128): """Test multi-CTA grid FMHA with n_h query heads (MQA).""" torch.manual_seed(42) scale = 1.0 / math.sqrt(hd) q = torch.randn(batch, n_h, T, hd, dtype=torch.bfloat16, device='cuda') k = torch.randn(batch, s_k, hd, dtype=torch.bfloat16, device='cuda') v = torch.randn(batch, s_k, hd, dtype=torch.bfloat16, device='cuda') o = torch.zeros(batch, n_h, T, hd, dtype=torch.bfloat16, device='cuda') lse = torch.zeros(batch, n_h, T, dtype=torch.float32, device='cuda') # FP32 reference ref = reference_attention(q, k, v, scale) # Run kernel with multi-CTA grid kernel = FmhaKernel( head_dim=hd, s_k=s_k, num_query_heads=n_h, batch_size=batch, use_smem_p=(hd > 64), normalize=True, ) stream = cuda.CUstream(torch.cuda.current_stream().cuda_stream) kernel(q, k, v, o, stream, lse=lse) torch.cuda.synchronize() cos = torch.nn.functional.cosine_similarity( o.flatten().float().unsqueeze(0), ref.flatten().unsqueeze(0) ).item() status = "PASS" if cos >= 0.99 else "FAIL" print(f' hd={hd}, n_h={n_h}, batch={batch}, T={T}, s_k={s_k}: cos {cos:.6f} {status}') return cos >= 0.99 def test(): print("=== D2: Multi-CTA Grid (flat_divide approach) ===\n") all_pass = True # n_h=1 regression (should match existing single-head behavior) all_pass &= test_multicta(64, 1, 1, 128, 128) # n_h=2, single batch all_pass &= test_multicta(64, 2, 1, 128, 128) # n_h=4, batch=2 all_pass &= test_multicta(64, 4, 2, 128, 128) # n_h=8 all_pass &= test_multicta(64, 8, 1, 128, 128) print(f'\nOverall: {"ALL PASS" if all_pass else "SOME FAILED"}') if __name__ == '__main__': test()