Skip to content

[Feat] QSA: Add cache sharding for Qwen3.8 hybrid models - #43527

Open
shiyang814-cpu wants to merge 6 commits into
sgl-project:mainfrom
shiyang814-cpu:feat/qsa-cache-sharding
Open

shiyang814-cpu wants to merge 6 commits into
sgl-project:mainfrom
shiyang814-cpu:feat/qsa-cache-sharding

Conversation

@shiyang814-cpu

@shiyang814-cpu shiyang814-cpu commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR introduces QSA cache sharding for QSA-enabled Qwen3.8 hybrid models. It shards the sequence-length-dependent QSA states:

  • QSA raw K/V history
  • QSA compressed cache

The implementation reuses SGLang's page-interleave placement and allocator infrastructure, and adds:

  • allocator-visible logical QSA cache sharding
  • decode allocation over the widened logical slot space
  • exact distributed QSA Top-K
  • owner-side sparse attention
  • FP32 log-sum-exp output merging
  • CUDA Graph-compatible communication and metadata buffers
  • one shared CUDA Graph collective arena across all QSA layers

The implementation is functionally validated and benchmarked with the Qwen3.8-Flash-Next-FP8 checkpoint on NVIDIA H20 GPUs.

Performance

The benchmark uses theQwen3.8-Flash-Next-FP8 model on 8 NVIDIA H20 GPUs with TP8 and EP8. It uses random token IDs with an output length of 1, a maximum concurrency of 1, and a chunked prefill size of 8192, with Decode CUDA Graph enabled and Radix Cache disabled.

Input length Mode TTFT Input throughput Logical capacity
256K Unsharded 16,798.12 ms 15,605.55 tok/s 2,692,032
256K QSA shard 4 15,471.77 ms 16,943.38 tok/s 10,218,240
512K Unsharded 58,526.52 ms 8,958.13 tok/s 2,692,032
512K QSA shard 4 35,682.70 ms 14,693.06 tok/s 10,218,240
1M Unsharded 279,878.39 ms 3,572.98 tok/s 2,692,032
1M QSA shard 4 90,356.03 ms 11,067.33 tok/s 10,218,240
Input length TTFT reduction Speedup Throughput improvement
256K 7.90% 1.09x +8.57%
512K 39.03% 1.64x +64.02%
1M 67.72% 3.10x +209.75%

QSA cache sharding increases the logical QSA cache capacity from 2,692,032 to 10,218,240 tokens, approximately 3.80x.

Concurrent Long-Context Workload

With an input length of 1M tokens, 8 requests, and a maximum concurrency of 8:

Metric Unsharded QSA shard 4 Improvement
Input throughput 12,135.16 tok/s 14,351.96 tok/s +18.27%
Mean TTFT 372.84 s 314.44 s -15.66%
P99 TTFT 653.09 s 552.14 s -15.46%
Benchmark duration 659.24 s 557.42 s -15.45%

All 8 requests completed successfully in both configurations.

Accuracy

The standard SGLang GSM8K evaluation used 1,314 examples. The LongBench-v2 evaluation used 120 examples filtered to 10K-200K context lengths, with temperature 0.6, top-p 0.95, and up to 16,384 output tokens.

Both evaluations used chunked_prefill_size=8192.

Dataset Baseline QSA shard 4 Delta
GSM8K 0.977 0.978 +0.001
LongBench-v2 0.554 0.549 -0.005

The sharded results remain close to the unsharded baseline on both short-context reasoning and long-context evaluation.

Motivation

The QSA raw K/V history and compressed cache grow linearly with sequence length.

Before this change, every TP rank stored the complete QSA history. This caused two long-context bottlenecks:

  1. the replicated QSA history limited the total cache capacity to the physical capacity of one rank;
  2. every rank scanned the full compressed history during QSA token selection.

The impact becomes increasingly significant as the context length grows. On Qwen3.8-Flash-Next, the unsharded implementation spends substantially more time scanning and maintaining QSA history at 512K and 1M context lengths.

This PR assigns each QSA cache page to one owner rank. Each rank stores and scans only its local shard while preserving the exact unsharded QSA semantics.

Implementation

QSA cache placement

QSA raw K/V history and compressed cache reuse SGLang's existing page-interleave placement and allocator infrastructure.

Each QSA cache page is assigned to one owner rank. The scheduler, request token mapping, cache allocator, and QSA KV pools operate on the same widened logical slot space, while each rank stores only its local physical shard.

The allocator supports both prefill and decode allocation, keeping cache placement consistent throughout the request lifecycle.

Distributed QSA execution

Each rank scans only its local compressed-cache shard and produces local candidates.

The local candidates are merged into an exact global Top-K using deterministic global token-ID tie-breaking. The selected tokens are then routed to their raw K/V owners for sparse-attention computation.

Owner-side partial outputs are merged using FP32 log-sum-exp normalization, preserving the original unsharded QSA semantics.

The distributed path supports both eager execution and CUDA Graph replay.

CUDA Graph buffers

QSA communication uses fixed-address buffers for CUDA Graph compatibility.

All QSA layers share one collective buffer arena because the layers execute serially and do not require concurrent per-layer storage.

For the largest tested graph bucket with 48 QSA layers, this reduces the collective arena from approximately 4.42 GiB to 94.35 MiB.

CUDA Graph metadata

QSA CUDA Graph metadata construction is limited to compressed pages visible to the current sequence.

Unused page-table tails are not cleared during every replay because downstream consumers are bounded by graph_compressed_lengths.

This preserves correctness while reducing metadata overhead for long contexts.

Memory accounting

The KV cache configurator reserves NCCL CUDA Graph private pools and PLE prefill workspace before sizing the KV cache.

The QSA collective arena additionally uses exact byte accounting verified against its allocated tensor storage.

Usage

python3 -m sglang.launch_server \
  --model-path /models/Qwen3.8-Flash-Next-FP8 \
  --tp-size 8 \
  --ep-size 8 \
  --qsa-cache-sharding-size 4 \
  --chunked-prefill-size 8192 \
  --max-prefill-tokens 8192 \
  --mem-fraction-static 0.85 \
  --cuda-graph-max-bs-decode 16 \
  --context-length 1048576 \
  --linear-attn-prefill-backend flashinfer

--qsa-cache-sharding-size 4 creates a four-rank QSA cache-sharding group inside the TP group.

Testing

The implementation is validated with the Qwen3.8-Flash-Next QSA configuration.

Correctness coverage includes:

  • unsharded and sharded QSA token selection;
  • exact distributed Top-K;
  • deterministic global token-ID tie-breaking;
  • raw K/V owner mapping;
  • owner-side sparse attention;
  • FP32 LSE merging;
  • prefill and decode paths;
  • eager execution;
  • CUDA Graph capture and replay;
  • shrinking sequences and padded graph rows;
  • shared collective arena byte accounting.

Production-path distributed integration tests run with:

  • 2 GPUs using NCCL;
  • 4 GPUs using NCCL.

The distributed prefill and decode outputs are compared against the unsharded reference, including CUDA Graph replay after input mutation.

Test results:

  • test_qsa.py: 201 passed, 1 skipped
  • test_qsa_kv_pool.py: 5 passed
  • Ruff import and error checks: passed
  • Ruff format check: passed
  • Python compileall: passed
  • git diff --check: passed
  • Qwen3.8-Flash-Next 256K/512K/1M prefill benchmark: passed

Scope

This PR only shards QSA cache states for Qwen3.8-Flash-Next-style hybrid QSA models.

The following remain unchanged:

  • GDN recurrent states
  • PLE states
  • MoE expert placement

Pipeline parallelism and PD disaggregation are not supported by QSA cache sharding in this PR.


CI States

Latest PR Test (Base): ⏳ Run #42155951214
Latest PR Test (Extra): ❌ Run #42155951040
Latest PR Test (AMD ROCm 10): ❌ Run #42155951136

Tip

Base CI only covers the core cases, and its workload may not exercise your change. Use /rerun-test to run the tests your change touches, or copy this prompt for an agent:

Find the registered tests this PR affects and run them with /rerun-test, following https://github.com/sgl-project/sglang/blob/main/.agents/skills/rerun-test/SKILL.md

@shiyang814-cpu shiyang814-cpu changed the title [Feat] Shard QSA Cache Across Context Ranks [Feat] Shard QSA cache across context ranks Oct 10, 2026
@shiyang814-cpu shiyang814-cpu changed the title [Feat] Shard QSA cache across context ranks [QSA] Shard QSA cache across context ranks Oct 10, 2026
shiyang814-cpu added a commit to shiyang814-cpu/sglang that referenced this pull request Oct 10, 2026
Expand deferred block indices, including the pending tail, before the
owner fallback maps logical token IDs to KV slots.

Validate cache-sharding groups against the model's KV-head replica width
using attention TP size, and reject unsupported QSA plus DCP composition.

Keep configurator results in physical rows and convert once through the
runner and allocator. Pass logical capacity unchanged to worker request
limits, scheduler admission, load reporting, and pool invariant checks.

Add regressions to the existing QSA and scheduler test files. Normalize
formatting in the touched files and fix the unresolved Optional annotation.

Validation:
- Targeted suite: 96 passed, 1 skipped, 555 subtests passed.
- Related suite: 244 passed, 17 skipped, 161 subtests passed.
- Final focused rerun: 24 QSA tests and 15 capacity/admission tests passed.
- Four-GPU owner attention agrees with FP32 reference in eager, static,
  and CUDA Graph execution (maximum absolute error 0.005144).
- H20 TP8/sharding4 completes 512K and 1M prefill smoke requests.
- TP4/sharding4 with 24Q/2KV is rejected before weight loading.
- Ruff selected lint rules, isort, formatting, and git diff --check pass.

Validation limit: synthetic random-token generation is not token-exact
against the unsharded baseline. These regressions and kernel checks do
not establish full-model deterministic equivalence.

Refs: sgl-project#43527
@shiyang814-cpu
shiyang814-cpu marked this pull request as ready for review October 12, 2026 03:03
@shiyang814-cpu
shiyang814-cpu force-pushed the feat/qsa-cache-sharding branch 2 times, most recently from 1e06478 to 0c69e62 Compare October 12, 2026 12:26
@shiyang814-cpu shiyang814-cpu changed the title [QSA] Shard QSA cache across context ranks [QSA] Add QSA cache sharding for Qwen3.8 hybrid models Oct 12, 2026
@shiyang814-cpu
shiyang814-cpu force-pushed the feat/qsa-cache-sharding branch from a588d40 to d8a5294 Compare October 14, 2026 08:11
detain added a commit to detain/sglang that referenced this pull request Oct 15, 2026
…ls (TP-sharded QSA states, distributed top-k, owner attention, FP32 LSE merge, graph comm buffers)

Squashed net diff of shiyang814-cpu#43527 (base 72730d6) applied with
git apply -3; 27 conflict hunks hand-reconciled so stack semantics survive:
- _qsa_write_plan: 5-tuple(valid) x 7-tuple(cross-prefix) -> 8-tuple; ring
  snapshot (_snapshot_cross_prefix_members read-before-store, host-prefix
  gate) threaded through; _overwrite_cross_prefix_groups gains owner_rows
  so straddling groups honor cache-shard ownership (slot-0 inert when
  unsharded, owner-masked skip when sharded).
- metadata.get_prefill_mqa_inputs: PR sharded local-page-table branch
  (prefill_page_table set only when sharding active) + our fused
  qsa_pack_prefill_compressed_keys path kept for the unsharded default.
- sparse_attn: KV_IS_FP8 descale (merge-4 d6b9eb1) + PR RETURN_LSE in
  union; (total_q,device_index) geometry sig + batch-invariance gate intact.
