mirror of
https://github.com/kvcache-ai/sglang.git
synced 2026-11-05 01:07:39 +00:00
[PR #46] fix(v4-flash): make ExpertDistributionRecorder cuda-graph-safe + per-layer for DeepSeek-V4-Flash #47
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#47
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/46
Author: @yiqiliu2
Created: 5/8/2026
Status: 🔄 Open
Base:
main← Head:upstream-pr/fix-v4-flash-recorder📝 Commits (2)
103bc87fix(v4-flash): cuda-graph-safe + shape-safe ExpertDistribution recorderd6e0e89fix(v4-flash): wrap deepseek_v4 forward loop with recorder current_layer ctx📊 Changes
2 files changed (+40 additions, -12 deletions)
View changed files
📝
python/sglang/srt/eplb/expert_distribution.py(+19 -6)📝
python/sglang/srt/models/deepseek_v4.py(+21 -6)📄 Description
Summary
Two coupled bug fixes in
--expert-distribution-recorder-mode staton DeepSeek-V4-Flash. Without these, V4-Flash users hit:RuntimeError: Index tensor must have the same number of dimensions as self tensorandCUDA error: operation not permitted when stream is capturingduring cuda graph capture, andlogical_count.ptonly has data for layer 0 → downstream frequency-based GPU expert placement puts all 172 experts on layer 0 → useless.Fix 1:
_SelectExpertsSinglePassGatherer.on_select_experts(cuda-graph + shape safe)_on_hooklets the recorder fire during cuda graph capture (theis_current_stream_capturing()clause). The original implementation:This crashes on V4-Flash routing tensors with the dimension-mismatch error. An intermediate rewrite using
bool(valid_mask.any())+flat_ids[valid_mask]synced device→host (.item()/ nonzero), forbidden during cuda graph capture.The new version uses pure GPU ops:
clamp(-1 → 0)so all indices are in rangesrc = (id >= 0).to(dtype)so invalid entries contribute 0 (no-op writes)No host sync, no boolean indexing, no nonzero. Verified by booting V4-Flash with
--expert-distribution-recorder-mode stat; cuda graph capture succeeds and a 44 MB .pt dumps cleanly.Fix 2:
deepseek_v4.pyforward loop wraps each layer withwith_current_layer(i)The other DeepSeek/Qwen models in this repo all wrap their
for i in range(...)layer loop inget_global_expert_distribution_recorder().with_current_layer(i)(gated byenable_piecewise_cuda_graph).deepseek_v4.pywas missing this. Without it,self._current_layer_idx.valuestays at None throughout the forward pass and everyon_select_expertswrite lands in slot 0 of the gatherer's_datatensor.Symptom: dumped
logical_count.pthas counts only on layer 0; remaining 42 layers report 0.torch.topkon this inkt_ep_wrapper.generate_gpu_experts_masksthen places all GPU expert quota on layer 0 regardless of K.Test plan
--expert-distribution-recorder-mode stat. Before: cuda graph capture crashes with the recorder error above. After: capture succeeds in 7.79s..ptas--init-expert-locationwith--kt-num-gpu-experts 4 --kt-expert-placement-strategy frequency. Before: all 172 experts placed on layer 0. After: distributed 2-9 per MoE layer (sum 172).🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.