Skip to content

[Bugfix][ROCm] Stream-order AITER MLA FP8 prefill PS metadata updates - #5

Closed
amd-mghanimi wants to merge 42 commits into
mainfrom
rocm-aiter-mla-ps-metadata-stream-order
Closed

amd-mghanimi wants to merge 42 commits into
mainfrom
rocm-aiter-mla-ps-metadata-stream-order

Conversation

@amd-mghanimi

@amd-mghanimi amd-mghanimi commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Purpose

Fix a GPU memory fault (Memory access fault ... Write access to a read-only page, address
~0x6c000-0x6f000) in the ROCm AITER MLA backend with FP8 KV cache and async scheduling. It
also removes a likely source of silent prefill attention corruption on the same path.

aiter.get_ps_metadata_v1 plans the FP8 MLA prefill schedule on the host. It then writes the
plan into the caller's device tensors with blocking hipMemcpy that is not ordered on the
current stream
(aiter v1_2_host.cuh L395-L418).
AiterMLAMetadataBuilder._build_fp8_prefill_ps_metadata passes the persistent
fp8_ps_* device buffers directly, and every step's metadata aliases those buffers
(L901-L941).

With async scheduling, step N+1 is built while step N's prefill kernels
(mla_prefill_ps_asm_fwd + mla_reduce_v1, one launch per layer) are still queued. Step N
can then run with step N+1's work/reduce maps. The existing .item() sync on
reduce_indptr[-1] comes after the rewrite, so it does not help.

This PR plans into two pinned host staging slots and copies them to the device buffers with
copy_(non_blocking=True) on the current stream. That orders the update after every
previously launched kernel. A slot is reused only after its previous copy has completed
(CUDA event). num_partial_tiles is read from the host plan, which removes one GPU sync per
prefill step. work_metadata is not written by the host planner and stays on device.

Only rocm_aiter_mla.py calls get_ps_metadata_v1 in vLLM.

Test plan

Kimi-K3, TP8, MI355X, vllm/vllm-openai-rocm:nightly-rocm100-29468dde… (ROCm 10), dummy
weights, FP8 KV, max_num_batched_tokens=16384, max_num_seqs=256, FULL_AND_PIECEWISE,
async scheduling. sglang.bench_serving random 8k/1k, max concurrency 32, 1024 prompts.

  1. Reproducer without the fix (deterministic).
  2. Same with the fix (patched file bind-mounted, nothing else changed).
  3. Diagnostics isolating the cause (below).
  4. Plan equivalence: host-output plan equals device-output plan for 5 batch shapes.

Test result

Crash: unpatched vs this PR on the same request stream

Each row pairs runs from the same environment. Whether a given request stream triggers the
fault varies, so every fix run is paired with an unpatched run that faults on that stream.

Request stream (8k/1k random) Unpatched This PR
MC32, 1024 prompts, seed 4 fault at request 111 (x2, and with --enforce-eager) 1024/1024; second run 949/1024 with no fault (stopped early)
MC32, 2048 prompts fault at request 79 2048/2048
MC64, 1024 prompts fault at request 61 1024/1024
MC32, 1024 prompts, seed 5 fault at request 117 1024/1024

Diagnostics on the seed-4 stream, all unpatched otherwise:

Change Result
FP8 ASM prefill disabled 1024/1024
torch.cuda.synchronize() before get_ps_metadata_v1 1024/1024 (x2)
--no-async-scheduling 1024/1024

Regression checks

Check Unpatched This PR
8k/1k MC32, output tok/s 1083.0 1082.6
8k/1k MC32, median ITL 18.14 ms 18.14 ms
8k/1k MC32, mean TTFT 577 ms 574 ms
8k/1k MC4, output tok/s 236.05 236.05
8k/1k MC4, median ITL 15.49 ms 15.50 ms
8k/1k MC4, mean TTFT 371 ms 369 ms
8k/1k MC32, --enforce-eager, 1024 prompts n/a 1024/1024
ROCm 7.2 image, 8k/1k MC32, 1024 prompts n/a 1024/1024

Accuracy (real weights, niah_single_2, 4k, a single run on each build)

