Expand description
The Q4_K weight encoder: a transcription of llama.cpp b7650’s
quantize_row_q4_K_ref (ggml/src/ggml-quants.c:1280), not a
reimplementation of it.
A K-quant is NOT min/max over a block. Q4_K’s 256-element
super-block is fitted in three stages, all of which live in
super::fit because Q5_K’s fit is the same three stages with four
numbers changed:
- Each of the 8 sub-blocks of 32 gets an iterative affine fit
(
make_qkx2_quants): 21 candidate inverse scales are tried, each one re-solves a weighted least-squares for (scale, min) from the integer codes it produced, and the lowest weighted squared error wins. The weights aresqrt(mean(x^2)) + |x|, so a sub-block’s large values pull the fit toward themselves. - The 8 scales and 8 mins are themselves quantized to 6 bits
against the super-block’s
d/dminand packed into 12 bytes. - The 4-bit codes are then recomputed against the 6-bit-rounded scale and min, not against the fit from stage 1 – so stage 3 sees a slightly different affine map than stage 1 did.
A naive min/max encoder skips all three and produces a file that
loads and generates measurably worse text. That is the failure this
module exists to not ship, so the arithmetic in super::fit is
deliberately the same shape as the C, down to the operation order in
the least-squares accumulation.
With an importance matrix the same three stages run with the
weights, grid and stage 2 of quantize_row_q4_K_impl
(ggml-quants.c:1376); that switch lives in super::fit too, and
this module only passes the slice through.
What is left HERE is only what is Q4_K’s own: the candidate grid it passes to the shared fit, and the nibble packing.
Functions§
- encode_
block_ q4_ k - Encodes one Q4_K super-block (exactly
Q4_K_BLOCK_ELEMSvalues) and appends itsQ4_K_BLOCK_BYTESbytes toout. - encode_
row_ q4_ k - Encodes a whole row (or any slice whose length is a multiple of
Q4_K_BLOCK_ELEMS) into Q4_K super-blocks, appending toout.