Skip to content

Feature Request: Vulkan: retune coopmat/MMQ tiles for RDNA3.5 / Strix Halo prefill #28843

Description

@Ankk98

Prerequisites

  • I am running the latest code. Mention the version if possible as well.
  • I carefully followed the README.md.
  • 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.

Measurements / observations

Setup: Radeon 8050S (32 CU), RADV / Mesa 26.1.8, uma:1, Qwen3.8-27B
UD-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/s
  • 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)
  • 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_l
    stays 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/B for int path
  • vulkan-shaders/mul_mmq_funcs.glsl — int-dot dequant + dot
  • Unmerged prototype branch: 0cc4m/vulkan-coopmat-int8
    (mul_mmq_cm1.comp, int8 coopmat MMQ, tip 918f32dcf)

Proposed behavior

  1. 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.
  2. Generic AMD path and all other vendors/drivers stay exactly as now.
  3. 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.

Notes

  • Assisted by a coding AI agent
  • Current Commit: 002a12a

Motivation

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions