ggml-cuda: fix divergent barrier in f16 flash attention - #27870
Merged
ggerganov merged 2 commits intoSep 7, 2026
Merged
Conversation
Contributor
Author
|
The issue is still reproducible on the latest |
Contributor
Author
|
@JohannesGaessler would you be able to take a look at his PR? It fixes the FlashAttention issue described above. |
Comment on lines
+1503
to
+1504
| const int jc_meta = threadIdx.y*cols_per_warp + (np*cols_per_warp < warp_size ? threadIdx.x % (np*cols_per_warp) : threadIdx.x); | ||
| const float2 * const meta_ptr = ((float2 *) tile_Q) + jc_meta*(tile_stride/2) + nbatch_combine/2; |
Contributor
There was a problem hiding this comment.
Move these outside the conditional statement in order to have only one place where they are defined.
siavashnorouzi
force-pushed
the
fix-27678-fattn-barrier
branch
from
September 5, 2026 01:48
ddc7fa9 to
c4b9b7e
Compare
JohannesGaessler
approved these changes
Sep 5, 2026
x1250
pushed a commit
to x1250/llama.cpp
that referenced
this pull request
Sep 9, 2026
* ggml-cuda: fix divergent barrier in f16 flash attention * ggml-cuda: avoid duplicate metadata pointer setup
zbrad
pushed a commit
to zbrad/llama.cpp
that referenced
this pull request
Sep 10, 2026
* ggml-cuda: fix divergent barrier in f16 flash attention * ggml-cuda: avoid duplicate metadata pointer setup
Contributor
Author
|
Thank you @JohannesGaessler for taking the time to review this and @ggerganov for merging it. I really appreciate it and am looking forward to contributing more! |
1 task done
1 task
pl752
pushed a commit
to pl752/llama.cpp
that referenced
this pull request
Sep 15, 2026
* ggml-cuda: fix divergent barrier in f16 flash attention * ggml-cuda: avoid duplicate metadata pointer setup
zsogitbe
pushed a commit
to zsogitbe/llama.cpp
that referenced
this pull request
Sep 17, 2026
* ggml-cuda: fix divergent barrier in f16 flash attention * ggml-cuda: avoid duplicate metadata pointer setup
crusaderky
added a commit
to crusaderky/llama.cpp
that referenced
this pull request
Sep 18, 2026
Port of upstream ggml-org/llama.cpp ggml-org#27870 (b74f590, PR by Siavash Norouzi), adapted to keep the beellama 0xFFFFFFFFULL shuffle masks and the KVarN dst_final_meta whole-tile publishing block. The old shape (kept since ggml-org#13469) put the meta-combine __syncthreads() inside 'if (np > 1 && threadIdx.y % np == 0)' with a separate 'else if (np > 1) __syncthreads()'. The paired barriers are formally divergent per the CUDA spec, and in practice the if-branch's post-barrier meta write-back races with the other warps re-entering the tile_Q reuse loop, which corrupts attention output data- and timing-dependently. This is the root cause of the catastrophic per-chunk KLD/PPL blowups seen on K2-Horizon-7B (GQA ratio 4, head dim 128 -> np = 4) with f16/bf16 KV caches and any exact tail: f16/f16, kvarn4 (intrinsic f16 tail) and bf16-tail runs collapse on whole chunks (chunk-9 PPL 5.11 -> 10.68 on Q5_K_M|f16) while quantized-body runs without a tail stay clean because they dispatch to fattn-vec. CPU runs of the same chunks/configs are clean, isolating the fault to this CUDA kernel. Restructure per upstream: all threads enter 'if (np > 1)', the combine reads run under 'threadIdx.y % np == 0', the __syncthreads() is unconditional, and the write-back runs after it under the same guard.
Te-eMster
pushed a commit
to Te-eMster/mx-llama.cpp
that referenced
this pull request
Sep 18, 2026
* ggml-cuda: fix divergent barrier in f16 flash attention * ggml-cuda: avoid duplicate metadata pointer setup
marcospaulo
added a commit
to torad-labs/llama.cpp
that referenced
this pull request
Oct 1, 2026
…barrier (upstream b74f590) process_tile's combine for np > 1 had one __syncthreads() inside threadIdx.y % np == 0 and another in the else branch: a barrier the warps reached at different instructions. Every warp now reaches one barrier, and the combine and the write-back run in the np == 0 warps around it. Ported by hand from ggml-org/llama.cpp b74f590 (ggml-org#27870). No arithmetic changes. Measured against c986f0c's build: - compute-sanitizer synccheck on the RTX 5070 Ti: upstream's repro (hsk=192 hsv=128 nh=4 [8,1] kv=512 nb=3) 3680 errors before, 0 after; GLM-5.3's cases (512/512 [64,1] 8192, sparse, nb 1 and 3) 512 before, 0 after. - test-backend-ops FLASH_ATTN_EXT 3229/3229 on both cards. - PPL bit for bit: 386825.5220 (-c 256 -ub 1), 388534.0622 (-ub 3), 387892.2627 (-sm tensor), 349039.3239 (-c 8192 -sm tensor). - Kernel time, ncu at base clocks with L2 flushed (gpu__time_duration of flash_attn_ext_f16 over GLM's grid, 3 cache lengths x 8 batches, sparse and dense, 48 cells): new/base within 1.79 %; the instrument's base/base spread 1.44 %. Co-authored-by: Siavash Norouzi <35790025+siavashnorouzi@users.noreply.github.com>
oshbec
referenced
this pull request
in oshbec/llama.cpp
Oct 5, 2026
Hypothesis: every prefill FA launch for head_dim 256 was the scalar flash_attn_tile<256,256>, because fattn.cu gated the AMD WMMA (MMA_F16) path on D <= 128. FA was 59% of prefill at 32K depth and ~85% at 128K. Change (RDNA4 under HIP only; every other arch keeps the old expressions): - Port of upstream ggml-org/llama.cpp #28102 (gfx1201 FA tuning): WMMA for D=256 once Q rows * gqa_ratio_eff > 16; ncols2 chosen to divide the GQA ratio at D=256 (GQA 6 -> 2); RDNA D=256 config rows; stream-k only when tile efficiency < 75% (D=64 always). - Port of upstream #27870: divergent __syncthreads in the np>1 combine. - Ours: D=256 ncols=64 config stages Q in LDS with 32-half2 K/V chunks (Q_in_reg=false): VGPR spills 424 -> 48, FA kernel 5.44 -> 4.33 ms at 16K KV, 32.5 -> 27.7 ms at 64K. - test-backend-ops: model-shape cases (D=256, 4 KV heads, GQA 6; KV 512/4096/8192; nb 1..512 and 1024/1030 for -ub 1024; q8_0 KV). Benchmark (RX 9070 XT, Bonsai 2 27B PQ2_0, llama-bench -r 2): Before (deddbab): pp2048 @ 32K depth 518 t/s; pp512 1168; tg128 49.8 After: pp2048 @ 32K depth 906 t/s (+75%); pp512, tg128 same Earlier run (upstream config): @64k q8_0 340 -> 704, @128k 199 -> 498. Agent edit workload (ngram-mod + MTP draft 3, ~33-97-token verify batches, which now take the WMMA kernel): 307.2 -> 316.8 t/s, same acceptance. VRAM +32 MiB. Correctness: test-backend-ops FLASH_ATTN_EXT 2952/2952 (15/15 at the model shape). PPL (wikitext-2, 20 chunks) 7.8773 -> 7.8695 (-0.10%), identical at -ub 512 and -ub 1024; KLD vs previous 1.45e-4, same as the model's own ub1-vs-ub512 noise (1.57e-4): fp reduction order in attention. Decode (1 token) and MTP verify (<= 4 tokens) stay on the old kernels. Decision: KEEP Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
The issue #27678 reported a divergent block-wide barrier in the
flash_attn_ext_f16_process_tilekernel revolving around a block-wide__syncthreads()in the metadata-combine process.I moved the block-wide synchronization out of the
threadIdx.y % np == 0branch so all threads in thenp > 1case reach the same__syncthreads(), while keeping the metadata calculation and SHMEM writeback limited to the intended warps.Additional information
The reporter shared that
compute-sanitizerreveals this issue:which reports thousands of divergent-barrier errors.
The issue was initially reported on RTX 4070, CUDA toolkit 13.3.73, driver 610.57.04. I was able to reproduce, fix, and test the fix on RTX 5090, CUDA 13.3, driver 610.43.02.
compute-sanitizerreports 3232 errors before and 0 after this fix.Also, measured performance before and after this commit by running this config:
and the results are:
Therefore, No measurable performance regression.
Requirements