vllm.models.flint.ops.nvfp4_gemv
¶
Small-M BF16 x NVFP4 (W4A16) and BF16 x BF16 GEMM for SM100 in CuTe DSL.
out[M, N] = (x[M, K] @ dequant(W)[N, K]^T) * global_scale with the weight in
the ModelOpt layout used by the FlashInfer CuTe-DSL W4A16 kernel: weight
uint8 [N, K / 2] (two E2M1 codes per byte, low nibble first) and
weight_scale the 128x4-swizzled E4M3 block scales (one per 16 values), so
both kernels share the same tensors.
Numerics: every weight is dequantized exactly to BF16 (e2m1 * e4m3 via
cvt.rn.bf16x2.e2m1x2 and mul.rn.bf16x2), multiplied with the BF16
activations on tensor cores (mma.sync m16n8k16, FP32 accumulate), and the
FP32 global scale is applied to the FP32 accumulator before the single output
rounding to BF16.
Each CTA owns 16 output features (the MMA M dimension, swap-AB) and 8 * nt
tokens (nt = 1, 2 or 4, i.e. up to 32); its warps (and, with split > 1,
the CTAs of a cluster) split K and reduce through shared memory / DSMEM. All
weight loads are issued before griddepcontrol.wait so they overlap the
previous kernel under PDL.
Functions:
-
bf16_gemv–Small-M BF16 GEMM
x @ weight.T(FP32 accumulate); same kernel and -
dequantize_rows–Exact BF16
e2m1 * e4m3of all weight rows (global scale not -
nvfp4_gemv–Small-M W4A16 GEMM:
x @ dequant(weight).T * global_scale. -
pick_nt–Smallest tuned token tile count covering
m, or None if the GEMV -
tuned–Whether the GEMV is the fastest choice for this shape at some M.
-
warmup–Compile every variant the GEMV may pick for this shape.
bf16_gemv(x, weight, silu_mul=False, pdl=True)
¶
Small-M BF16 GEMM x @ weight.T (FP32 accumulate); same kernel and
arguments as nvfp4_gemv with a row-major BF16 [N, K] weight.
Source code in vllm/models/flint/ops/nvfp4_gemv.py
dequantize_rows(weight, weight_scale)
¶
Exact BF16 e2m1 * e4m3 of all weight rows (global scale not
applied); weight_scale is 128x4-swizzled.
Source code in vllm/models/flint/ops/nvfp4_gemv.py
nvfp4_gemv(x, weight, weight_scale, global_scale, silu_mul=False, pdl=True)
¶
Small-M W4A16 GEMM: x @ dequant(weight).T * global_scale.
Parameters:
-
(x¶Tensor) –BF16
[M, K]activations with unit inner stride;(N, K)and M must be covered by the tuned tables (pick_nt). -
(weight¶Tensor) –uint8
[N, K / 2]packed E2M1 codes (ModelOpt layout). -
(weight_scale¶Tensor) –128x4-swizzled E4M3 block scales (
swizzle_blockscale). -
(global_scale¶Tensor) –FP32 scalar tensor (one element).
-
(silu_mul¶bool, default:False) –Treat the output as
[gate | up]halves and return the BF16silu(gate) * up([M, N / 2]) of the BF16 gate / up outputs (exact SiLU, one BF16 rounding). -
(pdl¶bool, default:True) –Launch with programmatic dependent launch: weight loads start while the previous kernel drains. Disable after kernels that need the whole GPU to make progress (e.g. attention), whose remaining CTAs the early, waiting GEMV CTAs would starve.
Returns:
-
Tensor–The BF16
[M, N]([M, N / 2]withsilu_mul) output.
Source code in vllm/models/flint/ops/nvfp4_gemv.py
pick_nt(n, k, m, silu_mul=False, bf16=False)
¶
Smallest tuned token tile count covering m, or None if the GEMV
is not the fastest choice for this shape and M.
Source code in vllm/models/flint/ops/nvfp4_gemv.py
tuned(n, k, silu_mul=False, bf16=False)
¶
Whether the GEMV is the fastest choice for this shape at some M.
warmup(n, k, silu_mul=False, pdl=True, bf16=False)
¶
Compile every variant the GEMV may pick for this shape.