Add a BM=16 qmm tile for the small-M decode dead-zone#3863
Open
katlun-lgtm wants to merge 7 commits into
Open
Conversation
This workflow is designed to build a CMake project on multiple platforms, including Windows and Ubuntu, using different compilers.
This workflow installs Python dependencies, runs linting with flake8, and executes tests with pytest on push and pull request events.
Past the qmv batch-limit, affine qmm rounds M up to its 32-row tile, so M in [limit,16] all pay the M=32 price (flat plateau). Add a 16-row tile for M<=16: ~1.65x on M in [10,16] across 4-/2-bit and both projection and lm_head shapes; M>=17 and every other path byte-identical. Correctness exact vs dequantize-then- matmul; test_quantized.py green (32 passed, 2896 subtests). Refs ml-explore#3852
Member
|
Can you please provide the benchmark you ran? I think part of this should be handled by |
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.
Summary
Affine
quantized_matmulat small M (past the qmv batch-limit, up to 32) always pays for a full 32-row tile: theqmmpath uses a singleBM=32tile and launchesceil(M/32)M-tiles, so M=10 and M=32 take the same absolute time. This shows up as a flat plateau — see #3852 (@ARahim3): qmm is flat from M=10 to M=32, then steps at 33 / 65 / 97 (one step per 32-row tile).This adds a
BM=16tile and selects it forM <= 16in affine mode, recovering the[qmv-limit, 16]band that was rounding up to 32.Mechanism
qmm()launchesgrid = (ceil(N/32), ceil(M/32), B), so for M∈[1,32] that's one M-tile and the kernel computes 32 rows regardless of the real M. A fine M-sweep (M3 Max, 5120→17408, 4-bit) confirms the tile quantization is the whole story: flat ~0.51 ms for M=10→32, then +95% at M=33, +49% at M=65 — i.e. time =ceil(M/32)× per-tile cost. At M=32 the op runs at ~92 GB/s, far under the ~400 GB/s roofline, so it's tile/compute-bound with real headroom (not bandwidth-bound) — halving the tile actually helps rather than just re-reading weights.Change
qmm()(host):bm = (mode == "affine" && M <= 16) ? 16 : 32, and threadBMinto the kernel name + template instantiation. Thebm == 32path is byte-identical to before, so all existing kernels resolve unchanged.quantized.metal: two_bm-suffixed instantiation macros, plusaffine_qmm_t/affine_qmm_ninstantiated atBM=16(BK=BN=32).The
BM=16tile reuses the existingqmm_t_impl/qmm_n_impl(already templated onBM), so there is no new kernel logic.BM=8is intentionally not added:BM/wm = 8/2 = 4rows per simdgroup breaks the 8-row MMA fragment tiling (TM = BM/wm/8), soBM=16(TM=1) is the smallest valid tile.Results (M3 Max, min of 15×30, baseline = BM=32 plateau at M=24)
M≥17 is unchanged; the
qmv/qmv_widepaths (M below the batch-limit) are untouched.Correctness
max|Δ| = 0) for 4-bit and 2-bit at M = 10 / 12 / 16 / 17 / 32.python/tests/test_quantized.py: 32 passed, 2896 subtests passed.Scope
n > 1sampling (M in the[limit, 16]band). It deliberately does not touch theqmv_wideslope where single-stream speculative-decode verify (M = 2–6) lives — that path is already well-tuned (also noted in 2-bit quantized_matmul loses its size advantage over 4-bit at M >= 3 #3852).Refs #3852.