docs(vision): OCRBench quant ladder for gemma4:31b (q4/q8/bf16), and a paired summarizer - #325
glennneuber wants to merge 1 commit into
Conversation
…arizer Ran OCRBench 200 rows on ROCm/GGUF at q4_K_M, q8_0 and bf16 against mlx-metal's 0.875 on the same slice, all on 0.34.1-dynres-16649e8c (906 + dio knob + ADR 0036), think off, -c 16384 -np 1. The aggregate column reads 0.855 / 0.845 / 0.845 and invites an ordering the data does not support. Paired over the shared row set: q8_0 and bf16 are identical on all 200 items (zero discordant pairs), and q4_K_M differs by 3 won / 1 lost, exact two-sided p = 0.625. So 8-bit costs nothing here and q8_0 stands in for the unquantized arm -- the control the GGUF path had never had. The cross-backend gap to 0.875 is inside noise at n=200 and cannot be sharpened without mlx-metal's per-item file. Also measured, from ADR 0036's own diagnostic firing on every load: its 2048 floor is DENIED at every quantization on gfx1151, not for want of memory but because availableMemoryForLoad sizes an integrated GPU against the 31 GiB system figure while the scheduler logs 95.4 GiB of GPU free. So the ADR is inert on the fork's own production hardware, and -- worth stating because it was briefly assumed otherwise -- the image chunk still exceeds n_ubatch, so it does not mask the HIP MMQ race and compat 906 stays load-bearing for gemma4. Harness, to keep this reproducible rather than retyped: - summarize_extbench.py: H7 generator for ext_*.json, H13 provenance footer, --paired exact McNemar. Exact and not chi-square because the uncorrected form reads p=0.317 at 3-vs-1 against the true 0.625. - extbench.py now persists the host/server_version client.generate() already stamps (H11), collected as sets so a mid-run restart cannot let one build vouch for another's rows. The three files here predate that and render as "pre-H11 run (not recorded)" rather than inheriting a sibling's provenance. - test_summarizers.py: TestExtbenchSummary pins the footer cases and the exact p-values. 139 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Superseded by #326, which stacks the same measurement onto #323 instead of duplicating it. #323 landed the same OCRBench ladder from the CUDA host, with a renderer ( What survives, in #326: the ROCm arms as a third engine section in #323's doc, the |
|
Consolidated into #327, which merges this PR with the other two OCRBench streams (#323 CUDA, #324 mlx-metal, #325 ROCm/GGUF). It contains every commit from all three, so merging #327 closes them together and there is no three-way conflict to resolve later. What moved, so nothing is lost:
All three runs agree: no quantisation difference resolves on any host, and OCRBench cannot separate the kernels where the goldens can. 🤖 Generated with Claude Code |
Consolidates #323, #324 and #325 into one OCRBench test, renderer and format. #325 was closed unmerged, so this carries the only copy of the ROCm ladder and its summarizer. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
OCRBench, 200 rows,
gemma4:31bon ROCm/GGUF at three quantizations — run to answer MLX-Metal'scorrect: 175, accuracy: 0.875on the same slice, and to supply the unquantized control the GGUF path had never had (the 2026-09-18 learnings entry: a tier move is not evidence until bf16 is measured).One binary
0.34.1-dynres-16649e8c(0.34.1 + compat 906 + dio knob + ADR 0036), think off,-c 16384 -np 1,offloaded 61/61every arm, medianprompt_eval_count1113 in all three.The aggregate column is misleading, and the paired columns say why
q8_0andbf16are identical on every one of the 200 items. Zero discordant pairs. 8-bit costs nothing on this benchmark, soq8_0is a usable stand-in for the unquantized arm.q4_K_M's apparent lead is 3 items won and 1 lost — a coin-flip disagreement.The gap to MLX-Metal's 0.875 is inside noise at n=200 (95% interval on 0.855 is ±0.049) and cannot be sharpened without their per-item
ext_*_ocrbench.json. The doc says so explicitly rather than publishing a ranking.Note the GGUF ladder is flat where the MLX ladder was not: on Metal, nvfp4 and bf16 differed by a 9 px tier once ollama#3912 landed. Same model family, opposite result — so "quantization costs a tier" is a finding about a specific quantization and kernel, not a property of the checkpoint.
ADR 0036 is inert on gfx1151, and that is measured, not inferred
Its own diagnostic fires on every load:
num_batch=1024 image_chunk_batch=2048(q4,-np 1),512for q8/bf16,512at-np 2. Not for want of memory — the scheduler logsavailable="95.4 GiB"of GPU whileavailableMemoryForLoadreturns the 31 GiB system figure, because its iGPU branch prefers live system memory whenever it is smaller than shared GPU free. That branch's premise (iGPU free memory is "a static or slowly refreshed device baseline") does not hold on a Strix Halo carve-out.Consequence worth stating because I briefly assumed the opposite: the chunk still exceeds
n_ubatch, so ADR 0036 does not incidentally mask the HIP MMQ race, and906-revert-hip-integrated-flag.patchremains load-bearing for gemma4. ADR 0036 amended with this rather than left to read as if the optimization is active.The 1.5–1.9× prefill gain ADR 0036 measured is unavailable on gfx1151 until that sizing is revisited. Not fixed here — it is a scheduler change with a blast radius beyond this doc.
Harness
summarize_extbench.py— H7 generator forext_*.json, H13 provenance footer,--pairedexact McNemar. Exact and not chi-square because the uncorrected form reads p=0.317 at 3-vs-1 against the true 0.625, which is the kind of number that gets reported as "trending".extbench.pynow persists thehost/server_versionthatclient.generate()already stamped and it was discarding (H11) — as sets, so a mid-run container restart cannot let one build vouch for another's rows. The three files here predate that and renderpre-H11 run (not recorded); the build in the doc heading is attested from runner logs and labelled as inferred, per ADR 0024. Re-running purely to stamp them would cost ~5 h of GPU and ~90 GiB of pulls.test_summarizers.py::TestExtbenchSummary— unrecorded-file, mixed-campaign and clean-footer cases, plus the exact p-values. 139 tests pass.Confound, stated rather than buried
q4_K_Mran at-b 1024and the other two at-b 512(the memory arithmetic above). So q4's 3-vs-1 edge could be quantization or batch; these data cannot separate them.q8_0vsbf16is clean — same batch, same everything, zero discordant items.🤖 Generated with Claude Code