[CUDA] Add dense and MoE GGUF MMQ kernels for eight I-quant types - #36122
[CUDA] Add dense and MoE GGUF MMQ kernels for eight I-quant types#36122liuhao-labs wants to merge 3 commits into
Conversation
Add dense and batched MoE MMQ kernels for eight supported I-quant GGUF formats, with conservative routing and compatibility fallback for older sglang-kernel wheels. Fixes sgl-project#35019 Signed-off-by: Hao Liu <liuhao24@sjtu.edu.cn>
GB10 dense IQ MMQ crossoverThis plot uses the revision-pinned At the sampled MMQ boundary M=16, the two-run ranges retain at least Run the underlying benchmark twice from for run in 1 2; do
python benchmark/bench_gguf_mmq.py \
--batch-sizes 9,16,17,24,32 \
--shape 18944x1024 \
--local-files-only | tee "/tmp/gguf-mmq-run-${run}.md"
doneThe heatmap was rendered from those two benchmark tables; the plotting-only |
Additional end-to-end compatibility checkI ran the revision-pinned
Both greedy requests produced byte-for-byte identical output: The runs used read-only source/wheel/model mounts, no network or host port, a This is a small dense IQ3_S serving and released-wheel fallback check. It does |
Signed-off-by: Hao Liu <liuhao24@sjtu.edu.cn>
Signed-off-by: Hao Liu <liuhao24@sjtu.edu.cn>
Refreshed-head validationThe Draft branch is now synchronized and pinned to:
The feature diff from Validation on one GB10 (
I also reran the small revision-pinned IQ3_S serving check on
The two client JSON files were byte-for-byte identical (SHA-256 This remains a Draft. The original approximately 100 GB routed-expert 4k/16k A/B, official H100/B200 AOT runs, and official x86_64/aarch64 wheel CI are still pending. |

Motivation
SGLang supports I-quant GGUF weights for dequantization and MMVQ, but does not
currently include them in dense or batched-MoE MMQ dispatch. Beyond the
small-batch MMVQ boundary, dense I-quant prefill dequantizes the full weight to
BF16, while I-quant MoE prefill remains on the decode-oriented vector kernel.
This change adds the eight I-quant formats supported by the upstream MMQ
implementation.
IQ1_Mremains on fallback because that implementation doesnot provide its MMQ dot product.
Fixes #35019
Modifications
IQ1_S,IQ2_XXS,IQ2_XS,IQ2_S,IQ3_XXS,IQ3_S,IQ4_NL, andIQ4_XS.MMQ for M=9..16, and dequantization from M=17. Narrow matrices retain MMVQ
through M=16 and dequantization from M=17.
reuse, expert count, CUDA grid capacity, and both projection K alignments are
suitable.
sglang-kernelexposes that capability.Q8_1in the high-level selector and direct CUDA GGUFcompute entry points.
strides, padded-tail bounds, complete q8 scale-tile loading, low-level
alignment checks, and deterministic zero output for invalid or remote
experts.
coverage, and a checked-in dense benchmark using a revision-pinned GGUF
fixture.
The current SGLang dependency remains pinned to
sglang-kernel==0.4.6.post1. That released wheel does not expose the newcapability, so the patched SRT safely retains its existing dequant/vector
fallbacks. After this kernel source lands, a new
sglang-kernelwheel must bepublished and the SGLang pin updated in a follow-up before normal installations
enable the new MMQ path. This PR intentionally does not bump the pin to an
unreleased wheel.
The kernel implementation is adapted from
aimbit-ni/vllm@037e1d547c15313aa7e2bb5fc83390ab0c857314and the algorithmsin
ggml-org/llama.cpp#8495.THIRDPARTYNOTICES.txtincludes the ggml MITnotice.
Accuracy Tests
Local validation used the installed CUDA 13/aarch64 AOT wheel on one NVIDIA
GB10 (
sm_121), rather than JIT-compiled kernels.The main-sync validation pair was upstream base
0c84eaba7f8d6674a360839426cacde4e1acd851and clean local merge head4c3e4c2350f4d6c4ff2a785e9b294938766a3cc6, which is now the remote Draft PRhead.
626d6ee79dd37dae2242f2f18a97b0536c95dfa4c053cb56d7573de23324c6e010 passed57 passedpython/sglang/kernels/aot/tests/test_gguf.py:153 passedUsing the same CUDA 13/aarch64 build configuration, the compressed wheel grew
from 29.473 MiB to 30.999 MiB: +1.527 MiB (+5.18%). Each bundled
architecture-specific
common_opsshared object grew by 917,504 bytes.The wheel was built before the final main-only merge. The AOT tree, SRT GGUF
selector, and registered routing test have identical Git object IDs at the
wheel-build head and the validation head above; the intervening upstream commits
do not change this source or test surface.
The production smoke observed the new capability as enabled and covered:
Q8_1rejection, K-alignment guards, and invalid-expert zero outputMaximum reserved GPU memory during the production smoke was 528 MiB.
A compatibility smoke combined the patched SRT source with the currently pinned
sglang-kernel==0.4.6.post1baseline wheel (SHA-256c7aac3ab20ff3c704e2bbc1a2fa78e5142a65150f12bca74f8e4cbd4f651d958).It observed
capability=False, selecteddequantizefor an IQ dense input, andreturned shape
[9, 18944]. This verifies that the combined source remainscorrect before the new kernel wheel is released.
A final-head bounded end-to-end serving sanity check also passed with the
artifacts in
/tmp/sglang-36122-e2e-final.XwQYAuand the revision-pinnedlegraphista/Qwen2.5-0.5B-Instruct-IMat-GGUFQwen2.5-0.5B-Instruct.IQ3_S.gguffile (SHA-256b7685f565fc6e49a8f9bc0fe09b9bb22ca0d5e4b10635cd4b181597f113794b6).The installed patch wheel (SHA-256
626d6ee7...) reportedcapability=True;the same synced SRT with the released baseline wheel (SHA-256
c7aac3ab...)reported
capability=False. Both configurations loaded the model, returnedHTTP 200 from the health and generation requests, and recorded zero cached
tokens for generation. Their client JSON files were byte-for-byte identical
with SHA-256
bd3c11d390f7a373e534f5361807119b2c040bc325cfe1f6fd2c8165d4426933:11 prompt tokens, 16 completion tokens, a length finish, and text:
Both runs used a single GB10 (
sm_121, CUDA 13, aarch64), read-only source,wheel, and model mounts, no network or host port, a 10 GiB container memory
limit,
--mem-fraction-static 0.03,--max-total-tokens 1024, one runningrequest, Triton attention, PyTorch sampling, and CUDA graphs disabled. The patch
run loaded 0.88 GB of weights and allocated approximately 0.02 GB of KV cache.
This validates a small dense IQ3_S model and the released-wheel fallback; it
does not replace testing the original approximately 100 GB routed-expert model.
The critical server-log scan found no traceback, CUDA error, NaN, or
illegal-memory failure; the remaining messages were the expected
nvidia-smifallback and shared local-tokenizer warnings.
The official Lint workflow
passed for the prior remote head
0137a1e..., includingpre-commit run --all-files, the repository lint checks, and the dedicatedsgl-kernel clang-format check. A new Lint run for the synced head is in progress;
normal platform CI remains Draft-gated.
The complete local AOT collection is not claimed as passing. A bounded run
reached 971 passed and 2 skipped before an unrelated large AWQ parameter
exceeded the allocator cap. Excluding AWQ reached 970 passed and 2,310 skipped
before FlashMLA sparse prefill rejected SM121.
Normal/full PR CI is still pending while this PR is a Draft. The current red PR
Test entries are draft-gate failures and their wheel, H100, and B200 jobs were
skipped; they are not kernel test failures. Before merge, the PR must be marked
ready and run the normal full workflow so it builds and installs the PR-local
wheel on the official x86_64/aarch64 and H100/B200 environments.
Speed Tests and Profiling
These are directional route-selection microbenchmarks from a shared GB10 that
retained a live Qwen service. They are not uncontended end-to-end throughput or
cross-architecture claims. They predate the main sync and were not rerun; the
sync did not change the IQ kernel patch represented by these measurements.
The checked-in benchmark compares direct MMQ with dequantization plus BF16
matmul using revision-pinned
18944x1024GGUF fixtures. The table below usestwo independent benchmark invocations. Each value is the mean speedup, with the
two-run range in brackets; speedup is
(dequantize + BF16 matmul) / MMQ.The full M=9/16/17/24/32 matrix and reproduction notes are in the
benchmark comment.
The M=16 ranges retain at least 1.24x measured headroom across all eight
formats. Although the isolated M=17 sample was also faster, M=18..23 were not
measured and M=24 regressed on multiple formats. The shared GB10 measurements
do not justify interpolating a larger universal CUDA gate, so this PR uses the
conservative M<=16 boundary. M=17 and above retain dequantization.
Directional MoE measurements were:
TTFT, TPOT, serving throughput, and the original approximately 100 GB report
model remain unmeasured. The representative serving check above is an accuracy
and compatibility sanity check, not a throughput result.
The Issue author has offered to run the original model and benchmark harness as
a pinned three-arm 4k/16k comparison: the upstream snapshot with the released
wheel, the refreshed PR source with the released wheel, and the same PR source
with a wheel built from that checkout. That external result is still pending,
so the PR remains Draft; see the
reviewer response
and the
pinned U/H protocol.
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ❌ Run #32939745573
Latest PR Test (Extra): ❌ Run #32939745211
Latest PR Test (AMD ROCm 7.2): ❌ Run #32939745576