Skip to content

[Bugfix][Core] Sync reused pinned input buffers under PP batch queue (fixes IMA with sparse MLA + PP)#47644

Open
thomaslwang wants to merge 2 commits into
vllm-project:mainfrom
thomaslwang:fix-pp-pinned-buffer-race
Open

[Bugfix][Core] Sync reused pinned input buffers under PP batch queue (fixes IMA with sparse MLA + PP)#47644
thomaslwang wants to merge 2 commits into
vllm-project:mainfrom
thomaslwang:fix-pp-pinned-buffer-race

Conversation

@thomaslwang

Copy link
Copy Markdown

Purpose

Fix a race on reused pinned CPU input buffers when engine steps overlap under the PP batch queue.

prepare_inputs_event (consumed by synchronize_input_prep()) was only created when async scheduling is enabled. But the PP batch queue creates exactly the same overlap (max_concurrent_batches == pp_size): input prep for step N+1 rewrites the reused pinned CPU tensors (seq_lens_cpu, query_start_loc_cpu, block-table staging, …) while step N's non_blocking H2D copies from those same buffers may not have executed yet. When the copy engine finally runs, step N's kernels consume step N+1's values.

For DSA sparse-MLA models this is fatal rather than silent: the indexer sizes its prefill-chunk buffers from step N's CPU values but its GPU kernels index with the (now newer, possibly larger) device seq_lens — out-of-bounds scatter → Triton Error [CUDA]: an illegal memory access was encountered. Reported in the field in #38476 (multi-node TP×PP, and single-node repro below). For dense models the same race can silently corrupt inputs.

The fix creates the event whenever max_concurrent_batches > 1, so synchronize_input_prep() guards every overlapped-step configuration (async scheduling ⇒ ≥ 2; PP ⇒ pp_size). Single-batch configurations are unchanged.

Why the symptom is so elusive

Test Plan / Test Result

Repro hardware: 8×A800-80G PCIe (SM80), GLM-5.2 NVFP4 via #47629, TP=2 × PP=4, --no-async-scheduling, bf16 KV:

  • Before: 9 concurrent long prefills (26k–86k tokens, 3-way concurrency) crash the engine within ~2 minutes (illegal memory access, surfacing at the indexer's build_prefill_chunk_metadata kernel launch). Reproduced twice; also reproduced by @Ph0enix89 on multi-node in [Feature] TRITON_MLA_SPARSE backend for SM8x/11x/12x DSA Sparse MLA Support #38476.
  • After: same stress ×3 rounds — 27/27 requests complete, all needle-retrieval answers correct.
  • Short-context PP serving, TP-only serving, and tool calling unaffected.

Notes

  • Not a duplicate: no open issue/PR covers this (searched "pipeline parallel illegal memory access", "batch queue pinned race", prepare_inputs_event).
  • The V2 model runner has its own input-prep path and is not touched here.
  • AI assistance (Claude Code) was used to root-cause and draft this fix; the submitter reviewed every line and ran the tests above.

🤖 Generated with Claude Code

prepare_inputs_event was only created with async scheduling, but the PP
batch queue creates the same overlap: input prep for step N+1 rewrites
the reused pinned CPU tensors (seq_lens_cpu, query_start_loc_cpu, ...)
while step N's non_blocking H2D copies from those buffers may still be
pending, so step N's kernels can consume step N+1's values. Observed as
nondeterministic illegal memory accesses with DSA sparse-MLA models
under PP with --no-async-scheduling (kernels index with device seq_lens
into buffers sized from the CPU values of the earlier step); disappears
under CUDA_LAUNCH_BLOCKING=1 and with TP-only.

Create the event whenever max_concurrent_batches > 1 so
synchronize_input_prep() guards every overlapped-step configuration.

Repro: GLM-5.2 NVFP4 on 8xA800 (SM80, vllm-project#47629), TP=2 PP=4, 9 concurrent
50-90k-token prefills crashed within ~2 min; with this fix 27/27
requests across 3 rounds complete with correct outputs.

Signed-off-by: Thomas Wang <thomas.l.wang@gmail.com>
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging.

To run CI, PR reviewers can either: Add ready label to the PR or enable auto-merge.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban.

🚀

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify

mergify Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @thomaslwang.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jul 7, 2026
@Kasempiternal

Copy link
Copy Markdown

Production data point from a large A100 (sm80) deployment, in case it helps — we run the TRITON_MLA_SPARSE backend (#47629) in production and have been hitting the IMA this PR targets.

For the "is sm80 sparse-MLA worth supporting?" question upstream: GLM-5.2 on A100 is only possible via the Triton sparse-MLA path, and it's been serving a multi-day batch-generation workload for us — so there's at least one real production user depending on it.

Setup

  • GLM-5.2, vLLM v0.23.0
  • 8 nodes × 4× A100 80GB, --tensor-parallel-size 4 --pipeline-parallel-size 8, Ray executor
  • TRITON_MLA_SPARSE (DeepGEMM unavailable on sm80 → Triton fallback for the sparse-attn indexer), DEEPSEEK_V32_INDEXER KV backend
  • enforce_eager=False (PIECEWISE cudagraph), chunked prefill + prefix caching on, max_model_len=131072
  • No --async-scheduling
  • Continuous high-concurrency generation (~16–24 running requests), sustained ~130–155 tok/s decode, multi-day

Symptom

  • CUDA error: an illegal memory access was encountered (cudaErrorIllegalAddress), surfaced by the NCCL ProcessGroup watchdog (ProcessGroupNCCL.cpp:2119), on multiple PP ranks.
  • Always at decode time under concurrency, mid-generation — never at startup/model-load.
  • Frequency: 13 of 381 serve instances over the run.

Because CUDA errors are reported asynchronously, the watchdog stacktrace only shows where the error surfaced (the next NCCL collective), not the faulting kernel — so I can't prove from the trace alone that it's the reused-pinned-buffer race described here. But the trigger conditions match this PR's analysis exactly: PP batch queue (max_concurrent_batches == pp_size == 8) + no async scheduling + sparse-MLA, crashing during overlapping decode steps. A restart-from-checkpoint supervisor masks it (the workload completes regardless), which is likely why it hasn't surfaced more loudly from batch users.

Offer: since our serves cycle frequently anyway, I can apply this PR across the fleet and report whether the decode-time IMA rate drops from ~13/381 to zero over comparable serve-hours — a clean before/after on real sm80 hardware. Happy to test against whatever commit / combination with #47629 is most useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working needs-rebase v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants