Skip to content

Avoid device syncs when releasing paged SWA segments - #35953

Closed
weireweire wants to merge 7 commits into
sgl-project:mainfrom
weireweire:perf/paged-swa-segment-free
Closed

weireweire wants to merge 7 commits into
sgl-project:mainfrom
weireweire:perf/paged-swa-segment-free

Conversation

@weireweire

@weireweire weireweire commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add segment-aware paged release using fixed-stride page representatives instead of data-dependent torch.unique.
  • Preserve request boundaries and CPU-known SWA eviction frontiers through deferred free groups.
  • Release Full KV completely while releasing only the still-live SWA suffix for hybrid SWA, DSV4 HiSparse, and shared-ID unified allocators.
  • Route chunk-cache, unified radix-cache, over-allocation cleanup, sliding-window eviction, and unified component actions through the segment-aware APIs.
  • Validate page-dense Full-to-SWA mappings rebuilt by HiCache and tombstone recovery, while retaining the legacy fallback when request-level SWA geometry is unavailable.

Motivation

Paged SWA cleanup previously rediscovered physical pages from token-slot tensors with torch.unique and dynamic filtering. Their data-dependent output sizes can synchronize the scheduler thread with the CUDA stream.

For a contiguous request segment, the touched pages are already determined by its logical start position, length, and allocator page size. Fixed-stride representatives and the CPU-maintained SWA eviction frontier provide fixed-shape release geometry without GPU-to-CPU size discovery.

Deferred releases must also preserve request boundaries: flattening segments from different requests can incorrectly treat equal relative positions as a shared boundary page.

This focused change is extracted from the broader integration work in #34515, which increase E2E throughput by 40%. And the E2E test include this change is done there.


CI States

Latest PR Test (Base): ❌ Run #33233754247
Latest PR Test (Extra): ❌ Run #33233754226
Latest PR Test (AMD ROCm 7.2): ❌ Run #33233754342

@weireweire

Copy link
Copy Markdown
Contributor Author

/tag-and-rerun-ci

@weireweire
weireweire force-pushed the perf/paged-swa-segment-free branch 6 times, most recently from f41b008 to 6b997a2 Compare August 25, 2026 07:55
weireweire added a commit to weireweire/sglang that referenced this pull request Aug 25, 2026
Root cause:
Paged SWA cleanup rediscovered physical pages with torch.unique and dynamic
mapping filters, whose data-dependent output sizes can synchronize the
scheduler thread with the CUDA stream. Deferred segment release also flattened
different requests, allowing equal relative positions to be mistaken for a
shared boundary page.

Fix:
Use fixed-stride page representatives and request-scoped segment release with
the CPU-maintained SWA eviction frontier. Preserve request boundaries through
free groups, validate page-dense mappings rebuilt by load-back and recovery,
and route hybrid SWA, DSV4 HiSparse, and shared-ID unified cleanup through the
fixed-geometry paths while retaining the unknown-geometry legacy fallback.

Validation:
- pre-commit run --all-files --show-diff-on-failure
- Python syntax compilation for all changed modules and tests
- git diff --check and added-line getattr audit
weireweire added a commit to weireweire/sglang that referenced this pull request Aug 25, 2026
Root cause:
Paged SWA cleanup rediscovered physical pages with torch.unique and dynamic
mapping filters, whose data-dependent output sizes can synchronize the
scheduler thread with the CUDA stream. Deferred segment release also flattened
different requests, allowing equal relative positions to be mistaken for a
shared boundary page.

Fix:
Use fixed-stride page representatives and request-scoped segment release with
the CPU-maintained SWA eviction frontier. Preserve request boundaries through
free groups, validate page-dense mappings rebuilt by load-back and recovery,
and route hybrid SWA and DSV4 HiSparse cleanup through fixed-geometry
paths while retaining the unknown-geometry legacy fallback.

Validation:
- pre-commit run --all-files --show-diff-on-failure
- Python syntax compilation for all changed modules and tests
- git diff --check and added-line getattr audit
@weireweire
weireweire force-pushed the perf/paged-swa-segment-free branch from 6b997a2 to d92f2b5 Compare August 25, 2026 09:18
@YAMY1234

