Skip to content

feat(inference): HiSparse vLLM wheel for GLM-5.x PD decode instances#2949

Draft
faresobeid wants to merge 3 commits into
mainfrom
feat/hisparse-decode-wheel
Draft

feat(inference): HiSparse vLLM wheel for GLM-5.x PD decode instances#2949
faresobeid wants to merge 3 commits into
mainfrom
feat/hisparse-decode-wheel

Conversation

@faresobeid

@faresobeid faresobeid commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Enables HiSparse host-resident sparse-MLA decode (vllm-project/vllm#46326) for GLM-5.2 deployments. Three commits:

  1. Wheel pin: x86_64 vLLM moves to the fork wheel (hisparse-c6f2044, v0.24.0 release base). aarch64 stays upstream; runtime patches/plugin apply unchanged.
  2. kv_cache_offload.roles: scopes the Mooncake store to a subset of P/D roles. Out-of-scope nodes skip the store client and get a NIXL-only transfer config — decode-node RAM goes to HiSparse pinned pools (ranks × host_pool_gib) instead of a store segment.
  3. Graceful teardown + hardening in the sbatch templates: TERM traps with a bounded drain window (decode ranks unpin multi-hundred-GiB pinned pools in-process; a SIGKILLed unpin runs in uninterruptible kernel context, outlives SLURM's KillWait, and drains the node), VLLM_WORKER_SHUTDOWN_TIMEOUT_SECONDS=600, component-crash escalation (scancel --signal=TERM + CRASH_<host> marker — an engine death can no longer leave a silently wedged deployment), envoy --use-dynamic-base-id (a stale /dev/shm/envoy_shared_memory_0 from another user's crashed run SIGABRTs the default base-id; reproduced and fix-validated on a poisoned node), orphan-proof mooncake store launcher, per-rank uv run --no-sync, decode on auto-detected multi-rail UCX_NET_DEVICES.

Why

A GLM-5.2 wide-EP decode rank has O(10 GiB) of GPU KV after weights and sparse-stack workspaces — a handful of long-context requests per engine. HiSparse keeps the full sparse-MLA KV in pinned host memory and serves decode from per-request GPU hot buffers of the indexer top-k.

Measured (GLM-5.2-FP8, this branch's wheel)

16-node stack (8 prefill + 8 decode DP64, llm-d, NIXL, mooncake), A/B vs plain GPU-KV decode — identical topology, traffic, and 50-min saturated window:

decode side GPU-KV HiSparse
generation throughput 10,653 tok/s 12,951 tok/s (+22%)
requests completed 84,026 101,653 (+21%)
preemptions 5,174 0
TTFT p99 99.9 s 2.5 s
KV usage peak — GPU KV vs host pool 100.0% (pinned) 57.5%

Pushed to seat saturation (c=6500): 26,056 decode tok/s sustained, 99% peak seat occupancy, zero preemptions — 3.3× the c=1000 operating point; the binding constraint is max_num_seqs, not memory.

Agentic RL workload (r2e-gym through the router, c=1000, 4P+2D): baseline pinned at 99.9% KV with 1,533 preemptions, 5 of 155 rollouts solved; HiSparse: zero preemptions, 585 solved, +124% steady-state decode throughput.

Deployment notes

  • Enable via decode overrides: attention_config = { hisparse_config = { host_pool_gib = <N> } } per rank; budget node RAM for ranks × pool (+ any co-tenants — hence roles = ["prefill"] on the store).
  • Cap decode max_num_seqs (e.g. 96): hot buffers are eager (~370 MB/request across GLM-5.2's 78 sparse layers) and the seat count is the admission control — size it to sustained decode compute at your context lengths, or rely on orchestrator inflight caps.
  • Decode gpu_memory_utilization can go to 0.9 (the GPU KV budget mostly idles under HiSparse).
  • Cancel HiSparse jobs with the two-step TERM-then-scancel flow (documented in the monitor-run skill) so pools unpin in-process.

🤖 Generated with Claude Code

@faresobeid faresobeid force-pushed the feat/hisparse-decode-wheel branch 2 times, most recently from 5d72dfb to 72e117b Compare July 9, 2026 02:33
@faresobeid faresobeid changed the base branch from feat/vllm-0.24.0-bump to main July 9, 2026 02:36
faresoPrime and others added 3 commits July 10, 2026 00:11
…2044)

Swaps the upstream 0.24.0 wheel for the HiSparse fork build
(faresobeid/vllm#46326, v0.24.0 release base): host-resident sparse-MLA
decode for GLM-5/DSA models. aarch64 stays on the upstream wheel; the
runtime patches/plugin apply unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kv_cache_offload.roles limits the Mooncake store to the named roles:
out-of-scope nodes skip the store client and get a NIXL-only
kv_transfer_config, freeing their RAM. Needed for HiSparse decode nodes,
whose RAM budget goes to pinned host pools (ranks x host_pool_gib); the
store master follows the first in-scope node.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ti-tenant hardening

Teardown: batch/node TERM traps with a bounded drain window so decode ranks
unpin their host pools in-process (a SIGKILLed unpin runs in uninterruptible
kernel context, outlives SLURM KillWait, and drains the node);
VLLM_WORKER_SHUTDOWN_TIMEOUT_SECONDS=600 grace; component-crash escalation
(scancel --signal=TERM + CRASH_<host> marker) so an engine death cannot
leave a silently wedged deployment.

Hardening: envoy launches with --use-dynamic-base-id (a stale
/dev/shm/envoy_shared_memory_0 from another user SIGABRTs the default
base-id at startup; reproduced on a shared node); mooncake store launcher is
orphan-proof (setsid + process-group kill, fail-loud readiness via the
kernel listen table); per-rank uv run --no-sync (concurrent re-syncs race on
the shared uv cache); decode inherits the auto-detected multi-rail
UCX_NET_DEVICES instead of a single-HCA pin; install_nixl_from_source.sh
hardened against a UCX cross-thread ownership abort.

Skills updated to match (two-step cancel, bring-up gotchas, current routing
guidance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@faresobeid faresobeid force-pushed the feat/hisparse-decode-wheel branch from 949796b to fc929c4 Compare July 10, 2026 00:13
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.

2 participants