Repository navigation
feat(gguf): serve GGUF checkpoints on vendored ggml-cuda kernels - #690
Conversation
…nd drop the old Q4_0 path
…ntermediates in bf16
|
GGUF experts in the offload slot cache have no MMQ tail padding ggml's MMQ kernels read past the last row of the weight matrix they get, up to The resident (fused) banks have it: Reproduced at 128d0e2 with In cpu mode the cache is exactly 2 x num_experts slots (256 here), so staging buffer 1 ends at the end of the bank. Offload and hybrid with 1024 slots run fine on the same checkpoint. Proposed fix, for GGUF layouts with K % 512 != 0 only (the tail is 0 for everything else):
|
|
Clarification of the exact commit sets from the single-GPU AMD integration branch: zihaomu/FreeToken:feat/pr690-pr691-rocm-compat, head Base prerequisite: rebase #690 onto current A. ROCm-specific enablement and correctness commitsFor the tested R9700 (
The BF16 workaround is separate from #691: it addresses Triton #11217 / #11227, where BF16 multiplication is lowered to truncating B. General GGUF/GGML correctness fixes, reviewed independently of ROCmThese address format, storage and tokenizer behavior shared by CUDA and ROCm. The two defensive candidates left for design discussion are
Putting a fix in B does not make its triggered failure optional: the tested Qwen tokenizer and small-cache MMQ cases still need a solution. The separation is that these are general GGUF bugs with independently discussable implementations, not ROCm-only dependencies. Latest targeted validation: one R9700, TP=1, Torch |
|
Reconciling the remaining runtime work in #587 with the ROCm integration set here. QSA LDS clamp — overlaps gguf fixes — superseded by this PR. #587's other two changes — Net: once #690 + the ROCm integration set land, #587 is fully covered — QSA by |
|
@zihaomu Taken into this PR (with your authorship):
Not taken:
For a new ROCm PR from you against main: f1826a5 (reconciled with the QSA change in #587), 034e52a and 8a69381. It does not depend on this PR, except the On hold: the rest of 90f9833 (NVFP4 |
|
Four fixes on top of a3558d2, tested on an RTX PRO 6000 Blackwell (sm_120). 8682d4e – quantized PLE projections ( 0918f1e – float parts in a fused GGUF Linear dfbe98f – quantized hyper-connection and GDN
64ef88f – NaN after prefill with offload
Still open, not in these commits
|
The qsa_sparse_paged_attention tiles are tuned for the GB300's 228KB shared memory; RDNA gfx11/gfx12 have ~64KB/CU, so k+v staging overflows LDS. Query the device's actual shared-memory limit and shrink the KV tile only when it doesn't fit, ROCm-gated so NVIDIA tiles stay byte-identical. The gguf ROCm-compile fixes this branch also carried are now covered upstream by the ggml-cuda vendoring in FlashML-org#690 (separate DEFAULT_HIP_CFLAGS + vendors/hip.h), so this branch reduces to the QSA clamp only.
The qsa_sparse_paged_attention tiles are tuned for the GB300's 228KB shared memory; RDNA gfx11/gfx12 have ~64KB/CU, so k+v staging overflows LDS. Query the device's actual shared-memory limit and shrink the KV tile only when it doesn't fit, ROCm-gated so NVIDIA tiles stay byte-identical. The gguf ROCm-compile fixes this branch also carried are now covered upstream by the ggml-cuda vendoring in #690 (separate DEFAULT_HIP_CFLAGS + vendors/hip.h), so this branch reduces to the QSA clamp only.
Part of #671 (GGUF experts, GPU).
Related: #34, #549, #658
Summary
GGUF checkpoints now load through the quant layer like the other formats. A
GGUFquant kind reads each tensor's ggml type from the file and runs llama.cpp's CUDA kernels, vendored and bound through tvm-ffi. Qwen3.8-Flash-Next (qwen4exp) is new; Gemma4 GGUF moves onto this path and the old Q4_0-only path is deleted.gemma4), Qwen3.8-Flash-Next (qwen4exp); text only--moe-strategyfused,offload;hybrid/cpufor Q4_0 or BF16 expertsVendored ggml
What is copied, from llama.cpp 8c2134a8:
kernel/csrc/ggml/: the ggml public headers, two ggml-base internal headers, and from ggml-cuda the MMQ / MMVQ / MoE-id / quantize / convert / get_rows kernels with the 22 MMQ template instances.third_party/gguf/: gguf-py'sgguf_reader,constants,quantsandlazy. This drops theggufPyPI dependency; 0.19.0 lacks type 42 (Q2_0), which Flash-Next uses.How it is maintained: each tree is upstream plus one
freetoken.patch, and itsVERSIONrecords the pin, lists the changes and gives the update steps (copy the same files from a newer llama.cpp, apply the patch, regenerate it). 68 of the 138 changed files (32.6k of the 35.7k added lines) are these copies, so reviewing the two patches covers them.What the ggml patch changes:
GGML_MMQ_F16_DSTis defined.GGML_CUDA_FP4_MMAis defined; it needs an sm_120a/sm_120f build, and plain sm_120 failed to compile it.The gguf-py patch trims
__init__to the four modules and makes the reader import its constants relatively.Our own code next to it:
freetoken/ggml_shim.cu(the ggml-base runtime the kernels need) andfreetoken/ggml_ops.cu(the tvm-ffi ops:mul_mat,mul_mat_id, fused GLU, MoE weighted sum,get_rows,dequantize).kernel/ggml.pybuilds it with--compress-mode=size, and the kernel cache includes it.Changes
QuantKind.GGUFwith Linear, MoE and embedding methods. Fused Linears run one GEMM per run of equal types; MoE uses MMVQ for small batches and MMQ above, with intermediates in the activation dtype (llama.cpp keeps fp32). NewLayerKind.EMBEDDING; a tied LM head takes its logits from the embedding method, and quant kinds without an embedding method fall back to unquantized.qwen4_exp/gguf.pyis new, including the PLE table read in place from the GGUF (quantized rows dequantized on the GPU, float rows cast).gemma4/gguf.pyis rewritten.fused).csrc/gguf/,kernel/gguf.py,layers/gguf.py,models/gguf/dequant.py,moe/fused_q4_0.py).Validation
tok/s on H100 80GB (hybrid CPU: Xeon Platinum 8480+, 26 vCPUs). AIME25 problem 1, greedy, 256 tokens, one run each. The timed request is the second of two identical requests and reuses the cached prompt (Flash-Next prefills 34 of 98 prompt tokens, Gemma 1 of 63), so the numbers are close to decode speed.
offload and hybrid cache 3072 of 24576 experts (12.5%) for Flash-Next and 1024 of 3840 (26.7%) for Gemma. Measured at 371a4c2; the five later commits compress the fatbin, fix reading float PLE tables, pad the offload slot cache for MMQ tail reads, and, from @zihaomu, add HIP build support to the ggml ops (not run on AMD here) and make
dequantizecopy same-type floats and reject types without a ggml converter.* BF16 offload was measured before this branch was rebased onto b416f85, BF16 hybrid at 128d0e2.
Not covered
get_rowshas no NVFP4 case and aborts. Needs a follow-up..scaletensors that llama.cpp's converter writes forweight_scale_2are not read. Needs a follow-up.hybriddecode with more than 8 tokens in a step: CPU routes are parked on slot 0 with weight 0 because the GGUF MoE kernel cannot skip inactive slots, so expert ids repeat within a token and MMQ hits an illegal memory access. The hybrid numbers above are bs=1. Needs a follow-up.