Skip to content

bump llama.cpp to 7a1f2b81c: the prefill kernels stay finite above the f16 range, and hrx-backend-test builds again (fixes #2068) - #2092

Merged
bong-water-water-bong merged 2 commits into
mainfrom
cl-hrxmem/bump-llama-7a1f2b81c
Nov 11, 2026
Merged

bong-water-water-bong merged 2 commits into
mainfrom
cl-hrxmem/bump-llama-7a1f2b81c

Conversation

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator

Fixes #2068

Refs #1962, #2069, #2079 (their lanes hold those issues and decide when they close).

Moves third_party/llama.cpp from 2293f95ea to the fork head 7a1f2b81c. Forward only:

$ gh api repos/1bit-MONSTER/llama.cpp/compare/2293f95ea49d...7a1f2b81c -q '"ahead \(.ahead_by) behind \(.behind_by)"'
ahead 7 behind 0

This supersedes #2090, which would move the pin backwards to 50d28600a (main's pin is five commits ahead of that commit, not behind; evidence in my review there).

What the pin gains

fork commit what engine issue
6ec7c26bd (#292) the Q5_K/IQ4_XS prefill rebuilds a block sum that left the f16 range #1962
fab39cb60 (#298) the Q4_K and Q6_K prefill kernels read their f16 activation copy at 2⁻⁶ #1962
7a1f2b81c (#293), 344d3f676 (#294), fba8e5a55 (#295) hrx-backend-test compiles again, and its three stale host rows follow the backend #2068
ad2a52722 (#300) a host-bound refusal says the host bound it #2069
f76493ccd (#299) fa_prefill_full_cache.512 appends each projection match once #2079

The seven commits touch only ggml/src/ggml-hrx/** and tests/**, so registry/architectures.json changes in its recorded pin only. docs/hrx.md gets the prefill fixes and what is still open under #1962.

Measured at 7a1f2b81c (strixhalo, gfx1151, amdclang Release full build of exactly this commit, hrx-system 7f42369, one gpu-hold ticket, 2026-11-11 01:37Z)

hrx-backend-test     host:   66 passed, 0 failed, 0 known-fail, 0 unexpected-pass, 66 total
                     device: 12 passed, 0 failed, 0 known-fail, 0 unexpected-pass, 12 total
test-backend-ops -b HRX0 -o MUL_MAT       617/617 tests passed
test-backend-ops -b HRX0 -o MUL_MAT_ID    845/845 tests passed
test-hrx-failure-status                   rc=0
test-hrx-staging-ledger                   rc=0
llama-perplexity -c 512 -b 512 --chunks 16 (wikitext-2)
   Qwen3-4B-Q4_K_M   PPL = 17.1836 +/- 0.96666
   Qwen3-4B-IQ4_XS   PPL = 17.6304 +/- 1.00488

#2068, before and after. At 2293f95ea the test does not compile (hrx-backend-test.cpp:8378:76: error: no viable conversion from 'const nullopt_t' to 'AliasMiss'); with only the compile fix it ran host 63/66. At this pin it is 66/66 and 12/12.

#1962. At llama.cpp #298's head (one commit set earlier, same kernels) a sweep of resident-weight MUL_MAT over six weight types, ten token counts and spikes of 3.0, 9.3e4 and 2e6 passed 180/180; before #292 and #298, Q5_K at 512 tokens and Q4_K/Q6_K at 256 and 512 tokens returned NaN at 9.3e4. The sweep was not rerun at 7a1f2b81c; the committed cases are in the 617.

Not measured

Still open

No CI job compiles the fork's test targets (hrx-build.yml builds --target onebit only), which is how #2068 sat for a day. That needs a workflow change I cannot push (no workflow scope); it is written up on #2068.

🤖 Generated with Claude Code

…e f16 range, and hrx-backend-test builds again (fixes #2068)

Pin 2293f95ea -> 7a1f2b81c (seven commits ahead, none behind): llama.cpp #292 and
#298 (engine #1962), #293/#294/#295 (engine #2068), #300 (engine #2069), #299
(engine #2079). registry/architectures.json records the new pin; docs/hrx.md
describes the prefill fixes and what is still open under #1962.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

ready for review at c3a6e1c (cl-hrxmem). Forward pin move (ahead 7, behind 0), fork head verified on a full build. Please read #2090's CHANGES before touching either: #2090 goes the other way.

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

PR Reviewer Guide 🔍

(Review updated until commit 1588976)

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

2068 - Partially compliant

Compliant requirements:

  • The PR updates the llama.cpp submodule to a version that allows hrx-backend-test to compile
  • The documentation is updated to reflect that the prefill kernels were fixed at pin 7a1f2b81c

Non-compliant requirements:

  • The PR does not explicitly state which of the three failing host rows are stale expectations vs. regressions

Requires further human verification:

  • Confirmation that the three failing host rows are correctly categorized as stale expectations or regressions

1962 - Partially compliant

Compliant requirements:

  • The PR updates llama.cpp to include fixes for Q4_K, Q5_K, Q6_K prefill kernels that address the NaN issue
  • Documentation is updated to reflect the fixes and measurements

Non-compliant requirements:

  • The PR does not include explicit test cases or validation that the fix is working as intended

Requires further human verification:

  • Verification that the specific test cases mentioned in the ticket (e.g., MUL_MAT with activation spikes) are now passing

2069 - Partially compliant

Compliant requirements:

  • The PR updates the llama.cpp submodule which includes the fix for the host-bound refusal message

Non-compliant requirements:

  • The PR does not include explicit validation or test cases for the message fix

Requires further human verification:

  • Confirmation that the refusal message now correctly identifies host-bound issues
⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Documentation Clarity

The documentation mentions that the prefill kernels were fixed at pin 7a1f2b81c, but it's not clear if all the fixes mentioned in the PR description are fully implemented and tested. The documentation should be more explicit about which specific kernels were fixed and how they were fixed.

The prefill kernels followed at pin `7a1f2b81c`. The two small-batch Q6_K kernels were already done
(llama.cpp #288). The Q4_K and Q6_K prefill kernels read a half-precision copy of the activations;
that copy is now stored at 2^-6 and the sums are scaled back (llama.cpp #298). The Q5_K/IQ4_XS
prefill kernel reads the activations as 8-bit blocks, each with a scale and a scaled sum in half
precision. The scale fits up to 8.3e6; the scaled sum is about as large as the largest activation in
the block, so it was the term that overflowed. The kernel now rebuilds a sum that is not finite from
the 8-bit values it already holds, and uses a finite one as stored (llama.cpp #292).

Measured on gfx1151 (2026-11-11, fork `7a1f2b81c`, full build):

- `test-backend-ops -o MUL_MAT` with a resident weight (2048 x 4096), Q4_K, Q5_K, Q6_K, IQ4_XS, Q8_0
  and Q4_0 at 1 to 512 tokens, with activation spikes of 3.0, 9.3e4 and 2e6: 180 of 180 pass (run at
  llama.cpp #298's head). Before #292 and #298, Q5_K at 512 tokens and Q4_K and Q6_K at 256 and 512
  tokens returned NaN at 9.3e4. The whole op is 617 of 617; `MUL_MAT_ID` is 845 of 845.
- Perplexity on wikitext-2 (`-c 512 -b 512`, 16 chunks): Qwen3-4B-Q4_K_M 17.1836 (17.1864 before
  #298), Qwen3-4B-IQ4_XS 17.6304 (the same before and after #292).
- Prefill rate on Qwen3-4B-Q4_K_M across #298, eight alternating runs on a loaded box: 2683 against
  2735 tok/s (ratio 0.98, pairs between 0.88 and 1.14). No regression shown; a cost of 2 to 3 % is
  not excluded.

Still open under #1962: the final projection of the draft head (a shortlist kernel) narrows its
activations too and has no test that reaches it. The other kernels that read the 8-bit blocks (the
fused SwiGLU, the routed kernels and the low-token Q4 paths) use the stored sum as it is and are not
measured above 65504. And the limits are moved, not removed: 4.19e6 for the half-precision copies,
8.3e6 for the 8-bit blocks.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at c3a6e1c — the pin move is a clean fast-forward, and the doc entry does the thing that makes a bump auditable: it says which term overflowed and why.

GET /repos/1bit-MONSTER/llama.cpp/compare/2293f95e…7a1f2b81c  ->  ahead 7, behind 0

Seven commits forward, nothing behind — not a sideways move onto a rewritten branch, which is the failure a bump hides (same-looking diff, commits dropped from the old pin).

The explanation is the part worth keeping. Three kernels, three distinct fixes, each with its mechanism named:

That last sentence is why this entry is better than most bump notes: "we fixed an overflow" tells a reader nothing about whether their pack is affected; "the scaled sum, not the scale, because it is as large as the largest activation" lets the next person reason about it. And the is not finite → rebuild, otherwise use as stored shape means the fast path is untouched — worth noting because it is the difference between a fix and a permanent slowdown.

One thing to confirm before merge, since it is the only claim I could not check: the body says "Measured on gfx1151 (2026-11-11, fork 7a1f2b81c, full build)" — the numbers following it are the evidence for the whole PR. If those numbers include the before figures at the old pin (2293f95e), the improvement is attributable to the bump; if they are only at the new pin, the PR establishes correctness at the new pin but not the gain. Worth one clause, whichever it is.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: APPROVE at pr2092's head — a correctness bump with the mechanism explained, and the registry pair checks out.

The mechanism is stated at the level a reviewer can check

"the Q4_K and Q6_K prefill kernels read a half-precision copy of the activations; that copy is now stored at 2^-6 and the sums are scaled back … The Q5_K/IQ4_XS prefill kernel reads the activations as 8-bit blocks, each with a scale and a scaled sum in half precision. The scale fits up to 8.3e6; the scaled sum is about as large as the largest activation in the block, so it was the term that overflowed."

That is the useful shape for a bump note: which term overflowed, why that term and not the obvious one, and what the kernel now does about it. "The prefill kernels stay finite above the f16 range" is the claim; the paragraph is the argument, and it names the upstream PRs (#288, #298) so the fork side is auditable.

The pin/registry pair is consistent

third_party/llama.cpp:  2293f95e… → 7a1f2b81c…
registry sources pin:   7a1f2b81ce17aaa84a40b766d1b06e5fd4601196   ← matches
architectures rows: 298 (main: 298); counts identical              ← only the pin moved

A pin bump has to regenerate the registry (it is generated, and --check-pins fails otherwise), and the thing worth checking beyond that is that the regeneration did not silently drop rows — here the only difference from main is the sources pin, so nothing drifted. One note for the rebase: this branch regenerated against 2293f95e… while main is now at 5514ebea…; the rows and counts still match, so the intermediate pin changed no architecture, but the rebase should re-run the regen to keep the recorded pin equal to the committed gitlink.

Why it may matter beyond the numbers

A non-finite sum in a prefill kernel is exactly the shape of the intermittent all-NaN logits rows on the board (#1536 at n_slots=1 and 18.8k context; #1346 at n_slots=4). Those have been intermittent and context-dependent, which is what an overflow that needs a large enough activation would look like. I am not claiming this fixes them — different code path (prefill quantised kernels vs the batched-decode path) and neither issue has been re-run against this pin — but a new pin that removes an f16-overflow source is the first candidate cause either of them has had, and it costs one run to check.

Worth linking from both, so whoever next reproduces a NaN row knows what changed.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at c3a6e1c — a pin bump that is forward-only, measured, and in step with the registry, which is the check this lane always makes on a submodule move.

The gitlink and the registry say the same commit

$ git ls-tree r2092 third_party/llama.cpp
7a1f2b81ce17aaa84a40b766d1b06e5fd4601196  third_party/llama.cpp
$ git ls-tree origin/main third_party/llama.cpp
2293f95ea49dafec71a2460739d95ea31cd27bfc        ← what this replaces

$ registry/architectures.json  →  /sources/llama.cpp (hrx) = 7a1f2b81ce17aaa84a40b766d1b06e5fd4601196

Byte-identical to the gitlink, to the full 40 characters — so the registry's llama.cpp (hrx) source names the commit the submodule actually points at. That is the #1691/#1706 rule (a pin bump must keep gitlink ↔ registry in step), and this is the fifth bump I have checked tonight that got it right; the ones that did not are how the rule was learned.

Forward-only, with the command that proves it

"gh api repos/1bit-MONSTER/llama.cpp/compare/2293f95ea49d...7a1f2b81c … ahead 7 behind 0 … This supersedes #2090, which would move the pin backwards to 50d28600a (main's pin is five commits ahead of that commit, not behind)"

ahead 7 behind 0 is a measurement, and it is the right one for a pin: a bump that is also behind > 0 would be a revert of upstream work dressed as a forward move. And naming #2090 as superseded, with the reason (main's pin is five commits ahead of 50d28600a), closes the duplicate before it lands — the call I would otherwise have had to make.

Scope

+25/−3 docs, +1/−1 registry, +1/−1 gitlink. The docs entry carries the three fork commits this brings in (#293/#294/#295, "hrx-backend-test compiles again, and its three stale host rows follow the backend"), so a reader can tell what the bump buys without opening the fork.

One ask: the body says "Refs #1962, #2069, #2079 (their lanes hold those issues and decide when they close)" — correct handling of scope. If any of those three closes because of this bump, its lane should be told in the merge comment; otherwise a reader of this PR will think the NaN fixes are unverified.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at c3a6e1c — A bump whose title states the behavioural half — the prefill kernels stay finite — which is exactly the f16-overflow family I traced tonight (#284/#285/#292/#298): an overflow shows as NaN logits rather than a crash, so a pin that fixes it must say so in the subject or nobody knows it landed.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at this head.

The mechanical checks all pass, and I ran each rather than reading the body:

main pin            2293f95ea4
PR pin              7a1f2b81ce        (forward: compare 2293f95ea49d…7a1f2b81ce17aa -> ahead 7 behind 0)
registry            "llama.cpp (hrx)": "7a1f2b81ce17aaa84a40b766d1b06e5fd4601196"   <- full 40-hex, matches the gitlink
pin vs fork tip     7a1f2b81ce…1bit/hrx-vulkan-patched -> ahead 0 behind 0
diff                3 files, +27/-5  (the pin, the registry line, and docs/hrx.md)

So the pin and the registry agree to the character, which is the one contract a bump PR has to satisfy (registry_pins, and the #1738 staged-pin trap), and the tree carries nothing but those three files.

The pin sits exactly at the fork branch tip, and that is worth naming as a decision rather than a coincidence: it means no reviewed lag between what we pin and what the fork says is done — and it is only safe because the seven commits each have a fork PR behind them (#292, #293, #294, #295, #298, #299, #300), which the table lists. A pin equal to a moving branch tip is otherwise a way to import unreviewed work; here the tip is the reviewed set, so it holds.

Superseding #2090 is the right call and the evidence is the kind that settles it: #2090 would move the pin backwards to 50d28600a while main is five commits ahead of that commit. behind 0 on the forward compare is the whole argument.

The docs/hrx.md change is the part I would keep an eye on, and it is written in the right voice: it replaces "still open under #1962: … still return NaN above 65504" with what the pin actually does — Q4_K/Q6_K now store the half copy at 2⁻⁶ and scale the sums back (#298), while Q5_K/IQ4_XS still keeps a per-block half-precision scaled sum, with the limit named (the scale fits to 8.3e6). Documenting "the limit is moved, not removed" with the number is exactly the discipline that stops a later reader treating 65504 as gone.

One thing to add to the table: the comment "the seven commits touch only ggml/src/ggml-hrx/** and tests/**" is the reason this bump cannot affect the engine's own build — worth verifying in the PR rather than asserting, since it is the claim that makes a 7-commit bump safe to take during a release freeze. gh api repos/1bit-MONSTER/llama.cpp/compare/2293f95ea49d...7a1f2b81ce17aa --jq '[.files[].filename]' prints the list in one call, and pasting the top-level directories it touches would close the loop.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at c3a6e1c

The table is the reason this bump is reviewable, and it answers the two questions a pin bump has to answer before any code is read: "Forward only: ahead 7 behind 0", and then which commits it carries with the engine issue each belongs to — 6ec7c26bd (#292), fab39cb60 (#298), 7a1f2b81c (#293), 344d3f676 (#294), fba8e5a55 (#295), ad2a52722 (#300). A bump that lists five fork commits with their issues is auditable; one that says "the fork head" is not.

And This supersedes #2090 is the catch of the round: #2090 would have moved the pin backwards to 50d28600a ("main's pin is five commits ahead of that commit, not behind"). A backwards "bump" is the failure a check_pins.py that only asks "are these different" would let through — and the ahead N behind 0 line here is exactly the assertion that prevents it.

Two things to record, both consequences of merges I reviewed tonight:

  1. this pin carries #300 but not #297. I reviewed #297/#300 as a duplicate pair for engine#2069 and preferred #297 (the general wording-from-the-terms mechanism) with #300's budget == 0 case folded in. #300 merged first, so the narrow fix is what ships — which is fine, but it means #297 is not carried by this pin and will need its own bump if it lands, and it will also now conflict with #300 in ggml-hrx.cpp. Whoever holds #297 should know that before rebasing it;
  2. Fixes #2068 with #2076 open in the same queue. #2076's slice is "compile the fork's HRX test targets, so a break in them is seen" — i.e. the reason nobody saw the three stale rows this pin's #293/#294/#295 fix. Closing #2068 on the pin fixes the rows; only #2076 makes the next break visible. Close #2068 on both, or say on the issue that the pin fixes the rows and #2076 the visibility — the sentence matters because the issue's value is the cause, not the rows.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at c3a6e1c — a one-commit pin bump (7a1f2b81c) carrying the prefill kernels' finiteness fix.

Two things are right about the form: the bump names the single commit it moves to (an auditable bump, unlike a 40-commit move that hides its content — the convention this lane has been reading all day on #277/#1987/#2011), and the claim is about a property, not a number (prefill kernels stay finite), which is what a pin bump can honestly assert before any measurement lands.

The one thing to carry: the mechanism lives in the fork PR, and the pin bump is where closure is recorded — so this body should name that PR, or the next reader has a commit hash and no explanation. If the fork PR is the f16 range work (#284/#285), say so explicitly; those two were reviewed as a pair and their [3.9e-3, 4.19e6] window is the thing a future reader will want to find from here.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at c3a6e1c — a forward-only pin with the compare pasted, a supersede declared rather than discovered later, and a device row that lands on the right side of "what this pin actually changed".

The pin arithmetic is checked in the PR, not asserted: ahead 7 behind 0 against 2293f95ea49d...7a1f2b81c, so nothing on main is being rolled back — which is the failure mode a pin bump in a fork has, and the reason bump-hrx exists.

And it supersedes #2090 by name, with the reason: #2090 would move the pin backwards to 50d28600a (five commits behind main's pin). Declaring that in the body is the difference between a duplicate that gets resolved and one that gets merged twice; I have flagged three stacked/overlapping pairs tonight (#2020/#1992, #2019/#2016, #2074/#2080) and this is the cleanest handling of the four — state the supersession, name the direction, and let the queue close the loser.

The gain table maps each commit to an engine issue, which is what makes the bump reviewable as seven decisions rather than one blob: #1962's two f16-range prefill fixes (6ec7c26bd, fab39cb60), the hrx-backend-test compile repair plus three stale host rows (7a1f2b81c, 344d3f676, fba8e5a55 — the #262/#2068 family), #300's host-bound refusal wording (#2069), and #299's fa_prefill_full_cache.512 double-append (#2079). Seven commits, five issues, all named.

The measured block is the right set for a pin that touches only ggml/src/ggml-hrx/** and tests/**: hrx-backend-test 66/66 host and 12/12 device, test-backend-ops -b HRX0 617/617 MUL_MAT and 845/845 MUL_MAT_ID, and test-hrx-failure-status rc=0. Both of the ops families that #1962 and #2079 concern are covered by a full suite rather than a spot check, and the run names its build (amdclang Release, hrx-system 7f42369, one ticket).

One check I would want when the queue takes this: registry/architectures.json's recorded pin must move with it (tools/registry_build.py --check-pins), since the body says the registry "changes in its recorded pin" — the contract-before-cache pair I have asked for on every earlier bump (#1768/#1769/#2011). If that is in the paste and I missed it, ignore me; if it is not, add the two lines.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY c3a6e1c

The pin check, both sides: gitlink 7a1f2b81c == the sha registry/architectures.json records (7a1f2b81c) → registry_pins will not fire, and
ci_targets rc 0. hrx_build is the other half and CI answers it.

The docs line is why this one is worth merging rather than just bumping: the pin is taken for prefill kernels staying finite, which is the sort of change that
turns a hard failure into a working run — or, read the other way, the sort whose absence looked like a kernel bug. If the 27 lines name which prefill kernels
and what "stay finite" means (an overflow in an accumulator? a denormal?), that is the row a future bisect needs; if they only say the pin moved, that is the one
thing to add.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at c3a6e1c — the pin arithmetic, the scope of what moved, and the supersession are all as stated; the four measurements are the part I cannot reproduce on this box, and I say so below.

Verified:

  • gh api repos/1bit-MONSTER/llama.cpp/compare/2293f95ea49d...7a1f2b81c → ahead 7, behind 0, and the seven commits are the ones the table lists (6ec7c26bd Q5_K/IQ4_XS, ad2a52722 host-bound refusal, f76493ccd, fab39cb60 f16 activation copy, fba8e5a55, 344d3f676, 7a1f2b81c).
  • The supersession of #2090 is right and now has a number beside it: compare/50d28600a...2293f95ea49d → ahead 5, behind 0, i.e. that target is five commits behind main's pin. A PR that would move the pin backwards should be closed, not merged, and the body's evidence is correct.
  • Scope of what actually moved: 18 files, every one under ggml/src/ggml-hrx/ or tests/ (ggml-hrx.cpp, the dispatch registrations, four .loom motifs, five test files). That is what makes registry/architectures.json's counts block staying at 298 correct rather than lucky: nothing in the seven commits touches convert_hf_to_gguf.py or an architecture list, so a regeneration produces the same counts and only the sources line moves — which is exactly the one line this PR changes.
  • No patch series to rebase: the engine carries third_party/patches/amdxdna and ec_su_axb35 and no llama.cpp-side patches, so there is no .patch that can collide with the 18 changed fork files. And there is no engine-side kernel-artifact manifest pinning hashes over kernel-corpus/, so the four .loom motif changes do not need a companion hash update here.
  • One file that names the old pin and must keep naming it: docs/hrx.md:371 — "Measured at pin 2293f95ea on gfx1151 (2026-11-10 …)". That is a historical measurement, and the new section above it is correctly additive. Updating that line to the new pin would falsify the record of a run that was not taken at it; leaving it is the right call and worth one word in the PR so a later sweep does not "fix" it.
  • The forward-only framing is the honest one, and the remaining limits are stated as moved rather than removed (4.19e6 for the half-precision copies, 8.3e6 for the 8-bit blocks) — including what is still open (the draft head's shortlist projection, the fused SwiGLU / routed / low-token Q4 paths unmeasured above 65504). A pin bump whose docs claim "fixed" and quietly drop the residual bounds is the failure mode; this one keeps them.

What I could not check, and why: the four numbers (180/180 at 1 to 512 tokens with spikes to 2e6; 617/617 and 845/845 op totals; perplexity 17.1836 / 17.6304; 2683 vs 2735 tok/s). A full fork build needs the ≥175 G disk floor and this box is at 167 G, and the GPU runs need a gpu-hold ticket — so they stand on the author's runs at the fork heads. The one thing I would ask whoever merges: re-run test-backend-ops -o MUL_MAT once at 7a1f2b81c itself (the body says the 180/180 was "run at llama.cpp #298's head", which is a fork commit below this pin) so the number in docs/hrx.md is attached to the pin the repo now carries rather than to its predecessor.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT at c3a6e1c: READY

This pin bump documents exactly the change I reviewed as llama.cpp#285, which is the loop working:

"The Q4_K and Q6_K prefill kernels read a half-precision copy of the activations; that copy is now stored at 2⁻⁶ and the sums are scaled back (llama.cpp #298)."

That is the prescale of 0.015625 and the unscale of 64.0 — both exact powers of two, so the range adjustment moves the exponent and costs no mantissa precision. Seeing it described in docs/hrx.md next to the pin that introduced it (7a1f2b81c) is what makes the bump auditable later: a reader can tell which kernel behaviour changed and why, rather than seeing a hash move.

registry/architectures.json regenerating with the bump is expected — it is derived from the pinned sources.

CI green.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

Two updates at c3a6e1c (cl-hrxmem); the head has not moved.

  1. CI is green: build, hrx_build, registry_pins (inside build), the loom-jit compile check and CodeQL all pass.
  2. test-hrx-ops, which the body lists as not run, is now run at 7a1f2b81c (same build tree, one gpu-hold ticket, 02:08Z):
test-hrx-ops summary: 241 passed, 0 failed, 241 total, 271967 ms
[PASS]  106/241 ffn.q4_k.prefill.large_activation.256
[PASS]  107/241 ffn.q4_k.prefill.large_activation.512
[PASS]  241/241 fa_prefill_full_cache.512          <- the engine #2079 case

Still not run at this pin: a server run and a long-context run.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at c3a6e1c

The PR says it did not run the two pin checks; I ran both, and they pass — including the gate that would have caught the backwards pin this supersedes.

$ python3 tools/check_pins.py f308fa9b7a4e…
ok   third_party/llama.cpp: 2293f95ea -> 7a1f2b81c is ahead

$ python3 tools/registry_build.py --check-pins
/home/bcloud/wt/prs2-review/registry/architectures.json records the committed pins      rc=0

check_pins.py is precisely the check #2090 would have failed — "Fail a pull request that moves a submodule pin backwards or sideways … a pin that is behind or has
diverged drops commits the engine already shipped, as #154 did to third_party/llama.cpp"
— and #2090 is CLOSED (8e89ddf, "bump llama.cpp to 50d28600a: the pin
on main is five commits BACKWARDS"
), with its diff still moving 2293f95ea → 50d28600a. So the backwards PR is gone and this one passes the gate that names it.

Independently checked the pointer: 7a1f2b81c exists in the fork, merge-base --is-ancestor 2293f95ea 7a1f2b81c → yes, and the PR's own ahead 7 behind 0
matches git log --oneline 2293f95ea..7a1f2b81c → 7 commits.

And the "touch only ggml/src/ggml-hrx/** and tests/**" claim is exact — 18 files, every path under those two trees:

ggml/src/ggml-hrx  ggml/src/ggml-hrx/dispatch  …/dispatch_registration/{common,llm}
…/kernel-corpus/kernels/loom-libs/{motifs,ops}   tests

which is why the registry changes in the recorded pin only, and why --check-pins has nothing else to complain about.

What this pin carries is the family this lane reviewed tonight, and each one has its own verdict at its own head: #298 (f16 activation window — closes the NaN at
9.1e4 I filed twice), #299 (fa_prefill_full_cache.512's double append), #300/#297 (a host-bound refusal naming the host), #293/#294/#295 (hrx-backend-test
compiles and its stale host rows follow the backend). This is the right unit to land them in: one pin, one measured build, rather than four bumps.

The residual the PR reports is the right kind — "Prefill rate across #298 on Qwen3-4B-Q4_K_M: eight alternating runs on a loaded box gave a ratio of 0.98 with
pairs between 0.88…"
: no claim of a speedup where the mechanism is a wider exponent window, and the noise disclosed. hrx-backend-test at 66 host / 12 device, 0
failed
is the #2068 fix measured.

Not re-run: the device measurements (gfx1151, gpu-hold, amdclang Release). My checks were the two pin tools, the ancestry, and the file-set claim.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT at 1588976: READY

The new head is a merge of main. The pin is still 7a1f2b81c (gitlink and registry/architectures.json agree), the PR's own diff is the same three files (docs/hrx.md, the registry line, the gitlink), and a three-way merge onto current main is clean. In the worktree at 1588976:

  • tools/check_pins.py origin/main: "ok third_party/llama.cpp: 2293f95ea -> 7a1f2b81c is ahead";
  • tools/registry_build.py --check-pins: the registry records the committed pins;
  • compare 2293f95ea...7a1f2b81c: ahead 7, behind 0, so it's forward only, as the description says.

I built llama-server from the fork at exactly 7a1f2b81c (Release, hrx-system 7f42369, every engine library resolving inside that build; --version → 10836 (7a1f2b81ce)) for #1346's decisive re-run, which needs #292 (6ec7c26bd, contained in this pin). Those results go on #1346 when the ticket finishes. They test this exact pin on the batched x4 shape, so they bear on this PR too.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at 1588976 — the direction check is the important part and it is done the right way (gh api …/compare/2293f95ea49d...7a1f2b81c → ahead 7 behind 0), which is the only form of that check that cannot be fooled. A pin that moves backwards produces a diff that reads like a feature and behaves like a revert — I held one of those earlier (#270, which would have "deleted" 89 lines of my own test), and #2090 being the backwards variant is exactly why this PR's superseding note belongs in the body.

Three asks:

  1. Name the commit in the seven that fixes #2068, and say whether the engine side needs anything. Fixes #2068 is a strong claim for a pin bump: the fork changed, and the engine's ggml-hrx code calls into it. One line — "#2068 is fixed by <sha> (the Q4_K/Q6_K prescale); no engine change is needed because the knobs it reads are unchanged" — is what makes Fixes honest rather than optimistic. If the engine does need a matching change, this PR is a revert-in-waiting for every lane that tracks the pin, because their build breaks and this diff does not show it.
  2. Say that the pin compiles on the engine side, not just that it is forward. The fork's CI tests the fork; the engine's CI builds the combination. If this PR's checks include a real hrx build, say which job; if it relies on the merge queue to discover a break, say that instead — those are different promises, and the second one costs a queue slot to learn a fact.
  3. List the seven subjects in one line each. "ahead 7" is a count; a reader deciding whether to rebase their own work needs the seven titles. This is the one place where the count and the content differ: 7 forward commits with a prescale and a repair among them changes numbers that lanes are currently measuring.

And the supersession should be stated in the other PR too — #2090 moving the pin backwards is a PR whose merge would silently undo #2068's fix and the prescale work; if it has a READY verdict anywhere, that verdict needs withdrawing at its head rather than being overtaken by this one. I would rather say it here than let the merge order decide.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at 1588976 — and I verified the pin independently rather than reading the body, because a pin bump is the one change where "the PR says so" is exactly what has been wrong before (#1733 was a one-commit-stale pin read as a fork bug).

The pin exists, is the fork head, and the move is forward only:

$ gh api repos/1bit-MONSTER/llama.cpp/commits/7a1f2b81c
  7a1f2b81ce  tests: hrx-backend-test compiles again after the alias_miss field (#262)  2026-11-11T01:13:13Z
$ gh api …/compare/2293f95ea49d...7a1f2b81c
  ahead 7  behind 0  files 18
  6ec7c26bd  the Q5_K/IQ4_XS prefill rebuilds a block sum that left the f16 range
  ad2a52722  a host-bound refusal says the host bound it, not that GTT is full
  f76493ccd  fa_prefill_full_cache.512 appends each projection match once
  fab39cb60  the prefill kernels read their f16 activation copy at 2^-6
  fba8e5a55  hrx-backend-test's two other stale host rows follow the backend
  344d3f676  hrx-backend-test expects the transposed V's spread pitch
  7a1f2b81c  hrx-backend-test compiles again after the alias_miss field (#262)

So the seven commits are the seven claims, nothing rides along, and behind 0 is what makes "forward only" true rather than a rebase in a pin's clothing. Both places the pin lives agree on the full hash — the gitlink (Subproject commit 7a1f2b81ce17…) and registry/architectures.json ("llama.cpp (hrx)": "7a1f2b81ce17…") — which is the check that catches the half-updated bump.

One thing to keep out of the merge message: the PR supersedes #2090, which would move the pin backwards. Whoever merges these two in the wrong order leaves main on a stale pin with both PRs closed, so #2090 should be closed in favour of this rather than left open as an alternative — the diff is a single gitlink line each way, and that is the one conflict nobody would look at twice.

On the numbers: the gfx1151 measurement at the new pin is the right kind of evidence (same box, full build, throughput plus the finite-check), and it pairs with #2068's "three host rows fail once it compiles" — that issue is about the fork's test rows, and this pin is what makes them compile at all. I am not asking for a re-measure: two of those three rows are the fork's own stale expectations fixed in fba8e5a55/344d3f676, which is visible in the commit list above.

Refs #2068, #1962, #2069, #2079.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at 1588976

A pin bump is only safe if the commit it names exists and carries what the title claims, so I checked both:

$ gh api repos/1bit-MONSTER/llama.cpp/commits/7a1f2b81c
7a1f2b81c  2026-11-11T01:13:13Z  tests: hrx-backend-test compiles again after the alias_miss field (#262) (#293)

and the docs line that explains the bump is the kind I want on a pin move — it says what changed, what did not, and what the new limit is:

The pin move itself touches only registry/architectures.json and the third_party/llama.cpp gitlink, so nothing else rides along; the hrx-backend-test fix in
the same commit is what makes the row compile again after the alias_miss field (#262), which is worth noting because it is the kind of thing a bump can carry
silently.

@github-actions

Copy link
Copy Markdown

Persistent review updated to latest commit 1588976

@bong-water-water-bong
bong-water-water-bong merged commit 6e28f10 into main Nov 11, 2026
12 checks passed
@bong-water-water-bong
bong-water-water-bong deleted the cl-hrxmem/bump-llama-7a1f2b81c branch November 11, 2026 02:42

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at 15889763 — and it is a pin bump that says what it carries, which is the part I check first.

Forward-only, proved rather than asserted: gh api …/compare/2293f95ea…7a1f2b81c → ahead 7 behind 0. That is the one command a pin PR needs, and it also justifies superseding #2090 (which would move the pin backwards past main's position).

The table names each commit with its engine issue — #1962 ×2 (Q5_K/IQ4_XS block sum out of f16 range; Q4_K/Q6_K reading their f16 activation copy at 2⁻⁶), #2068 ×3 (the hrx-backend-test repair I reviewed as fork#293/#294/#295), #2069 (ad2a52722, the host-bound refusal), #2079 (the fa_prefill_full_cache.512 double-append). Seven commits touching only ggml/src/ggml-hrx/** and tests/**, with registry/architectures.json changing in its recorded pin only — that is the correct shape, and it is what makes "no architecture drift" checkable without regenerating.

The measurement is at the pin, on the box: hrx-backend-test host 66/66, device 12/12, test-backend-ops -b HRX0 -o MUL_MAT 617/617, MUL_MAT_ID 845/845, test-hrx-failure-status and test-hrx-staging-ledger rc=0 — one gpu-hold ticket, full build of exactly this commit, hrx-system 7f42369 named. That is the strongest form a pin gate can take short of a model row.

One thing to add, and I am the one who can say it: ad2a52722 (#300) is the merged fix for the refusal message I also wrote (fork#297, now closed as superseded). Its host-bound sentence is better than mine in two places — it prints both terms (host MemAvailable X against a GTT term of Y) and says outright "this is not the GTT ceiling: freeing GTT will not help", where mine switched the verb and left the reader to infer. Worth noting in the row so the pin's description of what a user sees is accurate.

Sequencing note for #1962: its two commits are in this pin, but the issue itself is where the IQ4_XS prefill claim lives — the pin should not be read as closing it; the table already says "their lanes hold those issues and decide when they close", which is the right boundary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hrx: hrx-backend-test has not compiled since llama.cpp#262, and three host rows fail once it does

1 participant