- graph_metadata: 10-tuple launcher (num_groups + world/rank union).
- capacity: scheduler/tp_worker drop * kv_shard_widening (runner reports
  logical incl page-interleave); configurator reserves graph comm pools.
Gate: --qsa-cache-sharding-size (alias --state-cp-size) default 1 = OFF;
validation short-circuits when 1 (prod TP4 QSA behavior byte-unchanged).
Our CPU write-plan tests adapted to the 8-tuple; test_qsa ours+theirs unions.
detain added a commit to detain/sglang that referenced this pull request Oct 15, 2026
… stubs, CUDA/ops gates, guard-safe helper extraction

- test_qsa.py: our write-plan CPU tests unpack the new 8-tuple (+valid);
  PR's unguarded page_sharded topk tests get the file's CUDA skipif.
- test_qsa_fused_kv_prepare.py: __new__ stub pools must publish the same
  construction contract the PR's backend __init__ demands from real pools
  (cache_sharding_runtime size=1); eligibility + GPU-window stubs fixed.
- test_qsa_fp8_kv.py: trtllm-descale stub gained qsa_profile/_trtllm_counters
  and the pre-existing device-cuda failure is now an honest CUDA skip.
- test_custom_all_reduce_vmm_guard.py (pre-existing, unrelated): positive
  path needs the custom-AR ops extension -> skipif when not loaded.
- backend/metadata: prefill host-length tolist and sharded index_select pack
  moved into dedicated helpers so the stack's source-scoped hot-path guards
  (no host materialization / no eager gather chain) keep protecting the
  unsharded hot path exactly as before.
- srt qsa_indexer: drop now-unused get_is_capture_mode import (our sync-free
  RoPE capacity contract intentionally replaced the PR's guarded item() path);
  restore typing.Tuple for the snapshot signatures.
detain added a commit to detain/sglang that referenced this pull request Oct 15, 2026
…ps: whitelist validate_replayssm_spec_algorithm and validate_linear_lossless_verify at their pipeline positions; list --enable-linear-lossless-verify and --qsa-cache-sharding-size in the undocumented-flag allow list

Co-Authored-By: opencode <noreply@opencode.ai>
detain added a commit to detain/sglang that referenced this pull request Oct 15, 2026
STACK=qwennext-stack-204-2026-10-15, code tip c8792c2. Entries: 200
sgl-project#43527 QSA cache sharding (default OFF), 201 sgl-project#39716 tokenizer-clone
preprocessing (DEFAULT-ON), 202 sgl-project#38650 reconcile (upstream adopted,
entry-156 helper dropped), 203 sgl-project#42388 linear lossless-verify (default
OFF, replayssm-exclusive A/B arm), 204 no-GPU test maintenance trio.
Header/CAVEATS: FI 0.7.1 venv bump marked resolved (entries 162-164
PCIe-IPC ACTIVE next restart; 10-09/10-14 INERT notes annotated
HISTORY), sgl-project#44115 re-skipped at 0.7.1 (uniform_q_len still absent from
wrapper plan()), former DEFER/DEDICATED-WINDOW block replaced with
resolution pointers, new BEHAVIOR WATCH bullet for the restart.

Co-Authored-By: opencode <noreply@opencode.ai>
detain added a commit to detain/sglang that referenced this pull request Oct 19, 2026
The PR sgl-project#43527 port added the LSE stride slots and RETURN_LSE to the paged
chunk-prefill launch, but _sparse_gqa_chunk_prefill_paged has no LSE
output. The two extra positionals shifted onto NUM_KV_HEADS, so every
paged chunk prefill (SGLANG_QSA_CHUNK_PREFILL_KV_SOURCE=paged, or the
dense-pack OOM fallback) died with
"dynamic_func() got multiple values for argument 'NUM_KV_HEADS'".

