feat(moe): rp-native tiny-decode kernel for w4a8_mx (M=1) — A8 decode reaches A16 parity - #22
Conversation
… reaches A16 parity New MoETinyRpKernelBackend (CuTe DSL, micro-family style): two plain launches (FC1 -> fp32 intermediate, FC2 with inline SiLU and router-weighted bf16x2 scatter-add) that read the N256/K128 in-place-repacked FP4 weights and e8m0 sfb grids directly via their verified inverse bit mappings (tests/test_w4a8_rp_inverse_mapping.py), with BF16 activations (no input quantization) and f32 accumulation. Core of the layout story: thread (n8c, r8, cgrp) issues one 16B v4 load per k32 covering the four 8-apart logical rows of an rp word quad, so warps read fully coalesced 512B runs and a 4-lane butterfly folds k. fp4_dot4 hardware decode does the math in f16 pairs (same numerics class as the w4a16 kernel). Integration: w4a8_mx tiny band resolves to the compact workspace family when B12X_W4A8_TINY_RP=1 (default off) and dispatches to the new kernel; weight views flat-view the rp storage (never re-flip halves in place). Two new fp4 primitives: red_add_global_f32, cvt_bf16x2_to_f16x2. Measured (DS4-Flash TP2, E=256 K=4096 N=1024 topk=6, RTX PRO 6000): - isolated full b12x_moe_fp4 graph at M=1: 20.6 us/layer (dynamic path 37.8, w4a16 fused 22.5); cos vs fp32 oracle 0.999980 (dynamic: 0.9990) - E2E serve decode cc1: 133.7 -> 140.2 tok/s, matching the A16 reference (140.5) while keeping the A8 prefill advantage (128k prefill unchanged) - a first cooperative single-launch variant deadlocked under TP2 serving (grid-barrier co-residency); the landed two-launch form has no co-residency assumptions and no barrier state at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughAdds two PTX helper intrinsics (global FP32 reduction, BF16x2→F16x2 conversion), a new CUTLASS/CUTE-backed ChangesTiny-RP W4A8-MX decode path
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant LaunchMicro as _launch_micro
participant Op as tp_moe_tiny_rp_launch (custom op)
participant FlatWrapper as _launch_tiny_rp_flat
participant Backend as MoETinyRpKernelBackend
participant Inter as inter_fp32 buffer
participant Out as output tensor
LaunchMicro->>LaunchMicro: check w4a8_mx + tiny_rp enabled/supported
LaunchMicro->>Op: invoke with weight pointers, ids, barriers
Op->>FlatWrapper: dispatch launch
FlatWrapper->>Backend: MoETinyRpKernelBackend.launch(...)
Backend->>Inter: zero + write FC1 router-weighted partials
Backend->>Out: zero + FC2 scatter_add bf16 results
Backend-->>LaunchMicro: kernel execution complete
Compact metadata
Poem ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Done in |
Per your feedback on the vLLM-side attempt (local-inference-lab/vllm#70): here's the tiny-decode band as a b12x CuTe DSL kernel integrated into the normal kernel selection — no vLLM changes needed at all.
What
b12x/moe/fused/tiny_rp.py—MoETinyRpKernelBackend, micro-family style, two plain launches:ld.global.nc.v4per k32 covering the four 8-apart logical rows of an rp word quad → warps read fully coalesced 512 B runs of the N256/K128 in-place-repacked storage directly (inverse mappings fromtests/test_w4a8_rp_inverse_mapping.py); a 4-lane butterfly folds k.fp4_dot4hardware decode (f16-pair math, same numerics class as w4a16), router-weightedscatter_add_bf16x2epilogue straight into the bf16 output.Activations stay BF16 (no input quantization — at M=1 they're 8 KB; skipping the MXFP8 quant removes work and beats the dynamic path's numerics: cos vs fp32 oracle 0.999980 vs 0.9990).
Integration:
_resolve_workspace_layoutroutes the w4a8_mx tiny band to the compact family whenB12X_W4A8_TINY_RP=1(default off);_launch_microdispatches to the new kernel;_get_weight_viewsflat-views rp storage (and never re-flips halves in place). Two new fp4 primitives:red_add_global_f32,cvt_bf16x2_to_f16x2.Measured (DS4-Flash TP2 shapes, RTX PRO 6000)
b12x_moe_fp4graph)E2E serve (hybrid DG-linear base): decode cc1 133.7 → 140.2 tok/s, i.e. A8 now matches the A16 reference (140.5, ITL 7.131 vs 7.136 ms) while keeping the A8 prefill advantage (128k prefill unchanged, 12.1k tok/s; 30k coherence clean, CJK 0).
Notes
configure()accepts m≤4 for future batched-decode experiments.Builds on #21 (the verified inverse-mapping test this kernel consumes).
🤖 Generated with Claude Code
Summary by CodeRabbit