Repository navigation
Add optional int8 path for quantized matmul with affine weights - #4722
Open
magnuslundstedt wants to merge 2 commits into
Open
magnuslundstedt wants to merge 2 commits into
magnuslundstedt wants to merge 2 commits into
Conversation
Contributor
Author
|
Benchmark script used for the single-op table. Save it as |
magnuslundstedt
force-pushed
the
qmm-int8-staging
branch
from
October 21, 2026 08:19
b999045 to
f788228
Compare
magnuslundstedt
force-pushed
the
qmm-int8-staging
branch
from
October 26, 2026 16:05
f788228 to
c8a1312
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
☑️ I understand it is strictly prohibited to use AI to write PR description
Implements the int8 half of mlx#4627 to stage the matmul's weights and activations as int8 instead of dequantizing to fp16; the fp8 half will follow in a separate PR. Enabled with the environment variable
MLX_QMM_INT8, off by default; stock path unchanged.Validation lists: Speed improvements for quantized matmul. Measured on 36969c0, the PR is now rebased to 8329918.
(prefill M=2048, decode M=1)
Exactness: with the switch off (default), every single-op cell is bit-identical to the unmodified build (12/12); decode steps are bit-identical on both hosts; the upstream
test_quantized.pypasses in every build, including the three new tests.Single-op table: Speed improvements (M = 2048, bf16 input, switch off over on, median of nine pairs; modes 1 / 2 / 4), as measured on base 36969c0.
lmstudio-community/Qwen3.8-27B-MLX-4bit, affine 4-bit g64, oMLX): prefill 1.44-1.51x at a measurable quality cost, depending on policy:Quality impact: the 27B worst-domain upper bound (full staged int8, +2.08%) fails the research's own +1% bar, literature and science degrade, math and code are near parity; task-level parity was not tested (no GSM8K or coding suite). For the smaller Qwen3-8B on the same path we measured similar prefill speedups, with a +0.56 / +0.76 / +0.59 / +0.18% relative PPL impact (worst upper 0.92%) on base commit. The mechanism is opt-in and off by default; per-layer policy lives in the serving harness, not in MLX.
Note: the numbers are from before [Metal] Add staged affine_qmm_t_nax kernels with split-k #4682 which is now in main and makes M6 stock slower at large M, while flat/faster on M5. This is a separate issue, which I may report separately. This PR is not addressing that issue.
Benchmark-script: qmm_8bit_bench.py (attached in comment to PR)
Selector rules for new GEMM QMM path:
MLX_QMM_INT8: default0(off); set to1,4or2to enable, most to least precise; other values are ignored; read when the op is built.gather_qmm untouched
SIMD fix (c8a1312) to remove undefined behavior for partial SIMD groups in affine_qmm_i8_quantize_x (padded threadgroup), sweep over 624 cells/host across 13 K values (9 not multiples of 32) are bit-identical; no arithmetic change; gates/tests unchanged
test_quantized.py: 57 OK on stock build, 60 OK on head build. JIT build (MLX_METAL_JIT=ON) on the pushed head sweep bit-identical; JIT and non-JIT outputs agree.FP8: This PR adds only the int8 path. Staging QMM on fp8 instead of int8 (which additionally exploits the M6 fp8 lanes) will follow in a separate PR.
AI usage disclosure:
Written by me (human) and I understand it is strictly prohibited to use AI to write PR description. Agents did assist in providing the solution, performing the measurements and preparing the data tables.