Skip to content

GLM-DSA: improve TG performance#2067

Merged
ikawrakow merged 1 commit into
mainfrom
ik/glm_dsa_opt2
Jul 2, 2026
Merged

GLM-DSA: improve TG performance#2067
ikawrakow merged 1 commit into
mainfrom
ik/glm_dsa_opt2

Conversation

@ikawrakow

Copy link
Copy Markdown
Owner

As part of the effort to reduce the compute buffer sizes required for GLM-DSA, the indexer computation was done in a loop over indexer attention heads.

This PR changes the approach for small batches (<=8) to compute the indexer score via a single matrix multiplication. RELU, and sum over attention heads. The change is limited for batch sizes <=8 to preserve the compute buffer reduction of the loop over attention heads.

The change improves GLM-DSA TG performance by nearly 10%.

DSA is still slower than no-DSA, but hopefully we can improve that in follow up PRs.

Below are some sweep-bench results with this PR compared to no-DSA. GLM-5.2-Q4_K_M, 13x3090 (limited to 200W each), Ryzen-3995WX CPU. Command line is

GGML_CUDA_NO_PINNED=1 ./bin/llama-sweep-bench \
    -m /zfsdata/data/GLM-5.2-GGUF/UD-Q4_K_M/GLM-5.2-UD-Q4_K_M-00001-of-00011.gguf \
    -t 64 -ngl 100 -b 4096 -ub 4096 -c 20480 -n 64 -amb 256 \
    --fit --fit-margin 2048 --gpu-fit-margin 0,614

which results in routed experts in 37 layers being left in RAM.

No DSA

PP TG N_KV T_PP s S_PP t/s T_TG s S_TG t/s
4096 64 0 23.851 171.73 5.764 11.10
4096 64 4096 28.275 144.86 5.958 10.74
4096 64 8192 32.856 124.66 6.118 10.46
4096 64 12288 37.068 110.50 6.245 10.25
4096 64 16384 41.191 99.44 6.388 10.02

DSA, this PR

PP TG N_KV T_PP s S_PP t/s T_TG s S_TG t/s
4096 64 0 25.027 163.66 5.860 10.92
4096 64 4096 30.496 134.31 6.183 10.35
4096 64 8192 35.914 114.05 6.419 9.97
4096 64 12288 40.847 100.28 6.613 9.68
4096 64 16384 45.941 89.16 6.776 9.45

@ikawrakow
ikawrakow merged commit dbe2ecb into main Jul 2, 2026
ikawrakow pushed a commit that referenced this pull request Jul 2, 2026
)

The batch >8 indexer path in build_deepseek2_dsa_indexer accumulates the
per-head scores with ggml_add_inplace into an accumulator that is seeded
from a view of KQ_mask. On -fa 0, KQ_mask is the raw F32 input tensor, so
the in-place writes land in the shared KQ_mask buffer and corrupt the causal
mask that build_deepseek2_dsa_sparse_mask and the later softmax layers read
back, which gives garbage perplexity.

-fa 1 is unaffected (its F16 mask is cast to a private F32 buffer), and the
small-batch path added in #2067 is unaffected (it uses a non-inplace add).
Take a private copy of the seed in the batch >8 -fa 0 path (raw F32 mask)
before the accumulation, matching what those two paths already do.

4K -fa 0 --dsa PPL goes from thousands to 2.7134 (dense 2.6972, -fa 1 --dsa
2.7111). -fa 1 and non-DSA builds are byte-identical.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ikawrakow pushed a commit that referenced this pull request Jul 3, 2026
#2071)

- fix incorrect reshape in the small-batch (n_tokens <= 8) indexer path
- anchor inp_dsa_sink in the graph with ggml_build_forward_expand
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant