mirror of
https://github.com/kvcache-ai/sglang.git
synced 2026-11-05 01:07:39 +00:00
[PR #98] fix(kt): reserve VRAM for the generic full-GPU prefill slot, and honour it #98
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/sglang#98
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/kvcache-ai/sglang/pull/98
Author: @05yuki
Created: 9/25/2026
Status: 🔄 Open
Base:
main← Head:fix/kt-fullgpu-prefill-reservation📝 Commits (1)
0917f65fix(kt): reserve VRAM for the generic full-GPU prefill slot, and honour it📊 Changes
3 files changed (+132 additions, -16 deletions)
View changed files
📝
python/sglang/srt/layers/moe/kt_ep_wrapper.py(+98 -6)📝
python/sglang/srt/model_executor/model_runner.py(+20 -10)📝
python/sglang/srt/model_executor/model_runner_kv_cache_mixin.py(+14 -0)📄 Description
Problem
--kt-gpu-prefill-token-threshold Nwith any--kt-methodother than MXFP4 takes the generic full-GPU prefill path: the first prompt of at least N tokens builds oneSharedFullContext, a full copy of one MoE layer's experts on the GPU, shared by every layer. Two things keep that from working on a card that is otherwise full:ModelRunneronly asks for a reservation whenkt_method == "MXFP4"(get_mxfp4_layerwise_prefill_reservation_bytes). For FP8, BF16, INT4 and the rest, the KV cache takes the wholemem_fraction_staticbudget, and the first qualifying prefill dies with CUDA OOM insideSharedFullContext._build_layers. The scheduler goes down with it.mxfp4_layerwise_prefill_reservation_bytesis subtracted only in the DeepSeek-V4 compressed-pool path.profile_max_num_token, which every other model uses, never subtracts it, so the number is computed and then ignored.Seen on GLM-5-Next (FP8, TP2 on two 16 GB cards): KV 706,432 tokens at startup, then
1.12 GiB requested / 831 MiB freeon the first 20k-token prompt.Change
get_full_gpu_prefill_reservation_bytes()inkt_ep_wrapper.py: repeats whatSharedFullContext._build_layersdoes (copy the layer, set the expert counts to the global total,quant_config.get_quant_method(...).create_weights(...)) on the meta device, and sums the parameter bytes. It gives the exact size for every quant method without allocating anything and without copying each method's shape formulas. On the setup above it returns 3.38 GiB per rank, which matches the hand count for FP8 block-128 (3.375 GiB).KTEPWrapperMethod.create_weightsregisters one layer for the sizing when the threshold is set.ModelRunner: for methods other than MXFP4, it stores that value in the same attribute the MXFP4 reservation already uses.profile_max_num_token: subtracts the reservation, so every model honours it, not only DSv4.--mem-fraction-static,--kt-gpu-prefill-token-threshold 0). A module flag then stops the gate from choosing the full-GPU path again for later requests, instead of failing each one.Results
Same setup,
--kt-method FP8, threshold 512, chunk 2048:With the threshold unset nothing changes: no layer registers and the reservation stays 0.
🤖 Generated with Claude Code
https://claude.ai/code/session_01R57AidCMwH17PTFpX7HfQ5
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.