Files
nvfp4-megamoe-kernel/MAY_24_26_PLAN.md

5.2 KiB
Raw Blame History

May 24, 2026 — Session Start Plan

Quick Context

You're working on the DSV4 (DeepSeek V4 Pro) NVFP4 inference kernel for Blackwell B200. The FMHA (Fused Multi-Head Attention) kernel is working at hd=64/128/256 (cos 0.999998). The next milestones are: fix O rescale for multi-KV-tile, add multi-head grid (D2), and verify NVFP4 primitives.

B200: See MEMORY.md for access (not committed to repo) Repo: git@sweetapi.com:2222/biondizzle/nvfp4-megamoe-kernel.git Local: ~/dev/nvfp4-megamoe-kernel Test command: ~/.openclaw/workspace/fire_b200_test <test_file>

Execute in This Order

1. NVFP4-0: Verify FP4 Primitives (20 min, NO CODE CHANGES)

These are print-only diagnostics. If any reveal a wrong dtype, stop and fix it before everything else.

  • NVFP4-0.1 — Trace sf_dtype through gemm_runner.pydense.pyblockscaled_utils. NVFP4 uses FP8 E4M3 scales (NOT UE8M0 which is MXFP4). If the runner is passing E8M0, every FP4 GEMM is wrong.
  • NVFP4-0.2 — Verify SF TMEM layout is UE4M3 packed (4 FP8 E4M3 per int32), NOT UE8M0 (MXFP8).
  • NVFP4-0.3 — Verify float4_e2m1fn_x2 survives into TMA descriptors (not downcast to uint8).
  • NVFP4-0.4 — Verify tcgen05 MMA kind resolves to NVFP4 (16-element blocks, E4M3 scales), not MXFP4 (32-element, UE8M0).

How: Add print() calls in the Python layer, run any FP4 GEMM test, check output. Remove prints after.

2. Test O Rescale at s_k > 128 (30 min)

The problem: The O rescale code (for multi-KV-tile, kt>0) is guarded away with const_expr(n_kv_tiles > 1) at n=128. It uses hand-constructed TMEM atoms. Untested and likely broken.

Why it matters NOW: DSV4 Pro uses top_k=1024 → s_k=1024 → n_kv_tiles=8. D2 multi-head will exercise s_k>128. If rescale is broken, all D2 production tests fail.

How to test:

  1. Create test_d1_multi_kv.py with FmhaKernel(head_dim=64, s_k=256, normalize=False) (2 KV tiles)
  2. Run it on B200
  3. If cos < 0.99, O rescale is broken → fix before D2
  4. If cos ~0.999, rescale works → proceed to D2

If broken, fix approach: Replace hand-constructed TMEM round-trip with CUTLASS correction_rescale_and_partition pattern (one-way TMEM→SMEM). See STAGE_D.md D1.5 Issue 2.

3. Start D2: Multi-Query Grid (main work)

See STAGE_D2.md for the full plan. Summary:

  • Add num_query_heads to FmhaKernel constructor
  • Change grid from (1,1,1) to (ceil_div(T, 128), num_query_heads, batch)
  • Map block_idx(m_tile, head_idx, batch_idx) inside kernel
  • Q TMA indexed per-head, K/V shared (MQA)
  • Test with n_h=2 → n_h=8 → n_h=64/128

First step: Create test_d2_multihead.py with n_h=1 regression test (verify nothing breaks), then n_h=2.

4. NVFP4-3: use_2cta_instrs Conditional (30 min, parallel)

Pure perf win for MoE GEMMs. Add use_2cta_instrs = (M >= 256 and cluster_m % 2 == 0) in gemm_runner.py. 1.71.9× throughput at prefill shapes. No FMHA dependency.

5. NVFP4-1.1: Fuse FP4 into SwiGLU Epilogue (1 day, parallel)

Biggest bandwidth win. Current: L1 GEMM → SwiGLU → BF16 GMEM → quantize → FP4 GMEM → L2 GEMM. Target: L1 GEMM → SwiGLU → FP4 pack in registers → FP4 GMEM → L2 GEMM. Saves entire quantize kernel launch + 2× bandwidth. See STAGE_D.md for full spec.


File Map (what to read for context)

File What it contains
STAGE_D.md Full FMHA kernel status, NVFP4 precision roadmap, D1.5 gaps
STAGE_D2.md D2 multi-query grid plan with 9-item to-do list
README.md Architecture, CuTeDSL constraints (#1#16), test harness docs
dsv4/kernels/attention/fmha.py The FMHA kernel (518 lines, FmhaKernel class)
dsv4/model/config.py DSV4 dimensions: Flash n_h=64, Pro n_h=128, hd=512
dsv4/ops/decode_sparse.py Sink merge formula, MQA op interface
MEMORY.md Long-term memory (B200 access, all stage results)
memory/2026-05-24.md Today's daily log (hd=512 SMEM fix, MLIR hang, all bug fixes)

Key Numbers

Config n_h top_k s_k n_kv_tiles O rescale needed?
Flash decode 64 512 512 4 YES
Pro decode 128 1024 1024 8 YES
Current test 1 128 1 No (guarded away)

D1 Status Summary

  • hd=64/128/256: cos 0.999998, LSE err 0.0
  • hd=512: SMEM fits (192KB) but MLIR compilation hangs (3+ hours). External k_sub merge mathematically impossible. Need either: (a) pre-compile offline, (b) no-softmax mode for S accumulation, or (c) raw CUDA C++ kernel.
  • ⚠️ O rescale (kt>0): untested for s_k>128, likely broken
  • D5a (un-normalized O + LSE): done
  • D5b (Python sink merge): done, cos 0.961

Rules (don't forget)

  • NEVER edit on B200. Edit locally → commit → push → pull → test.
  • ALWAYS use fire_b200_test or run_test.sh. Never raw SSH+nohup.
  • ALWAYS verify hd=64 regression (cos ~0.999998) after every change.
  • Guard dead code with const_expr(). CuTeDSL compiles both branches.
  • CuTeDSL if blocks create separate MLIR regions — variables NOT visible across blocks.
  • After every P store to TMEM, call cute.arch.fence_view_async_tmem_store().
  • NOHUP DOES NOT WORK on B200. Screen sessions survive SSH drops.