The same port's owner LSE launch predated this branch's K/V descale
slots and KV_IS_FP8; pass unit descales and the FP8 flag so it launches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shiyang814-cpu shiyang814-cpu changed the title [QSA] Add QSA cache sharding for Qwen3.8 hybrid models [Feat] QSA: Add cache sharding for Qwen3.8 hybrid models Oct 20, 2026
@github-actions

This comment has been minimized.

@shiyang814-cpu
shiyang814-cpu force-pushed the feat/qsa-cache-sharding branch from 0fb8a3a to 4f0a18f Compare October 26, 2026 08:58
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>
detain added a commit to detain/sglang that referenced this pull request Oct 30, 2026
…ge damage — entries 61,75,133,137,140,162,176,178,201,247,300,110

LAST B4 COMMIT: 14 markers consumed (correction to B4-3's body: the
scheduler/schedule_policy pair was NOT deleted there -- consumed here, so the
true session census is 23/23, B4=0 on the tree, foreign B1 15/B2 2/B5 23
INTACT (grep census).)

IO_STRUCT 1F VERDICT (the session-1 NEEDS-ATTENTION flag): NOT a fork-delta
loss, NOT env -- UPSTREAM'S OWN guard extension vs stale fork stub:
_validate_joint_schema_request grew a pointer_head arm in-range
(origin/main tokenizer_manager.py:1455, ModelConfig.pointer_head), while our
test's SimpleNamespace stub predated it. Fixed test-side pointer_head=None,
matching the pattern the two sibling stubs (test_hidden_state_server_mode,
test_sampling_mask_validation) already adopted. 1F -> file GREEN.

