feat(moe): rp-native Triton tiny-decode path for b12x w4a8_mx (M=1) — DS4 A8 decode 133.7 → 138.7 tok/s - #70
Conversation
Two Triton kernels (FC1+SiLU staged in fp32 gmem, FC2 with router-weighted fp32-atomic scatter) that read the b12x N256/K128 in-place-repacked FP4 expert weights and e8m0 sfb grids directly via their verified inverse bit mappings (b12x tests/test_w4a8_rp_inverse_mapping.py), with BF16 activations (no input quantization) and fp32 accumulation. Numerics: cos vs fp32 oracle 0.999999 (better than the w4a8 dynamic kernel's 0.9990, which quantizes activations); cos vs the dynamic kernel 0.999. Isolated graph-replay at DS4-Flash TP2 shapes (E=256 K=4096 N=1024 topk=6): 28.7 us/layer at M=1 vs 34.8 us for the dynamic grouped kernel (plus ~3 us of wrapper fills/copies this path also bypasses). Enabled via VLLM_B12X_W4A8_MX_TINY_DECODE=1; engages only for quant_mode=w4a8_mx, silu, w31 layout, M==1, shape multiples of 256; everything else falls through to the b12x dynamic path. First E2E serve measured 138.7 tok/s DS4 TP2 A8 decode cc1 (from 133.7 baseline); a restart-to-restart variance question is still open (see rtx6kpro wiki). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sem='relaxed' on the fp32 atomic_add scatters read neutral in the isolated graph-replay microbench (28.7 vs 28.8 us/layer, L2-warm identical routing) but cost ~7% E2E decode in real serving (131.0-131.3 vs 138.7-138.8 tok/s, DS4 TP2 A8 cc1). Default semantics restored; E2E reproducible at 138.7+. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ 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 |
|
Superseded per Luke's feedback by the b12x-native CuTe DSL version: local-inference-lab/b12x#22 — same design, integrated into the normal b12x kernel selection ( |
What
New
b12x_tiny_decode.py: two Triton kernels +maybe_run_tiny_w4a8mx_moe, hooked at the top of_run_b12x_moe_fp4. At M=1 withquant_mode=w4a8_mx(silu, w31 layout, shape multiples of 256) it replaces the b12x dynamic grouped kernel; everything else falls through unchanged. Env-gated, default off:VLLM_B12X_W4A8_MX_TINY_DECODE=1.The kernels read the N256/K128 in-place-repacked FP4 weights and e8m0 sfb grids directly via the verified inverse bit mappings (b12x PR local-inference-lab/b12x#21,
tests/test_w4a8_rp_inverse_mapping.py) — zero extra weight memory. Activations stay BF16 (no input quant), accumulation fp32: FC1+SiLU staged in a 48 KB fp32 scratch, FC2 scatters router-weighted fp32 atomics.Stacked on #69 (retarget to
dev/eldritch-enlightenmentafter it merges).Why
The whole DS4 A8-vs-A16 decode gap (~130 vs ~140 tok/s) is the MoE at M=1: w4a8_mx tiny decode is hard-wired to the dynamic kernel (34.8 µs/layer) because the in-place repack blocks the fused path (22.5 µs). All config/env knobs around it are falsified — full analysis in b12x-dense-fp8-gemm-vs-deepgemm.md §6.8.
Measured
voipmonitor/vllm:eldritch-enlightenment-v8e6e417c-b12x77bd50e-tinymoe-overlay-cu132-20260702.Notes for review
sem='relaxed'on the atomic scatters: isolated-neutral but −7 % E2E (131.3). PDL overlap (gdc_wait/launch_dependents) measured the same −7 % and is deliberately absent. Both documented in the kernel wiki page with the full optimization journey (flat-load vectorization is the load-pattern that matters; num_stages/num_warps traps listed).🤖 Generated with Claude Code