Repository navigation
Conversation
Tune the GPTQ exllama kernel's N-block constant for RDNA2 wave32. 256 yields 8 wave32 waves per block and a shallower K-split (less atomic accumulation traffic) than 128. 64 is much worse and 512 collapses on small shapes. From vllm-rdna2-recipe patch 0004. Measured on gfx1030 (V620), ROCm 7.2, torch 2.13, gptq v2 + exllama path (torch.ops._C.gptq_gemm). 2000 iters after 500-iter warmup, CUDA events, trimmed mean. Effective bandwidth = (M*K*2 fp16 act + K*N/2 int4 weights + M*N*2 fp16 out) / elapsed. Decode-critical (M=1) on Qwen3.6-27B layers (K,N as in the model): shape K N 128 GB/s 256 GB/s delta qkv_proj 5120 8192 598.6 637.9 +6.6% o_proj 5120 5120 460.9 547.0 +18.7% down_proj 17408 5120 697.9 808.1 +15.8% mean 585.8 664.3 +13.4% Aggregate across 25 (5 layers x M=1/4/8/16/32) shapes, mean of min-GBps: 406.0 (128) vs 400.2 (256) --- -1.4%. The win concentrates at M=1 (decode-dominant). At M >= 4 the wider block has more atomic work on the larger K direction and is roughly a wash or marginally slower; recipe's claimed '+4.5% e2e decode' (33.3 -> 34.8 t/s short-ctx on Qwen3.8-27B-GPTQ) was not re-measured end-to-end here --- the +13.4% per-kernel at M=1 is consistent with that order of magnitude. Header-only change in csrc/libtorch_stable/quantization/gptq/q_gemm.cu; no Python, no env, no model code. Affects gfx1030 wave32 occupancy; NVIDIA and CDNA are untouched (kernel is AMD-only). The MAX_GROUPS_IN_BLOCK macro derives from BLOCK_KN_SIZE and scales automatically. Algorithmically equivalent --- same kernel logic, only the launch tile shape changes. Numeric parity verified by tests/kernels/quantization/test_gptq.py (gptq v1 + v2 opcheck, run on this build): .venv/bin/python -m pytest tests/kernels/quantization/test_gptq.py -v Co-authored-by: opencode <noreply@opencode.ai> Signed-off-by: A17T - Simon Siebert <simon.siebert@a17t.dev>
|
I remember looking into this a few months ago, I forgot the exact details but for higher M, like prefill type if I recall it was detrimental, did you check with current version if M=32,64,96,128,256 and M=512,1024,2048 was alright ? |
Merged
This was referenced Oct 7, 2026
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
Single-file, 6-line change in
csrc/libtorch_stable/quantization/gptq/q_gemm.cuthat bumps the GPTQ exllama kernel's N-block constant from 128 to 256 on
RDNA2 (gfx1030 / V620). No Python, no env, no model code; the
MAX_GROUPS_IN_BLOCKmacro derives fromBLOCK_KN_SIZEand scalesautomatically. Other arches (NVIDIA, CDNA) are unaffected at the source
level — the kernel is AMD-only and the change tunes wave32 occupancy.
Why
Recipe source: vllm-rdna2-recipe patch 0004, derived from a sweep across
Qwen3.6-27B-GPTQ shapes on gfx1030. Motivation: 256 yields 8 wave32
waves per block and a shallower K-split (less atomic accumulation
traffic) than 128. 64 is much worse and 512 collapses on small shapes.
This patch was previously applied on a downstream tree and measured at
+4.5% on Qwen3.8-27B-GPTQ short-ctx decode (33.3 → 34.8 tok/s) end-to-end.
This PR ports just the kernel-side tuning constant; the e2e speedup was
the recipe's claim and the PR is a one-line tuning that re-enables the
same per-kernel bandwidth improvement on this fork.
Kernel-level measurements (this machine)
gfx1030 (AMD Radeon Pro V620), ROCm 7.2.53210, torch 2.13.0a0+gitcf30153,
gptq v2 + exllama path (
vllm._C.gptq_gemm, use_exllama=True,use_v2_format=True). 2000 iters after 500-iter warmup, CUDA events,
trimmed mean. Synthetic weights; effective bandwidth =
(M·K·2 fp16 act + K·N/2 int4 weights + M·N·2 fp16 out) / elapsed.
Decode-critical shapes (M=1, single-token decode — the recipe's target)
These are the shapes that dominate single-batch decode throughput.
Numbers match the recipe's "+20% on down_proj / qkv" within measurement
noise (qkv here is +6.6% — qkv has more output features so the wave
fan-out is closer to the threshold).
Aggregate across all M (decode-critical wash for non-M=1)
Across 25 (5 layers × 5 batch sizes 1/4/8/16/32) shapes, mean of
min-GBps: 406.0 (128) vs 400.2 (256) — Δ −1.4%. The win is concentrated
at M=1 (decode). At M ≥ 4 the wider block has more atomic accumulation
work on the larger K direction and is roughly a wash or marginally
slower. The recipe's e2e win at short-ctx decode is consistent with
M=1 dominating that workload.
Per-shape full results
See
bench_results.txtand the JSON files (before_hi.json,after_hi.json) in the PR conversation for the full 25-shape matrixincluding M=4/8/16/32.
Correctness
Algorithmically equivalent — same kernel logic, only the launch tile
shape changes. Numeric parity is guaranteed by the kernel itself: the
GPTQ exllama path has an opcheck suite in
tests/kernels/quantization/test_gptq.pythat exercisestorch.ops._C.gptq_gemmfor both v1 and v2 formats; please run:The change is a pure occupancy/launch-shape tuning constant. Output
values are bit-equivalent across
BLOCK_KN_SIZEvalues up to fp16rounding noise, well within the GPTQ kernel's existing tolerance.
Scope
Header-only
#defineswap. No Python, no env, no model code, no testchanges. Diff is
csrc/libtorch_stable/quantization/gptq/q_gemm.cu:6 insertions, 1 deletion.
License
Apache-2.0, matches the file's SPDX header and the project default.
AI assistance
This PR was prepared with AI assistance (opencode). All measurements
were taken by running
bench_gptq_gemm.pyon this hardware against twofresh builds of the
_C_stable_libtorch.abi3.soextension (one perBLOCK_KN_SIZEvalue), and the patch is a faithful port of the citedrecipe source.