[FlashInfer V0.6.18] feat(dsv4): support --dsa-topk-backend flashinfer with fused top-k (#33237)

This commit is contained in:
Ziang Li
2026-09-01 01:18:10 -07:00
committed by GitHub
parent 3484f7f836
commit 5edcd0a445
8 changed files with 333 additions and 31 deletions
+5 -1
View File
@@ -1698,7 +1698,11 @@ def _set_envs_and_config(server_args: ServerArgs):
# Check flashinfer version
if not get_bool_env_var("SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK"):
if "flashinfer" in attention_backends_of(resolved_view(cfg)):
if (
"flashinfer" in attention_backends_of(resolved_view(cfg))
or cfg.dsa_topk_backend == "flashinfer"
or cfg.speculative_dsa_topk_backend == "flashinfer"
):
assert_pkg_version(
"flashinfer_python",
"0.6.18",
@@ -704,6 +704,7 @@ class DeepseekV4AttnBackend(
page_size=self.page_size,
page_table=core_attn_metadata.page_table,
c4_seq_lens=core_attn_metadata.c4_topk_lengths_raw,
use_topk_v2=self.dsa_topk_backend.should_use_topk_v2() and not _is_xpu,
# The SM120 FP4 kernel schedules split_kv=128, while the generic
# JIT metadata planner encodes split_kv=256.
force_deep_gemm_metadata=(
@@ -492,6 +492,7 @@ class DeepseekV4HipRadixBackend(
page_size=self.page_size,
page_table=core_attn_metadata.page_table,
c4_seq_lens=core_attn_metadata.c4_topk_lengths_raw,
use_topk_v2=False,
)
def init_forward_metadata_decode(
@@ -404,11 +404,44 @@ def topk_transform_512_flashinfer_unfused(
)
def topk_transform_512_flashinfer_fused(
scores: torch.Tensor,
seq_lens: torch.Tensor,
page_tables: torch.Tensor,
out_page_indices: torch.Tensor,
page_size: int,
out_raw_indices: Optional[torch.Tensor] = None,
) -> None:
import flashinfer
from sglang.srt.layers.attention.dsa.dsa_topk_backend import (
_flashinfer_tie_break_value,
)
flashinfer.top_k_page_table_transform(
scores,
page_tables.contiguous(),
seq_lens.contiguous(),
out_page_indices.shape[1],
deterministic=envs.SGLANG_DSA_TOPK_FLASHINFER_DETERMINISTIC.get(),
tie_break=_flashinfer_tie_break_value(),
dsa_graph_safe=True,
page_size=page_size,
out=out_page_indices,
out_raw_indices=out_raw_indices,
)
class C4IndexerBackendMixin:
def __init__(self):
super().__init__()
self.debug_use_external_c4_sparse_indices: bool = False
self.dsa_topk_backend: DSATopKBackend = DSATopKBackend.SGL_KERNEL
self.flashinfer_topk_transform: Callable[..., None] = (
topk_transform_512_flashinfer_fused
if envs.SGLANG_DSA_FUSE_TOPK.get()
else topk_transform_512_flashinfer_unfused
)
def _forward_prepare_multi_stream(
self,
@@ -829,7 +862,7 @@ class C4IndexerBackendMixin:
raw_indices,
)
elif self.dsa_topk_backend.is_flashinfer():
topk_transform_512_flashinfer_unfused(
self.flashinfer_topk_transform(
logits,
c4_seq_lens,
page_table,
@@ -837,7 +870,7 @@ class C4IndexerBackendMixin:
indexer_metadata.c4_page_size,
raw_indices,
)
elif envs.SGLANG_OPT_USE_TOPK_V2.get() and raw_indices is None:
elif self.dsa_topk_backend.should_use_topk_v2() and raw_indices is None:
topk_transform_512_v2(
logits,
c4_seq_lens,
@@ -112,6 +112,7 @@ class PagedIndexerMetadata:
page_size: int
page_table: torch.Tensor
c4_seq_lens: torch.Tensor
use_topk_v2: bool
force_deep_gemm_metadata: bool = False
use_prefill_cuda_graph: bool = False
deep_gemm_metadata: Any = field(init=False, repr=False)
@@ -152,7 +153,7 @@ class PagedIndexerMetadata:
assert isinstance(self.deep_gemm_metadata, torch.Tensor)
if envs.SGLANG_OPT_USE_TOPK_V2.get() and not is_xpu():
if self.use_topk_v2:
from sglang.kernels.ops.attention.dsv4 import plan_topk_v2
self.topk_metadata = plan_topk_v2(self.c4_seq_lens)
@@ -188,6 +189,7 @@ class PagedIndexerMetadata:
"page_size",
"force_deep_gemm_metadata",
"use_prefill_cuda_graph",
"use_topk_v2",
],
copy_fields=copy_fields,
assign_fields=assign_fields,