CERIN AMROTH · ML systems

grouped-nf4-gemm

4-bit GPU kernels that compute directly on packed Mixture-of-Experts weights, for training and inference.

v0.51.0 · current status → · Install · Try the example · Check the limits

What it does

Use this package when dequantising each active expert into a high-precision weight before its matmul is the bottleneck. It computes the grouped expert GEMM directly over the packed NF4 (bitsandbytes gemm_4bit layout) or native MXFP4 (e2m1 + e8m0) representations, and ships the int4 decode GEMV, the fp8 paged attention, the decode glue and the host/NVMe primitives a 4-bit MoE serving path needs around it. It is a kernel package: experts4bit-qlora drives it.

Choose a task

Task guideStatusConditions
How do I run a grouped GEMM directly on NF4 packed MoE expert weights, without dequantizing to bf16 first?supportedModels and limits
How do I run MoE expert inference natively on MXFP4 (e2m1 + e8m0) weights, straight from the released checkpoint bytes?supportedModels and limits
How do I run a single-token INT4 decode GEMV over routed MoE experts, and pack calibrated (GPTQ) weights for it?measured-privateModels and limits
How do I run paged decode attention over an FP8 KV cache for a quantized MoE serving path, with sliding windows, attention sinks and a custom scale?
capability fp8-paged-attention-fp8-compute
supportedModels and limits
How do I run paged decode attention over an FP8 KV cache for a quantized MoE serving path, with sliding windows, attention sinks and a custom scale?
capability fp8-paged-attention-f32-compute
supportedModels and limits
How do I run paged decode attention over an FP8 KV cache for a quantized MoE serving path, with sliding windows, attention sinks and a custom scale?
capability decode-glue-kernels
measured-privateModels and limits
How do I run a MoE whose experts do not fit in VRAM, streaming them from pinned host RAM or an NVMe arena?supportedModels and limits
How do I verify that the quantized expert bytes I serve or train on are the released checkpoint bytes?supportedModels and limits

Install

Routes from docs/capabilities.json at the pinned commit; the first entry of the register is the primary route.

pip install grouped-nf4-gemm

Primary route: kernel package.

Alternatives:

Environment (from the capability register; one list for all of these routes, so not every item applies to each): OS: Linux · Python: >=3.11 tested in CI (pyproject says >=3.9; 3.9/3.10 are not tested) · Accelerator: NVIDIA CUDA GPU for the serving tiers and for the default NF4 quantise bake (nvme_bake_nf4.bake_nf4 with quantize_fn=None); the relocation bake and verify (nvme_arena.bake / bake_expert_tensors / verify) need no GPU; NVIDIA CUDA GPU, sm_80 or newer (sm_120 is the primary serving target); NVIDIA CUDA GPU, sm_80 or newer (the composition was measured on the RTX 5090, sm_120); NVIDIA CUDA GPU, sm_80 or newer; this is the path sm_80-sm_88 take by default. Reference tests measured on an RTX A2000 (sm_86) and an RTX 5090 (sm_120), torch 2.8.0+cu128 / triton 3.4.0, with the arms pinned to the compute mode they name: identical errors on both, every one a bf16 output ULP, none over tolerance (gnf4.serve.f32-arms-ran-fp8); NVIDIA CUDA GPU, sm_89 or newer (the fp8 tensor-core dot); measured on the RTX 5090 (sm_120) only -- sm_89 and sm_90 meet the requirement but no registered cell was run there; none: pure torch (a CUDA GPU is optional) · Requires: GNF4_ATTN_F32_PRECISION selects the split path's dot precision: tf32 (the default, and what the compiler picked before it was named), tf32x3 and ieee (both exact against the fp32 oracle, both slower -- the measured trade is in gnf4.serve.f32-arms-ran-fp8). The default is the shipped behaviour; the others are opt-in; a local NVMe or fast block device for the arena; O_DIRECT reads; bitsandbytes and CUDA for the NF4 quantise bake (nvme_bake_nf4.bake_nf4 with the default quantiser); the geometry/manifest path is pure torch when a quantize_fn is injected; macOS/Windows: the pure-torch surface (pack references, dequant, provenance, arena bake/verify) imports and runs without triton via _triton_shim; the Triton kernels need a CUDA GPU; macOS and Windows are not exercised by CI; pinned host RAM sized from measured free memory (capacity_for_bytes); shape constraints, all from fp8_paged_attn.fp8_compute_unsupported (the single predicate the default selector and the path's own asserts share): v_groups == 1; k_groups in (1, 2, 4, 8, 16); head_dim // k_groups >= 32; q in bf16 or fp16; split branch: ktile >= 32 when the caller supplies it; packed branch (pack_heads=True): block_tokens * n_kv_heads >= 32. A call that fails any of these with GNF4_ATTN_COMPUTE unset takes the f32 path (its own entry); torch>=2.8 (pre-releases accepted); triton>=3.4 (Linux-only distribution)

Smallest verified example

CPU-only, no Triton: the pure-torch pack reference and the oracle every kernel is asserted against. Executed on a triton-less host by the page authors; the GPU form (gemm_4bit_grouped against the same oracle) is in the solution page.

import torch
from nf4_pack_ref import quantize_pack_nf4
from nf4_grouped import dequant_ref

w = torch.randn(64, 128)
packed, absmax = quantize_pack_nf4(w)                 # [64, 64] uint8, [64, 2] fp32
back = dequant_ref(packed, absmax, 64, 128)           # the checkable oracle
assert (back - w).abs().max() < 0.25 * w.abs().max()  # NF4 round-trip inside the codebook's spacing
How each capability addresses the problem

Use this when

Do not use this when

Limitations — what it does not promise

Support depends on the model and execution path. Check the model and hardware conditions before choosing a route; the full repository limits for each capability are below.

grouped-nf4-gemm · full limits
native-mxfp4-moe-inference · full limits
int4-decode-gemv · full limits
fp8-paged-attention-fp8-compute · full limits
fp8-paged-attention-f32-compute · full limits
decode-glue-kernels · full limits
stream-experts-from-host-or-nvme · full limits
verify-checkpoint-provenance · full limits

Current measured position

Representative active claims, selected from docs/claims.json at the source commit; retired and superseded claims never appear here. The whole register at that commit holds 11 confirmed · 36 measured · 3 measured-private · 1 projected · 2 open · 1 superseded · 4 retired; each card below is an active claim and links its receipt at the pinned commit.

The fused NF4 grouped GEMM (fp32 accumulate, bf16 epilogue) has never measured less accurate than the dequantize-to-bf16-then-GEMM baseline, in every confirmatory cell.confirmed
gnf4.kernel.fused-more-accurate-than-dequant-bf16 · sm_86 (A2000, 3090), sm_89, sm_90 · measured 2026-07-14 · receipt (pinned)
At batch-1 decode on sm_86, census MoE shapes (OLMoE, Qwen3-30B, Gemma-4, gpt-oss-120b) run 1.16-2.73x the dequant baseline at median; top_k=1 and tiny (<~5M weight elements) shapes are known losers.confirmed
gnf4.kernel.decode-speed-census · sm_86 · measured 2026-07-14 · receipt (pinned)
Against a CUDA-graphed per-expert baseline at the decode band (T=32) the fused path LOSES on both 4090 and H100 (0.949x, 0.858x); the memory-traffic win survives only at training shape on bandwidth-limited cards (1.489x on the 4090, parity 1.059x on the H100).confirmed
gnf4.kernel.graphed-baseline-decode-loses · RTX 4090 (sm_89), H100 (sm_90) · measured 2026-08-13 · receipt (pinned)
Serving gpt-oss-120b on its exact released MXFP4 bytes scores exact-chunk ppl 26.72 against the shipped-precision reference 26.75, deleting the +9.4% ppl / KL 0.066 NF4-requantisation tax; per-shard provenance sha256(loaded) == sha256(file range) on a 4-tensor spot sample (a spot check, not shard-level coverage).confirmed
gnf4.mxfp4.serve-tax-deleted · DO H200 pod · measured 2026-07-19 · receipt (pinned)
Qwen3-235B-A22B with all NF4 experts in ~128 GB pinned host RAM streams at 5.57 tok/s = 102-103% of the measured 44.3 GB/s link's waterfall ceiling on a 13.6 GB working set (synthetic weights, real attention + router); the dequant path on the identical pipeline: 1.81 tok/s.confirmed
gnf4.flagship.235b-phaseA · datacenter PCIe link 44.3 GB/s · measured 2026-07-14 · receipt (pinned)
The NVMe tier is a batch tier: at the measured per-box S ~= 3.45 GB/s a fully cold 235B streams ~2.3 s/token and a K3-class model ~7.5 s/token. What it buys is reachability and provenance, not latency.measured
gnf4.nvme.tier-batch-only · QNAP Xeon W-1250, FireCuda 530 on PCIe Gen3 x4 · measured 2026-07-27 · receipt (pinned)

