Commit Graph

16 Commits

Author SHA1 Message Date
56dff8d185 fix: W_gate is (H, E) but F.linear expects (E, H), transpose before linear 2026-05-31 23:55:16 +00:00
5396a04c28 router: broaden except to catch all CuTeDSL errors, fall through to cuBLAS+activation_topk path 2026-05-31 23:54:16 +00:00
3b5b9f487c fix: compute num_tma_load_bytes inside cute.compile context 2026-05-31 23:53:13 +00:00
1bc0da0f35 fix: properly scope swap code inside else/guard blocks, replace continue with if guard 2026-05-31 23:51:43 +00:00
d0d765e1f2 fix: replace break statements with flag-based loops in router kernel (CuTeDSL restriction) 2026-05-31 23:50:39 +00:00
210391e571 fix: PersistentTileSchedulerParams constructor takes (problem_shape, cluster_shape) not from_shape 2026-05-31 23:49:12 +00:00
824d054ad7 fix: inside cute.compile args are already CuTe tensors, no conversion needed 2026-05-31 23:47:33 +00:00
6375e54396 fix: use from_dlpack + mark_layout_dynamic instead of non-existent to_cuTe_tensor in router 2026-05-31 23:46:35 +00:00
cb2ca8591f fix: add @cute.jit to router compiled function 2026-05-31 23:44:53 +00:00
d5d2b7b4b8 fix: defer router MMA/TMA setup into cute.compile context (matches MoE pattern) 2026-05-31 23:44:00 +00:00
157f1c5258 fix: use OperandMajorMode from nvgpu (not deprecated tcgen05) and mma_tiler_mn in router kernel 2026-05-31 23:39:50 +00:00
1dbc57e2cd fix: use mma_tiler_mn in _create_tiled_mma (attribute exists at init time) 2026-05-31 23:36:01 +00:00
d05dd50bf5 fix: OperandMajorMode.K not MAJOR_K (correct CuTeDSL API) 2026-05-31 23:34:54 +00:00
0d06e55770 Router: Blackwell-native fused decode kernel — real CuTeDSL implementation
DenseRouterDecodeKernel: BF16 GEMM + sqrt(softplus) + bias + top-k
in a single kernel launch on Blackwell SM100.

Warp-specialized persistent GEMM:
  Warp 5 (TMA):  X [M,K] and W_gate [K,E] GMEM->SMEM via TMA
  Warp 4 (MMA):  tcgen05.mma BF16, FP32 accumulator -> TMEM
  Warps 0-3 (EPI): TMEM->register (tcgen05.ld), activation, top-k, store

Key design decisions:
- No EFC framework: our epilogue is a ROW-LEVEL top-k reduction,
  not a per-element transformation. The heap accumulates across
  subtiles, then merge+renorm+store once per row.
- Per-thread register heap: 6 entries (score, index, unbiased act)
  as CuTeDSL scalars (not Python lists — those dont compile to registers)
- Shared memory merge: 128 threads dump heaps, thread 0 merges final top-6
- Identity tensor for expert index: maps register position -> global e_idx
- Numerically stable softplus: max(x,0) + log(1+exp(-|x|)) in FP32

dense_router_decode.py now dispatches to this kernel for N<=64,
falls back to activation_topk.cu for N>64.

This is a real Blackwell kernel. No pass statements. No fake code.
2026-05-21 22:04:20 +00:00
9c39f48443 Router: clean up dense_router_decode.py — realistic architecture, no fake code
The first draft had a fake CuTeDSL kernel body with pass statements and
Python lists as register heaps. That is not the right way. This commit
replaces it with honest documentation of what the kernel does and what
needs to happen.

Current working path:
- All N routes through torch.nn.functional.linear + activation_topk.cu
- activation_topk is a single-pass fused CUDA kernel (all 6 steps)
- This is correct and performant for all N

CuTeDSL fused decode kernel (DenseRouterDecodeKernel):
- Class structure and warp specialization defined
- Full documentation of the TMA/MMA/epilogue pipeline
- The novel part is the row-level top-k epilogue (cross-subtile heap)
- EFC framework does not apply — our epilogue is not per-element
- Implementation deferred until profiling shows the GMEM round-trip
  on logits matters for decode latency

No fake code. No pass statements. No Python lists as GPU registers.
The working path is the activation_topk kernel. The CuTeDSL kernel
will be built on top of it when the optimization is needed.
2026-05-21 21:58:31 +00:00
abfe4485f7 Router: full kernel stack — hash, topk, activation+topk, dense decode/prefill
Step 1: Hash router (hash_router.cu)
- One thread per token, gather from [vocab_size, k] LUT
- Uniform 1/k weights, FP32 output
- 3 MB LUT fits in L2 for repeated decode calls

Step 2: topk_select.cu — general top-k primitive
- Per-thread register min-heap (k=6, compile-time unrolled)
- Shared memory merge: thread 0 merges 64 partial heaps
- Tie-breaking: lower index wins on equal scores
- Reusable by CSA indexer

Step 3: activation_topk.cu — fused sqrt(softplus) + bias + topk + renorm
- Single kernel: all 6 steps of the router math, no intermediate buffers
- Numerically stable softplus: max(x,0) + log1p(exp(-|x|))
- Per-thread heap with unbiased activation co-stored
- Shared memory merge → sort descending → renormalize → store

Step 4: dense_router_decode.py — CuTeDSL fused GEMM kernel (skeleton)
- BF16 GEMM with tcgen05.mma, FP32 accumulator
- Custom epilogue: activation + bias + top-k (structure defined, needs TMA/MMA boilerplate)
- Dispatch: N<=64 uses fused decode, N>64 uses prefill path

Step 5: dense_router_prefill.py — prefill path
- torch.nn.functional.linear for GEMM (DeepGEMM integration deferred)
- Calls activation_topk for fused post-GEMM processing

Step 6: Router class + ops/router.py + test_router.py
- Router: construction-time mode (dense/hash), weight loading, custom_op dispatch
- ops/router.py: torch.library.custom_op wrappers, integer-keyed registry
- test_router.py: spec oracle tests (DO NOT RUN — Carmine is testing Stage C)

Test strategy: each kernel tested against its mathematical spec in FP32.
No reference implementation, no two debug streams. The oracle IS the math.
2026-05-21 21:54:05 +00:00