Repository navigation
perf(kernel): avoid layout conversions in nvfp4 marlin decode - #631
Merged
Merged
Conversation
This was referenced Oct 8, 2026
pretor
pushed a commit
to pretor/FreeToken
that referenced
this pull request
Oct 8, 2026
This was referenced Oct 8, 2026
KarrAcaRn
pushed a commit
to KarrAcaRn/FreeToken-ByAI
that referenced
this pull request
Oct 9, 2026
Upstream's kernel perf PRs overlap our own FP4/KV work: - mxfp4 split-K GEMV (FlashML-org#653): keep upstream's column-pair int16 reads, decode the codes with our bit-placement e2m1_code_f32 instead of the LUT. - nvfp4 Marlin decode (FlashML-org#631): take upstream's kernel body (same fp16 bit trick plus register-layout and wide activation loads); import both _nvfp4_pair_f16 and _nvfp4_pair_f32. - Triton extend attention (FlashML-org#632): keep upstream's mask-free tile ranges and exp2 math; quantized KV caches (fp8 codes with per-token scales, nvfp4) go through the new _extend_attend_kv_quant_tile inside the same loops, bf16 stays on upstream's _extend_attend_tile. Decode keeps our per-kv-head grid (group % VALID_BLOCK_H != 0) plus upstream's 64-key sliding-window tiles. - CUDA JIT (FlashML-org#638, FlashML-org#134): upstream's sm_90/ROCm PDL guards and kDLROCM device matchers, with our MSVC-safe __forceinline__ and .template spellings. - docs/install_amd.md: keep both ROCm sections. Not GPU-tested (no GPU on the box); CPU test runs were unreliable on the current unstable host. Assisted-by: Claude Opus 5.5
trcwebdesign
pushed a commit
to trcwebdesign/FreeToken
that referenced
this pull request
Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #629: fixes the Triton 3.8 slowdown of the NVFP4 MoE decode GEMV.
Call path:
TritonNvfp4MoEKernel.apply(decode) ->fused_experts_decode_nvfp4_marlin->_decode_gemm_marlin->_decode_nvfp4_marlin_kernel, once for gate_up and once for down. Prefill, the activation kernel and the sum-reduce are unchanged. "Marlin" here is the name of FreeToken's Triton GEMV (int32 wide loads, deferred K reduction), not vLLM's Marlin backend.On Triton 3.8 the K loop of
_decode_nvfp4_marlin_kernelcompiles with 14convert_layoutops and 2 KB of shared memory, against 1 and 32 B on 3.6 (default tile; the same change shows up on sm_80, sm_86, sm_89, sm_90, sm_100 and sm_120 in a compile-only check).Changes:
tl.interleave; the e2m1 codes are decoded with the existing_nvfp4_pair_f32fromnvfp4_linearinstead of a LUT gather; with contiguous, 16-byte-aligned bf16/fp16 activations, the 8 activations of a word are read as two int64 values and unpacked. Other activations keep the per-element loads.With the change the loop compiles to 1
convert_layoutand 16 to 32 B of shared memory on all six targets under both Triton versions, with no spills.Kernel time
µs,
triton.testing.do_bench_cudagraph, best of two medians, cold weights over 8 rotating routings, GPU used by the benchmark only. old =main377a3bc. 3.6 = torch 2.11.0 / Triton 3.6.0, 3.8 = torch 2.14.1 / Triton 3.8.0 (#630). H100 80GB HBM3 (driver 580.95.05) and RTX PRO 6000 Blackwell Server Edition (sm_120, driver 595.91.07).Over all 30 GEMM shapes (Qwen3.6-35B-A3B, Qwen3.8-Flash-Next, MiniMax-M2.5, Gemma-4-26B-A4B and GLM-4.7; gate_up and down; M = 1, 4, 8), relative to old@3.6:
On the RTX PRO 6000 under Triton 3.6, six MiniMax-M2.5 and GLM-4.7 shapes at M = 4 and 8 are 0.4% to 3.8% slower than old; three separate runs gave the same ratios. Under Triton 3.8 all 30 shapes are faster than old@3.6 on both GPUs.
All shapes, H100
All shapes, RTX PRO 6000
Correctness and tests
tests/moe/test_nvfp4_backends.pyandtests/kernels/test_e4m3_compat.pypass under both versions: 13 passed and 7 skipped on H100, 15 passed and 5 skipped on the RTX PRO 6000.End to end
AIME25 problem 1, then a long-prompt probe: TTFT and greedy 256-token decode after an 8k-token and a 32k-token prompt, median of 3. old@3.8 is
mainwith the dependency change of #630.Every run of this branch answered AIME25 problem 1 correctly (70). Gemma-4 also runs Triton attention, whose Triton 3.8 change is handled in #632; with both changes Gemma-4 decodes at 121.7 tok/s at 8k on H100.
Not covered: timing on other GPUs (sm_80, sm_86, sm_89 and sm_100 were only compiled), ROCm.