Current status and compatibility

v0.51.0 · current status → — the position page is docs/STATUS.md at the pinned commit (latest on main, unpinned; not the source of any fact rendered here); the site's status and compatibility pages are generated from the same commit, and the evidence words are defined once in the system manifest's vocabulary.

Problems this solves

Package identity, supported platforms and source links
Canonical PyPI package
grouped-nf4-gemm
Canonical repository
github.com/pjordanandrsn/grouped-nf4-gemm
Import
nf4_grouped, mxfp4_grouped, int4_b32, fp8_paged_attn, fp8_kv, nvme_arena, nvme_reader, nvme_residency, nvme_bake_nf4, mxfp4_loader, gptq_pack, nf4_pack_ref, mxfp4_pack_ref, verify_provenance
License
MIT
Repository version
0.51.0 (at the pinned commit)
Latest PyPI version
0.51.0 — published
Source commit
30adb1bfa76f (2026-10-24) · files at this commit
Claim register
claims tiered in the public register: 11 confirmed · 36 measured · 3 measured-private · 1 projected · 2 open · 1 superseded · 4 retired — docs/claims.json (pinned)
Current status
v0.51.0 · current status → · capability table · docs/STATUS.md (pinned)
System manifest
kernels package of one system with experts4bit-qlora — system-manifest.json (verbatim, identical in both repositories; provenance)

Also discoverable as nf4gemm, gnf4, grouped-mxfp4-gemm. These are lookup-only aliases from the system manifest; grouped-nf4-gemm is the canonical project.

What it supports

Modes
benchmark, calibration, inference, offload, packing, serving, streaming, training, verification
Formats
bf16, fp8, int4, mxfp4, nf4
Model families
DeepSeek-V4 lineage; Kimi K3 lineage (reference decode); Qwen3-235B-A22B (host-RAM flagship); any checkpoint whose experts the bake can enumerate; any expert or projection weight packed with pack_int4_b32 / gptq_pack_int4_b32 (driven by experts4bit-qlora's serve lanes); any fused-expert MoE whose experts are packed in the bitsandbytes NF4 gemm_4bit layout (Qwen3-MoE, OLMoE, Mixtral, GraniteMoe, Gemma-4 text tower via experts4bit-qlora); any safetensors checkpoint; MXFP4 expert tensors for gpt-oss / DeepSeek-V4 / Kimi lineage; driven by experts4bit-qlora's paged engine for Qwen3-MoE, OLMoE, GraniteMoe, gpt-oss, Gemma-4, Mixtral; gpt-oss (20b, 120b); gpt-oss / DeepSeek-V4 / Kimi lineage MXFP4 arenas
Operating system
Linux
Python
>=3.11 tested in CI (pyproject says >=3.9; 3.9/3.10 are not tested)
Accelerator
NVIDIA CUDA GPU for the serving tiers and for the default NF4 quantise bake (nvme_bake_nf4.bake_nf4 with quantize_fn=None); the relocation bake and verify (nvme_arena.bake / bake_expert_tensors / verify) need no GPU; NVIDIA CUDA GPU, sm_80 or newer (sm_120 is the primary serving target); NVIDIA CUDA GPU, sm_80 or newer (the composition was measured on the RTX 5090, sm_120); NVIDIA CUDA GPU, sm_80 or newer; this is the path sm_80-sm_88 take by default. Reference tests measured on an RTX A2000 (sm_86) and an RTX 5090 (sm_120), torch 2.8.0+cu128 / triton 3.4.0, with the arms pinned to the compute mode they name: identical errors on both, every one a bf16 output ULP, none over tolerance (gnf4.serve.f32-arms-ran-fp8); NVIDIA CUDA GPU, sm_89 or newer (the fp8 tensor-core dot); measured on the RTX 5090 (sm_120) only -- sm_89 and sm_90 meet the requirement but no registered cell was run there; none: pure torch (a CUDA GPU is optional)
Public entry points
arena_experts:ArenaExpertSource, cli:python -m nvme_arena, cli:python -m nvme_bake_nf4, cli:python -m verify_provenance, dense_gemv:gemv_bf16_bw, dense_gemv:gemv_i8_bw, dense_gemv:quantize_rows_int8, dense_i8:linear_i8, flag:GNF4_ATTN_COMPUTE, flag:GNF4_GEMV_BW, fp8_kv:fp8_kv_append_bt1, fp8_kv:fp8_kv_append_t1, fp8_kv:quantize_kv_fp8, fp8_paged_attn:compute_counts, fp8_paged_attn:fp8_compute_unsupported, fp8_paged_attn:fp8_paged_decode_attention, fp8_paged_attn:paged_attn_available, fp8_paged_attn:paged_attn_ref, gptq_pack:HessianAccumulator, gptq_pack:gptq_pack_int4_b32, int4_b32:combine_rows, int4_b32:gemm_int4_b32_grouped_captured, int4_b32:gemv_int4_b32, int4_b32:gemv_int4_b32_grouped, int4_b32:quant_x_rows, int4_b32:reduce_partials, int4_b32:rmsnorm_resid_rows, int4_b32:rmsnorm_rows, int4_b32:rope_heads, int4_b32:rope_norm_heads, int4_b32:rope_norm_qk, int4_b32:router_epilogue, int4_b32:scaled_resid_add_rows, int4_b32:swiglu_rows, int4_pack_ref:dequant_int4_ref, int4_pack_ref:pack_int4_b32, int4_smallm:gemm_int4_b32_grouped_smallm, int4_smallm:gemm_int4_b32_smallm, int4_smallm:plan_smallm, int4_smallm:smallm_workspace, mxfp4_grouped:gemm_mxfp4_grouped, mxfp4_grouped:gemm_mxfp4_grouped_smallm, mxfp4_grouped:gemv_mxfp4_b32, mxfp4_loader:file_tensor_sha256, mxfp4_loader:provenance_table, mxfp4_loader:to_kernel_shapes, mxfp4_loader:verify_arena_matches, mxfp4_native_load:build_native_qlora_model, mxfp4_pack_ref:dequant_mxfp4, mxfp4_pack_ref:quantize_pack_mxfp4, mxfp4_qlora, mxfp4_residency:Mxfp4NvmeResidency, nf4_grouped:build_group_tiles_device, nf4_grouped:dequant_ref, nf4_grouped:dgrad_4bit_grouped, nf4_grouped:gemm_4bit_grouped, nf4_grouped:gemm_4bit_grouped_captured, nf4_grouped:repack_from_bnb, nf4_pack_ref:quantize_pack_nf4, nf4_qlora:fused_grouped_lora, nf4_qlora:gemm_4bit_grouped_train, nf4_route:decoded_dgrad, nf4_route:decoded_forward, nf4_route:dense_dgrad, nf4_route:dense_forward, nf4_route:dequant_groups, nf4_route:grouped_mm_dgrad, nf4_route:grouped_mm_forward, nf4_route:route_for, nf4_smallm:gemm_nf4_grouped_smallm, nf4_smallm:pair_lut, nvme_arena:bake, nvme_arena:bake_expert_tensors, nvme_arena:verify, nvme_bake_nf4:bake_nf4, nvme_reader:ArenaReader, nvme_reader:alloc_landing, nvme_residency:ColdTier, nvme_residency:capacity_for_bytes, row_pool:RowPool, verify_provenance:main
Owns (system manifest)
  • grouped packed GEMM (NF4 and native MXFP4) and its dgrad
  • decode GEMV (int4-b32, MXFP4) and split-K reduce
  • FP8 paged attention and the fp8 KV appends
  • decode glue kernels (rope, norm and residual folds, swiglu, combine)
  • pack and pure-torch reference operations, GPTQ packing, provenance verification
  • host/NVMe primitives (arena, reader, row tier, bake, residency primitives)
  • kernel-level measurement and the claims register for kernel-level numbers
Related package
experts4bit-qlora — one system, two independently released packages: the runtime package depends on the kernel package through its optional `fast` extra; the kernel package never depends on the runtime package. Dependency direction: experts4bit-qlora -> grouped-nf4-gemm.

rendered from grouped-nf4-gemm 0.51.0 · source: pjordanandrsn/grouped-nf4-gemm@30adb1bfa76f · checked 2026-10-25