num_concurrent Unpatched This PR
4 0.974 0.974
32 0.954 0.978
64 0.970 0.984

Suggestive, not conclusive: single runs.

Long context (real weights, niah_single_2, num_concurrent=32, a single run on each build):

Context Unpatched This PR
64k 0.922 0.928
128k 0.888 0.888

No accuracy change at long context (within single-run noise).

Full sweep with real weights (this PR)

12-cell serving sweep plus GPQA and NIAH, real weights, default max_num_seqs, FP8 KV,
FULL_AND_PIECEWISE, async scheduling. All 12 cells completed with no fault.

Cell (random, sglang.bench_serving) Output tok/s
8k/1k, concurrency 4 / 8 / 16 / 32 216.9 / 353.3 / 542.7 / 799.6
8k/1k, concurrency 64 / 128 / 256 1097.8 / 1383.2 / 1648.9
60k/600, concurrency 4 / 16 / 64 110.1 / 161.5 / 189.5
128k/1k, concurrency 4 / 16 91.6 / 123.8
Eval Score
GPQA (sglang.test.run_eval, thinking on, 32k max tokens) 0.889
niah_single_2, 64k, num_concurrent=32 0.928
niah_single_2, 128k, num_concurrent=32 0.908

Related: DSpark startup fault (vllm-project#58814)

vllm-project#58814 reports a GPU memory fault in the Kimi-K3 DSpark draft (stale KV cache
pointers after the startup profiling pass). This A/B checks whether this PR also covers it.
Kimi-K3 TP8 + DSpark (K=5, TRITON_MLA draft), ROCm 10 nightly 29468dde, real weights,
FULL_AND_PIECEWISE, async scheduling.

