[Deepseek V3.2] Support Overlap Spec + NSA (#15307)
Co-authored-by: Brayden Zhong <b8zhong@users.noreply.github.com>
This commit is contained in:
@@ -77,6 +77,10 @@ python -m sglang.launch_server --model deepseek-ai/DeepSeek-V3.2-Exp --tp 8 --sp
|
|||||||
- The best configuration for `--speculative-num-steps`, `--speculative-eagle-topk` and `--speculative-num-draft-tokens` can be searched with [bench_speculative.py](https://github.com/sgl-project/sglang/blob/main/scripts/playground/bench_speculative.py) script for given batch size. The minimum configuration is `--speculative-num-steps 1 --speculative-eagle-topk 1 --speculative-num-draft-tokens 2`, which can achieve speedup for larger batch sizes.
|
- The best configuration for `--speculative-num-steps`, `--speculative-eagle-topk` and `--speculative-num-draft-tokens` can be searched with [bench_speculative.py](https://github.com/sgl-project/sglang/blob/main/scripts/playground/bench_speculative.py) script for given batch size. The minimum configuration is `--speculative-num-steps 1 --speculative-eagle-topk 1 --speculative-num-draft-tokens 2`, which can achieve speedup for larger batch sizes.
|
||||||
- The default value of `--max-running-requests` is set to `48` for MTP. For larger batch sizes, this value should be increased beyond the default value.
|
- The default value of `--max-running-requests` is set to `48` for MTP. For larger batch sizes, this value should be increased beyond the default value.
|
||||||
|
|
||||||
|
```{tip}
|
||||||
|
To enable the experimental overlap scheduler for EAGLE speculative decoding, set the environment variable `SGLANG_ENABLE_SPEC_V2=1`. This can improve performance by enabling overlap scheduling between draft and verification stages.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Function Calling and Reasoning Parser
|
## Function Calling and Reasoning Parser
|
||||||
The usage of function calling and reasoning parser is the same as DeepSeek V3.1. Please refer to [Reasoning Parser](https://docs.sglang.io/advanced_features/separate_reasoning.html) and [Tool Parser](https://docs.sglang.io/advanced_features/tool_parser.html) documents.
|
The usage of function calling and reasoning parser is the same as DeepSeek V3.1. Please refer to [Reasoning Parser](https://docs.sglang.io/advanced_features/separate_reasoning.html) and [Tool Parser](https://docs.sglang.io/advanced_features/tool_parser.html) documents.
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ class Indexer(CustomOp):
|
|||||||
blocksize = page_size
|
blocksize = page_size
|
||||||
if (
|
if (
|
||||||
forward_batch.forward_mode.is_target_verify()
|
forward_batch.forward_mode.is_target_verify()
|
||||||
or forward_batch.forward_mode.is_draft_extend()
|
or forward_batch.forward_mode.is_draft_extend(include_v2=True)
|
||||||
):
|
):
|
||||||
seqlens_32 = metadata.get_seqlens_expanded()
|
seqlens_32 = metadata.get_seqlens_expanded()
|
||||||
else:
|
else:
|
||||||
@@ -900,7 +900,7 @@ class Indexer(CustomOp):
|
|||||||
if (
|
if (
|
||||||
forward_batch.forward_mode.is_decode_or_idle()
|
forward_batch.forward_mode.is_decode_or_idle()
|
||||||
or forward_batch.forward_mode.is_target_verify()
|
or forward_batch.forward_mode.is_target_verify()
|
||||||
or forward_batch.forward_mode.is_draft_extend()
|
or forward_batch.forward_mode.is_draft_extend(include_v2=True)
|
||||||
):
|
):
|
||||||
topk_result = self._get_topk_paged(
|
topk_result = self._get_topk_paged(
|
||||||
forward_batch, layer_id, q_fp8, weights, metadata
|
forward_batch, layer_id, q_fp8, weights, metadata
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ class NativeSparseAttnBackend(AttentionBackend):
|
|||||||
page_table = torch.repeat_interleave(
|
page_table = torch.repeat_interleave(
|
||||||
page_table, repeats=self.speculative_num_draft_tokens, dim=0
|
page_table, repeats=self.speculative_num_draft_tokens, dim=0
|
||||||
)
|
)
|
||||||
elif forward_batch.forward_mode.is_draft_extend():
|
elif forward_batch.forward_mode.is_draft_extend(include_v2=True):
|
||||||
assert (
|
assert (
|
||||||
forward_batch.extend_seq_lens_cpu is not None
|
forward_batch.extend_seq_lens_cpu is not None
|
||||||
and forward_batch.extend_seq_lens is not None
|
and forward_batch.extend_seq_lens is not None
|
||||||
@@ -422,9 +422,20 @@ class NativeSparseAttnBackend(AttentionBackend):
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
page_table = torch.repeat_interleave(
|
if forward_batch.forward_mode.is_draft_extend_v2():
|
||||||
page_table, repeats=forward_batch.extend_seq_lens, dim=0
|
# DRAFT_EXTEND_V2: V2 worker pre-fills draft KV cache with ALL speculated
|
||||||
)
|
# tokens upfront. All requests extend by the same fixed
|
||||||
|
# (speculative_num_draft_tokens). Use scalar to avoid GPU sync.
|
||||||
|
page_table = torch.repeat_interleave(
|
||||||
|
page_table, repeats=self.speculative_num_draft_tokens, dim=0
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# DRAFT_EXTEND (v1): V1 worker extends by (accept_length + 1) per request
|
||||||
|
# after verification. Lengths vary per request based on how many tokens
|
||||||
|
# were accepted.
|
||||||
|
page_table = torch.repeat_interleave(
|
||||||
|
page_table, repeats=extend_seq_lens_cpu, dim=0
|
||||||
|
)
|
||||||
|
|
||||||
elif forward_batch.forward_mode.is_extend():
|
elif forward_batch.forward_mode.is_extend():
|
||||||
assert (
|
assert (
|
||||||
@@ -632,7 +643,9 @@ class NativeSparseAttnBackend(AttentionBackend):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
flashmla_metadata = None
|
flashmla_metadata = None
|
||||||
elif forward_mode.is_target_verify() or forward_mode.is_draft_extend():
|
elif forward_mode.is_target_verify() or forward_mode.is_draft_extend(
|
||||||
|
include_v2=True
|
||||||
|
):
|
||||||
cache_seqlens_int32 = (seq_lens + self.speculative_num_draft_tokens).to(
|
cache_seqlens_int32 = (seq_lens + self.speculative_num_draft_tokens).to(
|
||||||
torch.int32
|
torch.int32
|
||||||
)
|
)
|
||||||
@@ -796,7 +809,7 @@ class NativeSparseAttnBackend(AttentionBackend):
|
|||||||
seqlens_expanded, self.nsa_index_topk
|
seqlens_expanded, self.nsa_index_topk
|
||||||
)
|
)
|
||||||
metadata.nsa_cache_seqlens_int32.copy_(nsa_cache_seqlens)
|
metadata.nsa_cache_seqlens_int32.copy_(nsa_cache_seqlens)
|
||||||
elif forward_mode.is_draft_extend():
|
elif forward_mode.is_draft_extend(include_v2=True):
|
||||||
max_seqlen_k = int(seq_lens_cpu.max().item())
|
max_seqlen_k = int(seq_lens_cpu.max().item())
|
||||||
cache_seqlens = seq_lens.to(torch.int32)
|
cache_seqlens = seq_lens.to(torch.int32)
|
||||||
metadata.cache_seqlens_int32.copy_(cache_seqlens)
|
metadata.cache_seqlens_int32.copy_(cache_seqlens)
|
||||||
|
|||||||
Reference in New Issue
Block a user