YAMY1234 commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Validation result on the Qwen3.5 AgentX workload:

  • Total TPS/GPU: 118,677.58 vs. 117,919.87 baseline (+0.643%)
  • P90 TPS/User: 110.465 vs. 108.131 baseline (+2.158%)

We observed no measurable performance regression from this isolated cherry-pick. The positive movement is still within our 3% run-to-run threshold, so we are not claiming a material or statistically significant improvement.

Root cause:
Paged SWA cleanup rediscovered physical pages with torch.unique and dynamic
mapping filters, whose data-dependent output sizes can synchronize the
scheduler thread with the CUDA stream. Deferred segment release also flattened
different requests, allowing equal relative positions to be mistaken for a
shared boundary page.

Fix:
Use fixed-stride page representatives and request-scoped segment release with
the CPU-maintained SWA eviction frontier. Preserve request boundaries through
free groups, validate page-dense mappings rebuilt by load-back and recovery,
and route hybrid SWA and DSV4 HiSparse cleanup through fixed-geometry
paths while retaining the unknown-geometry legacy fallback.

Validation:
- pre-commit run --all-files --show-diff-on-failure
- Python syntax compilation for all changed modules and tests
- git diff --check and added-line getattr audit
@weireweire
weireweire force-pushed the perf/paged-swa-segment-free branch from d92f2b5 to b69be4b Compare August 27, 2026 09:16
@nvpohanh

Copy link
Copy Markdown
Collaborator

[by Codex] The required PR Test Base failure appears caused by this PR. Both root failures exercise unified-memory allocation/release paths changed here:

  • test_disaggregation_unified_memory.py reports a scheduler invariant failure: full-pool memory leak (total=5604, available=5593; 11 slots missing), then the server exits.
  • test_unified_memory_deterministic.py also exits during unified-memory server startup.

The other red Base jobs are fast-fail cascades from these roots. Please audit the new free_segments/free_swa_segment and grouped Full/SWA component-release paths for slots that are not returned to the full allocator.

Root jobs:

Root cause:
The segment-aware cleanup path queues free_segments calls separately from legacy free calls while a free group is active. Unified Mamba and shared-SWA allocators overrode free_group_end but only drained the legacy queue, leaking every Full slot from a finished request; the failing CI request retained 11 slots.

Fix:
Reset and drain the segment queue in both unified composite allocators. Preserve shared-SWA request boundaries and free its still-live suffix directly from the CPU-known eviction frontier.

Validation:
- 13 tests passed in test_paged_free_segment.py inside the SGLang CUDA container
- uvx pre-commit run --all-files --show-diff-on-failure
- Python compileall for changed source and test
- git diff --check and added-line getattr audit
Resolve the free-group state refactor by adopting the new None/list sentinel for deferred segment queues. Keep grouped Full/SWA and Mamba segment release draining after the group switches back to immediate-free mode.

Validation: python compileall and focused pre-commit checks pass.
Preserve deferred segment draining alongside the new full-only SWA release path. Both queues now participate in group lifecycle without bypassing deferral.

Validation: compileall and focused pre-commit checks pass.
Root cause: the unified SWA allocator bypasses the static SWA parent constructor and free-group hooks, so the newly added full_free_group state was neither initialized nor drained. The Base CPU test failed on the first grouped free_full call with AttributeError; initializing only the field would leave a silent deferred-release leak.

Fix: initialize and reset full_free_group with the allocator lifecycle, create a fresh queue at free_group_begin, and drain it after Base finishes ordinary and segment releases.

Validation: compileall, diff checks, focused pre-commit, and full pre-commit pass. The exact runtime test could not be run locally because this checkout has no Torch/Numpy environment; PR CI provides the runtime confirmation.
@nvpohanh

nvpohanh commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

@weireweire could you fix the conflicts?

@weireweire

Copy link
Copy Markdown
Contributor Author

closing as supersede by @hnyls2002 's #36637 and follow up PRs

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants