Conversation
Add per-model tuned GEMM configurations for google/gemma-4-31B-it served with FP8 block-scale quantization (RedHatAI/gemma-4-31B-it-FP8-block). The tuned configs cover 85 (M,N,K) shapes across 7 unique weight shapes and 13 batch sizes (M=1..16384), including: - The lm_head GEMM (N=262144, K=5376) — previously untuned entirely - Prefill batch sizes M=16384 — previously untuned - Decode batch size M=1 — finds 37-46% faster configs for the small projection GEMMs (N=5376) vs the default kernelId=8 splitK=0 Tuned on gfx942 (MI325X, 304 CUs) using `csrc/ck_gemm_a8w8_blockscale/gemm_a8w8_blockscale_tune.py` with `--libtype ck --splitK --shape_grouped --warmup 5 --iters 101`. 6 shapes at very large M+N combinations have no valid CK kernel and are omitted (fall back to default): - (M=1024, N=5376, K=16384) - (M=4096/8192, N=262144, K=5376) - (M=16384, N=5376, K=21504) - (M=16384, N=43008, K=5376) - (M=16384, N=262144, K=5376) The file is auto-discovered by aiter's `get_config_file()` mechanism via the `model_configs/` glob — no env var or code change needed. AI assistance was used. All tuned entries were verified for numerical correctness (atol=0.01, rtol=0.01) by the tuner. Co-authored-by: Mustafa Yildirim <mustafa@character.ai> Signed-off-by: Mustafa Yildirim <mustafa@character.ai>
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
PR title tags: |
There was a problem hiding this comment.
Pull request overview
Adds a per-model tuned CK GEMM configuration table for running Gemma-4-31B FP8 block-scale (a8w8_blockscale) workloads on gfx942, enabling the runtime to auto-merge and use these tuned entries via the existing model_configs/ discovery mechanism.
Changes:
- Introduces a new tuned CSV for
a8w8_blockscaleGEMM covering key Gemma-4-31B shapes (including lm_head and large prefill/decode batches). - Provides kernelId/splitK selections and measured perf metadata (
us,tflops,bw,errRatio) for gfx942 MI325X-class GPUs.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
CKTile backend covers shapes that CK couldn't: - (M=1024, N=5376, K=16384) — QKV projection during mid-size prefill - (M=16384, N=5376, K=21504) — Gate/up projection during max prefill - (M=16384, N=43008, K=5376) — Down projection during max prefill 3 shapes remain uncovered (lm_head N=262144 at M=4096/8192/16384) — no backend (CK, CKTile, ASM, Opus) supports these on gfx942. They fall back to the default CK config. Total: 88 tuned entries (85 CK + 3 CKTile). Signed-off-by: Mustafa Yildirim <mustafa@character.ai>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
aiter/configs/model_configs/a8w8_blockscale_tuned_gemm_gemma4_31b.csv:87
- This row has
errRatio=0.0242, which exceeds the PR description’s stated correctness bounds (atol=0.01, rtol=0.01). IferrRatiois the metric used for that claim, either re-tune this shape with a stricter error threshold or adjust the PR description to reflect the actual error bound being enforced.
gfx942,304,1024,5376,16384,cktile,2,3,690.845,a8w8_blockscale_cktile_128x128x128_1x4x1_16x16x64_intrawave_0x1x0_2,261.11,167.72,0.0242
|
The GEMM tunings look sensible, though I haven't tested them in detail. (I've used AI analysis to check the config shape coverage, lookup reachability, duplicate/collision safety, hardware/model dimensions, and description.) Remaining questions include whether the CKTile errRatio=0.0242 is acceptable, and whether the performance summary is sufficient already. @valarLip @yzhou103 Please could you review these points, and advise whether anything else is needed for this PR? |
|
build aiter wheels failed. The 3 CKTile rows at the bottom trigger a pre-existing bug in gemm_a8w8_blockscale_cktile_instance.py:155-162: candidate_kernels_by_name is built from only the single arch that get_gfx() returns, but build_tune_dict filters CSV rows for all build targets via get_build_targets(). In a multi-target build (GPU_ARCHS=gfx942;gfx950), get_gfx() picks gfx950 (last entry), so the name registry only has gfx950 kernels (K_Warp_Tile=128). The gfx942 CKTile rows reference 16x16x64 kernels that don't exist in the gfx950 registry → codegen crashes → lookup.h never generated → compilation fails. Same bug exists in cktile_gemm_a8w8_bpreshuffle/gemm_a8w8_bpreshuffle_cktile_common.py:415. Suggested fix (either as a prerequisite PR or included here): make kernels_by_name the union of all arch kernel lists instead of only the get_gfx() arch. candidate_kernels_cktile_dict (used for codegen) stays single-arch — only the name lookup dict needs the union. |
About the errRatio, errRatio=0.0242 is within the tuner's default threshold (0.05), so it's acceptable at the per-op level. Whether it's acceptable end-to-end depends on the model owner's accuracy requirements. If not sure, was a splitK=1 or splitK=2 alternative tried for this shape (M=1024, N=5376, K=16384)? If a lower-splitK config exists with comparable performance but lower error, it should be preferred. |
|
Thanks @copilot for the review. Both points addressed:
|
Build fix (reported by @yzhou103): candidate_kernels_by_name in both - gemm_a8w8_blockscale_cktile_instance.py - gemm_a8w8_bpreshuffle_cktile_common.py was built from only the current get_gfx() arch. In a multi-target build (GPU_ARCHS=gfx942;gfx950), get_gfx() returns gfx950 (last entry), so the name registry only had gfx950 kernels. CKTile rows referencing gfx942 kernel names (16x16x64) crashed codegen. Fix: make kernels_by_name the union of all arch kernel lists. errRatio fix (suggested by @yzhou103): CKTile entry (M=1024, N=5376, K=16384) used splitK=3 with errRatio=0.0242. Re-tuned with --profile_file: splitK=2 is only 5% slower (675us vs 642us) with errRatio=0.0078 (within atol=0.01). Now all 88 entries have errRatio <= 0.01. Signed-off-by: Mustafa Yildirim <mustafa@character.ai>
|
Thanks @yzhou103 for the detailed review! Both issues addressed in the latest push: 1. Multi-target build fix: Fixed 2. errRatio on (M=1024, N=5376, K=16384): Re-tuned with
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (2)
csrc/cktile_gemm_a8w8_bpreshuffle/gemm_a8w8_bpreshuffle_cktile_common.py:415
- Merging the expanded kernel dicts with
{**a, **b}drops kernels because both arches use overlapping integer IDs (e.g., 0, 1, ...). That meanskernels_by_namemay still miss names from the earlier arch and can reproduce the multi-target crash this change is trying to fix. Build the name registry from the concatenated values instead of merging dicts by key (and reuse the already-expandedkernels_listto avoid extra work).
_all_bpreshuffle_kernels = {**expand_blockpercu(kernels_list_942), **expand_blockpercu(kernels_list_950)}
kernels_by_name = {v.name: v for v in _all_bpreshuffle_kernels.values()}
csrc/ck_gemm_a8w8_blockscale/gemm_a8w8_blockscale_cktile_instance.py:153
{**expand_blockpercu(kernels_list_942), **expand_blockpercu(kernels_list_95x)}merges by integer ID, so keys collide (both dicts start at 0) and one arch’s kernels are silently dropped. That defeats the purpose of including all arches for multi-target builds. Buildcandidate_kernels_by_namefrom the concatenated values instead (and reusecandidate_kernels_cktile_dictfor the current arch).
_all_cktile_kernels = {**expand_blockpercu(kernels_list_942), **expand_blockpercu(kernels_list_95x)}
candidate_kernels_by_name = {v.name: v for v in _all_cktile_kernels.values()}
{**a, **b} merge drops entries because both arches use overlapping
integer IDs (0, 1, ...). Use list(values) + list(values) instead to
collect all kernel instances before building the name lookup dict.
Copilot review caught this on the previous push.
Signed-off-by: Mustafa Yildirim <mustafa@character.ai>
|
please fix code style check, so it can run ci tests. |
|
Here's a merge that adds the linebreaks from the black formatter, which should fix the code style errors and unblock the ci tests: mustafayildirim/aiter@mustafa/gemma4-31b-blockscale-tuned-gemm...dwiddows:aiter:dwiddows/pr5062-black-wraps |
CI Black 26.5.1 failed Checks on these two 88-char lines; GPU jobs never ran. Signed-off-by: Dominic Widdows <dwiddows@amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Upstream commit 3b2a9ce removed aiter/ops/flydsl/utils.py entirely and replaced the LDS checks with chip_info.get_lds_capacity_bytes(). Our FLYDSL_GPU_ARCH override in utils.py is now dead code that also causes merge conflicts. Drop both the util change and its test. Signed-off-by: Mustafa Yildirim <mustafa@character.ai>
…blockscale-tuned-gemm
|
Fixed both items:
The PR diff is now minimal: the Gemma-4-31B tuned CSV (85 CK entries) + the multi-arch |
There was a problem hiding this comment.
🟢 Approval recommended
The changes are consistent with existing tuned-config discovery/format and the multi-target kernelName registry fix aligns with how build_tune_dict validates CSV rows across multiple GPU_ARCHS targets.
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0 new
- Review effort level: Lite
# Conflicts: # csrc/cktile_gemm_a8w8_bpreshuffle/gemm_a8w8_bpreshuffle_cktile_common.py
|
Rebased onto latest main (39 new upstream commits, including #5280 which adds the |
There was a problem hiding this comment.
🟡 Changes recommended
The shipped tuned CSV appears to be missing at least one claimed-covered (M,N,K) shape, creating a discrepancy with the PR description and forcing a fallback to default dispatch for that shape.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
Summary
Add per-model tuned GEMM configurations for
google/gemma-4-31B-itserved with FP8 block-scale quantization (RedHatAI/gemma-4-31B-it-FP8-block).The tuned configs cover 85 (M,N,K) shapes — 7 unique weight shapes × 13 batch sizes (M=1..16384) — including:
Notable wins:
kernelId=8 splitK=0Tuning details
csrc/ck_gemm_a8w8_blockscale/gemm_a8w8_blockscale_tune.py--libtype ck --splitK --shape_grouped --warmup 5 --iters 101vllm/vllm-openai-rocm:v0.28.0image — including them causesRuntimeErrorat vLLM startup on that image. The 3 CKTile shapes fall back to default CK (no regression); they can be added back once a vLLM image ships an aiter build that includes this CSV in its prebuild manifest.Correctness
All 85 entries have errRatio ≤ 0.01 (max = 0.0032, atol/rtol = 0.01).
Multi-target build fix
Also fixes a pre-existing bug in
candidate_kernels_by_name(bothgemm_a8w8_blockscale_cktile_instance.pyandgemm_a8w8_bpreshuffle_cktile_common.py) where the name registry was built from only the currentget_gfx()arch. In a multi-target build (GPU_ARCHS=gfx942;gfx950), this caused codegen to crash on cross-arch kernel names. Fix: makekernels_by_namethe union of all arch kernel lists (usinglist(values) + list(values)to avoid integer-key collisions). Reported by @yzhou103.Branch state
Rebased onto upstream main (Sep 2026). The diff is 3 files: the tuned CSV plus the multi-arch name-registry fix in the two cktile instance/common files. A previously included FlyDSL LDS override was dropped as obsolete after upstream #5116 removed
aiter/ops/flydsl/utils.py.Remaining uncovered shapes
6 shapes have no CK tuning and fall back to the default CK config (same as current behavior, no regression):
The 3 CKTile rows can be restored once a vLLM image ships an aiter build whose prebuild manifest includes this CSV. The 3 lm_head shapes need new CK kernel instances (C++ CK template work) — tracked as a follow-up.
How it works
The file is auto-discovered by aiter's
model_configs/glob — no env var or code change needed. Any deployment using aiter with a Gemma-4-31B FP8-block model picks up these tuned configs automatically.Verification
module_gemm_a8w8_blockscale_cktile.sofrom this branch compiles the previously-missing128x128x128_1x4x1_16x16x64BPC≥2 variants, after which the full 88-entry CSV (85 CK + 3 CKTile) loads and runs without errors.AI assistance was used. All tuned entries were verified for numerical correctness by the tuner.