You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FlyDSL] [CI] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support - #5556
This PR aims to integrate the native gfx950 FP8 paged-prefill attention with asymmetric Q/K and V head dimensions and packed variable-length sequence support from ROCm/FlyDSL#1066 into AITER.
AITER already supports FlyDSL dense FP8 attention through ROCm/aiter#5326, but paged prefill still needs a native path that consumes the serving both kv cache layout used by sglang SGLANG_AITER_KV_CACHE_LAYOUT directly:
SGLANG_AITER_KV_CACHE_LAYOUT=nhd: Linear KV-cache layout with page size 1
SGLANG_AITER_KV_CACHE_LAYOUT=vectorized_5d: Vectorized 5D KV-cache layout with page size 16/64/1024
Technical Details
Add native causal packed-varlen FP8 paged attention for gfx950 based on FlyDSL 0.3.4.1 runtime.
Support D128/V128, D192/V128, and D192/V192 with BF16 output.
Support page-1 linear/linear3d caches and page-16/64/1024 vectorized caches.
Accept both block-table metadata and native CSR metadata (kv_indptr, kv_page_indices, and kv_last_page_lens).
Add public API aiter.ops.flydsl.flydsl_flash_attn_paged_prefill_func for downstream farmwork integration.
The FlyDSL source column uses PR #1066 commit 8a662b0 with its locally built FlyDSL 0.3.3 runtime. The AITER migrated columns use commit c933927e with FlyDSL 0.3.2.
Port delta is AITER paged attention with direct block-table latency versus FlyDSL source paged attention latency. Paged/dense uses the AITER public CSR page metadata path (used by aiter.ops.mha.mha_batch_prefill_func) versus AITER FlyDSL dense attention; values above 100% mean paged is faster.
Key results:
The migrated paged kernel is within -0.60% to +1.05% latency of the current FlyDSL source implementation across all 12 shapes.
AITER public CSR dispatch is within 0.45% of the direct migrated CSR kernel.
Paged attention is 3.46% to 3.91% faster than dense attention for D128/V128 and 4.96% to 8.34% faster for D192/V192.
For D192/V128, page attention is 1.98% to 2.65% behind the Flydsl dense attention in AITER.
Compare current FlyDSL PR source with the direct AITER port using block-table metadata.
Compare direct AITER block-table and CSR paths.
Compare the AITER public CSR dispatcher with the direct CSR kernel.
Compare AITER paged CSR with AITER FlyDSL dense attention using identical logical Q/K/V tensors.
Cross-check source and port output in separate processes to avoid copied JIT-kernel cache collisions.
Test Result
.................................................................................................................... [ 54%]
............................................................................................... [100%]
===================================================== warnings summary =====================================================
../../../../opt/venv/lib/python3.10/site-packages/Cython/Distutils/old_build_ext.py:15
../../../../opt/venv/lib/python3.10/site-packages/Cython/Distutils/old_build_ext.py:15
/opt/venv/lib/python3.10/site-packages/Cython/Distutils/old_build_ext.py:15: DeprecationWarning: dep_util is Deprecated. Use functions from setuptools instead.
from distutils.dep_util import newer, newer_group
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
211 passed, 2 warnings in 141.51s (0:02:21)
Direct AITER block-table, direct CSR, and public CSR outputs are bit-identical for all 12 benchmark shapes.
Paged versus dense passes rtol=0.02, atol=0.02; maximum absolute difference is 0.001953125, and minimum row cosine is 0.9999994.
Flydsl FP8 paged attention vs AITER migrated paged attention checks at 4K/8K pass for all supported dimension pairs. D128/V128 is bit-identical; D192 maximum absolute difference is 0.001953125, with minimum row cosine at least 0.99999958.
Add the explicit flydsl_flash_attn_paged_prefill_func API for gfx950 causal
FP8 prefill with packed queries, BF16 output and optional FP32 LSE.
Support page-1 linear or page-16/64/1024 vectorized KV caches through rectangular or CSR metadata
Supporting Q/K–V pairs 128/128, 192/128 and 192/192.
Avoids mandatory dense KV materialization for the existing dense/varlen interface.
Validation and unverified scope
MI350X/gfx950, 256 CUs, ROCm 7.2, PyTorch 2.9.1, FlyDSL 0.4.1: python -m pytest -q op_tests/test_flydsl_paged_fmha.py: 140 passed, no failures or skips.
Unverified for this revision: downstream model integration.
PR-specific question
The CI change adds one literal filename to the existing pytest route in .github/scripts/aiter_test.sh and a 240-second sharding estimate in .github/split-test-times/aiter.tsv. It adds no workflow event, token permission, credential or runner configuration.
Changed op tests
op_tests/test_flydsl_paged_fmha.py is the only added op-test file. Existing
dense FMHA tests cannot exercise shuffled page IDs, CSR ranges, page tails or
independent paged V addressing. All categories below belong to this PR's new
test file; each parameterized case is counted once.
Added test category
Cases
Purpose
Core paged layouts and ragged requests
15
Check all supported cache layouts and Q/K–V width pairs against FP32 attention.
LSE and caller-owned buffers
18
Check LSE, empty requests, buffer validation and output canaries.
All standard extended tests (excludes ci:atom_full)
Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 5556 --add-label <label>
PR title tags & labels:
Component tags ([Triton/Gluon], [HIP], [CK], [ASM], ...) are added to the PR title and as PR labels automatically from the changed files and re-synced on every push — change-type tags like [fix]/[Perf], op tags like [MLA], and human labels (ci:*) are left untouched. Add the no-auto-title label to opt this PR out.
github-actionsBot
changed the title
[FlyDSL] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
[FlyDSL] [CI] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
Sep 15, 2026
Adds correctness, stream, graph, regression, and CI coverage.
Critical finding: aiter/ops/mha.py unconditionally imports FlyDSL, causing ModuleNotFoundError in AITER_TRITON_ONLY=1 builds instead of using the existing fallback.
File summaries
File
Summary
op_tests/test_flydsl_paged_fmha.py
Adds comprehensive paged FP8 correctness and regression tests.
aiter/ops/mha.py
Integrates public FP8 dispatch.
aiter/ops/flydsl/kernels/fmha_gfx950/pipeline.py
Refactors shared dense and paged pipeline helpers.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Four unresolved review findings remain, including three critical issues and a FlyDSL version-gating issue.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
aiter/ops/flydsl/init.py:46
This new lazy export is backed by code explicitly tied to FlyDSL 0.3.2 (requirements.txt pins that release), but the package-level gate still accepts FlyDSL 0.2.4 and later. On a 0.2.4–0.3.1 installation, accessing this attribute can fail inside the paged module instead of falling back; raise _MIN_FLYDSL_VERSION to 0.3.2 or version-gate this path.
For the supported D192/V128 specialization, NUM_DMA_K=2 and _load_vectorized() still runs on all 8 waves, although a 64×192 tile has only (64*192)/(2*64*16)=6 valid wave slots. Waves 6–7 therefore issue zero/OOB-padded K loads that are never consumed, wasting about 25% of K-staging DMA work on every tile. Apply the same copy_waves guard used by the V192 path to skip these loads while keeping all waves in the rendezvous schedule.
[inferred] This unconditional branch makes the new kernel the default for every supported mha_batch_prefill_func call, but the performance table compares the port with the FlyDSL source rather than with the pre-change AITER/CK path. That leaves a possible regression in the production dispatcher unmeasured even though the new test passes. Author must add a reproducible base-versus-head benchmark for the public dispatcher (or explicitly limit the performance claim to source-port parity).
if q.dtype == torch.float8_e4m3fn:
try:
from .flydsl.fmha_kernels import flydsl_flash_attn_batch_prefill_func
except ModuleNotFoundError as exc:
if exc.name != "flydsl":
raise
else:
flydsl_result = flydsl_flash_attn_batch_prefill_func(
github-actionsBot
changed the title
[FlyDSL] [CI] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
[Triton/Gluon] [HIP] [CK] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
Sep 16, 2026
github-actionsBot
changed the title
[Triton/Gluon] [HIP] [CK] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
[FlyDSL] [CI] gfx950 FP8 paged-prefill attention with asymmetric head dim and varlen support
Sep 16, 2026
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Three unresolved findings remain: two moderate fallback issues and one nit involving D192/V128 staging.
Review details
Suppressed comments (3)
aiter/ops/flydsl/fmha_kernels.py:317
This dispatcher is called before the existing CK fallback, but it does not gate the native wrapper's CSR precondition for page sizes greater than one: flydsl_flash_attn_paged_fp8_func rejects kv_last_page_lens=None for those layouts. A public mha_batch_prefill_func call without that optional metadata therefore raises from the native path instead of returning None and falling back. Check this condition before dispatch (while retaining the native path when last-page lengths are supplied).
[verified] In the supported D192/V128 specialisation, HEAD_DIM_V == 192 is false, so this loader runs all eight waves and two DMA bands even though D192 has only 12 valid 16-byte D-groups. The valid mask turns groups 12–15 into zero/sentinel loads, but those four groups still consume roughly 25% extra K staging traffic on every tile; only D192/V192 takes the six-wave compact path. Author must either compact K staging based on HEAD_DIM == 192 as well or provide a measured reason this extra traffic is required.
The optional-backend guard only handles a missing flydsl module. Importing .flydsl.fmha_kernels also executes aiter/ops/flydsl/__init__.py, which raises ImportError for an unavailable/unsupported FlyDSL version (__init__.py:15-24); in that environment every FP8 batch-prefill call now raises here instead of reaching CK/Triton. Handle that version-check failure as an unavailable optional backend while preserving unrelated import errors.
except ModuleNotFoundError as exc:
if exc.name != "flydsl":
raise
Duplicate test row causes duplicate sharding and execution
.github/split-test-times/aiter.tsv:39
This added row duplicates the existing op_tests/test_flydsl_pa_mqa_logits_fp4_prefill.py entry at line 41. The shard script indexes rows rather than deduplicating paths, so that test is assigned and run twice; remove the duplicate row to avoid inflating CI time and distorting shard timing.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Approval should be deferred because this large gfx950-specific FlyDSL kernel depends on MI355X/ROCm runtime validation of its LDS/MFMA scheduling, addressing, and graph/stream lifetime behavior, which is unavailable in the review environment.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The new LDS DMA path uses the undocumented literal address-space value 2 instead of the established fx.AddressSpace.Shared enum, creating an avoidable API and backend-mapping risk.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed because a critical verified issue allows BF16 output storage to exceed the kernel descriptor’s 2 GiB byte limit despite the element-count check, potentially causing incorrect memory addressing in both wrapper paths.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
A critical active issue remains because the fixed-base output descriptor can wrap at 2 GiB and silently misaddress valid BF16 outputs, while the current guard is too high and the element-count check does not prevent it.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
A critical masking defect remains in the grouped K staging path, allowing padded tokens from partial or zero-length pages to affect softmax normalization and LSE.
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
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.
Motivation
This PR aims to integrate the native gfx950 FP8 paged-prefill attention with asymmetric Q/K and V head dimensions and packed variable-length sequence support from ROCm/FlyDSL#1066 into AITER.
AITER already supports FlyDSL dense FP8 attention through ROCm/aiter#5326, but paged prefill still needs a native path that consumes the serving both kv cache layout used by sglang SGLANG_AITER_KV_CACHE_LAYOUT directly:
SGLANG_AITER_KV_CACHE_LAYOUT=nhd: Linear KV-cache layout with page size 1SGLANG_AITER_KV_CACHE_LAYOUT=vectorized_5d: Vectorized 5D KV-cache layout with page size 16/64/1024Technical Details
0.3.4.1runtime.D128/V128,D192/V128, andD192/V192with BF16 output.kv_indptr,kv_page_indices, andkv_last_page_lens).Performance
MI355X (
gfx950) with ROCm/HIP7.2.26015, Torch2.9.1+rocm7.2.0,B=1,Hq=16,Hkv=1, causalQ:KV=1:2, page size 64, vectorized FP8 K/V, and preallocated BF16 output.The FlyDSL source column uses PR #1066 commit
8a662b0with its locally built FlyDSL0.3.3runtime. The AITER migrated columns use commitc933927ewith FlyDSL0.3.2.Port deltais AITER paged attention with direct block-table latency versus FlyDSL source paged attention latency.Paged/denseuses the AITER public CSR page metadata path (used byaiter.ops.mha.mha_batch_prefill_func) versus AITER FlyDSL dense attention; values above 100% mean paged is faster.Key results:
-0.60%to+1.05%latency of the current FlyDSL source implementation across all 12 shapes.0.45%of the direct migrated CSR kernel.3.46%to3.91%faster than dense attention forD128/V128and4.96%to8.34%faster forD192/V192.D192/V128, page attention is1.98%to2.65%behind the Flydsl dense attention in AITER.Test Plan
Performance coverage:
Test Result
rtol=0.02, atol=0.02; maximum absolute difference is0.001953125, and minimum row cosine is0.9999994.4K/8Kpass for all supported dimension pairs.D128/V128is bit-identical; D192 maximum absolute difference is0.001953125, with minimum row cosine at least0.99999958.Reviewed revision
fdd594f
Behavior and intent
Add the explicit
flydsl_flash_attn_paged_prefill_funcAPI for gfx950 causalFP8 prefill with packed queries, BF16 output and optional FP32 LSE.
Validation and unverified scope
MI350X/gfx950, 256 CUs, ROCm 7.2, PyTorch 2.9.1, FlyDSL 0.4.1:
python -m pytest -q op_tests/test_flydsl_paged_fmha.py: 140 passed, no failures or skips.Unverified for this revision: downstream model integration.
PR-specific question
The CI change adds one literal filename to the existing pytest route in
.github/scripts/aiter_test.shand a 240-second sharding estimate in.github/split-test-times/aiter.tsv. It adds no workflow event, token permission, credential or runner configuration.Changed op tests
op_tests/test_flydsl_paged_fmha.pyis the only added op-test file. Existingdense FMHA tests cannot exercise shuffled page IDs, CSR ranges, page tails or
independent paged V addressing. All categories below belong to this PR's new
test file; each parameterized case is counted once.
Submission Checklist