Support piecewise cuda graph for dsv3 fp4 (#15531)

This commit is contained in:
Ke Bao
2025-12-21 14:50:32 +08:00
committed by GitHub
parent 6014365564
commit 8fe3e37468
7 changed files with 148 additions and 16 deletions

View File

@@ -12,6 +12,7 @@ import torch
import triton
import triton.language as tl
from sglang.srt.compilation.piecewise_context_manager import is_in_piecewise_cuda_graph
from sglang.srt.layers.attention.flashinfer_mla_backend import (
FlashInferMLAAttnBackend,
FlashInferMLAMultiStepDraftBackend,
@@ -582,10 +583,11 @@ class TRTLLMMLABackend(FlashInferMLAAttnBackend):
):
# For extend batch with prefix length > 0, fallback to ragged kernel implemented in flashinfer MLA backend
# when chunked prefix cache is disabled.
# Also fallback to flashinfer MLA backend when in piecewise cuda graph, since it only supports MLA forward mode.
has_prefix = any(forward_batch.extend_prefix_lens_cpu)
fallback_to_flashinfer_impl = (
self.disable_chunked_prefix_cache and has_prefix
)
) or is_in_piecewise_cuda_graph()
if fallback_to_flashinfer_impl:
super().init_forward_metadata(forward_batch)

View File

@@ -41,7 +41,13 @@ from sglang.srt.layers.moe.token_dispatcher.standard import (
StandardDispatcher,
StandardDispatchOutput,
)
from sglang.srt.layers.moe.topk import StandardTopKOutput, TopKOutput, TopKOutputChecker
from sglang.srt.layers.moe.topk import (
BypassedTopKOutput,
StandardTopKOutput,
TopKConfig,
TopKOutput,
TopKOutputChecker,
)
from sglang.srt.layers.moe.utils import RoutingMethodType
from sglang.srt.layers.quantization.base_config import (
FusedMoEMethodBase,
@@ -1210,16 +1216,21 @@ class FlashInferFP4MoE(FusedMoE):
return hs_fp4, hs_sf
def forward(self, hidden_states: torch.Tensor, topk_output: TopKOutput):
assert TopKOutputChecker.format_is_bypassed(
topk_output
), "Only bypassed topk output is supported for flashinfer fp4 moe"
if is_in_piecewise_cuda_graph():
assert TopKOutputChecker.format_is_standard(
topk_output
), "Only standard topk output is supported for piecewise cuda graph"
return torch.ops.sglang.moe_forward_piecewise_cuda_graph_impl(
hidden_states,
topk_output.topk_weights,
topk_output.topk_ids,
topk_output.router_logits,
self.layer_id,
return (
torch.ops.sglang.flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl(
hidden_states,
topk_output.router_logits,
topk_output.topk_config.top_k,
topk_output.topk_config.topk_group,
topk_output.topk_config.num_expert_group,
topk_output.topk_config.correction_bias,
self.layer_id,
)
)
else:
return self.forward_impl(hidden_states, topk_output)
@@ -1343,9 +1354,52 @@ def moe_forward_piecewise_cuda_graph_impl_fake(
return torch.empty_like(hidden_states)
def flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl(
hidden_states: torch.Tensor,
router_logits: torch.Tensor,
top_k: int,
topk_group: Optional[int],
num_expert_group: Optional[int],
correction_bias: Optional[torch.Tensor],
layer_id: int,
) -> torch.Tensor:
topk_output = BypassedTopKOutput(
hidden_states=hidden_states,
router_logits=router_logits,
topk_config=TopKConfig(
top_k=top_k,
topk_group=topk_group,
num_expert_group=num_expert_group,
correction_bias=correction_bias,
),
)
forward_context = get_forward_context()
moe_layer = forward_context.moe_layers[layer_id]
return moe_layer.forward_impl(hidden_states, topk_output)
def flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl_fake(
hidden_states: torch.Tensor,
router_logits: torch.Tensor,
top_k: int,
topk_group: Optional[int],
num_expert_group: Optional[int],
correction_bias: Optional[torch.Tensor],
layer_id: int,
) -> torch.Tensor:
return torch.empty_like(hidden_states)
direct_register_custom_op(
op_name="moe_forward_piecewise_cuda_graph_impl",
op_func=moe_forward_piecewise_cuda_graph_impl,
mutates_args=[],
fake_impl=moe_forward_piecewise_cuda_graph_impl_fake,
)
direct_register_custom_op(
op_name="flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl",
op_func=flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl,
mutates_args=[],
fake_impl=flashinfer_fp4_moe_forward_piecewise_cuda_graph_impl_fake,
)

View File

@@ -17,7 +17,6 @@ from sglang.srt.layers.quantization.compressed_tensors.schemes import (
)
from sglang.srt.layers.quantization.modelopt_quant import (
FLASHINFER_FP4_GEMM_BACKEND,
_sglang_fp4_gemm,
enable_flashinfer_fp4_gemm,
fp4_quantize,
)
@@ -154,7 +153,7 @@ class CompressedTensorsW4A4Fp4(CompressedTensorsScheme):
w = layer.weight_packed.T
w_blockscale = layer.weight_scale.T
out = _sglang_fp4_gemm(
out = torch.ops.sglang.fp4_gemm(
x_fp4,
w,
x_blockscale,

View File

@@ -1229,7 +1229,7 @@ class ModelOptFp4LinearMethod(LinearMethodBase):
backend = (
FLASHINFER_FP4_GEMM_BACKEND if FLASHINFER_FP4_GEMM_BACKEND else "cutlass"
)
out = _sglang_fp4_gemm(
out = torch.ops.sglang.fp4_gemm(
x_fp4,
w,
x_scale_interleaved,

View File

@@ -20,6 +20,7 @@ from __future__ import annotations
import concurrent.futures
import logging
import os
from contextlib import nullcontext
from enum import IntEnum, auto
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
@@ -400,6 +401,9 @@ def handle_attention_fa4(attn, forward_batch):
def handle_attention_trtllm_mla(attn, forward_batch):
if is_in_piecewise_cuda_graph():
return AttnForwardMethod.MLA
sum_extend_prefix_lens = _get_sum_extend_prefix_lens(forward_batch)
if forward_batch.forward_mode.is_extend_without_speculative() and (
not attn.disable_chunked_prefix_cache or sum_extend_prefix_lens == 0
@@ -3188,7 +3192,13 @@ class DeepseekV2Model(nn.Module):
normal_end_layer = normal_start_layer = 0
aux_hidden_states = []
for i in range(normal_start_layer, normal_end_layer):
with get_global_expert_distribution_recorder().with_current_layer(i):
# NOTE: torch dynamo does not support graph break in context manager
ctx = (
nullcontext()
if get_global_server_args().enable_piecewise_cuda_graph
else get_global_expert_distribution_recorder().with_current_layer(i)
)
with ctx:
if i in self.layers_to_capture:
aux_hidden_states.append(hidden_states + residual)
layer = self.layers[i]