Skip to content

ggml-webgpu: tune subgroup split (d_split) in flash_attn_vec#25418

Merged
yomaytk merged 1 commit into
ggml-org:masterfrom
yomaytk:improve-fa
Jul 8, 2026
Merged

ggml-webgpu: tune subgroup split (d_split) in flash_attn_vec#25418
yomaytk merged 1 commit into
ggml-org:masterfrom
yomaytk:improve-fa

Conversation

@yomaytk

@yomaytk yomaytk commented Jul 7, 2026

Copy link
Copy Markdown
Member

Overview

This PR adds tuning of D_SPLIT (= subgroup_size / VEC_NE, where VEC_NE was the value hardcoded on master) in flash_attn_vec to split the subgroup when accumulating Q * K and P * V, based on head_dim and subgroup_size, instead of hardcoding it. The following table shows the TG performance improvement when the context length reaches 16K.

The command is like this: llama-bench -m Llama-3.2-3B-Instruct-Q4_K_M.gguf -fa 1 -p 0 -n 128 -d 16384 -r 3 -dev WebGPU

NVIDIA V100

Model master (t/s) PR (t/s) Speedup
gemma4 E4B Q4_K_M 26.02 ± 0.16 27.21 ± 0.15 +4.6%
gpt-oss 20B MXFP4 MoE 26.35 ± 0.37 27.78 ± 0.36 +5.4%
llama 3B Q4_K_M 25.55 ± 1.44 34.78 ± 2.57 +36.1%

M2

Model master (t/s) PR (t/s) Speedup
gemma4 E4B Q4_K_M 6.79 ± 1.53 6.83 ± 1.50 +0.6%
gpt-oss 20B MXFP4 MoE 20.12 ± 0.17 22.22 ± 0.16 +10.4%
llama 3B Q4_K_M 18.18 ± 0.05 20.18 ± 0.01 +11.0%

This tuning is similar to the Vulkan backend. In practice, VEC_NE is set to 8 in many cases, and I can confirm that it performs better than other values of master branch.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: Yes, I used AI to investigate vulkan's flash attention implementation, and analyze the performance logs.

@yomaytk yomaytk requested a review from a team as a code owner July 7, 2026 21:56
@github-actions github-actions Bot added ggml changes relating to the ggml tensor library for machine learning WebGPU labels Jul 7, 2026
if (key.common.k_type == GGML_TYPE_F16 && key.common.v_type == GGML_TYPE_F16) {
const uint32_t D = key.common.head_dim_qk | key.common.head_dim_v;
const uint32_t D_lsb = D & (~(D - 1u));
d_split = std::min(std::min(context.min_subgroup_size, 4u), std::max(D_lsb / 4u, 1u));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vulkan sets this upper limit of D_SPLIT to 8u, but I can confirm that 4u works better on both M2 and V100.

@reeselevine

Copy link
Copy Markdown
Contributor

pretty nice speedups!

@yomaytk

yomaytk commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@ggml-org/maintainers can I get a second review please?

@yomaytk yomaytk merged commit 32e41fa into ggml-org:master Jul 8, 2026
26 of 29 checks passed
@yomaytk yomaytk deleted the improve-fa branch July 8, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ggml changes relating to the ggml tensor library for machine learning WebGPU

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants