Repository navigation
GLM-5.3-Flash on CUDA: read nvidia/GLM-5.3-Flash-NVFP4 (ModelOpt NVFP4) as stored, W4A16 #308
Copy link
Copy link
Closed as duplicate
Closed as duplicate
Copy link
Description
What
GLM's CUDA engine reads the MLX 4-bit and EXL3 checkpoints. I would like it to read NVIDIA's ModelOpt NVFP4
checkpoint, nvidia/GLM-5.3-Flash-NVFP4 (revision 423acf37583782c51c142d145aef733d72943d93), without converting
it. I have a branch for it and would like to know what it needs to land before I open the pull request.
The checkpoint
- The routed experts (layers 3-44) and the dense MLP (layers 0-2) are ModelOpt NVFP4: e2m1 codes, an e4m3 scale per
16 inputs, an fp32weight_scale_2per tensor.input_scaleis stored as well (static activations). - Everything else is BF16: every attention projection, the shared experts, the router, the LM head and embeddings,
and the whole MTP layer, its 288 routed experts included. quantization_config.kv_cache_schemedeclares an FP8 KV cache (static, 8-bit float); the checkpoint stores no KV
scales. That is a separate question, in its own issue.
What the branch does (W4A16, the checkpoint's bytes as stored)
- Weights stay as stored. Routed experts load into the existing NVFP4
Experts4blocks (the grouped kernel Flash Next
uses) withweight_scale_2as the per-expert multiplier. The dense MLP runs onFp4Linear(gate and up apart,
since their tensor scales differ). The shared expert runs as a BF16 MLP, as for EXL3. - Activations stay BF16 (W4A16).
input_scaleis not read, and--precision checkpointnamed on the command line is
refused, because the grouped NVFP4 expert kernel takes bf16 rows only. The checkpoint's own FP4 x FP4 math is a
separate step (as Flash Next CUDA: routed NVFP4 experts in the checkpoint's own math (FP4 x FP4), prompts −9…−10 % #211 did for Flash Next). - One change to stored weights, for drafting only: the MTP layer's BF16 routed experts are packed to NVFP4 by
ModelOpt's recipe at load, a projection at a time. TensorFold has no BF16 grouped expert kernel; these experts only
draft, and verification never reads them, so drafted replies still equal"draft": falseones. It saves about
4.85 GiB a rank. I would like to know whether you prefer a BF16 path for them instead. - Two ranks split each
weight_scalewith its codes, so both keep whole 16-input groups and the grouped kernel's
32-wide tiles. I checked that on all 147,661 tensor headers of the real checkpoint. - NVIDIA stores the KDA conv taps as fp32. The KDA kernels already widened each tap to fp32, so they now read fp32 taps
and the loader keeps the stored values. MLX and EXL3 store the taps bf16; widened at load, they give the same bits
as before. - The startup estimate counts what the loader holds: about 90.9 GiB a rank on the real headers.
Questions
- Is W4A16 with the checkpoint's bytes as stored the right first step, with FP4 x FP4 later?
- Is packing the MTP layer's BF16 experts to NVFP4 for drafting acceptable?
- The header test uses a 435 KB gzipped dump of the real checkpoint's safetensors headers
(tests/fixtures/glm53_flash_nvfp4/headers.json.gz, names, dtypes and shapes only). Keep it, shrink it to the
tensors the checks need, or drop the test? - A follow-up gives NVFP4 routed experts a prompt-shaped kernel. It changes prompt bits (each pair's sum in a
different order from decode's, the same for any chunking), as the MLX experts' prefill form does. Is that
acceptable for a family where prompt and decode bits already differ?
Tested on two DGX Sparks (GB10, TP=2). I have no Mac in this loop, and the change touches CUDA only.
Written with Weave (My Symbiotic AI)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
ashhart commentedon Oct 6, 2026
Thank you, @Bizuayeu. Asking before opening the pull request, and checking the split on every tensor header, saved a wrong turn. The Python engine is frozen (#286), so the loader won't land there. GLM-5.3-Flash isn't on the Zig engine yet, and Zig CUDA doesn't serve yet. When both are there, reading
nvidia/GLM-5.3-Flash-NVFP4as stored, W4A16, is the right first step, and your branch is the reference for it, with your credit. The other questions, the drafting-only repack of the MTP experts and the prompt-shaped expert kernel's sum order, we'll settle when that family is built.ashhart commentedon Oct 7, 2026
Thank you, @Bizuayeu. Reading nvidia/GLM-5.3-Flash-NVFP4 as stored, W4A16, means the loader accepts the ModelOpt pack and does not ask the user to repack it first.
The Zig tree has no NVFP4 reader. The Flash Next family it does have admits MLX affine packs. GLM-5.3-Flash on CUDA is the port that grows the NVFP4 reader, and this checkpoint is one of its fixtures. Weights that do not match the stored layout fail at load. We will not convert them on the fly and call that the same model. Thank you for naming the repository and the W4A16 contract.
ashhart commentedon Oct 10, 2026
Thank you, @Bizuayeu. Reading NVIDIA's NVFP4 checkpoint as stored, W4A16, is step 4 of #593, on top of #587's interface and the NVFP4 entry. The FP8 KV question stays off the default path, since KV stays bf16. Closing in favour of #593.