Repository navigation
ggml-hrx: IQ3_XXS routed experts take the table decode by default, with routed-shape test cases (engine #572) - #281
Conversation
…efault (engine ggml-org#572) The table decode from #216 was opt-in behind GGML_HRX_IQ3S_TABLE_DECODE=1, and with it set the matcher swapped the kernel for every format pair. Select it only when the gate or up weight is IQ3_XXS, by default; =0 restores the select chain. One log line states which decode a run used, because both kernels share one registration name. tests: MUL_MAT_VEC_FUSION cases at the Flash-Next routed prefill shape (2560 -> 640, 10 routes, broadcast input, 80 and 512 tokens) for IQ3_XXS and IQ4_XS, and GGML_TEST_PRINT_ERR=1 to print the measured error of a passing case. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
ready for review at d17623e |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at d17623e — with two things to note about the branch
The change itself is small and has the right escape hatches. A table decode for IQ3_XXS gate/up weights becomes the default only for that one case —
It is the default for the one case it exists for — a gate or up weight in IQ3_XXS — and is never selected for any other format pair, so a model without
IQ3_XXS routed experts runs exactly the kernel it ran before.
GGML_HRX_IQ3S_TABLE_DECODE=0puts IQ3_XXS back on the select chain (the A/B arm, and the way out if a device disagrees). Thetest-backend-ops
MUL_MAT_VEC_FUSIONcases at the routed prefill shape run both.
A default that is scoped to one format pair, with an environment escape for the case where a device disagrees, and an A/B arm at the real shape — that is the
shape a "make it the default" change should have, because the alternative (a silent global switch) is unfalsifiable on a box that has no IQ3_XXS model.
Two branch facts worth stating, because they change what a reviewer is looking at:
- this branch contains #278's content —
tests/test-hrx-arena-ledger.cppis md5-identical to #278's, and the diff against #278 shows this PR removing
test-hrx-staging-ledger.cppandtest-hrx-failure-status.cpp's additions, i.e. the branch predates them rather than carrying them. So the IQ3_XXS change is
the only thing to review here, and it will conflict with #278 wherever those tests land; - the bit-identity claim is stated but its measurement is not in this diff (
IQ4_XS instruction mix bit-identical)is the tail of a comment about a
different format pair): if the table decode is now the default, the bar it has to clear is that the IQ3_XXS outputs are identical to the select chain —
and the A/B arm runs both, so that is checkable, but the number should be quoted in the body rather than implied.
Not built: no llama.cpp tree here and -DGGML_HRX=ON needs the private runtime.
Recommendation for the cohort: land #278 first (it carries the ledger arms this branch would otherwise delete), then rebase this — and quote the A/B
comparison in the body.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at d17623e: READY
IQ3_XXS routed experts taking the table decode by default is the right routing: an XXS quant has a lookup table by construction, and forcing it through the arithmetic path would either be wrong or silently slower. Defaulting a shape to the path its format implies, rather than making every caller remember, is the same principle that keeps the int4 code and its scale paired.
CI green. I read the diff and CI; I did not build or run this fork.
…ml-org#572) (#329) The #281 routed cases use 16 experts (50-320 routed rows per expert), so they never reach the small-row regime of the real model: 10 routes over 512 experts is ~1.6 / 10 / 40 rows per expert at 80 / 512 / 2048 tokens. Adds, at 512 experts and those token counts: - eval: gate/up + SwiGLU for IQ4_XS (UD-IQ4_XS) and IQ2_S (UD-IQ3_XXS), and the 640 -> 2560 down MUL_MAT_ID for IQ4_NL and Q5_0; - perf: the same down MUL_MAT_ID cases. These cover the gpu-kernels routed-expert tile fit (IQ4_XS / Q5_0 on the HIP prefill GEMM, 8-wave down and IQ2_S widths). On HRX0 vs CPU, two rounds each of default, GGML_HRX_HIP_MMID_TILE_FIT=0 and GGML_HRX_HIP_MMID_IQ4XS_Q5_0=0: MUL_MAT_ID 6/6 and MUL_MAT_VEC_FUSION 6/6 every run (performance mode). Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Part of 1bit-MONSTER/engine#572 (ask 2). Not "Fixes": the model-level cell below is still owed.
What changes
GGML_HRX_IQ3S_TABLE_DECODE(the table decode from ggml-hrx: read the IQ3_XXS grid code from a workgroup table instead of a 256-way select chain (engine #572) #216, documented in enginedocs/hrx.md) was opt-in, and when set it swapped the routed gate/up kernel for every format pair. Now the table decode is selected by default, and only when the gate or up weight is IQ3_XXS. Any other format pair runs the kernel it ran before, whatever the variable says.GGML_HRX_IQ3S_TABLE_DECODE=0puts IQ3_XXS back on the select chain (the A/B arm and the way out).ggml_hrx: IQ3_XXS routed gate/up decode: workgroup table). Both kernels sit under one registration name, so a dispatch log could not tell them apart.tests/test-backend-ops.cpp: fourMUL_MAT_VEC_FUSIONcases at the Qwen3.8-Flash-Next routed prefill shape (2560 -> 640, 10 routes per token, one broadcast input row, 80 and 512 tokens) for IQ3_XXS and IQ4_XS. Until now no case in the suite compared the IQ3_XXS routed decode with the CPU at all: the existing fusion cases arem=1,n=32,k=256overbase_types, which has no IQ3_XXS.GGML_TEST_PRINT_ERR=1prints the measured error of every compared value. These cases allow 5e-3, so "OK" alone does not say how close the backend was.Proof (strixhalo gfx1151, this head, one
gpu-holdclaim, 21 s)test-backend-ops test -b HRX0 -o MUL_MAT_VEC_FUSION -p "n=640,k=2560", default and thenGGML_HRX_IQ3S_TABLE_DECODE=0:Run per format, each selects
common.mul_mat_id_swiglu.f32_f32_wmma (fused).Before this change, on a build of
cef5e2e20(kernel, matcher and motifs are byte-identical to the engine pin5514ebea4): the whole existingMUL_MAT_VEC_FUSIONset is 374 OK / 0 FAIL with the variable unset and with=1.What this does not show
docs/hrx.md(1.18x-1.29x, PPL identical to four decimals) were taken on 2026-11-06 on a commit before hrx: SET_ROWS keeps the rows it does not name, and publishes its host copy before the graph returns #227. The long-prompt cell on UD-IQ4_XS at the current pin has not been re-run: it needs the 89 GiB file loaded and the box has not had the memory today. That row is what remains before engine#572's ask (2) can be called done.docs/hrx.mdstill says "off by default"; it has to change in the engine PR that bumps the pin to include this.🤖 Generated with Claude Code