Skip to content

block_quant: role-aware weight quantization policy#2433

Draft
czoli1976 wants to merge 2 commits into
sonos:mainfrom
czoli1976:feature/role-aware-quant
Draft

block_quant: role-aware weight quantization policy#2433
czoli1976 wants to merge 2 commits into
sonos:mainfrom
czoli1976:feature/role-aware-quant

Conversation

@czoli1976

Copy link
Copy Markdown
Contributor

What this does

Gates the block_quant transform on a role-aware policy instead of quantizing every constant matmul weight uniformly: quant-sensitive tensors (embeddings, normalizations, output heads) and matmuls too small to benefit are left in f32, and the rest are quantized to Q4_0.

fn should_block_quant(weight_name: &str, k: usize, n: usize) -> bool {
    const PROTECTED: &[&str] =
        &["embed", "Embed", "norm", "Norm", "pooler", "classifier", "lm_head", "logits"];
    !PROTECTED.iter().any(|p| weight_name.contains(p)) && k * n >= 1 << 14
}

Why

Quantizing every weight uniformly degrades quality on the few sensitive tensors (embeddings/norms/heads are small and numerically sensitive — quantizing them costs accuracy and saves almost nothing) while small matmuls aren't worth the overhead. Protecting them by name + a size floor is the convention llama.cpp / GPTQ / bitsandbytes all converge on. The weight names survive ONNX import, so the policy can key on them.

Tests: protected/tiny weights are skipped, the rest are quantized (L1), and the quantized result matches X @ Q4_0(W) across both ONNX orientations (L2).

Notes

  • Stacked on block_quant: quantize einsum weights at either input slot #2428 — the first commit is that block_quant slot-orientation fix (its dependency); the policy is the second commit.
  • This is the "which-tensors" axis only. The asymmetric bit-width half of the recipe (bump attn_v/ffn_down to 8-bit) is a natural follow-up once a Q8_1-weight matmul path exists.

Question for you

This bakes a name-based protected-list into core. Is that the shape you'd want, or would you rather it be configurable (transform params / a caller-supplied predicate or regex list), or kept out of core entirely? Happy to refactor toward whatever you prefer — opening as a draft to get your call before polishing.

🍍

czoli1976 and others added 2 commits June 30, 2026 19:36
The block_quant rewrite assumed the constant weight was always einsum
input 0, so on imported ONNX `activation @ weight` matmuls (weight at
input 1) it wired the block-quant tensor and the injected group axis to
the wrong operands and tripped the EinSum rank check. Derive the weight
and activation slots from the matched input and wire them accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Quantizing every constant matmul weight uniformly degrades quality on
the few quant-sensitive tensors (embeddings, normalizations, output
heads) while saving little on small matmuls. Gate the block_quant
rewrite on a policy that protects those tensors by name and skips
matmuls below a size threshold, quantizing the rest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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