[CK_TILE][FMHA] Fix sink un-mask under right-window and emit fp8bf16 batch_prefill sink kernels - #6914
Merged
Merged
Conversation
Add F_sink ∈ {t,f} to the fp8bf16 codegen loop so that fp8bf16 +
kv_blockscale variants also produce kernel instances supporting
StreamLLM sink token. The underlying qr_async pipeline already gates
sink logic via constexpr kHasSink, so this only widens the dispatch
table; non-sink callers keep using the existing _nsink_* blobs.
Made-with: Cursor
The previous sink un-mask predicate ((i_y + x) > 1) gated on the query
row index instead of the key column, with two consequences:
- For causal masking (x = 1) and sink_size = S, queries 1..S-1
attended to their own future sink positions (i_x in (i_y, sink)),
breaking autoregressive correctness.
- Query 0 was *excluded* from sink un-mask entirely and fell back to
the plain causal mask, so it could not attend to any sink position
other than column 0.
Replace the row-side guard with the column-side bound (i_x < i_y + x),
which lets sink un-mask precisely those sink columns that lie inside
the query's causal/right-window past, restoring StreamLLM semantics.
Made-with: Cursor
Replace the historical fix-rationale note above the sink un-mask check with a clause-by-clause explanation of i_x < sink, i_x < i_y + x, y < y_total, and i_y < x_total so future readers can map the predicate to the StreamLLM sink + sliding-window semantics directly. Co-authored-by: AI Coding Agent Made-with: Cursor
LJ-underdog
marked this pull request as ready for review
April 29, 2026 04:39
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR fixes StreamLLM sink + sliding-window behavior in ck_tile FMHA masking and updates fp8(KV)/bf16(QO) batch-prefill codegen to emit sink-enabled kernels for correct runtime dispatch.
Changes:
- Fix sink “unmask” gating under right-window/local masking by using a column-based predicate (
i_x < i_y + x) instead of a row-based gate. - Emit fp8bf16 batch-prefill pipeline variants with
F_sinkenabled (t/f) so sink-aware kernels can be generated and dispatched. - Improve inline documentation explaining the sink unmask predicate.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| projects/composablekernel/include/ck_tile/ops/fmha/block/block_masking.hpp | Adjusts sink unmask predicate to respect right-window and clarifies predicate documentation. |
| projects/composablekernel/example/ck_tile/01_fmha/codegen/ops/fmha_batch_prefill.py | Extends fp8bf16 batch-prefill pipeline generation to include sink-enabled variants. |
Comments suppressed due to low confidence (1)
projects/composablekernel/include/ck_tile/ops/fmha/block/block_masking.hpp:269
i_x < i_y + xis described as “< x_end modulo the min with x_total”, but it does not actually enforce themin(..., x_total)part. Ifi_y + x > x_totalandsink > x_total, this predicate can unmask sink columnsi_xthat are already out of range w.r.t.x_total, while the rest of the masking logic usesx_endas the true upper bound. Consider usingi_x < x_endin the sink-unmask condition (it matches the effective right boundary in both the padded and non-padded cases).
index_t x_start = -y + i_y + 1;
index_t x_end = min(i_y + x, x_total);
// Sink un-mask predicate, clause by clause:
// i_x < sink : the column lives inside the StreamLLM sink prefix.
// i_x < i_y + x : the column is not in the masked-out future of the
// window (= < x_end modulo the min with x_total);
// without this, queries <= sink-1 would be allowed
// to look at later sink rows than they should under
// causality / right-window.
// y < y_total : the local window doesn't already span everything
// (otherwise sink un-mask is meaningless).
// i_y < x_total : the query row is in-range vs. the key sequence
// (handles seqlen_q > seqlen_k padding).
if constexpr(IsLocal)
{
if((i_x < sink) && (i_x < i_y + x) && (y < y_total) && i_y < x_total)
return false;
else
return i_x < x_start || i_x >= x_end;
}
else
{
if((i_x < sink) && (i_x < i_y + x) && (y < y_total) && i_y < x_total)
return false;
else
return i_x >= x_end || i_y >= y_total;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
poyenc
reviewed
Apr 29, 2026
In get_pipelines() for both fp16/bf16 and fp8bf16 dispatch tables, the
sink axis is iterated together with the mask axis via itertools.product,
which produces (sink="t", mask="no") and (sink="t", mask="s_no") rows
that the underlying qr_async pipeline cannot meaningfully run: kHasSink
only takes effect when a real causal/right-window mask is in play, so
those instances would compile to dead kernels that no caller ever
dispatches.
Add a `continue` guard in both branches that skips the sink="t" rows
whenever mask is one of the no-op variants ("no", "s_no"), shrinking
the emitted kernel matrix without losing any dispatchable shape.
Addresses review feedback from poyenc on PR #6914.
Co-authored-by: AI Coding Agent
Made-with: Cursor
2 tasks
Contributor
|
LGTM |
poyenc
approved these changes
Apr 30, 2026
poyenc
enabled auto-merge (squash)
April 30, 2026 03:33
Jeff-Huang
approved these changes
Apr 30, 2026
asleepzzz
approved these changes
May 7, 2026
assistant-librarian Bot
pushed a commit
to ROCm/composable_kernel
that referenced
this pull request
May 7, 2026
[CK_TILE][FMHA] Fix sink un-mask under right-window and emit
fp8bf16 batch_prefill sink kernels (#6914)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
Two related fixes to `ck_tile` FMHA so that StreamLLM-sink +
sliding-window
batch-prefill works correctly for fp8 KV / bf16 compute.
Review the commits in this order:
1. `fmha: emit sink kernels for fp8bf16 batch_prefill`
Extends `example/ck_tile/01_fmha/codegen/ops/fmha_batch_prefill.py` so
the fp8(KV) / bf16(QO) batch-prefill codegen also emits the
`mask=mask_enum::generic_with_sink` variant. Without this the runtime
could not dispatch to a sink-aware kernel for the fp8bf16 path.
2. `fmha: respect right-window in IsOutOfSinkBound`
The sink un-mask in `GenericAttentionMask::IsOutOfSinkBound` (local-mask
branch) used `(i_y + x) > 1` as the gate, which conditioned on the row
index instead of the column index. As a result, queries `1..sink-1`
could attend to *future* sink positions (violating causal /
right-window),
while query `0` fell back to the plain causal mask. The fix replaces the
guard with `i_x < i_y + x` so every query only sees sink columns up to
its own right-window boundary.
3. `fmha: clarify IsOutOfSinkBound predicate comment`
Doc-only follow-up that rewrites the comment above the predicate as a
clause-by-clause explanation (`i_x < sink`, `i_x < i_y + x`,
`y < y_total`, `i_y < x_total`).
## Test plan
- [x] Repro on aiter `op_tests/test_batch_prefill.py` (fp8 +
bf16_dequant
modes with `sink=4`, `win_left=1023`, `softcap=0.0`, `sal=True`)
now passes for all parametrized shapes.
- [x] Existing fp16/bf16 batch-prefill paths (no sink) unchanged —
codegen
diff only adds the `generic_with_sink` variant for fp8bf16; existing
kernel object lists unaffected.
## Submission Checklist
- [x] Look over the contributing guidelines at
https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests.
1 task
LJ-underdog
added a commit
that referenced
this pull request
May 13, 2026
…7272) ## Summary In `fmha_bwd_runner.hpp`, the `sink_host` `HostTensor` is allocated with first dimension `shape_batch` (= 1 in group mode), but the reference forward loop accesses `sink_host(wb, i_h)` with `wb ∈ [0, batch-1]`. For any `wb >= 1` this is an out-of-bounds heap read, silently corrupting the reference forward math chain (`lse_host`, `o_host`) and turning the bwd-side `d_sink_head_acc` reference into non-deterministic garbage. `HostTensor::operator()` does not bounds check, so the OOB is not caught at runtime. This manifests as intermittent `tile_example_fmha_bwd` failures (25–67% fail rate) when `-sink_grad=1` is combined with `-mode=1` (group mode), with bit-exact but spurious `max_err` values like 4.27 / 14.6. ## Fix One-line: allocate `sink_host` with `batch` (the real per-batch dim) instead of `shape_batch`, mirroring how `sink_host` is accessed by the loop. ```diff - sink_grad ? std::array<ck_tile::index_t, 2>{shape_batch, nhead} + sink_grad ? std::array<ck_tile::index_t, 2>{batch, nhead} Repro tile_example_fmha_bwd -b=2 -h=2 -s=516 -s_k=253 -prec=bf16 -d=72 \ -bias=n -dbias=0 -p_drop=0 -iperm=1 -operm=1 -deterministic=0 \ -v=3 -mode=1 -kname=1 -sink_grad=1 Verification - 0/30 fail on the repro config after fix - Baselines (before fix): - sink=1, mask=n: 25% fail rate (p ≈ 1.8e-4) - sink=1, mask=t: 67% fail rate (p ≈ 6e-15) Attribution Shape bug introduced together with sink_grad in #5504. Unrelated to #6914 (which is a fwd-only fix on a different code path) ``` ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests. --------- Signed-off-by: junlin12 <junlin12@amd.com> Co-authored-by: Max Podkorytov <4273004+tenpercent@users.noreply.github.com>
valarLip
pushed a commit
to ROCm/aiter
that referenced
this pull request
May 15, 2026
Bumps 3rdparty/composable_kernel from fdf4bb7fc → 33b62ed08, the mirror merge of ROCm/rocm-libraries#6914. Also brings in the following rocm-libraries PRs that landed on the mirror between these two pins: #6152, #7046, #6932, #6912, #6972, #6574, #6741, #6209, #6701. Co-authored-by: Linjun-AMD <Jun.Lin@amd.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: LJ-underdog <105184542+LJ-underdog@users.noreply.github.com>
aledudek
pushed a commit
that referenced
this pull request
May 20, 2026
…batch_prefill sink kernels (#6914) ## Summary Two related fixes to `ck_tile` FMHA so that StreamLLM-sink + sliding-window batch-prefill works correctly for fp8 KV / bf16 compute. Review the commits in this order: 1. `fmha: emit sink kernels for fp8bf16 batch_prefill` Extends `example/ck_tile/01_fmha/codegen/ops/fmha_batch_prefill.py` so the fp8(KV) / bf16(QO) batch-prefill codegen also emits the `mask=mask_enum::generic_with_sink` variant. Without this the runtime could not dispatch to a sink-aware kernel for the fp8bf16 path. 2. `fmha: respect right-window in IsOutOfSinkBound` The sink un-mask in `GenericAttentionMask::IsOutOfSinkBound` (local-mask branch) used `(i_y + x) > 1` as the gate, which conditioned on the row index instead of the column index. As a result, queries `1..sink-1` could attend to *future* sink positions (violating causal / right-window), while query `0` fell back to the plain causal mask. The fix replaces the guard with `i_x < i_y + x` so every query only sees sink columns up to its own right-window boundary. 3. `fmha: clarify IsOutOfSinkBound predicate comment` Doc-only follow-up that rewrites the comment above the predicate as a clause-by-clause explanation (`i_x < sink`, `i_x < i_y + x`, `y < y_total`, `i_y < x_total`). ## Test plan - [x] Repro on aiter `op_tests/test_batch_prefill.py` (fp8 + bf16_dequant modes with `sink=4`, `win_left=1023`, `softcap=0.0`, `sal=True`) now passes for all parametrized shapes. - [x] Existing fp16/bf16 batch-prefill paths (no sink) unchanged — codegen diff only adds the `generic_with_sink` variant for fp8bf16; existing kernel object lists unaffected. ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests. --------- Co-authored-by: fengjunda.aml <fengjunda.aml@bytedance.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: root <root@smci350-rck-g03-f12-31.rck.dcgpu>
aledudek
pushed a commit
that referenced
this pull request
May 20, 2026
…7272) ## Summary In `fmha_bwd_runner.hpp`, the `sink_host` `HostTensor` is allocated with first dimension `shape_batch` (= 1 in group mode), but the reference forward loop accesses `sink_host(wb, i_h)` with `wb ∈ [0, batch-1]`. For any `wb >= 1` this is an out-of-bounds heap read, silently corrupting the reference forward math chain (`lse_host`, `o_host`) and turning the bwd-side `d_sink_head_acc` reference into non-deterministic garbage. `HostTensor::operator()` does not bounds check, so the OOB is not caught at runtime. This manifests as intermittent `tile_example_fmha_bwd` failures (25–67% fail rate) when `-sink_grad=1` is combined with `-mode=1` (group mode), with bit-exact but spurious `max_err` values like 4.27 / 14.6. ## Fix One-line: allocate `sink_host` with `batch` (the real per-batch dim) instead of `shape_batch`, mirroring how `sink_host` is accessed by the loop. ```diff - sink_grad ? std::array<ck_tile::index_t, 2>{shape_batch, nhead} + sink_grad ? std::array<ck_tile::index_t, 2>{batch, nhead} Repro tile_example_fmha_bwd -b=2 -h=2 -s=516 -s_k=253 -prec=bf16 -d=72 \ -bias=n -dbias=0 -p_drop=0 -iperm=1 -operm=1 -deterministic=0 \ -v=3 -mode=1 -kname=1 -sink_grad=1 Verification - 0/30 fail on the repro config after fix - Baselines (before fix): - sink=1, mask=n: 25% fail rate (p ≈ 1.8e-4) - sink=1, mask=t: 67% fail rate (p ≈ 6e-15) Attribution Shape bug introduced together with sink_grad in #5504. Unrelated to #6914 (which is a fwd-only fix on a different code path) ``` ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests. --------- Signed-off-by: junlin12 <junlin12@amd.com> Co-authored-by: Max Podkorytov <4273004+tenpercent@users.noreply.github.com>
shumway
pushed a commit
to ROCm/composable_kernel
that referenced
this pull request
May 27, 2026
[CK_TILE][FMHA] Fix sink un-mask under right-window and emit fp8bf16 batch_prefill sink kernels (#6914)
## Summary
Two related fixes to `ck_tile` FMHA so that StreamLLM-sink +
sliding-window
batch-prefill works correctly for fp8 KV / bf16 compute.
Review the commits in this order:
1. `fmha: emit sink kernels for fp8bf16 batch_prefill`
Extends `example/ck_tile/01_fmha/codegen/ops/fmha_batch_prefill.py` so
the fp8(KV) / bf16(QO) batch-prefill codegen also emits the
`mask=mask_enum::generic_with_sink` variant. Without this the runtime
could not dispatch to a sink-aware kernel for the fp8bf16 path.
2. `fmha: respect right-window in IsOutOfSinkBound`
The sink un-mask in `GenericAttentionMask::IsOutOfSinkBound` (local-mask
branch) used `(i_y + x) > 1` as the gate, which conditioned on the row
index instead of the column index. As a result, queries `1..sink-1`
could attend to *future* sink positions (violating causal /
right-window),
while query `0` fell back to the plain causal mask. The fix replaces the
guard with `i_x < i_y + x` so every query only sees sink columns up to
its own right-window boundary.
3. `fmha: clarify IsOutOfSinkBound predicate comment`
Doc-only follow-up that rewrites the comment above the predicate as a
clause-by-clause explanation (`i_x < sink`, `i_x < i_y + x`,
`y < y_total`, `i_y < x_total`).
## Test plan
- [x] Repro on aiter `op_tests/test_batch_prefill.py` (fp8 +
bf16_dequant
modes with `sink=4`, `win_left=1023`, `softcap=0.0`, `sal=True`)
now passes for all parametrized shapes.
- [x] Existing fp16/bf16 batch-prefill paths (no sink) unchanged —
codegen
diff only adds the `generic_with_sink` variant for fp8bf16; existing
kernel object lists unaffected.
## Submission Checklist
- [x] Look over the contributing guidelines at
https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests.
---------
Co-authored-by: fengjunda.aml <fengjunda.aml@bytedance.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: root <root@smci350-rck-g03-f12-31.rck.dcgpu>
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.
Summary
Two related fixes to
ck_tileFMHA so that StreamLLM-sink + sliding-windowbatch-prefill works correctly for fp8 KV / bf16 compute.
Review the commits in this order:
fmha: emit sink kernels for fp8bf16 batch_prefillExtends
example/ck_tile/01_fmha/codegen/ops/fmha_batch_prefill.pysothe fp8(KV) / bf16(QO) batch-prefill codegen also emits the
mask=mask_enum::generic_with_sinkvariant. Without this the runtimecould not dispatch to a sink-aware kernel for the fp8bf16 path.
fmha: respect right-window in IsOutOfSinkBoundThe sink un-mask in
GenericAttentionMask::IsOutOfSinkBound(local-maskbranch) used
(i_y + x) > 1as the gate, which conditioned on the rowindex instead of the column index. As a result, queries
1..sink-1could attend to future sink positions (violating causal / right-window),
while query
0fell back to the plain causal mask. The fix replaces theguard with
i_x < i_y + xso every query only sees sink columns up toits own right-window boundary.
fmha: clarify IsOutOfSinkBound predicate commentDoc-only follow-up that rewrites the comment above the predicate as a
clause-by-clause explanation (
i_x < sink,i_x < i_y + x,y < y_total,i_y < x_total).Test plan
op_tests/test_batch_prefill.py(fp8 + bf16_dequantmodes with
sink=4,win_left=1023,softcap=0.0,sal=True)now passes for all parametrized shapes.
diff only adds the
generic_with_sinkvariant for fp8bf16; existingkernel object lists unaffected.
Submission Checklist