You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
I reviewed the Discussions, and have a new and useful enhancement to share.
Feature Description
Add a Strix Halo (gfx1151 / RDNA3.5) specific tuning for the Vulkan KHR_cooperative_matrix (coopmat) matrix-multiply tiles, to make prompt processing (prefill) faster on models like Qwen3.8-27B.
Today the AMD coopmat path uses one generic large tile for all AMD cards; Strix Halo is an integrated GPU with its own cache sizes and wavefront behavior, so it should get its own tile sizes, picked by measuring.
Prefill is >90% GEMM (MUL_MAT), all on the coopmat/MMQ path:
shape
iq4_xs
q4_K
q5_K
m=17408, k=5120 (FFN up/gate)
69x 2087us (10.9 TFLOPS)
17x 2084us (11.0 TFLOPS)
14x 2045us (11.2 TFLOPS)
m=5120, k=17408 (FFN down)
29x 2587us (8.8 TFLOPS)
12x 2533us (9.0 TFLOPS)
14x 2718us (8.4 TFLOPS)
Path checks (same flags, prove which code runs):
GGML_VK_DISABLE_COOPMAT=1 → pp128 falls to 106.21 (-45%), tg32
unchanged. So prefill runs on coopmat, decode does not.
GGML_VK_DISABLE_INTEGER_DOT_PRODUCT=1 → pp128 falls to 174.53
(-10%), tg32 unchanged. So the integer-dot MMQ path is active in
prefill with a modest share.
History: PR #18749 (generic AMD large tile {256,128,128}) gave
+35-75% prefill on 8060S. That tile reuses medium TM/TN/TK values and
was never specialized for gfx1151. The card reports only 16x16x16
fp16/int8 coopmat shapes (verified with a Vulkan probe), so there is
room left in workgroup geometry, subgroup size, and LDS traffic.
Related files and functions
All in ggml/src/ggml-vulkan/ (line numbers at HEAD 002a12ad2):
ggml-vulkan.cpp:4540-4545 — AMD+coopmat large-tile override
(this is where a gfx1151 branch goes)
ggml-vulkan.cpp:4490-4498 — tm/tn/tk from probed coopmat_m/n/k
ggml-vulkan.cpp:4568-4627 — shared-memory guards that silently
disable tiles that do not fit (must check when adding tiles)
Unmerged prototype branch: 0cc4m/vulkan-coopmat-int8
(mul_mmq_cm1.comp, int8 coopmat MMQ, tip 918f32dcf)
Proposed behavior
Detect gfx1151 narrowly (AMD + coopmat + not proprietary driver + uma + 64 KiB shared memory + STRIX_HALO device name) and give it
its own l/m_warptile_mmq* values, found by measurement: first
BM/BN/BK geometry (including non-square), then subgroup 32 vs 64,
then LOAD_VEC_A / LDS bank padding per quant type.
Generic AMD path and all other vendors/drivers stay exactly as now.
Longer term: rebase and evaluate the int8-coopmat prototype branch,
starting with NVFP4 (simple dequant, already in the upstream MMQ
type lists) before attempting iq4_xs.
Prefill at n=128 is compute-bound (about 380 FLOP/byte vs a machine balance of about 325), while decode (n=1) is memory-bandwidth-bound near the ~200 GB/s wall. So tile tuning moves prefill/TTFT without being able to hurt decode much and the per-shape table above shows prefill GEMM at ~9-11 TFLOPS against a ~65 TFLOPS WMMA roof, i.e. mostly headroom. Prior art (#18749) already proved tiles alone can move Strix Halo prefill by tens of percent.
Possible Implementation
Step 1: sweep l_mmq BM/BN/BK ({256,128,128} vs {256,64,128}
vs {128,128,128} vs {256,128,64}) and m_mmq at n=128;
keep s tiles stable; verify each candidate survives the matmul_shmem_support guard via GGML_VK_PERF_LOGGER=1.
Step 2: clone the winner with WARP 64 -> 32 (RDNA3 is natively
wave32; current tiles use 64).
Step 3: LOAD_VEC_A 4 -> 8 for q4_K/q5_K/iq4_xs int paths, SHMEM_STRIDE_PAD 8 vs 4/16 on the winning tile.
Step 4: measure (do not assume) B-operand layout per dtype; expect
~0% on fp16.
Step 5: rebase 0cc4m/vulkan-coopmat-int8, test-backend-ops all
covered quants, measure pp128/512/2048 + tg32; NVFP4 first, then
consider iq4_xs (43.8% of prefill, covered nowhere today).
Bench rule: matched -b/-ub flags, cool-downs, tg32 guard on every
step, test-backend-ops on every tile change. Tiles must stay
bit-identical (same accumulation order) or pass greedy exact-match
(--temp 0 --top-k 1 --seed 42).
Prerequisites
Feature Description
Add a Strix Halo (gfx1151 / RDNA3.5) specific tuning for the Vulkan KHR_cooperative_matrix (coopmat) matrix-multiply tiles, to make prompt processing (prefill) faster on models like Qwen3.8-27B.
Today the AMD coopmat path uses one generic large tile for all AMD cards; Strix Halo is an integrated GPU with its own cache sizes and wavefront behavior, so it should get its own tile sizes, picked by measuring.
Measurements / observations
Setup: Radeon 8050S (32 CU), RADV / Mesa 26.1.8,
uma:1, Qwen3.8-27BUD-Q4_K_S,-p 128 -n 32 -b 128 -ub 128 -r 3 -fa on -ngl 99:pp128: 194.13 ± 1.45 t/s,tg32: 12.86 ± 0.10 t/sMUL_MAT), all on the coopmat/MMQ path:Path checks (same flags, prove which code runs):
GGML_VK_DISABLE_COOPMAT=1→ pp128 falls to 106.21 (-45%), tg32unchanged. So prefill runs on coopmat, decode does not.
GGML_VK_DISABLE_INTEGER_DOT_PRODUCT=1→ pp128 falls to 174.53(-10%), tg32 unchanged. So the integer-dot MMQ path is active in
prefill with a modest share.
History: PR #18749 (generic AMD large tile
{256,128,128}) gave+35-75% prefill on 8060S. That tile reuses medium TM/TN/TK values and
was never specialized for gfx1151. The card reports only
16x16x16fp16/int8 coopmat shapes (verified with a Vulkan probe), so there is
room left in workgroup geometry, subgroup size, and LDS traffic.
Related files and functions
All in
ggml/src/ggml-vulkan/(line numbers at HEAD002a12ad2):ggml-vulkan.cpp:4540-4545— AMD+coopmat large-tile override(this is where a gfx1151 branch goes)
ggml-vulkan.cpp:4490-4498—tm/tn/tkfrom probedcoopmat_m/n/kggml-vulkan.cpp:4568-4627— shared-memory guards that silentlydisable tiles that do not fit (must check when adding tiles)
ggml-vulkan.cpp:4166-4289—ggml_vk_matmul_shmem_support/ggml_vk_matmul_int_shmem_support(LDS budget math)ggml-vulkan.cpp:7320-7327— AMD tile enables (mul_mat_id_lstays
false, see Eval bug: vulkan: enable large warptile for MUL_MAT_ID on AMD with coopmat #23106)vulkan-shaders/mul_mm.comp:43-47,161-192,383-386—LOAD_VEC_A,spec constants, hardcoded A-RowMajor / B-ColumnMajor coop loads
vulkan-shaders/mul_mmq.comp:103-104—LOAD_VEC_A/Bfor int pathvulkan-shaders/mul_mmq_funcs.glsl— int-dot dequant + dot0cc4m/vulkan-coopmat-int8(
mul_mmq_cm1.comp, int8 coopmat MMQ, tip918f32dcf)Proposed behavior
uma+ 64 KiB shared memory +STRIX_HALOdevice name) and give itits own
l/m_warptile_mmq*values, found by measurement: firstBM/BN/BK geometry (including non-square), then subgroup 32 vs 64,
then
LOAD_VEC_A/ LDS bank padding per quant type.starting with NVFP4 (simple dequant, already in the upstream MMQ
type lists) before attempting
iq4_xs.Notes
Motivation
Prefill at
n=128is compute-bound (about 380 FLOP/byte vs a machine balance of about 325), while decode (n=1) is memory-bandwidth-bound near the ~200 GB/s wall. So tile tuning moves prefill/TTFT without being able to hurt decode much and the per-shape table above shows prefill GEMM at ~9-11 TFLOPS against a ~65 TFLOPS WMMA roof, i.e. mostly headroom. Prior art (#18749) already proved tiles alone can move Strix Halo prefill by tens of percent.Possible Implementation
l_mmqBM/BN/BK ({256,128,128}vs{256,64,128}vs
{128,128,128}vs{256,128,64}) andm_mmqatn=128;keep
stiles stable; verify each candidate survives thematmul_shmem_supportguard viaGGML_VK_PERF_LOGGER=1.WARP 64 -> 32(RDNA3 is nativelywave32; current tiles use 64).
LOAD_VEC_A4 -> 8 forq4_K/q5_K/iq4_xsint paths,SHMEM_STRIDE_PAD8 vs 4/16 on the winning tile.~0% on fp16.
0cc4m/vulkan-coopmat-int8,test-backend-opsallcovered quants, measure pp128/512/2048 + tg32; NVFP4 first, then
consider
iq4_xs(43.8% of prefill, covered nowhere today).-b/-ubflags, cool-downs, tg32 guard on everystep,
test-backend-opson every tile change. Tiles must staybit-identical (same accumulation order) or pass greedy exact-match
(
--temp 0 --top-k 1 --seed 42).