Repository navigation
Conversation
ormandj
requested review from
Ying1123,
hnyls2002,
merrymercy and
xiezhq-hermann
as code owners
September 2, 2026 13:25
Open
2 tasks done
ormandj
force-pushed
the
pr/hybrid-ssm-admission-latch
branch
2 times, most recently
from
September 8, 2026 21:44
5d8f335 to
7624e35
Compare
ormandj
force-pushed
the
pr/hybrid-ssm-admission-latch
branch
from
September 30, 2026 01:20
7624e35 to
e2a2879
Compare
Contributor
Author
|
Updated the code and PR body. The scheduler clears the full-batch admission latch each round for the affected Mamba configuration so queued prefills can retry when capacity recovers. |
ormandj
force-pushed
the
pr/hybrid-ssm-admission-latch
branch
from
October 7, 2026 05:43
e2a2879 to
df1a10c
Compare
ormandj
requested review from
alphabetc1,
hanming-lu,
huangtingwei9988,
hzh0425,
ispobock and
yizhang2077
as code owners
October 7, 2026 05:43
Retrying admission re-runs the prefix match, whose Mamba copy-on-write allocation asserted when no slot could be freed. Capacity can shrink after an earlier refusal, so raise a dedicated error there and treat it as a NO_TOKEN refusal in prefill admission.
ormandj
force-pushed
the
pr/hybrid-ssm-admission-latch
branch
from
October 10, 2026 12:50
df1a10c to
2dd9bc5
Compare
detain
added a commit
to detain/sglang
that referenced
this pull request
Oct 15, 2026
…ests queued instead of asserting [batch-apply-h 2026-10-15] MambaCowAllocError(RuntimeError) in base_prefix_cache; unified mamba.py finalize_match_result_in_cache COW site raises instead of asserting (:226 crash class). Scheduler _get_new_batch_prefill_raw: try/except around init_next_round_input -> res=NO_TOKEN (falls into existing revert block, then alloc_group_end still runs; raise happens pre-pool_idx-set so holds_mamba False -> no double-free); batch_is_full per-round reset extended with is_hybrid_ssm and tree_cache.supports_mamba(). Union: our staging hunk keeps observe_storage_staging_ready inside the else; our is_empty()/has_chunked/ min_free_slots_delayer/QSA truncation_align_size blocks intact. Test fixtures adapted to our drifted scheduler: running_batch.is_empty stub (our empty-batch reset block), adder.preempt_list (our preemption requeue), s.hisparse_coordinator (our post-init_new assign). Squash 8f55e71+ f648184+2dd9bc5902.
detain
added a commit
to detain/sglang
that referenced
this pull request
Oct 15, 2026
- test_hisparse_unit.py: module-level get_device() crashed collection on accelerator-less hosts (register_cuda_ci file); skip allow_module_level instead, matching the all-GPU-files convention. - test_scheduler_batch_is_full_latch.py: the __new__ Scheduler stub lacked is_hybrid_ssm, which the sgl-project#37612 admission-gate arm now reads; set False so the gate short-circuits before tree_cache (stub stays non-hybrid, same semantics under test). Both byte-identical failures verified pre-existing at 64f204b in a temp worktree. 1E->1S, 1F->1P. Co-Authored-By: opencode <noreply@opencode.ai>
detain
added a commit
to detain/sglang
that referenced
this pull request
Oct 29, 2026
[Fix] scheduler: keep chunked prefill within allocatable KV under memory pressure. Three admission bugs: (1) a continuation chunk could ask alloc_extend for more KV than is free -- PrefillBudget. available_chunk_tokens now caps by real free KV minus the one-page over-ask and defers (None) instead of forcing a full chunk; (2) the single-unfinished-chunk guard now applies to ALL policies, not just shortest-prefill-first (a second unfinished chunk was untrackable); (3) batch_is_full is cleared unconditionally each round -- a latched flag was otherwise only cleared when the running batch shrinks, stalling the waiting queue until an unrelated finish (absorbs closed sgl-project#35609). UNION / DEVIATIONS: - scheduler.py hunk hand-merged: our region carried the entry-198 hybrid-SSM reset arm + is_empty arm; both are strict subsets of the unconditional clear and were removed. Entry-198's COW NO_TOKEN-retry semantics are unaffected (admission re-runs every round anyway). - Consequently the two entry-198 gate tests were re-pinned to the new unconditional behavior (non-hybrid now retries every round too); their mamba-arm and COW-recovery cases pass unchanged. - PR's new test_scheduler_batch_is_full_latch.py NOT imported: the file already exists in-tree (entry-222 wave) with fork stubs; kept ours, refreshed the stale sgl-project#37612-arm comment. - AITER backend hunk + test_aiter_attention_backend_handler.py SKIPPED per instruction (ROCm aiter path irrelevant to this stack). - test_prefill_memory_budget import hunk conflicted (our tree lacks the upstream ChainAllocator test rework): resolved as PrefillBudget + SWAPrefillBudget union; new TestContinuingChunkCap verbatim. - Chunk-guard hunk applied verbatim: our _select_prefill_admission matched the PR base exactly; no mixed-chunk adaptation fights it (mixed-chunk tracks its rows via the scheduler, not new_chunked_req). CPU: targeted (prefill_adder + memory_budget + 3 latch/retry + held_row) 83P/67sub; full managers dir 993P/2F/3skip/904sub == the 2F are pre-existing order-dependent test_mm_process_config failures (verified identical on the stashed baseline, 992P/2F). (cherry picked from commit 0954308) (cherry picked from commit d2bf2d29c4b5382291e672a3a1f0ac844cba196b)
detain
added a commit
to detain/sglang
that referenced
this pull request
Oct 29, 2026
… (+test re-anchors) Re-plants the fork-hunks patch (replant/...components__mamba.py.fork-hunks.patch) onto the #46970x component rewrite. B3 marker consumed in unified_cache/components/mamba.py. Per-hunk state: - entry 216 (prefix-lock release before the donation retry): ALREADY ABSORBED at the merge inside the old _alloc_mamba_slot; the replant keeps it verbatim while renaming to _try_alloc_mamba_slot -> Optional (test-verified shape). - entry 198 (sgl-project#37612): match-path COW failure raises MambaCowAllocError (class definition survived the merge; the RAISER was the dropped half). CROSS-NOTE FOR B4: the prefill-admission CATCHER (the merge dropped it too; test_scheduler_hybrid_ssm_admission_retry.py in managers awaits it — B4 zone). - entry 197 (sgl-project#37943): donation with a pinned pool SKIPS the boundary checkpoint + rate-limited capacity warning (_record_skipped_checkpoint; available-count via req_to_token_pool.mamba_allocator, the fork's accessor — the merge's storage abstraction offers no equivalent that survives the duck-typed harnesses). - entry 196 (sgl-project#39209): _mamba_value_misaligned + mamba_value_seqlen stamped at BOTH prepare sites (the InsertParams field survived the merge unused); commit refuses to stamp, cleanup frees the misaligned value. - entry 30 (sgl-project#39830 fencing, the L2 half): _token_depth/_record_host_ckpt_pos/ _host_ckpt_position_ok/_poison_stale_host_ckpt + prepare_load_back PrepareLoadBackResult(rejected=True) (the URC unwind rode B3-3) + the two record sites (BACKUP_HOST attach, LOAD_BACK attach). Host-pool surface (ckpt_pos_buffer/record_ckpt_pos/get_ckpt_pos in pool_host/mamba.py) verified PRESENT (survived) — not duplicated. _poison call adapted to the widened _evict_component_and_detach_lru signature (cache_actions positional). - entry 90: alloc_prefetch_staging shortfall reclaim (MAMBA half; the SWA half rode B3-4; the host-group half rode B3-4). - class-level tallies (_ckpt_pos_rejects/_skipped_checkpoint_count) follow the established __new__-harness convention. Test re-anchors (B2 owns this file's markers; these are the fork-case mechanical repairs its re-home left needing after the component landed): - test_mamba_donated_alloc_ratio.py: _RatioCache stub gained the req_to_token_pool the storage now routes donate through (+ the lazy-boundary batch stub carries token_to_kv_pool_allocator, schedule_batch.py:3661). - test_hicache_mamba_ckpt_pos_fence.py: the evict_and_detach mirror updated to the post-#4697x positional cache_actions. ACTUALS (damage -> after): test_mamba_donated_alloc_ratio 13P/8F/10sub -> ** 17P/0F/14sub ** (295 pin 16P/14sub: AT OR ABOVE) test_hicache_mamba_ckpt_pos_fence 12P/3F -> ** 15P/0F ** (entry-30 pin "fence 15P" EXACT) test_mamba_value_alignment 2P/1F -> 3P/0F (entry-196 guard) test_mamba_path_state_cap 5P/5S unmoved (honest CUDA skips; entry 199 half rides the URC already landed) test_hicache_mamba_sizing 30P/0F/17sub (unmoved, B3-4 verified) Lint: ruff format+F821/E9/F401 clean; py_compile+import OK. No GPU; no push.
detain
added a commit
to detain/sglang
that referenced
this pull request
Oct 30, 2026
…entries 122,198,200,211,215,220,267,268,305 Re-plants the scheduler.py fork-hunks (replant/...managers__scheduler.py.fork-hunks.patch) onto the post-sgl-project#46977 admission structure. tp_worker marker consumed (15/23 B4 markers still on the tree; per-file counts, damage-state from entry 310's map). PER-HUNK DECISIONS (all VERIFIED against the merged tree, not taken on faith): - entry 122 (sgl-project#40458): grammar-sync overlap disable RE-PLANTED for mixed mode (is_decode() OR is_mixed()) + the fork's trimmed comments; upstream's host-draft-only arm was the pre-sgl-project#40458 form (origin/main verified: absent). - entry 220 (sgl-project#39765, OPEN port): _has_pending_mamba_cache_update + the early pop_and_process/short-circuited disable-overlap RE-PLANTED into event_loop_overlap; the require_mlp_sync/disable/extra-buffer gate verbatim. - entry 198 (sgl-project#37612): THE CATCHER — B3-5 landed the raiser; the try/except MambaCowAllocError around init_next_round_input (res=NO_TOKEN, request stays queued; the revert block + unconditional alloc_group_end were already in the merged tree = the no-leak halves VERIFIED PRESENT) RE-PLANTED with the import. COW component test re-anchored to the #46970x kv_storage seam the B3-5 replant moved _state() behind (stub was the pre-split mamba_allocator shape). - entry 268 (sgl-project#46643, OPEN port -- VERIFIED NEVER MERGED: git log 12dc623..2a6c204 --grep 46643 = ZERO; only sgl-project#45491/sgl-project#45435/sgl-project#45472/sgl-project#45670 of the briefed merged-list arrived in-range): the UNCONDITIONAL batch_is_full clear RE-PLANTED on the scheduler side, subsuming the entry-198 hybrid-SSM arm and the priority-preemption/is_empty arms (policy side lands in B4-3). - entry 267 (sgl-project#46496): retract_decode new_token_ratio FLOOR clamp RE-PLANTED. - entry 211: triton_load_watch.prewarm_device_loads(self.model_worker) line RE-PLANTED between install() and mark_serving_started (the utils-side function survived the merge; only the call site was dropped). - entry 200 (sgl-project#43527) CAPACITY PAIR RE-PLANTED: model_runner .logical_max_total_num_tokens passes allocator= again (the configurator's PageInterleavePoolAllocator -> allocator.size branch SURVIVED the merge byte-identical, so the merged tree had the fork predicate with upstream's consumer-side multiplications = DOUBLE-COUNT); the three scheduler * kv_shard_widening multipliers back to the fork form (pool-stats shape, load_inquirer, and the init_req one-page-per-shard subtraction); tp_worker drops page_interleave_shard_size x + import. Upstream's invariant-checker hunk: OBSOLETE (the constructor no longer takes max_total_num_tokens -- absorbed by refactor). - entry 215 (sgl-project#44351/sgl-project#44401/sgl-project#44420): VERIFIED ALREADY PRESENT at the merge (filter_batch-every-step + reset ride, num_held_rows, budget_state FIRST statement, PD-gate deletion all byte-compare to the fork form) -- DEDUPED, no edit. Entry 107's local early-revision of sgl-project#40940 stays superseded (entry 215 rule), and its re-plant here would double-count. - entry 220's/305's pause-window busy accounting + write_fence_stream + is_empty arm: VERIFIED PRESENT (entry 305 landed patch-identical via sgl-project#46127; the fence assignment is the B3-2 controller half) -- DEDUPED. TEST FIXTURE RE-ANCHORS (not B2's: no markers, pure new-upstream-contract drift, per the entry-198 fixture-adaptation precedent): the two hybrid-ssm admission stubs gain disagg_prefill_bootstrap_queue=None (upstream's routing-key bootstrap_queue arg in calc_priority arrived in-range). PRUNE vs BREAKAGE (managers −523sub audit): the three managers test files vanished in-range (test_schedule_policy_dfs_weight, test_scheduler_batch_is _full_latch, test_uno_token_accounting) were ALL deleted by upstream's OWN sgl-project#45672 prune (3438ed6). Two are byte-identical upstream copies = zero fork delta. The third carried a 3-line fork comment/stub delta whose SEMANTICS the re-planted unconditional clear pins: its case was the is_empty-arm mirror of test_scheduler_hybrid_ssm_admission_latch (present, green, hybrid_swa/non-hybrid arms included) -- NOT re-homed, recorded. ACTUALS (damage -> after, CVD=9, prod venv, PYTHONPATH=python, per-file): test_scheduler_hybrid_ssm_admission_retry 4F -> ** 4P ** test_scheduler_hybrid_ssm_admission_latch 3F -> ** 4P ** test_mamba_prefill_cache_boundary 2F/12subF -> ** 5P/12sub EXACT (220 pin) ** test_scheduler_retract_ratio 1F -> ** 2P EXACT (267 pin) ** test_scheduler_init_req_max_new_tokens 1F -> ** 10P/6sub ** test_scheduler_grammar_mixed_tail_sync 1F -> ** 4P ** adjacent scheduler-stub files (held_row, running_batch_finished, pause_generation, disagg_idle, dp_converted, hicache_events) 56P/64sub UNMOVED -- no regression from the clear/catcher/capacity edits. Lint: ruff format + F821/E9 clean on all five files; imports OK (no GPU execution, no push). Co-Authored-By: OpenCode <noreply@opencode.ai>
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
A hybrid SSM server can leave requests queued even after Mamba-state capacity becomes available. Once admission marks the running batch as full, the scheduler does not retry while that batch remains unchanged. Cached states can become evictable during that time, so a previous capacity failure is not a valid reason to stop checking.
Retrying exposes a second problem. Each admission attempt re-runs the prefix match, and a match that hits a cached Mamba state allocates a per-request slot for the copy-on-write before
PrefillAdderchecks capacity. If no slot can be freed (for example, decode has consumed a shared Mamba/attention pool since the earlier refusal and the remaining cached states are locked), that allocation asserted and terminated the scheduler instead of leaving the request queued.This PR retries admission for hybrid SSM models whose cache supports Mamba state, and makes a failed copy-on-write allocation an ordinary admission refusal. It does not bypass capacity checks or enlarge the pool.
Modifications
MambaCowAllocErrorinstead of asserting. The matched node's lock is still released and the request is left without a slot.NO_TOKENrefusal: the request stays in the waiting queue and is retried in a later round. Other callers of the prefix match are unchanged apart from the exception type.Accuracy Tests
All tests below were run with real pytest 9.1.1 via
uv runin a CPU-only PyTorch 2.14.1 environment (no GPU), from the repository root withPYTHONPATH=python:test. The two new files pass 8 of 8 withpython -m pytest test/registered/unit/managers/test_scheduler_hybrid_ssm_admission_latch.py test/registered/unit/managers/test_scheduler_hybrid_ssm_admission_retry.py. These tests call scheduler and cache methods directly with stubbed collaborators; no model is loaded.batch_is_fulleach round.NO_TOKENverifies admission is retried each round for hybrid SSM; the non-hybrid case attempts admission once.MambaComponent.finalize_match_result_in_cachewith an allocator that has no free slot and an eviction that frees nothing. It raisesMambaCowAllocErrorwith balanced lock calls and no slot assigned (the previous code raisedAssertionError).init_next_round_inputraisesMambaCowAllocErrorin round 2, and in round 3 the stub succeeds and the adder stand-in accepts. Round 2 returns no batch and keeps the request queued without callingadd_one_req(on the previous code the error propagated out of the scheduler); round 3 passes the request to the (mocked)ScheduleBatch.init_newand empties the waiting queue. No real allocator capacity is consumed or recovered in this test.Existing related unit tests in the same environment:
test/registered/unit/mem_cache/test_mamba_donated_alloc_ratio.py,test_mamba_path_state_cap.py,test_mamba_unittest.py,test/registered/unit/managers/test_prefill_adder.py,test_schedule_policy.pyand the 18 othertest/registered/unit/managers/test_scheduler_*.pyfiles give 197 passed, 5 skipped (thetest_mamba_path_state_cap.pypool fixtures need CUDA) and 596 subtests passed. A successful copy-on-write allocation after real capacity recovery, with a real Mamba cache on GPU, has not been tested.Speed Tests and Profiling
Adds an admission attempt each round while capacity remains unavailable. Overhead was not measured.
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciDeveloped with AI assistance.
CI States
Latest PR Test (Base): ❌ Run #38053460648
Latest PR Test (Extra): ❌ Run #38053460464
Latest PR Test (AMD ROCm 10): ❌ Run #38053460574