Skip to content

IQ1_XS, IQ1_XXS, IQ1_XXXS on an upstream base so the nightly can pin them - #91

Merged
danielhanchen merged 1 commit into
iq1-narrow-upstream-basefrom
iq1-narrow-upstream
Aug 11, 2026
Merged

IQ1_XS, IQ1_XXS, IQ1_XXXS on an upstream base so the nightly can pin them#91
danielhanchen merged 1 commit into
iq1-narrow-upstream-basefrom
iq1-narrow-upstream

Conversation

@danielhanchen

@danielhanchen danielhanchen commented Aug 11, 2026

Copy link
Copy Markdown
Member

Same change as #61, on an upstream base so the nightly can pin it. #61 stays open for review of the design; this is the branch the prebuilds would actually merge.

Why #61 cannot be pinned as it is

resolve merges every pin onto the upstream base tag, not onto our master. Our master only shares history with upstream up to e95dae18d (2026-06-10), because upstream syncs land as squashes, most recently 53fd974b4 (Sync master with upstream, #80). #61 branches off that squash, so merging it onto b10356 drags two months of upstream work in as fresh additions:

merge-base(iq1-narrow, b10356)  = e95dae18d  2026-06-10   765 commits behind
merge-base(master,     b10356)  = e95dae18d  2026-06-10
merge-base(kimi-k3-vision-only, b10356) = 071327508  2026-08-04   86 commits behind

The result is hundreds of conflicts in files the change never touches, tools/ui/, vendor/cpp-httplib/, vendor/sheredom/, all of the "both sides add the same line(s)" shape, and additive_merge.py refuses them, correctly:

refused  tools/ui/vite.config.ts: both sides add the same line(s), so this is one change made twice
refused  vendor/cpp-httplib/httplib.cpp: merge base is not empty, so at least one side edited existing text
refused  vendor/sheredom/subprocess.h: merge base is not empty, so at least one side edited existing text
unslothai/llama.cpp#61 (36fe8e1c) does not merge cleanly onto b10356 + the PRs listed before it

That is a branch-base problem, not a code problem. #70 avoids it by sitting on an upstream commit and targeting kimi-k3-text-upstream, and this branch follows the same pattern: iq1-narrow-upstream is b10356 plus the single commit, targeting iq1-narrow-upstream-base, which is b10356 untouched.

The content is unchanged from #61: 41 files, 2334 insertions, 25 deletions, identical to what #61 reports. Cherry-picking 36fe8e1c onto b10356 applies with zero conflicts, and onto b10356 + 24423 + 25731 + 70 also with zero conflicts.

Checks on the merged nightly tree

Built the full mix (b10356 + 24423 + 25731 + 70 + this), CUDA sm_100, on a B200:

check result
resolve merge of all four pins clean, tag b10356-mix-e84bfed
build completes, no errors
ctest 59 of 60 pass; the 60th is test-backend-ops hitting the 1500s ctest timeout, run separately below
test-backend-ops -o MUL_MAT -b CUDA0 1219/1219, 2/2 backends
test-backend-ops -o MUL_MAT_ID -b CUDA0 874/874, 2/2 backends
test-quant-type-selection pass
test-llama-archs pass

The three types register in llama-quantize at the fork-local ids and quantize and generate end to end on Llama-3.2-1B with an imatrix:

  24  or  IQ1_S   :  1.56 bpw quantization      393551840 bytes
  64  or  IQ1_XS  :  1.44 bpw quantization      380182496
  65  or  IQ1_XXS :  1.31 bpw quantization      366813152
  66  or  IQ1_XXXS :  1.19 bpw quantization     353443808

Sizes fall in the order the bpw table predicts. libggml-cpu.so exports ggml_vec_dot_iq1_xs_q8_K, ggml_vec_dot_iq1_xxs_q8_K, ggml_vec_dot_iq1_xxxs_q8_K and the three grids, and the three CUDA MMQ instances compile.

Existing quant types are untouched

Built the identical tree without this commit and requantized the same model from the same imatrix with both binaries. The GGUFs are byte-identical:

IQ1_S    IDENTICAL  02dc2c2c1a63817dfb3998acc272923d8f68ed1ac10d06dc00e87b137c2c4482
IQ2_XXS  IDENTICAL  3a461ee80e793e93ab28b742da8513a9bd2342c5270f403a9398a7871efd657c
Q4_K_M   IDENTICAL  574d6de2b69c35bcb539dd210adee181b8eba1b7ae8864f525ef20b6ef83c2b3
Q8_0     IDENTICAL  05085ca8b9697115aeb2be01ee32873d476dec5b060abaaf2367b394fae82392

DiffusionGemma, Inkling, Kimi-K3 and Muse Glimmer all survive the merge alongside it: every arch registers in llama-arch.cpp, test-llama-archs passes, and the built libraries export their symbols (libllama.so: diffusion_gemma 17, inkling 24, kimi_k3 23, muse_glimmer 17; libmtmd.so: kimivl 7, muse_glimmer 14), with all four llama-diffusion-* binaries linking.

Pinning

Depends on #90, which drops the merged 26841 pin that currently blocks the merge before anything else is reached. Once both are in, the pin url is:

https://github.com/unslothai/llama.cpp/pull/91/commits/c86ed269986f2dced6325c5c58bda966a2e2ead1

Three sub-IQ1_S data types: IQ1_S's algorithm with the codebook the mapping step may choose
from cut to a subset of iq1s_grid, and the index stored in fewer bits.

  IQ1_XS    id 64  46 B / 256  1024-entry grid  10-bit index  1.4375 bpw
  IQ1_XXS   id 65  42 B / 256   512-entry grid   9-bit index  1.3125 bpw
  IQ1_XXXS  id 66  38 B / 256   256-entry grid   8-bit index  1.1875 bpw

Dequantization is IQ1_S's rule throughout, y[j] = d*(2*ls + 1)*(grid[idx][j] + delta).
GGML_TYPE_COUNT is 67; 42..63 are left for upstream, which already uses 42 for Q2_0, so a
stock build rejects these files rather than misreading them.

CPU, CUDA dequant, MMVQ and MMQ. The MMQ path targets the current
ggml_cuda_mmq_util_funcs / ggml_cuda_mmq_config API and registers the types in every
per-architecture config table; Blackwell falls through to Ampere and needs none.

scripts/iqxs_gen_tables.py regenerates all six codebook tables in ggml-common.h
byte-identically from the three committed .npy grids, so the tables are reproducible rather
than pasted.

Tested on B200, CUDA 13, sm_100. test-backend-ops -o MUL_MAT passes 2/2 backends both
default and with GGML_CUDA_FORCE_MMQ=1, 11 cases per type matching IQ1_S. Note the default
run never enters the new MMQ kernels, since small n routes to MMVQ.
@danielhanchen
danielhanchen merged commit e709916 into iq1-narrow-upstream-base Aug 11, 2026
12 of 33 checks passed
danielhanchen added a commit that referenced this pull request Aug 11, 2026
Adds IQ1_XS at 1.4375 bpw, IQ1_XXS at 1.3125 and IQ1_XXXS at 1.1875 to the
nightly. Pins #91 rather than #61: same commit content, but on an upstream
base, so it merges onto the base tag instead of dragging two months of
squash-synced master in behind it.

Replayed resolve on b10356 with this set: all four pins merge, tag
b10356-mix-1c79028, and the resulting tree hash matches the tree that was
built and tested (cdc8f949).
danielhanchen added a commit that referenced this pull request Aug 11, 2026
#92 merged into its stacked base branch rather than master, so the pin
landed on prset-drop-merged-26841 and never reached the file the nightly
reads. Same one-line addition, on top of master.

#91 is merged now, into iq1-narrow-upstream-base rather than master, so the
tree resolve builds still does not contain it and the pin is still what puts
it in. A merged required pin keeps being mixed in, with a warning, which is
the intended path here.
danielhanchen added a commit that referenced this pull request Aug 11, 2026
The first pin for #95 was cut from fork master, whose merge base with the
current base tag is from June 10, so merging it dragged in the whole
fork/upstream divergence and conflicted across ~1600 files.

Rebased the change onto b10359 and repinned to e2e842a. #95 now sits on
penalties-upstream-base, matching how #70 and #91 are carried.

Verified: all five pins merge onto b10359 in pr-set.json order, #70 via the
additive resolver as before, everything else clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant