# grouped-moe-gemv FlashRT native CUDA grouped expert projection kernels for Blackwell decode and small verify batches. Version 2 adds W4A4 with device-side top-k routing while preserving the version 1 W4A16 APIs. ## Hardware Backends - SM110 (Jetson AGX Thor): W4A16 decode and grouped expert GEMV use the FlashRT edge backend validated by FlashRT PR #169. This target is compiled independently with `FLASHRT_W4A16_EDGE_UNROLL=2`; the SM120 value remains 4. - SM120/SM121: W4A16 and block-scaled-MMA W4A4 paths are available. - W4A4 is intentionally rejected on SM110 because that implementation uses the SM120 block-scaled MMA path. It never silently falls back or launches an incompatible cubin. ## Functions - `w4a16_decode_gemv_bf16(x_bf16, weight_packed, sfb, alpha=1.0, out=None)` - `grouped_w4a16_gemv_bf16(activations, weight_stack, sfb_stack, alpha_stack, expert_idx, n, w_stride=None, sfb_stride=None, out=None)` - `quantize_activations_nvfp4_bf16(activations, packed=None, sfa=None)` - `quantize_weights_nvfp4_bf16(weights, packed=None, sfb=None)` - `grouped_w4a4_gemv_bf16(activations_packed, weight_stack, sfa, sfb_stack, alpha_stack, expert_idx, out=None)` - `grouped_w4a4_gemv_from_bf16(activations, weight_stack, sfb_stack, alpha_stack, expert_idx, packed=None, sfa=None, out=None)` The grouped API runs one BF16-activation x NVFP4-weight GEMV per routed slot. It is intended for static routed expert batches where the caller already owns packed weights and swizzled scale-factor buffers. On SM120/SM121, the W4A4 API accepts packed activations `[M,K/2]`, expert weights `[E,N,K/2]`, and a contiguous device routing tensor `[M,top_k]`. It emits `[M,top_k,N]` in one grouped compute launch. For down projections with a different activation per routed pair, flatten to `M=routed_pairs, top_k=1`. `K` must be divisible by 16 and `N` by 8. Target `K%64==0` shapes use tuned SM120 paths; the remaining `K%16` shapes use a fixed-order SIMT contract path. No atomics, host synchronization, or dynamic workspace are used by the native ops. Pass `packed`, `sfa`, and `out` buffers to the composed helper for allocation-free CUDA Graph capture. ## Example ```python from kernels import get_kernel import torch try: moe = get_kernel( "flashrt/grouped-moe-gemv", version=2, trust_remote_code=True ) except TypeError: # kernels==0.12.x compatibility moe = get_kernel("flashrt/grouped-moe-gemv", version=2) M, TOP_K, E, N, K = 7, 8, 8, 1024, 2048 x = torch.randn(M, K, device="cuda", dtype=torch.bfloat16) expert_idx = torch.randint(E, (M, TOP_K), device="cuda", dtype=torch.int32) def sf_bytes(rows, dim): return ((rows + 127) // 128) * (((dim // 16) + 3) // 4) * 512 # Do this once while loading the checkpoint, not in the inference hot path. weights_bf16 = torch.randn(E, N, K, device="cuda", dtype=torch.bfloat16) weights_packed = torch.empty(E, N, K // 2, device="cuda", dtype=torch.uint8) weight_sfs = torch.empty(E, sf_bytes(N, K), device="cuda", dtype=torch.uint8) for expert in range(E): moe.quantize_weights_nvfp4_bf16( weights_bf16[expert], packed=weights_packed[expert], sfb=weight_sfs[expert], ) weight_alpha = torch.ones(E, device="cuda", dtype=torch.float32) packed = torch.empty(M, K // 2, device="cuda", dtype=torch.uint8) sfa = torch.empty(sf_bytes(M, K), device="cuda", dtype=torch.uint8) out = torch.empty(M, TOP_K, N, device="cuda", dtype=torch.bfloat16) y = moe.grouped_w4a4_gemv_from_bf16( x, weights_packed, weight_sfs, weight_alpha, expert_idx, packed=packed, sfa=sfa, out=out, ) ``` The example buffers may be larger than the minimum; wrappers validate storage. For production code, derive SF sizes from the checkpoint packer metadata. ## Dispatch guidance Use the built-artifact benchmark to dispatch rather than selecting only by dtype. On the tested cu128 artifact W4A16 wins gate-up, W4A4 wins down verify, and down decode is effectively tied kernel-only. A fused/upstream FP4 producer removes the standalone quantization charge, but callers still should not assume lower precision is automatically faster. ## Validation ```bash python grouped-moe-gemv/tests/test_grouped_moe_gemv.py --backend source --mode full python grouped-moe-gemv/benchmarks/benchmark.py --backend source ```