RUNNER-ZONE MERGE DAMAGE (attributed AT ae6ee52 in a scratch worktree:
identical 7F there, NOT my regressions; tsv flashinfer_autotune/decode rows
were B4-classified without a tree marker):
- decode_cuda_graph_runner: _init_model_hooks DEFINITION lost at the merge
  while its __init__ CALL and the replay _replay_prepare_hook CONSUMER
  survived = every real DecodeCudaGraphRunner build dies AttributeError
  (boot-integrity class, same shape as B3-8's pool-side half). Re-planted
  VERBATIM from the entry-61 version (validate_model_support + the
  needs_replay_prepare-gated prepare_cuda_graph_replay hook; qwen4_exp
  still defines both).
- test_flashinfer_autotune_gate 5F: upstream grew TWO post-suite arms
  (kv-sharding get_parallel read + the block-FP8-as-MXFP8 model walk);
  pinned both in _should_run per the file's OWN per_tensor_fp8 precedent.
- test_graph_routing_context 2F: brand-new upstream file driving the
  fork-instrumented replay(); added the entry-61 hook off-pin to the
  __new__-built stub (entry-198 fixture-adaptation class).

PER-MARKER DECISIONS:
- prefill_cuda_graph_runner (300): RE-PLANT the ONE dropped line, the
  validate_model_support() call before capture (base_runner's method +
  model_context/capture/_capture/replay-context arms VERIFIED PRESENT --
  entry-300 union landed at merge).
- model_runner (300,187/sgl-project#43527): sgl-project#43527 half done IN B4-1 (allocator= kwarg);
  entry-300 half VERIFIED PRESENT (get_model().override(shared_experts=...)
  at split_prefill + forward ctx).
- eager_runner (61,176): fold VERIFIED LANDED (model_context execute,
  shared_read_event import retarget, forward_context(get_forward_context())
  decode wrap, resolve_prefill_shared_read_ends rename, cp_extend pair).
- runner_utils/__init__ (176): SUPERSEDED BY DESIGN -- upstream made the
  package initializer import-free (its own docstring says so) and ALL
  consumers import defining submodules (grep-audited, incl. the cp_extend
  pair used by eager/base runners).
- custom_all_reduce_v2 (75): SUPERSEDED with evidence -- upstream's own
  de26bb1 (sgl-project#46853) REMOVED the multi-node VMM allocator gate in-range
  (absent on origin/main); entry 75's LEGACY guard + shared probe live in
  custom_all_reduce.py:106 + cuda_vmm_utils:102; unit/distributed 156P/1S/
  35sub unmoved (the entry 308/309 guards stay intact).
- logits_processor (162): RE-PLANT the one dropped arm, pcie_ipc=True on the
  vocab _logits_gatherer (the MultimemAllGatherer pcie_ipc API + whole
  transport stack survived the merge -- only this opt-in call kwarg was
  lost); the out=/fp32-buffer/cast_to_float32 arms VERIFIED PRESENT.
  pcie selection/ar tests green.
- loader (178): RE-PLANT the sgl-project#42419 kv-scales-drop block (entries 178's
  recorded net-diff half) between the mxfp8 rename and the new-in-range
  monokernel wrapper; shared_experts resolve/override/attr arms VERIFIED
  PRESENT. unit/model_loader 161P/19S/91sub green.
- serving_responses (110,201): RE-PLANT both _preprocess offloads (the
  PreprocessExecutor machinery landed complete via upstream's sgl-project#39716
  absorption -- serving_base._preprocess + tokenizer_manager wiring +
  executor tests green); ADAPTED the _process_messages site with
  functools.partial to carry upstream's new-in-range output_constrained
  kw-only arg through the positional-only run() surface.
- qwen3_coder_detector (20,21,89,108-109,157-160): fold VERIFIED LANDED
  (math/jsonschema/referencing imports, tuple-return _get_arguments_config,
  _parse_finite_float, anyOf/oneOf union arm, parameters threading at both
  sites) -- merged with our streaming-string region (561 discards parameters
  DELIBERATELY, our entry-159 path needs config only).
- validation_hook (44,51) + moe_hook (247): VERIFIED -- union landed complete
  (no lost defs by AST diff; NGRAM+replayssm reject, b12x validator +
  FLASHINFER_B12X_W4A16 enum present; server_args 7F stays B6's re-pin).
- component_manager (140): RE-PLANTED IN FULL from the 309 tip -- the merge
  DROPPED the whole parallel-stage half while parallel_executor.py CALLS
  supports_parallel_stage_group/parallel_stage_group (LIVE runtime crash
  class) + AST-proved the ported methods byte-equal, _uses_seen/
  ResidentStrategy/ResidencyState(batch_is_warmup) all present, the 309->HEAD
  removed WarmupPhasePeak trio has ZERO callers (upstream's own in-file
  deletion). Diffusion import chain blocked at this seat by the missing
  imageio wheel (ENV class -- diffusion never ran here); battery = AST +
  py_compile + the executor's own unit contract file.
- mm scheduler (133,137): fold VERIFIED LANDED (all upstream-side symbols
  present: _wait_idle/_FINALIZE_IDLE_WAIT_S/release_wait_s/progress_reporter).

ACTUALS (damage -> after, CVD=9, prod venv, per-file):
  test_io_struct 1F -> ** 68P/2S/10sub **
  unit/model_executor/runner ** 7F -> 103P/2S/73sub EXACT-GREEN ** (7F
  proven merge-era at ae6ee52 in a scratch worktree)
  unit/model_loader 161P/19S/91sub GREEN; unit/distributed 156P/1S/35sub
  UNMOVED; pcie selection+ar GREEN.
  DIR unit/managers 1025P/83F/9S/427sub -> ** 1056P/2F/9S/474sub **
  (the 2F = the two DOCUMENTED order-dependent test_mm_process_config
  ENV-class F's, reproduce at base -- damage-map population preserved).
  DIR unit/spec 363P/20F/21S/238sub/2err -> ** 388P/0F/21S/238sub/0err **
  (seven consecutive full-dir runs EXACT; the one unrepeated 1F sighting
  during iteration is recorded as a non-reproducing flake, candidate class
  = the same cross-file module state as managers' mm_process_config pair).
  test_pcie_ipc_vocab_gather 27F IDENTICAL at ae6ee52 = register_cuda_ci
  4-gpu-b200 file run without GPU (ENV class, not this batch's dirs).
  serving_responses module import blocked by openai 2.6.1 vs required
  ==2.8.0 (upstream's own beam.py, pre-existing at merge -- ENV class).
DoD(c) FULL-DIR totals recorded above; DoD(d) trailing_endpoint re-run
** 17P = 17P ** post-B4 (B3 gate unmoved).
Lint: ruff format + F821/E9 clean across all touched files. No GPU; no push.

Co-Authored-By: OpenCode <noreply@opencode.ai>
@shiyang814-cpu
shiyang814-cpu force-pushed the feat/qsa-cache-sharding branch from 4f0a18f to b44c973 Compare November 4, 2026 03:12
@github-actions github-actions Bot added the hicache Hierarchical Caching for SGLang label Nov 4, 2026
@BBuf

BBuf commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

[BBuf Review Agent] Could you split it below 3000 changed lines (now 4625)?

@BBuf

BBuf commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

[BBuf Review Agent] Could you split it below 3000 changed lines (now 4146)?

@BBuf BBuf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[BBuf Review Agent] A few things to fix before this can go in.

"raw K/V write layout must match the owner-local cache: "
f"cache={tuple(cache_k.shape)}, buffer={tuple(key_buffer.shape)}"
)
owner_mask, loc = sharding.local_write_targets(loc)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[BBuf Review Agent] With shard size 4, production writes still go through the hybrid layer router directly to full_kv_pool, so this localization never runs. Owner attention reads slot // 4 while the writer uses the global slot, producing wrong KV reads and eventually out-of-bounds writes. Could we apply the mapping on the routed write path?

compressed_page_table,
compressed_lengths,
max_model_len,
min_scored_len=self.block_topk if use_fast_topk else 0,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[BBuf Review Agent] With shard size 4 and 256 compressed blocks per rank, this skips every local score even though the global merge still has to choose 512 of 1024 blocks. _maybe_merge_distributed_topk then ranks values from torch.empty, so token selection is incorrect. Could we disable the scoring shortcut when distributed merging is active?

forward_batch,
topk_indices: torch.Tensor,
) -> torch.Tensor:
output = self._dispatch_owner_sparse_attention(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[BBuf Review Agent] On B200 with BF16 queries and head dimension 256, decode returns from _try_fused_kv_attention before reaching this owner dispatch. That path uses global slots against the rank-local cache and skips the owner merge, causing incorrect reads or out-of-bounds accesses. Could we disable fused eligibility for sharded pools until it handles this layout?

@BBuf

BBuf commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

[BBuf Review Agent] Could you split it below 3000 changed lines (now 3107)?

@BBuf

BBuf commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label Nov 6, 2026
@BBuf

BBuf commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

/rerun-failed-ci

reviewer added 6 commits November 6, 2026 03:11
Rebase the validated cache-sharding feature state onto the latest upstream main while preserving owner-local attention and distributed candidate merge behavior.
Preserve graph-safe shard ownership and widening semantics while removing unused owner packing and consolidating redundant transport tests.
Inline the owner attention pipeline and replace redundant test matrices with focused multi-GPU coverage so the change remains reviewable without affecting measured performance.
Send cache-sharded QSA writes through the pool ownership mapping and exclude sharded layouts from the incompatible fused decode path.
Keep the local fast top-k path while forcing initialized scores whenever rank-local candidates participate in a global merge.
Consolidate sharding setup and regression fixtures so the PR remains below the 3,000-line review threshold without changing runtime behavior.
@BBuf

BBuf commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

/rerun-failed-ci

@shiyang814-cpu
shiyang814-cpu force-pushed the feat/qsa-cache-sharding branch from 3936f90 to c35bb78 Compare November 6, 2026 03:20

This branch has not been deployed

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

Labels

hicache Hierarchical Caching for SGLang jit-kernel memory-pool run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants