Skip to content

[GFX950] Relocate MLA Gluon kernel and unify decode dispatch - #4450

Merged
valarLip merged 1 commit into
ROCm:mainfrom
LiuYinfeng01:perf/mla-gluon-h12-split-tuning
Aug 15, 2026
Merged

valarLip merged 1 commit into
ROCm:mainfrom
LiuYinfeng01:perf/mla-gluon-h12-split-tuning

Conversation

@LiuYinfeng01

@LiuYinfeng01 LiuYinfeng01 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Relocate the current gfx950 MLA Gluon kernel to aiter/ops/triton/_gluon_kernels/gfx950/attention/mla.py.
  • Update sparse-prefill, benchmark, and test imports to the architecture-specific path.
  • Connect the validated low-head BF16 configuration to the unified mla_decode_fwd entry while preserving the Triton fallback for all other configurations.

Scope

The split-scheduling performance optimization originally developed in this PR has already landed through #4555. This revision does not add a new split policy or further kernel performance tuning.

The moved kernel is byte-for-byte identical to the current file on main, so the relocation carries the implementation from #4555 and the subsequent NaN fix from #4711 without reimplementing either change.

Unified decode dispatch

The gfx950 Gluon path is selected only for the validated configuration:

  • up to 16 query heads and one KV head
  • BF16 query, KV cache, and output
  • page size 1
  • 512 latent dimensions + 64 RoPE dimensions
  • contiguous, unshuffled tensors with no quantization scales

Unsupported configurations continue to use the existing Triton path.

Validation

  • Added routing guard coverage, including fallback cases.
  • Added gfx950 correctness coverage for 12/16 heads, single-token decode, MTP decode, and 100K context.
  • Ruff check passes on all changed Python files.
  • Python syntax compilation passes.
  • gfx950 execution tests require a ROCm gfx950 environment and were not run on the local Windows host.

@LiuYinfeng01
LiuYinfeng01 requested a review from a team July 30, 2026 01:04
@github-actions

Copy link
Copy Markdown
Contributor

🏷️ CI Guide

Runs automatically on every PR:

  • ✅ Pre-checks (submodule verification, code formatting)
  • ✅ Aiter op tests (gfx942 + gfx950)
  • ✅ Triton tests on MI35X (only when aiter/ops/triton/** or related paths are changed)

Extended tests (opt-in via labels):

Label Tests
ci:triton-300x Run an additional Triton test job on MI300X in PRs; main branch always runs both MI35X and MI300X
ci:sglang SGLang integration tests: DeepSeek-R1-MXFP4 accuracy, Qwen 3.5 accuracy
ci:atom ATOM benchmark: DeepSeek-R1-0528, GPT-OSS-120B
ci:atom_full ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm vLLM benchmark: GPT-OSS-120B, DeepSeek-R1-0528, Kimi-K2.5
ci:all 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 4450 --add-label <label>

@JohnQinAMD

Copy link
Copy Markdown
Contributor

This now overlaps #4405's caller-owned num_kv_splits override. #4450's
device-side runtime buckets are the more complete Kimi-K3 scheduling policy;
please preserve equivalent coverage for #4405's focused split-policy CI test
(test_mla_gluon_split_policy.py). If #4450 lands without that unit coverage,
I will rebase #4405 into a test-only follow-up rather than duplicate the
implementation.

@LiuYinfeng01

LiuYinfeng01 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@JohnQinAMD Thanks for pointing this out. I added equivalent split-policy and boundary coverage in commit dd521e2.

I confirmed that the #4450 measurements were collected on this machine, which has 8× AMD Instinct MI355X GPUs (gfx950). The end-to-end Kimi-K3 measurements used TP8, CUDA Graph enabled, and the 100K-input / 1K-output workload described in the PR.

The new coverage includes:

  1. A shared _resolve_num_kv_splits() helper that preserves the automatic policy when the override is None and validates explicit caller-owned overrides.
  2. test_mla_gluon_split_policy.py with 14 parameterized cases covering automatic-policy passthrough, explicit split values 1, 16, 32, and 256, out-of-range values, and invalid non-integer values.
  3. A focused Kimi-K3 TP8 CI invocation covering contexts 1, 31, 32, 63, 64, 65, and 8192 with an explicit 32-split override.
  4. The existing automatic runtime bucket behavior remains unchanged when no override is supplied.

Focused unit-test result:

14 passed in 5.73s

Explicit split-boundary command:

python op_tests/test_mla.py   --decode-only   -c 1 31 32 63 64 65 8192   -b 1 -n 12,1   -d bf16 -kvd bf16   -k 512 -qn 512 -qr 64 -vh 512 -blk 1   --varlen -splits 32

All seven boundary cases passed the PyTorch golden check with atol=0.01 and rtol=0.01, including cases where the explicit split count is greater than the sequence length.

I also reran the automatic graph-safe policy without an explicit override at contexts 4K, 100K, and 262K. Output and LSE checks passed at all three lengths, and the varlen batch=3, context=10000 case passed as well.

This should preserve #4405's focused split-policy and boundary coverage while keeping #4450 as the single runtime scheduling implementation.

Comment thread aiter/ops/triton/gluon/mla_gluon.py Outdated
Comment thread aiter/ops/triton/gluon/mla_gluon.py Outdated
@LiuYinfeng01
LiuYinfeng01 force-pushed the perf/mla-gluon-h12-split-tuning branch from c56bfa7 to b84ad71 Compare August 4, 2026 10:32
@azaidy
azaidy requested review from cagrikymk and k50112113 August 4, 2026 16:01
@LiuYinfeng01

Copy link
Copy Markdown
Contributor Author

The optimization from this PR has been incorporated into #4555, so I’m drafting this PR.

@LiuYinfeng01
LiuYinfeng01 marked this pull request as draft August 12, 2026 06:13
chien-an-chen added a commit to chien-an-chen/sglang that referenced this pull request Aug 13, 2026
Add aiter_mla_gluon.py and extend aiter_backend.py to route fp8 decode
through aiter mla_gluon with batch>1, zero-pad/repeat head padding for
h12, and graph-capture-safe kv_scale / min_kv_seq_len.

Update cache_ops.py and forward_mla.py for aiter/aiter/fp8 prefill:
cache_ops matches sgl-project#33341; forward_mla adds bf16 Q when
kv_cache_dtype is fp8 (Gluon bh16bn128 requires bf16 Q).

aiter runtime dependencies (container/image, not in this repo):
- ROCm/aiter#4480 (required): fp8 Gluon bh16bn128, batch>1, 64-bit KV base.
- ROCm/aiter#4450 (required for decode CUDA graph): graph-safe KV splits and
  HIP stream setup in mla_gluon.
- Triton >= 3.7 for Gluon cga_layout on gfx950.

sgl-project#33341: this change set vendors overlapping prefill/KV
hunks (cache_ops identical; aiter_backend prefill zero-pad refactored and
extended for fp8 Gluon). Does not require sgl-project#33341 to merge first; rebase
onto sgl-project#33341 when landed to drop duplicate cache_ops diff.

Co-authored-by: Cursor <cursoragent@cursor.com>
@LiuYinfeng01
LiuYinfeng01 force-pushed the perf/mla-gluon-h12-split-tuning branch from d1898b7 to 0ac8995 Compare August 14, 2026 02:38
Move the current gfx950 kernel into the architecture-specific hierarchy and connect validated low-head BF16 workloads to the unified MLA entry.

Signed-off-by: LiuYinfeng01 <yinfeliu@amd.com>
@LiuYinfeng01
LiuYinfeng01 force-pushed the perf/mla-gluon-h12-split-tuning branch from 0ac8995 to 21882c9 Compare August 14, 2026 03:44
@LiuYinfeng01 LiuYinfeng01 changed the title Optimize 12-head Gluon MLA split scheduling [GFX950] Relocate MLA Gluon kernel and unify decode dispatch Aug 14, 2026
@LiuYinfeng01
LiuYinfeng01 marked this pull request as ready for review August 14, 2026 04:16
@valarLip
valarLip merged commit 4f632dd into ROCm:main Aug 15, 2026
139 of 144 checks passed
@LiuYinfeng01
LiuYinfeng01 deleted the perf/mla-gluon-h12-split-tuning branch August 15, 2026 06:36
valarLip pushed a commit that referenced this pull request Aug 17, 2026
chien-an-chen added a commit to chien-an-chen/sglang that referenced this pull request Aug 17, 2026
Add aiter_mla_gluon.py and extend aiter_backend.py to route fp8 decode
through aiter mla_gluon with batch>1, zero-pad/repeat head padding for
h12, and graph-capture-safe kv_scale / min_kv_seq_len.

Update cache_ops.py and forward_mla.py for aiter/aiter/fp8 prefill:
cache_ops matches sgl-project#33341; forward_mla adds bf16 Q when
kv_cache_dtype is fp8 (Gluon bh16bn128 requires bf16 Q).

aiter runtime dependencies (container/image, not in this repo):
- ROCm/aiter#4480 (required): fp8 Gluon bh16bn128, batch>1, 64-bit KV base.
- ROCm/aiter#4450 (required for decode CUDA graph): graph-safe KV splits and
  HIP stream setup in mla_gluon.
- Triton >= 3.7 for Gluon cga_layout on gfx950.

sgl-project#33341: this change set vendors overlapping prefill/KV
hunks (cache_ops identical; aiter_backend prefill zero-pad refactored and
extended for fp8 Gluon). Does not require sgl-project#33341 to merge first; rebase
onto sgl-project#33341 when landed to drop duplicate cache_ops diff.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

5 participants