Arm Setup Patch Result
d3 vllm-project#58814 recipe: FP8 KV, max_num_seqs=8, 8k/1k MC4 none fault at startup, right after JIT kernel warmup: Memory access fault ... Reason: Unknown at a high address (matches vllm-project#58814)
d4 same this PR fault at startup, same signature as d3: this PR does not fix vllm-project#58814
d5 same vllm-project#58814 64/64, no fault (positive control; DSpark mean acceptance length 4.4-5.9 at K=5)
d1 DSpark OOB recipe (BF16 KV, max_num_seqs=128), 8k/1k MC4/8/16/32 none fault at startup on all ranks, same signature as d3, then collective timeout (matches vllm-project#58814's log)
d2 same this PR fault at startup on all ranks, same as d1

Conclusion: the two faults are independent. vllm-project#58814's fault is fixed by vllm-project#58814 and not by this
PR. It happens at startup, at a high address, with reason "Unknown". This PR's fault is a write
to a read-only page near address 0x6c000, while serving. Also, the code this PR changes only
runs with an FP8 KV cache, so it cannot affect d1/d2.

Standalone reproducer (no server, one GPU)

Plans batch A (one 8175-token prefill) into the persistent buffers, queues A's
mla_prefill_ps_asm_fwd + mla_reduce_v1 behind a GPU delay on a non-blocking stream, then
immediately plans batch B (three prefills) into the same buffers from the host.

Mode ROCm 7.2 ROCm 10
unpatched pattern GPU memory fault (write to a read-only page, near-null address) GPU memory fault (same signature)
stream sync before planning B output matches reference output matches reference
this PR's copy (pinned staging + copy_ on the stream) output matches reference output matches reference

Plan equivalence

Host-vs-device plan equivalence was verified on MI355X with a standalone script (all 5 shapes
byte-identical). No unit test is added: the check exercises AITER rather than vLLM code.

Still to run before marking ready

  • Repeat 4k NIAH (more runs).

Notes for reviewers

  • ROCm 7.2 has the same race: vLLM runs these kernels on a non-blocking stream on both
    runtimes, the stream-less blocking hipMemcpy in get_ps_metadata_v1 does not wait for it
    on either, and the standalone reproducer above faults on both. In serving, the overlap
    (next plan built while the previous prefill is still pending) happens about equally often on
    both, about 9% of prefill steps. The difference is what the copy does then. On ROCm 7.2 most
    of those plan updates (about 55 of 80 per rank) only return after the in-flight prefill has
    finished, so the runtime happens to order them. On ROCm 10 they return in under 1 ms, while
    the prefill is still reading. Which runtime change causes this is not pinned down yet (the
    two images ship very different HIP runtime builds). Either way it is accidental ordering,
    not a guarantee.
  • Runtime workarounds without this PR, each 1024/1024 on a ROCm 10 stream that faulted at
    request 78: AMD_SERIALIZE_COPY=1 (copies wait for already-queued work) and
    GPU_MAX_HW_QUEUES=1 (every stream shares one in-order hardware queue).
  • AITER-side follow-up (stream-ordered host planner, or a device-side planner like the decode
    v1_2_device path): ROCm/aiter#5879.
  • Related: [Bugfix][ROCm] Fix startup OOM in AITER MLA FP8 prefill workspace sizing vllm-project/vllm#57923 (FP8 prefill workspace sizing) touched the same function. This PR does not
    change workspace sizing.

amd-mghanimi and others added 2 commits September 25, 2026 14:29
aiter.get_ps_metadata_v1 plans the FP8 MLA prefill schedule on the host and
writes the result into the caller's device tensors with blocking hipMemcpy
that is not ordered on the current stream. The builder passed the persistent
fp8_ps_* device buffers directly, and every step's metadata aliases them.

With async scheduling the builder for step N+1 runs while step N's prefill
kernels (mla_prefill_ps_asm_fwd + mla_reduce_v1, once per layer) are still
queued, so step N can execute with step N+1's work/reduce maps. On ROCm 10
this faults the GPU (write to a read-only page near address 0x6c000) at a
deterministic point of an 8k/1k MC=32 Kimi-K3 run; when the indices stay in
bounds it silently corrupts prefill attention.

Plan into two pinned host staging slots instead and copy to the device
buffers with non_blocking copy_ on the current stream, which orders the
update after all previously launched kernels. A slot is reused only after
its previous H2D copy completed (CUDA event). num_partial_tiles is read from
the host plan, removing the per-prefill-step GPU sync (.item()).

work_metadata is not written by the host planner and stays on device.

Signed-off-by: Mehdi Ghanimifard <mehdi.ghanimifard@amd.com>
The FP8 MLA prefill builder plans into pinned host buffers and copies them
to the device on the current stream. Check that aiter.get_ps_metadata_v1
accepts host outputs and produces the same plan as device outputs.

Signed-off-by: Mehdi Ghanimifard <mehdi.ghanimifard@amd.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@amd-mghanimi

Copy link
Copy Markdown
Owner Author

Opened upstream as vllm-project#58887 (fixes vllm-project#58886).

amd-mghanimi and others added 27 commits September 27, 2026 02:51
It exercises AITER behavior rather than vLLM code and needs gfx950 with AITER.

Signed-off-by: Mehdi Ghanimifard <mehdi.ghanimifard@amd.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Allocate one CUDA event per pinned staging slot at init and record it
again after each copy, instead of creating a new event every prefill step.

Signed-off-by: Mehdi Ghanimifard <mehdi.ghanimifard@amd.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: simondanielsson <simon.danielsson99@hotmail.com>
…-project#59348)

Signed-off-by: Avishek Goswami <avishek.goswami@ibm.com>
Signed-off-by: Avishek Goswami <86944690+GOavi101@users.noreply.github.com>
Co-authored-by: Avishek Goswami <avishek.goswami@ibm.com>
…lm-project#58528)

Signed-off-by: Akash kaothalkar <akash.kaothalkar@ibm.com>
Co-authored-by: Akash kaothalkar <akash.kaothalkar@ibm.com>
Co-authored-by: Antigravity <antigravity@google.com>
Co-authored-by: Li, Jiang <jiang1.li@intel.com>
…llm-project#55781)

Signed-off-by: Ronald1995 <ronaldautomobile@163.com>
Signed-off-by: aoshen02 <aoshen02@users.noreply.github.com>
Co-authored-by: aoshen02 <aoshen02@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: aoshen02 <aoshen@inferact.ai>
…ject#59398)

Signed-off-by: aoshen02 <aoshen@inferact.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: vllmellm <vllm.ellm@embeddedllm.com>
Signed-off-by: Djordje Ramic <djoramic@amd.com>
Co-authored-by: Andreas Karatzas <akaratza@amd.com>
…ject#58797)

Signed-off-by: Mathew Odden <modden@redhat.com>
Co-authored-by: opencode+glm-5.3+vllm <opencode+glm-5.3+vllm@example.com>
…ading for TP >1 (vllm-project#58083)

Signed-off-by: Akash kaothalkar <akash.kaothalkar@ibm.com>
Co-authored-by: Akash kaothalkar <akash.kaothalkar@ibm.com>
Co-authored-by: Antigravity <antigravity@google.com>
Co-authored-by: Li, Jiang <jiang1.li@intel.com>
…llm-project#48133)

Signed-off-by: Francesco Fusco <ffu@zurich.ibm.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Luka Govedič <ProExpertProg@users.noreply.github.com>
…#50030)

Signed-off-by: aoshen02 <aoshen@inferact.ai>
Signed-off-by: S1ro1 <matej.sirovatka@gmail.com>
Co-authored-by: aoshen02 <aoshen@inferact.ai>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: aoshen02 <aoshen02@users.noreply.github.com>
Signed-off-by: Taimys <ffy2281693949@gmail.com>
Signed-off-by: Luyi Xiao <81631911+luyixiao95@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Luyi Xiao <81631911+luyixiao95@users.noreply.github.com>
Co-authored-by: Taimys <ffy2281693949@gmail.com>
Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s enabled (vllm-project#59195)

Signed-off-by: Jakub Zakrzewski <jzakrzewski@nvidia.com>
Co-authored-by: Codex <codex@openai.com>
…riance tested models (vllm-project#54441)

Signed-off-by: Yuval Luria <yluria@redhat.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…sing VSX (vllm-project#59149)

Signed-off-by: Rukhaiya <bibirukhaiya123@gmail.com>
Co-authored-by: Li, Jiang <jiang1.li@intel.com>
…project#59357)

Signed-off-by: Clinton Thomas <1033162+KernelClint@users.noreply.github.com>
Co-authored-by: Lucas Bourtoule <35483370+dhalf@users.noreply.github.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
…roject#59315)

Signed-off-by: Juan Pérez de Algaba <jperezde@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…roject#57172)

Signed-off-by: Michal Ganczarenko <michal.ganczarenko@intel.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Anna Mayne <anna.mayne@arm.com>
Co-authored-by: Li, Jiang <jiang1.li@intel.com>
…roject#57168)

Signed-off-by: Jakub Zakrzewski <jzakrzewski@nvidia.com>
Co-authored-by: Nicolò Lucchesi <nicolo.lucchesi@mistral.ai>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Julien Darve <jdarve@NVIDIA.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
…9379)

Signed-off-by: Chaojun Zhang <chaojun.zhang@intel.com>
Co-authored-by: Kunshang Ji <kunshang.ji@intel.com>
…lm-project#59029)

Signed-off-by: Giulio De Pasquale <git@depasquale.giugl.io>
Co-authored-by: Isotr0py <2037008807@qq.com>
Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com>
Co-authored-by: Lucas Wilkinson <LucasWilkinson@users.noreply.github.com>
Signed-off-by: Juan Pérez de Algaba <jperezde@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…workers (vllm-project#59200)

Signed-off-by: aoshen02 <aoshen@inferact.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… single Triton kernel (vllm-project#58008)

Signed-off-by: simondanielsson <simon.danielsson99@hotmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…nd round the expert-group count to a kernel that exists (vllm-project#55368)

Signed-off-by: Sergei Shliapnikov <sergei.shliapnikov@amd.com>
…llm-project#59271) (vllm-project#59373)

Signed-off-by: Yida Weng <84164537+YidaWeng@users.noreply.github.com>
Co-authored-by: Grok <grok@x.ai>
…t#59428)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
vllm-project#50300)

Signed-off-by: jperezde <jperezde@redhat.com>
Signed-off-by: Juan Pérez de Algaba <jperezde@redhat.com>
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.