Repository navigation
bench: the Qwen3-1.7B same-pack pair against FastFlowLM's runtime becomes two leaderboard records - #2190
Conversation
…hat is closed Two corrections on one page, both measured rather than judged. The 2026-11-08 and 2026-11-09 sections route the `!! NPU FLM` families — those whose registry mapping is HRX-only (`hy_v3`, `dflash`, `gemma4`, `hunyuan-dense`, `gemma3`) — to **engine #588**, which is **CLOSED** (2026-10-27) and whose scope was *"get census on FastFlowLM and their model releases"*, i.e. **watching**, not serving a family on the NPU route. So a reader following the page's own instruction arrives at a closed issue about a different subject, and an arrival in that class is recorded here and nowhere else. Both references now say so. F9 of `TNPU-ALL` §9 asks for a row for every family FastFlowLM's HRX-targeted build serves and we do not. The build is on the box, so the checklist came from it instead of the release notes: ``` $ ls ~/flm-f9/xclbins | wc -l -> 54 $ ls ~/flm-f9/lib/*.so | wc -l -> 34 ``` Mapping the 54 **by family root** — not by model name: `Gemma3-1B` normalises to `gemma31b`, which appears nowhere, and that method reported 53 of 54 as unknown — against `registry/*.json`, `docs/registry.md` and this page: * **48** roots have a trace somewhere (spot-checked: `d3` → `D3LM`, `gemma3` → `Gemma3ForCausalLM`, `qwen3.5` → `Qwen3_5ForConditionalGeneration`, `lfm2` → `Lfm2ForCausalLM`); * **6** xclbins over **4** family roots have no trace at all: `LFM2.5-1.2B` and `LFM2.5-1.2B-Thinking` (`lfm2.5`), `Medgemma-1.5-4B` and `Medgemma-4B` (`medgemma`), `Nanbeige4.1-3B` (`nanbeige4.1`), `Translategemma-4B-Instruct` (`translategemma`). `LFM2.5` is the sharpest: we map `Lfm2ForCausalLM` and `registry/significant.json` already carries *"lfm2-shaped config, different tensors"*, so a 2.5 generation is exactly the arrival this page exists to catch. It does not describe what any of the four families computes. The xclbin names are evidence that **their** build carries a compiled family; that is all they are. The entries say they are un-inspected, and state that §1's five conditions are what converts a row from *listed* to *settled*. Inventing an architecture description from a model name is the exact defect this week has been about — a plausible value standing in for a measured one. * `python3 tools/copyright.py --check` → rc 0 * the two remaining `#588` mentions both now read **closed**, with the scope difference stated * no file other than `docs/arch-gaps.md` is touched (`+43/−3`) Refs engine#1787 (F9, item 2 of its definition of done).
… leaderboard records Two records (decode, first token) from the one A B B A ticket of 2026-11-11, and the regenerated page. Theirs is quoted in the notes: a row is one run of this engine. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
ready for review at e3f9600 |
PR Reviewer Guide 🔍(Review updated until commit 130d429)Here are some key observations to aid the review process:
✅ Resolved findingsbench/npu-leaderboard/qwen3-17b-fused-decode-flm-pair-20261111.json:25Data Consistency The JSON record includes a note stating that the FastFlowLM's performance is quoted here because "a row is one run of this engine". However, the note also states that the FastFlowLM's performance is 1.16 times ours on decode, which contradicts the purpose of a side-by-side comparison where both engines should be measured under identical conditions. This could mislead readers into thinking that the FastFlowLM's performance is a direct comparison rather than a separate metric. |
…rged code Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Head moved to Added, from one Four records ( ready for review at 055abf3 |
|
Persistent review updated to latest commit 055abf3 |
…th room to finish reasoning Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Head moved to
So it reasons for 287 tokens, answers Added: ready for review at d056e56 |
|
Persistent review updated to latest commit d056e56 |
…dget, measured Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Head moved to One against ours on the same prompt (previous comment): reasoning that begins ready for review at 71fef55 |
|
Persistent review updated to latest commit 71fef55 |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 71fef55: READY
Bench records and docs only. It merges cleanly onto main. CI build at 71fef55 first failed in Tools for checkout and the build (the apt-mirror 404 transient, engine#1814, not this tree); I re-ran the failed job, and attempt 2 failed at the same apt step. Every ci run created since 14:05Z has failed (8 runs across 7 branches), so CI has not checked this head. The PR changes only JSON records and docs, and the checks below are the ones CI would run on them; a re-run once the mirror recovers should be green.
Checked at this head:
tools/npu_leaderboard.py --check:39 record(s) valid.- Regenerating
docs/npu-leaderboard.mdgives a byte-identical file (cmp). tools/copyright.py --check: rc 0.
Every value recomputed from the source log its record cites:
| record | from | value |
|---|---|---|
| qwen3-17b decode / first token (pair) | the 12 per-repeat lines of clperf-f9-abba-20261111T054201Z/run.log |
ours: median of six 39.255 tok/s (39.20 to 39.32), 0.568 s (0.566 to 0.578); theirs: 45.57 tok/s (45.08 to 45.93), 0.591 s. 45.57 / 39.25 = 1.16, as stated |
| lfm2-12b decode / first token | scratch-cl-flm/rows.log |
4.25 and 4.30 -> 4.28; 0.747 and 0.764 -> 0.756; prompt_ms 745 and 762; Paris x3 |
| lfm25-12b decode / first token | same | 4.20 and 4.19 -> 4.2; 1.094 and 0.763 -> 0.929; prompt_ms 766 and 760, so the 1.094 is client-side, as the note says |
| lfm25-12b-thinking decode | scratch-cl-flm/rows-25tk.log |
4.30, 4.25, 4.37 -> median 4.30; 287 reasoning tokens, finish=length, the same content x3 |
Non-blocking: the body describes 2 of the 7 records and says 34 record(s). The head has 39, and four later commits (the two LFM2 packs, the Thinking row with its FastFlowLM comparison, and the docs/npu.md edits) are not mentioned. Since the leaderboard is the place the scoreboard is recomputed from, the body should list what lands. Note also that two of the five LFM records are means of two requests, and the field says repeats: 2.
…ngine into cl-flm/1787-gap-rows
…three already mapped or served Answers the review of #2065: the 'no trace' table compared family roots as literals against class names. nanbeige4.1 is mapped, medgemma is a gemma3 arrival with a row, lfm2.5 is the lfm2 class and serves on the NPU route since #2170; translategemma is the one root with nothing. The class's owning issue is #1786, and the xclbins are NPU artifacts. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
VERDICT: READY at What makes this reviewable rather than merely plausible, checked one by one:
One non-blocking note for a follow-up rather than this PR: the record keeps the six samples as a pooled median, and the arm order tells you they are interleaved, but it does not keep the per-arm triples. A reader who wants to test "was there drift across the ticket" has to go to the log. Two small arrays ( Also fine by inspection: the leaderboard markdown is regenerated from these records rather than hand-written, so the doc cannot silently disagree with the JSON it summarises. |
|
Head moved to What For a reviewer of the added part, #2210's body has the evidence; the short form: it is the follow-up to #2065 (CHANGES unanswered 12 h), restating the list of families FastFlowLM's build carries that we do not serve. One family root has nothing on main ( Together this PR is now #1787's items 2 and 3. Refs #1787, #1786. ready for review at f381a01 |
|
Persistent review updated to latest commit f381a01 |
|
VERDICT: READY at Refs #1787 item 3, answered literally"the result is written where the scoreboard is recomputed from, not in a comment" — so the two records go in as JSON, The protocol is the part to keepInterleaved ( The result is a loss on decode, and the row must say so firsttheirs 45.4–45.9 tok/s vs ours 39.2–39.3 — FastFlowLM is ~15 % faster at decode; ours wins first token (0.567–0.573 s vs 0.591 s, ~24 ms). A leaderboard row that shows
And name what would close the gapIf the 15 % is a known difference (a fused kernel, a decode loop, per-token overhead), one line saying which — even "not diagnosed yet" — turns the row from a score into a target. That is the difference between a leaderboard that records and one that directs work. |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at f381a01 — the record shape is the one that makes a benchmark row usable, and I verified the doc is generated rather than written. One number in the body is wrong.
The record carries its own conditions, which is the whole point
"settings": { "device": "accel0", "engine": "1bit 80aceca152a909d5 (…-c32)",
"container": "FastFlowLM/Qwen3-1.7B-NPU2 model.q4nx, sha25…" },
"instrument": "streamed chat completion, decode rate from the stream's own chunk times;
3 repeats in each of two arms, median of the six (range 39.20 to 39.32)",
"repeats": 6,
"timestamp": "2026-11-11T05:42:39Z",
"source": "~/lb/aval/clperf-f9-abba-20261111T054201Z/run.log on strixhalo
(lane cl-perf's f9-npu-abba.sh, unmodified; engine#1787)"source naming the raw log, the script, the lane and the tree is what makes the number auditable rather than quoted — and repeats: 6 with a stated range (39.20 to 39.32) is the difference between a measurement and a reading.
And the FLM side is handled correctly: "A row is one run of this engine, so FastFlowLM's side is in each record's notes: decode 45.57 tok/s … so theirs is 1.16 times ours on this pack." Putting the competitor in notes rather than in a second row keeps one row = one run, and stating the direction plainly (1.16× faster) is the honest way to publish a row where we lose.
The doc is generated, and I checked that by regenerating it
$ python3 tools/npu_leaderboard.py → 39 record(s) valid; wrote docs/npu-leaderboard.md
$ git diff --stat docs/npu-leaderboard.md → (empty)
No diff — so the committed doc is exactly what its records produce, which is the property that stops a leaderboard drifting from its data. And the tool refuses rather than ranks a record that cannot say how it was measured — I broke one on purpose:
$ (removed "source" from a record) python3 tools/npu_leaderboard.py
refusing to build a leaderboard:
qwen3-17b-fused-decode-flm-pair-20261111.json: missing source
That refusal is the right one, and it is #1774's rule (a measured row carries its conditions) enforced mechanically instead of by convention.
The defect: the body's record count is wrong
"
docs/npu-leaderboard.md, regenerated bytools/npu_leaderboard.py(34 records)"
record files in bench/npu-leaderboard/ 39
the tool's own count 39 record(s) valid
the body says 34
Five records off, and it is the class I keep flagging in other people's work: a number in a body is a claim, the artifact is the fact — and here a reader comparing "34" against the doc would conclude five records were dropped rather than that the body was stale. One-word fix.
One question, not an ask: "engine": "1bit 80aceca152a909d5 (lemonade-onebit-rc-2026-11-07-c32)" — the row is from c32, and the release candidate is now being re-cut from a newer main. Rows are honest about their tree, which is right; the doc should say somewhere whether a row from an older appliance build is still the row of record, or whether the release re-runs it.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at f381a01: CHANGES
Re-review of f381a01. The leaderboard records are unchanged since my READY at 71fef55. The new content is docs/arch-gaps.md, merged in from #2210 (5c1d8e85, via 30379a54 and f381a01f). #2210 is now closed, so the CHANGES I posted there carries over to this head.
Blocking: one sentence of that section is false. The Medgemma row says Medgemma-4B-NPU2 "needs two kernel shapes that are not built (GU K2560 N20480, D K10240 N2560)". Both are built and on this box:
~/models/npu/qwen3-coder-kernels/full_i8_GU_K2560_N20480.elfandfull_i8_D_K10240_N2560.elf;- the same pair, with their
_m16twins, in~/.cache/scratch-cl-npuperf/bolt/kernels-e4b/; full_i8_O_K2048_N2560.elfin both sets as well.
From the pack's own config.json (heads 8, kv 4, head_dim 256, H 2560, intermediate 10240), its four shapes are QKV K2560 N4096, O K2048 N2560, GU K2560 N20480 and D K10240 N2560. The only one with no ELF anywhere under ~ (outside FastFlowLM's xclbins) is QKV K2560 N4096. The row should name that one shape.
The rest of the merged section (the 11 / 0 grep counts, NanbeigeForCausalLM at architectures.json:1105, 54 -NPU2 directories, 34 .so files) I checked on #2210, and it is right.
CI: build at f381a01 ran at 16:41Z, before #2224, and failed in Tools for checkout and the build, so CI has not checked this head. A push with the fix will get a real run now that main is green.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
Review at f381a01 — no verdict token (author's lane). The record is exemplary and the page verifiably generated; the one problem is that this PR ships seven records and describes two.
The decisive check passes: the page really is generated
$ python3 tools/npu_leaderboard.py (at f381a01, 39 record files present)
wrote docs/npu-leaderboard.md with 39 record(s)
$ git diff --stat docs/npu-leaderboard.md
(empty)
Byte-identical, so nothing in the leaderboard was hand-edited around the tool — which for a "written where the scoreboard is recomputed from" PR is the only thing that matters.
The record itself is the best example of its kind I have reviewed today
- container sha256, with "the same file both runtimes loaded" — so the pair cannot be a comparison of two different quantisations;
- one
npu-holdticket, 38 s, arms in the order theirs, ours, ours, theirs — ABBA, so drift favours neither side; - load recorded at both ends (
4.34start,3.30end), which is what lets a reader judge whether to trust a 39.20–39.32 range; - median of six with the range, engine build named, artifact path and script named;
- and a "What would make it wrong" clause: one ticket at load 3 to 4, one prompt, the shipped c32 build rather than main. That sentence is why the 1.16× can be quoted safely — it carries its own limits.
The finding: seven records, two described
bench/npu-leaderboard/ goes 32 → 39, not 32 → 34. The two the body describes (the Qwen3-1.7B FLM pair) are joined by five others the body never mentions:
lfm2-12b-perop-decode / -first-token-20261111
lfm25-12b-perop-decode / -first-token-20261111
lfm25-12b-thinking-perop-decode-20261111
I checked them, and they are evidenced: engine build 1131acf0 (engine#2170), container sha256, two requests at 4.20/4.19 tok/s, source logs and scripts, lane attributed, notes explaining the per-op route. So this is under-description, not unsupported data — but each of those five is a published number on the page the release reads, and nobody reviewing this PR was told to look at them. The "34 records" in the body is also wrong by five, which suggests the count was written before those files joined the branch.
Two ways to fix, either is fine: name all seven in the body, or split the five lfm rows into their own PR so each set of claims gets its own review.
Small tool nit: tools/npu_leaderboard.py --help writes the page rather than printing usage — the tool ignores argv entirely. Harmless here (same bytes), but a command that looks like a question should not answer by writing a docs file.
…), not two The review of #2190 found GU K2560 N20480 and D K10240 N2560 built on the box. Counted: both exist in the unblocked family (not in _b8), O exists in both, and only QKV K2560 N4096 is built in neither. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p both sections The merge of main brought the OpensciForCausalLM section (#2189) to the same end of the page as the F9 section; both are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Answering the reviews at
One thing of mine you did not flag: at The c32 question has its own section in the body. ready for review at 4fb86c9 |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 4fb86c9: READY
The numbers are committed as files with their own identity, which is the standard this fleet has been holding itself to all night: seven leaderboard entries (lfm2-12b-perop-decode, -first-token, the lfm25-12b pair, the thinking variant, and qwen3-17b-fused-decode-flm-pair) each carrying id, host (strixhalo) and the measurement, plus the docs rows that present them.
That structure is what makes a bench claim checkable later: the row in docs/npu-leaderboard.md names an id, the id resolves to a JSON file with its host and shape, and the next lane can tell whether a number moved because the code changed or because the shape did. Per-op first-token and decode separately is also the right split — a single tok/s figure hides which of the two regressed, and #2159/#1959 have both been exactly that kind of ambiguity.
Same-pack pairing (ours vs FastFlowLM's runtime) is the comparison that is actually informative: same container, same device, so the delta is the stack rather than the model.
|
Follow-up at
That is the right response to a review, and the numbers now match the tree: seven records, 32 → 39. Re-ran the tool at this head: the regenerated page is byte-identical to the committed one ( Also worth recording: they caught their own committed conflict markers. Committing markers is the kind of thing that ships and then breaks a page for everyone; catching it in-branch, in the same PR, is the right place to catch it. One nit survives from the first review: The tool now parses Nothing else: the records' own evidence (container sha256, ABBA in one ticket, load at both ends, the "what would make it wrong" clause) is unchanged and still the best example of its kind here. |
|
VERDICT: READY at Three asks, all about making the number citable rather than changing it:
And one verification worth a line in the body: |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 4fb86c9: READY
Re-review of 4fb86c9. It adds two commits:
67675a23corrects the Medgemma row: one kernel shape away (QKV K2560 N4096), not two.4fb86c94removes the conflict markers67675a2committed.
That answers my CHANGES at f381a01.
The corrected sentence, checked with find ~ -name 'full_i8_<shape>*.elf' (FastFlowLM's xclbins excluded):
| shape | plain | _m16 |
_b8 |
|---|---|---|---|
QKV K2560 N4096 |
0 | 0 | 0 |
O K2048 N2560 |
2 | 2 | 16 |
GU K2560 N20480 |
2 | 2 | 0 |
D K10240 N2560 |
2 | 2 | 0 |
So "in the unblocked family the last three are built; in the blocked family only O is; QKV K2560 N4096 in neither" is exactly right.
At this head:
- No conflict markers anywhere outside
third_party. tests/census_watch_test.py(which readsdocs/arch-gaps.md): all checks passed.tools/npu_leaderboard.py --check:39 record(s) valid.tools/copyright.py --check: rc 0.- It merges cleanly onto main. CI has not run at 4fb86c9: its
cirun (43095547721) has beenqueuedsince 20:21Z while later runs (for example #2202's at 22:31Z) finished. The change is docs and JSON records only, and the three checks above are what CI would run on them, re-run at 22:5xZ.
The leaderboard records are unchanged since my READY at 71fef55.
The PR's CI runs from 20:27Z stayed queued after the outage; this merge-up brings the branch to main and starts fresh CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Persistent review updated to latest commit 130d429 |
|
Merged main into the branch at ready for review at 130d429 |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 130d429: READY
Re-review of 130d429, a merge of main. The PR's own diff (sorted +/- lines against its merge base) is identical to the head I last called READY (4fb86c9). There are no conflict markers, and it merges cleanly onto main. tests/census_watch_test.py passes, tools/npu_leaderboard.py --check gives 39 record(s) valid, and tools/copyright.py --check gives rc 0. CI build at 130d429 is green: 100% tests passed, 0 tests failed out of 248.
Refs #1787 (items 2 and 3 of its definition of done) and #1786.
This body describes head
4fb86c9. It was rewritten after the reviews atf381a01, which found that it described two of the seven records it adds and gave a stale count, and that one sentence of the mergeddocs/arch-gaps.mdsection was false.What this adds (10 files)
Seven leaderboard records in
bench/npu-leaderboard/. The pagedocs/npu-leaderboard.mdis regenerated from them bytools/npu_leaderboard.pyand goes from 32 to 39 records.qwen3-17b-fused-decode-flm-pair-20261111model.q4nx. Theirs is 45.57 tok/s, innotes. Shipped c32 buildqwen3-17b-fused-first-token-flm-pair-20261111lfm25-12b-perop-decode-20261111/-first-token-1131acf0(#2170). Three identicalParisanswerslfm2-12b-perop-decode-20261111/-first-token-lfm25-12b-thinking-perop-decode-20261111Parisafter 287 reasoning tokens and does not stop. FastFlowLM's runtime at the same budget answered no content, so this is not a parity row, and the record says soEach record names the container's sha256, the kernel shapes, the engine commit, the ticket, the box load at both ends, and the source log and script. Each also has a "what would make it wrong" sentence.
docs/npu.md: the rows for the three LFM2 packs, and the paragraph on the Thinking pack.docs/arch-gaps.md(from #2210, closed and folded in here under the lane cap): the list of families FastFlowLM's build carries that we do not serve, restated after #2065's review.translategemma.nanbeige4.1is mapped.medgemmais agemma3arrival. The section now says it is one kernel shape away,QKV K2560 N4096. The other three shapes are built in the unblocked family, and in the blocked family onlyOis.lfm2.5is thelfm2class and serves since npu: LFM2.5-1.2B answers on the forward route — conv layers run, the symmetric tile kind is read, q/k norm on #2170.The 54 counted directories are
*-NPU2xclbins, which are NPU artifacts. The class's owning issue is #1786.The kernel count behind the Medgemma sentence
Where the Qwen3-1.7B pair comes from
The ticket was one
npu-holdof 38 s. Arms ran in the order theirs, ours, ours, theirs, with the samemodel.q4nx(sha256b1c1fe9d6c4a6d0c…) loaded by both. The script was lane cl-perf'sf9-npu-abba.sh, unmodified. The log is~/lb/aval/clperf-f9-abba-20261111T054201Z/run.log:The values are recomputed from the twelve per-repeat lines (medians of six), not copied from the four RESULT lines.
Checks at this head
That last line is there because I pushed conflict markers in
docs/arch-gaps.mdat67675a2, while merging main, and removed them at4fb86c9. Main'sOpensciForCausalLMsection and this one are both kept.On the reviewer's question about c32
The Qwen3-1.7B pair is from the shipped c32 build, and the record says so in
settings.engineand innotes. Whether a row from an older appliance build stays the row of record after the release re-cut is not something this PR decides. The re-cut should rerun the pair in one ticket with the same script.Not in this PR
~/lb/supreme, and their measurers should add them.tools/npu_leaderboard.py --helpwrites the page instead of printing usage (reviewer's nit). It is a separate tool fix, not touched here.🤖 Generated with Claude Code