Skip to content

docs(vision): a tier move needs the unquantized arm before it means anything - #321

Merged
glennneuber merged 1 commit into
mainfrom
docs/tier-needs-bf16-control
Sep 18, 2026
Merged

glennneuber merged 1 commit into
mainfrom
docs/tier-needs-bf16-control

Conversation

@glennneuber

Copy link
Copy Markdown

Adds the methodology entry behind the correction landed in #310.

The finding. A numerically wrong kernel can score higher than the correct one, because the error it introduces may compensate for a quantization loss on the scored sample. On gemma4:31b's 9px fine-text tier, one binary (0.34.0-maxusai-8a7ba949 / payload d9add9d1, post-MLX#3912), same window, powermode 2:

model vision tower LM think-off think-on
31b-nvfp4 nvfp4 nvfp4 [4,4,4,3,3] [4,4,4,3,3]
31b-mxfp8 bf16 mxfp8 [4,4,4,3,2] [4,4,4,4,3]
31b-mlx-bf16 bf16 bf16 [4,4,4,4,3] [4,4,4,4,3]

bf16 never enters QuantizedMatmul (x/mlxrunner/model/linear.go dispatches on .weight_scale; the bf16 checkpoint has zero across 1247 tensors). It scores 4, so 4 is the model's answer. nvfp4 on the fixed kernel scores 3; nvfp4 on the broken kernel scored 4. ollama#3912 did not cost a tier — it stopped hiding one.

Why this was nearly missed. Twelve runs split cleanly by build across both think modes, which read as a robust regression. A deterministic bug reproduces a lucky answer perfectly, so run-to-run consistency says nothing about whether the answer was earned.

Second trap. gemma4:31b-mxfp8 carries a bf16 vision tower, not an mxfp8 one — its vision mlp.down_proj blob is byte-identical in size to bf16's (9,916,560 = 1152 × 4304 × 2 + 144); only the LM is 8-bit. It is a second bf16-encoder arm, not an independent vision quantization. It still drops to 3 at think-off, so LM quantization alone moves the 9px tier — a tier is not a clean vision-encoder readout in either direction.

Pairs with quant_dims.py from #316: read blob sizes before believing a tag.

🤖 Generated with Claude Code

…nything

A numerically wrong kernel can score higher than the correct one when its
error compensates for a quantization loss on the scored sample. Measured on
gemma4:31b's 9px tier: bf16, which never enters QuantizedMatmul, scores 4;
nvfp4 on the fixed kernel scores 3; nvfp4 on the broken kernel scored 4.

Twelve runs had split cleanly by build across both think modes, which read as
a robust regression. It was not one — a deterministic bug reproduces a lucky
answer perfectly, so run-to-run consistency carries no information about
whether the answer was earned.

Also records that gemma4:31b-mxfp8 carries a bf16 vision tower, not an mxfp8
one (its vision down_proj blob is byte-identical in size to bf16's), so it is
a second bf16-encoder arm rather than an independent vision quantization — and
that it still drops to 3 at think-off, meaning language-model quantization
alone moves the tier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@glennneuber
glennneuber merged commit 16649e8 into main Sep 18, 2026
1 check passed
@glennneuber
glennneuber deleted the docs/tier-needs-bf16-control branch September 18, 2026 11:58
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