Add SGLang CUDA crash API logging inspired by FlashInfer (#20910)

This commit is contained in:
Xiaoyu Zhang
2026-03-22 16:39:40 +08:00
committed by GitHub
parent bb737d7a82
commit 766d225fcc
46 changed files with 1585 additions and 19 deletions
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit
if TYPE_CHECKING:
@@ -19,6 +20,7 @@ def _jit_awq_marlin_repack_module() -> Module:
)
@maybe_wrap_jit_kernel_debug
def awq_marlin_repack(
b_q_weight: torch.Tensor,
size_k: int,
@@ -37,6 +39,7 @@ def awq_marlin_repack(
return out
@maybe_wrap_jit_kernel_debug
def awq_marlin_moe_repack(
b_q_weight: torch.Tensor,
perm: torch.Tensor,
+45
View File
@@ -0,0 +1,45 @@
import os
from typing import Any, Callable, TypeVar, cast, overload
F = TypeVar("F", bound=Callable[..., Any])
def _wrap_jit_kernel_debug(func: F, op_name: str | None = None) -> F:
try:
if int(os.environ.get("SGLANG_KERNEL_API_LOGLEVEL", "0")) == 0:
return func
except Exception:
return func
try:
from sglang.kernel_api_logging import debug_kernel_api
except Exception:
return func
if getattr(func, "_debug_kernel_wrapped", False):
return func
wrapped = debug_kernel_api(func, op_name=op_name)
setattr(wrapped, "_debug_kernel_wrapped", True)
return cast(F, wrapped)
@overload
def maybe_wrap_jit_kernel_debug(func: F) -> F: ...
@overload
def maybe_wrap_jit_kernel_debug(func: F, op_name: str) -> F: ...
@overload
def maybe_wrap_jit_kernel_debug(*, op_name: str | None = None) -> Callable[[F], F]: ...
def maybe_wrap_jit_kernel_debug(
func: F | None = None, op_name: str | None = None
) -> F | Callable[[F], F]:
if func is None:
return lambda wrapped_func: _wrap_jit_kernel_debug(wrapped_func, op_name)
return _wrap_jit_kernel_debug(func, op_name)
@@ -5,6 +5,8 @@ import triton # type: ignore
import triton.language as tl # type: ignore
from torch import Tensor
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
# RMSNorm-fp32
def maybe_contiguous_lastdim(x):
@@ -450,6 +452,7 @@ class LayerNormFn:
return y
@maybe_wrap_jit_kernel_debug
def layer_norm_fn(
x,
weight,
@@ -537,6 +540,7 @@ def _norm_infer_kernel(
tl.store(Y + cols, y, mask=cols < N)
@maybe_wrap_jit_kernel_debug
def norm_infer(
x: Tensor,
weight: Optional[Tensor],
@@ -579,6 +583,7 @@ def norm_infer(
return out
@maybe_wrap_jit_kernel_debug
def rms_norm_fn(
x,
weight,
@@ -625,5 +630,53 @@ from sglang.multimodal_gen.runtime.platforms import current_platform
if current_platform.is_mps():
from .mps_fallback import norm_infer_native, rms_norm_fn_native
norm_infer = norm_infer_native
rms_norm_fn = rms_norm_fn_native
@maybe_wrap_jit_kernel_debug
def norm_infer(
x: Tensor,
weight: Optional[Tensor],
bias: Optional[Tensor],
eps: float,
is_rms_norm: bool = False,
out: Optional[Tensor] = None,
):
return norm_infer_native(x, weight, bias, eps, is_rms_norm, out)
@maybe_wrap_jit_kernel_debug
def rms_norm_fn(
x,
weight,
bias,
residual=None,
x1=None,
weight1=None,
bias1=None,
eps=1e-6,
dropout_p=0.0,
rowscale=None,
prenorm=False,
residual_in_fp32=False,
zero_centered_weight=False,
return_dropout_mask=False,
out_dtype=None,
out=None,
residual_out=None,
):
return rms_norm_fn_native(
x,
weight,
bias,
residual,
x1,
weight1,
bias1,
eps,
dropout_p,
rowscale,
prenorm,
residual_in_fp32,
zero_centered_weight,
return_dropout_mask,
out_dtype,
out,
residual_out,
)
@@ -2,6 +2,7 @@ import torch
import triton # type: ignore
import triton.language as tl # type: ignore
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.srt.utils.custom_op import register_custom_op
@@ -35,6 +36,7 @@ def _rms_norm_tiled_onepass(
tl.store(y_blk, x * rstd * w, mask=mask)
@maybe_wrap_jit_kernel_debug
@register_custom_op(op_name="triton_one_pass_rms_norm_cuda", out_shape="x")
def _triton_one_pass_rms_norm_cuda(
x: torch.Tensor, w: torch.Tensor, eps: float = 1e-6
@@ -72,4 +74,6 @@ from sglang.multimodal_gen.runtime.platforms import current_platform
if current_platform.is_mps():
from .mps_fallback import triton_one_pass_rms_norm_native
triton_one_pass_rms_norm = triton_one_pass_rms_norm_native
@maybe_wrap_jit_kernel_debug
def triton_one_pass_rms_norm(x: torch.Tensor, w: torch.Tensor, eps: float = 1e-6):
return triton_one_pass_rms_norm_native(x, w, eps)
@@ -2,6 +2,7 @@ import torch
import triton # type: ignore
import triton.language as tl # type: ignore
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.multimodal_gen.runtime.platforms import current_platform
@@ -64,6 +65,7 @@ def _rotary_embedding_kernel(
tl.store(output_row_ptr + offsets_x2, o2_vals.to(x2_vals.dtype), mask=mask)
@maybe_wrap_jit_kernel_debug
def apply_rotary_embedding(
x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor, interleaved: bool = False
) -> torch.Tensor:
@@ -110,9 +112,24 @@ def apply_rotary_embedding(
if current_platform.is_npu():
from .npu_fallback import apply_rotary_embedding_native
apply_rotary_embedding = apply_rotary_embedding_native
@maybe_wrap_jit_kernel_debug
def apply_rotary_embedding(
x: torch.Tensor,
cos: torch.Tensor,
sin: torch.Tensor,
interleaved: bool = False,
) -> torch.Tensor:
return apply_rotary_embedding_native(x, cos, sin, interleaved)
if current_platform.is_mps():
from .mps_fallback import apply_rotary_embedding_native
apply_rotary_embedding = apply_rotary_embedding_native
@maybe_wrap_jit_kernel_debug
def apply_rotary_embedding(
x: torch.Tensor,
cos: torch.Tensor,
sin: torch.Tensor,
interleaved: bool = False,
) -> torch.Tensor:
return apply_rotary_embedding_native(x, cos, sin, interleaved)
@@ -2,6 +2,7 @@ import torch
import triton # type: ignore
import triton.language as tl # type: ignore
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.multimodal_gen.runtime.platforms import current_platform
@@ -444,6 +445,7 @@ def fuse_scale_shift_gate_select01_kernel_blc_opt(
tl.store(gate_out_ptr + go_off, gate, mask=mask)
@maybe_wrap_jit_kernel_debug
def fuse_scale_shift_kernel(
x: torch.Tensor,
scale: torch.Tensor,
@@ -563,6 +565,7 @@ def fuse_scale_shift_kernel(
return output
@maybe_wrap_jit_kernel_debug
def fuse_scale_shift_gate_select01_kernel(
x: torch.Tensor,
scale0: torch.Tensor,
@@ -635,6 +638,7 @@ def fuse_scale_shift_gate_select01_kernel(
return output, gate_out
@maybe_wrap_jit_kernel_debug
def fuse_layernorm_scale_shift_gate_select01_kernel(
x: torch.Tensor,
weight: torch.Tensor | None,
@@ -724,6 +728,7 @@ def fuse_layernorm_scale_shift_gate_select01_kernel(
return output, gate_out
@maybe_wrap_jit_kernel_debug
def fuse_residual_layernorm_scale_shift_gate_select01_kernel(
x: torch.Tensor,
residual: torch.Tensor,
@@ -834,7 +839,19 @@ def fuse_residual_layernorm_scale_shift_gate_select01_kernel(
if current_platform.is_npu():
from .npu_fallback import fuse_scale_shift_native
fuse_scale_shift_kernel = fuse_scale_shift_native
@maybe_wrap_jit_kernel_debug
def fuse_scale_shift_kernel(
x: torch.Tensor,
scale: torch.Tensor,
shift: torch.Tensor,
scale_constant: float = 1.0,
block_l: int = 128,
block_c: int = 128,
):
return fuse_scale_shift_native(
x, scale, shift, scale_constant, block_l, block_c
)
if current_platform.is_mps():
from .mps_fallback import (
@@ -842,5 +859,41 @@ if current_platform.is_mps():
fuse_scale_shift_kernel_native,
)
fuse_scale_shift_kernel = fuse_scale_shift_kernel_native
fuse_scale_shift_gate_select01_kernel = fuse_scale_shift_gate_select01_kernel_native
@maybe_wrap_jit_kernel_debug
def fuse_scale_shift_kernel(
x: torch.Tensor,
scale: torch.Tensor,
shift: torch.Tensor,
scale_constant: float = 1.0,
block_l: int = 128,
block_c: int = 128,
):
return fuse_scale_shift_kernel_native(
x, scale, shift, scale_constant, block_l, block_c
)
@maybe_wrap_jit_kernel_debug
def fuse_scale_shift_gate_select01_kernel(
x: torch.Tensor,
scale0: torch.Tensor,
shift0: torch.Tensor,
gate0: torch.Tensor,
scale1: torch.Tensor,
shift1: torch.Tensor,
gate1: torch.Tensor,
index: torch.Tensor,
block_l: int = 128,
block_c: int = 128,
):
return fuse_scale_shift_gate_select01_kernel_native(
x,
scale0,
shift0,
gate0,
scale1,
shift1,
gate1,
index,
block_l,
block_c,
)
@@ -4,6 +4,8 @@ from typing import Callable, Optional, Tuple, Union
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
try:
from flash_attn.cute import flash_attn_varlen_func as _flash_attn_varlen_func
except Exception as _e: # pragma: no cover
@@ -17,6 +19,7 @@ def _maybe_contiguous(x: Optional[torch.Tensor]) -> Optional[torch.Tensor]:
return x.contiguous() if x is not None and x.stride(-1) != 1 else x
@maybe_wrap_jit_kernel_debug
def flash_attn_varlen_func(
q: torch.Tensor,
k: torch.Tensor,
@@ -89,6 +92,7 @@ def flash_attn_varlen_func(
return result
@maybe_wrap_jit_kernel_debug
def flash_attn_with_kvcache(
q: torch.Tensor,
k_cache: torch.Tensor,
@@ -13,6 +13,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import (
cache_once,
is_arch_support_pdl,
@@ -64,6 +65,7 @@ def can_use_nsa_fused_store(
return False
@maybe_wrap_jit_kernel_debug
def fused_store_index_k_cache(
key: torch.Tensor,
index_k_with_scale: torch.Tensor,
+2
View File
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
if TYPE_CHECKING:
@@ -31,6 +32,7 @@ def _or_empty(
return t if t is not None else torch.empty(0, device=device, dtype=dtype)
@maybe_wrap_jit_kernel_debug
def gptq_marlin_gemm(
a: torch.Tensor,
c: Optional[torch.Tensor],
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit
if TYPE_CHECKING:
@@ -22,6 +23,7 @@ def _jit_gptq_marlin_repack_module() -> Module:
)
@maybe_wrap_jit_kernel_debug
def gptq_marlin_repack(
b_q_weight: torch.Tensor,
perm: torch.Tensor,
+3
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
if TYPE_CHECKING:
@@ -66,6 +67,7 @@ def _default_unroll(element_size: int) -> int:
return 1
@maybe_wrap_jit_kernel_debug
def transfer_hicache_one_layer(
k_cache_dst: torch.Tensor,
v_cache_dst: torch.Tensor,
@@ -101,6 +103,7 @@ def transfer_hicache_one_layer(
)
@maybe_wrap_jit_kernel_debug
def transfer_hicache_all_layer(
k_ptr_dst: torch.Tensor,
v_ptr_dst: torch.Tensor,
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
if TYPE_CHECKING:
@@ -36,6 +37,7 @@ def _or_empty(
return t if t is not None else torch.empty(0, device=device, dtype=dtype)
@maybe_wrap_jit_kernel_debug
def moe_wna16_marlin_gemm(
a: torch.Tensor,
c_or_none: Optional[torch.Tensor],
@@ -2,6 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit
if TYPE_CHECKING:
@@ -21,6 +22,7 @@ def _jit_ngram_embedding_module() -> Module:
)
@maybe_wrap_jit_kernel_debug
def compute_n_gram_ids(
ne_n: int,
ne_k: int,
@@ -66,6 +68,7 @@ def compute_n_gram_ids(
)
@maybe_wrap_jit_kernel_debug
def update_token_table(
tokens: torch.Tensor,
ne_token_table: torch.Tensor,
+6
View File
@@ -5,6 +5,8 @@ from typing import TYPE_CHECKING, Optional
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
logger = logging.getLogger(__name__)
from sglang.jit_kernel.utils import (
@@ -78,6 +80,7 @@ def can_use_fused_inplace_qknorm(head_dim: int, dtype: torch.dtype) -> bool:
return False
@maybe_wrap_jit_kernel_debug
def fused_inplace_qknorm(
q: torch.Tensor,
k: torch.Tensor,
@@ -92,6 +95,7 @@ def fused_inplace_qknorm(
module.qknorm(q, k, q_weight, k_weight, eps)
@maybe_wrap_jit_kernel_debug
def rmsnorm(
input: torch.Tensor,
weight: torch.Tensor,
@@ -104,6 +108,7 @@ def rmsnorm(
module.rmsnorm(input, weight, output, eps)
@maybe_wrap_jit_kernel_debug
def fused_add_rmsnorm(
input: torch.Tensor,
residual: torch.Tensor,
@@ -114,6 +119,7 @@ def fused_add_rmsnorm(
module.fused_add_rmsnorm(input, residual, weight, eps)
@maybe_wrap_jit_kernel_debug
def fused_inplace_qknorm_across_heads(
q: torch.Tensor,
k: torch.Tensor,
+7
View File
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Optional, Tuple
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit
from sglang.srt.utils.custom_op import register_custom_op
@@ -195,6 +196,7 @@ def _jit_nvfp4_blockwise_moe_module() -> Module:
)
@maybe_wrap_jit_kernel_debug
def cutlass_scaled_fp4_mm(
a: torch.Tensor,
b: torch.Tensor,
@@ -211,6 +213,7 @@ def cutlass_scaled_fp4_mm(
return out
@maybe_wrap_jit_kernel_debug
def cutlass_fp4_group_mm(
a_fp4: torch.Tensor,
b_fp4: torch.Tensor,
@@ -290,6 +293,7 @@ def _scaled_fp4_quant_custom_op(
module.scaled_fp4_quant(output, input, output_scale, input_global_scale)
@maybe_wrap_jit_kernel_debug
def scaled_fp4_quant(
input: torch.Tensor, input_global_scale: torch.Tensor
) -> Tuple[torch.Tensor, torch.Tensor]:
@@ -359,6 +363,7 @@ def _scaled_fp4_experts_quant_custom_op(
)
@maybe_wrap_jit_kernel_debug
def scaled_fp4_experts_quant(
input_tensor: torch.Tensor,
input_global_scale: torch.Tensor,
@@ -443,6 +448,7 @@ def _scaled_fp4_grouped_quant_custom_op(
)
@maybe_wrap_jit_kernel_debug
def scaled_fp4_grouped_quant(
input_tensor: torch.Tensor,
input_global_scale: torch.Tensor,
@@ -503,6 +509,7 @@ def _silu_and_mul_scaled_fp4_grouped_quant_custom_op(
)
@maybe_wrap_jit_kernel_debug
def silu_and_mul_scaled_fp4_grouped_quant(
input_tensor: torch.Tensor,
input_global_scale: torch.Tensor,
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
from sglang.srt.utils.custom_op import register_custom_op
@@ -22,6 +23,7 @@ def _jit_per_tensor_quant_fp8_module(is_static: bool, dtype: torch.dtype) -> Mod
)
@maybe_wrap_jit_kernel_debug
@register_custom_op(
op_name="per_tensor_quant_fp8",
mutates_args=["output_q", "output_s"],
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
from sglang.srt.utils.custom_op import register_custom_op
@@ -72,6 +73,7 @@ def _per_token_group_quant_8bit_custom_op(
return None
@maybe_wrap_jit_kernel_debug
def per_token_group_quant_8bit(
input: torch.Tensor,
output_q: torch.Tensor,
+2
View File
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Optional
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import (
cache_once,
is_arch_support_pdl,
@@ -176,6 +177,7 @@ def apply_rope_inplace_with_kvcache(
# NOTE: this name is intentionally set as the old kernel in `sgl_kernel`
@maybe_wrap_jit_kernel_debug
def apply_rope_with_cos_sin_cache_inplace(
q: torch.Tensor,
k: torch.Tensor,
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
import torch
from sglang.jit_kernel.debug_utils import maybe_wrap_jit_kernel_debug
from sglang.jit_kernel.utils import cache_once, load_jit, make_cpp_args
if TYPE_CHECKING:
@@ -21,6 +22,7 @@ def _jit_timestep_embedding_module(dtype: torch.dtype) -> Module:
)
@maybe_wrap_jit_kernel_debug
def timestep_embedding(
t: torch.Tensor,
dim: int,
+470
View File
@@ -0,0 +1,470 @@
"""Kernel API crash debugging helpers for SGLang.
This module was developed with reference to FlashInfer's kernel API logging utility:
https://github.com/flashinfer-ai/flashinfer/blob/main/flashinfer/api_logging.py
"""
from __future__ import annotations
import fnmatch
import functools
import inspect
import json
import logging
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import Any, Callable
import torch
def _substitute_process_id(path: str) -> str:
if "%i" in path:
return path.replace("%i", str(os.getpid()))
return path
_KERNEL_API_LOG_LEVEL = int(os.environ.get("SGLANG_KERNEL_API_LOGLEVEL", "0"))
_KERNEL_API_LOG_DEST = _substitute_process_id(
os.environ.get("SGLANG_KERNEL_API_LOGDEST", "stdout")
)
_DUMP_DIR = Path(
_substitute_process_id(
os.environ.get("SGLANG_KERNEL_API_DUMP_DIR", "sglang_kernel_api_dumps")
)
)
_DUMP_INCLUDE_PATTERNS = [
p.strip()
for p in os.environ.get("SGLANG_KERNEL_API_DUMP_INCLUDE", "").split(",")
if p.strip()
]
_DUMP_EXCLUDE_PATTERNS = [
p.strip()
for p in os.environ.get("SGLANG_KERNEL_API_DUMP_EXCLUDE", "").split(",")
if p.strip()
]
_logger = logging.getLogger("sglang.kernel_api")
_dump_call_counter: dict[str, int] = {}
def _setup_logger() -> None:
for handler in list(_logger.handlers):
_logger.removeHandler(handler)
try:
handler.close()
except Exception:
pass
if _KERNEL_API_LOG_LEVEL == 0:
_logger.addHandler(logging.NullHandler())
_logger.setLevel(logging.CRITICAL + 1)
return
_logger.setLevel(logging.DEBUG)
if _KERNEL_API_LOG_DEST == "stdout":
handler = logging.StreamHandler(sys.stdout)
elif _KERNEL_API_LOG_DEST == "stderr":
handler = logging.StreamHandler(sys.stderr)
else:
handler = logging.FileHandler(_KERNEL_API_LOG_DEST, mode="a")
handler.setFormatter(logging.Formatter("%(message)s"))
_logger.addHandler(handler)
_logger.propagate = False
_setup_logger()
def _is_compiling() -> bool:
try:
if hasattr(torch, "compiler") and hasattr(torch.compiler, "is_compiling"):
return bool(torch.compiler.is_compiling())
if hasattr(torch, "_dynamo") and hasattr(torch._dynamo, "is_compiling"):
return bool(torch._dynamo.is_compiling())
except Exception:
return False
return False
def _timestamp() -> str:
return datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
def _is_cuda_graph_capture_active() -> bool:
try:
return torch.cuda.is_available() and torch.cuda.is_current_stream_capturing()
except Exception:
return False
def _append_line(lines: list[str], indent: int, text: str) -> None:
lines.append(" " * indent + text)
def _should_dump_function(func_name: str) -> bool:
if _DUMP_INCLUDE_PATTERNS and not any(
fnmatch.fnmatch(func_name, pattern) for pattern in _DUMP_INCLUDE_PATTERNS
):
return False
if _DUMP_EXCLUDE_PATTERNS and any(
fnmatch.fnmatch(func_name, pattern) for pattern in _DUMP_EXCLUDE_PATTERNS
):
return False
return True
def _serialize_tensor(tensor: torch.Tensor) -> list[str]:
lines = ["Tensor("]
_append_line(lines, 2, f"shape={tuple(tensor.shape)}")
_append_line(lines, 2, f"dtype={tensor.dtype}")
_append_line(lines, 2, f"device={tensor.device}")
_append_line(lines, 2, f"requires_grad={tensor.requires_grad}")
_append_line(lines, 2, f"is_contiguous={tensor.is_contiguous()}")
if _KERNEL_API_LOG_LEVEL >= 5:
if tensor.numel() == 0:
_append_line(lines, 2, "statistics=[empty tensor]")
elif tensor.device.type == "cuda" and _is_cuda_graph_capture_active():
_append_line(
lines, 2, "statistics=[skipped: CUDA graph capture in progress]"
)
else:
try:
detached = tensor.detach()
if detached.is_complex():
stats_source = detached.abs().float()
nan_count = int(torch.isnan(detached).sum().item())
inf_count = int(torch.isinf(detached).sum().item())
else:
stats_source = detached.float()
if detached.is_floating_point():
nan_count = int(torch.isnan(detached).sum().item())
inf_count = int(torch.isinf(detached).sum().item())
else:
nan_count = 0
inf_count = 0
_append_line(lines, 2, f"min={stats_source.min().item():.6f}")
_append_line(lines, 2, f"max={stats_source.max().item():.6f}")
_append_line(lines, 2, f"mean={stats_source.mean().item():.6f}")
_append_line(lines, 2, f"nan_count={nan_count}")
_append_line(lines, 2, f"inf_count={inf_count}")
except Exception as exc:
_append_line(
lines, 2, f"statistics=[unavailable: {type(exc).__name__}]"
)
lines.append(")")
return lines
def _serialize_value(value: Any, depth: int = 0) -> list[str]:
if depth >= 2:
return [f"{type(value).__name__}(...)"]
if isinstance(value, torch.Tensor):
return _serialize_tensor(value)
if isinstance(value, (str, int, float, bool, type(None))):
return [repr(value)]
if isinstance(value, (list, tuple)):
opener = "[" if isinstance(value, list) else "("
closer = "]" if isinstance(value, list) else ")"
lines = [opener]
for idx, item in enumerate(value[:4]):
item_lines = _serialize_value(item, depth + 1)
lines.append(f" [{idx}] {item_lines[0]}")
for extra in item_lines[1:]:
lines.append(f" {extra}")
if len(value) > 4:
lines.append(f" ... ({len(value) - 4} more items)")
lines.append(closer)
return lines
if isinstance(value, dict):
lines = ["{"]
items = list(value.items())
for key, item in items[:8]:
item_lines = _serialize_value(item, depth + 1)
lines.append(f" {key!r}: {item_lines[0]}")
for extra in item_lines[1:]:
lines.append(f" {extra}")
if len(items) > 8:
lines.append(f" ... ({len(items) - 8} more items)")
lines.append("}")
return lines
summary = [f"{type(value).__name__}("]
for attr in ("shape", "dtype", "device"):
if hasattr(value, attr):
try:
_append_line(summary, 2, f"{attr}={getattr(value, attr)}")
except Exception:
pass
if len(summary) == 1:
_append_line(summary, 2, f"repr={repr(value)[:200]}")
summary.append(")")
return summary
def _serialize_json_value(value: Any) -> Any:
if isinstance(value, torch.dtype):
return {"type": "torch.dtype", "value": str(value)}
if isinstance(value, (str, int, float, bool, type(None))):
return value
if isinstance(value, (list, tuple)):
return [_serialize_json_value(item) for item in value[:16]]
if isinstance(value, dict):
return {
str(key): _serialize_json_value(item)
for key, item in list(value.items())[:32]
}
return {"type": type(value).__name__, "repr": repr(value)[:200]}
def _collect_dump_entries(
prefix: str,
value: Any,
tensor_entries: dict[str, torch.Tensor],
metadata_entries: dict[str, Any],
) -> None:
if isinstance(value, torch.Tensor):
tensor_entries[prefix] = value.detach().cpu()
return
if isinstance(value, (list, tuple)):
for idx, item in enumerate(value):
_collect_dump_entries(
f"{prefix}_{idx}", item, tensor_entries, metadata_entries
)
metadata_entries[f"{prefix}__container"] = {
"type": type(value).__name__,
"length": len(value),
}
return
if isinstance(value, dict):
for key, item in value.items():
_collect_dump_entries(
f"{prefix}_{str(key)}", item, tensor_entries, metadata_entries
)
metadata_entries[f"{prefix}__container"] = {
"type": "dict",
"keys": [str(k) for k in value.keys()],
}
return
metadata_entries[prefix] = _serialize_json_value(value)
def _dump_metadata_path(dump_dir: Path) -> Path:
return dump_dir / "metadata.json"
def _write_dump_metadata(dump_dir: Path, metadata: dict[str, Any]) -> None:
_dump_metadata_path(dump_dir).write_text(json.dumps(metadata, indent=2))
def _read_dump_metadata(dump_dir: Path) -> dict[str, Any]:
return json.loads(_dump_metadata_path(dump_dir).read_text())
def _dump_function_inputs(
func_name: str, args: tuple[Any, ...], kwargs: dict[str, Any]
) -> Path | None:
if not _should_dump_function(func_name):
return None
_DUMP_DIR.mkdir(parents=True, exist_ok=True)
call_index = _dump_call_counter.get(func_name, 0) + 1
_dump_call_counter[func_name] = call_index
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
safe_func_name = func_name.replace("/", "_").replace("<", "_").replace(">", "_")
dump_dir = (
_DUMP_DIR
/ f"{timestamp}_pid{os.getpid()}_{safe_func_name}_call{call_index:04d}"
)
dump_dir.mkdir(parents=True, exist_ok=True)
tensor_entries: dict[str, torch.Tensor] = {}
metadata_entries: dict[str, Any] = {}
for idx, arg in enumerate(args):
_collect_dump_entries(f"arg_{idx}", arg, tensor_entries, metadata_entries)
for key, value in kwargs.items():
_collect_dump_entries(f"kwarg_{key}", value, tensor_entries, metadata_entries)
if tensor_entries:
torch.save(tensor_entries, dump_dir / "inputs.pt")
metadata = {
"function_name": func_name,
"timestamp": timestamp,
"process_id": os.getpid(),
"execution_status": "inputs_saved",
"input_metadata": metadata_entries,
"input_tensor_keys": list(tensor_entries.keys()),
"output_metadata": {},
"output_tensor_keys": [],
}
_write_dump_metadata(dump_dir, metadata)
_logger.debug("Dumped inputs to: %s", dump_dir)
return dump_dir
def _dump_function_outputs(dump_dir: Path, result: Any) -> None:
tensor_entries: dict[str, torch.Tensor] = {}
metadata_entries: dict[str, Any] = {}
_collect_dump_entries("result", result, tensor_entries, metadata_entries)
if tensor_entries:
torch.save(tensor_entries, dump_dir / "outputs.pt")
metadata = _read_dump_metadata(dump_dir)
metadata["execution_status"] = "completed"
metadata["output_metadata"] = metadata_entries
metadata["output_tensor_keys"] = list(tensor_entries.keys())
_write_dump_metadata(dump_dir, metadata)
_logger.debug("Dumped outputs to: %s", dump_dir)
def _mark_dump_exception(dump_dir: Path, exc: Exception) -> None:
metadata = _read_dump_metadata(dump_dir)
metadata["execution_status"] = "exception"
metadata["exception"] = {
"type": type(exc).__name__,
"message": str(exc),
}
_write_dump_metadata(dump_dir, metadata)
def _log_section(title: str, data: dict[str, Any]) -> None:
_logger.debug(title)
for key, value in data.items():
lines = _serialize_value(value)
_logger.debug(" %s=%s", key, lines[0])
for line in lines[1:]:
_logger.debug(" %s", line)
def _infer_func_name(func: Callable) -> str:
qualname = getattr(func, "__qualname__", getattr(func, "__name__", "unknown"))
qualname = qualname.replace(".<locals>.", ".").replace("<locals>.", "")
module = getattr(func, "__module__", "")
for prefix in ("sglang.", "sgl_kernel."):
if module.startswith(prefix):
module = module[len(prefix) :]
break
if module and module not in {"__main__", "builtins"}:
return f"{module}.{qualname}"
source_path = inspect.getsourcefile(func)
if source_path is not None:
return f"{Path(source_path).stem}.{qualname}"
return qualname
def debug_kernel_api(
func: Callable | None = None,
*,
op_name: str | None = None,
) -> Callable:
if _KERNEL_API_LOG_LEVEL == 0:
if func is None:
return lambda f: f
return func
def decorator(f: Callable) -> Callable:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> Any:
if _is_compiling():
return f(*args, **kwargs)
func_name = op_name or _infer_func_name(f)
dump_dir: Path | None = None
positional_args = args
try:
parameters = tuple(inspect.signature(f).parameters.values())
except (TypeError, ValueError):
parameters = ()
if args and parameters and parameters[0].name in {"self", "cls"}:
positional_args = args[1:]
_logger.debug("=" * 80)
_logger.debug("%s SGLang Kernel API Call: %s", _timestamp(), func_name)
if _KERNEL_API_LOG_LEVEL >= 3:
if positional_args:
_log_section(
"Positional input arguments:",
{f"arg[{idx}]": arg for idx, arg in enumerate(positional_args)},
)
if kwargs:
_log_section("Keyword input arguments:", kwargs)
if _KERNEL_API_LOG_LEVEL >= 10:
if _is_cuda_graph_capture_active():
_logger.debug("Tensor dump skipped: CUDA graph capture in progress")
else:
dump_dir = _dump_function_inputs(func_name, positional_args, kwargs)
try:
result = f(*args, **kwargs)
except Exception as exc:
if dump_dir is not None:
_mark_dump_exception(dump_dir, exc)
_logger.debug(
"%s SGLang Kernel API Exception: %s (%s: %s)",
_timestamp(),
func_name,
type(exc).__name__,
exc,
)
raise
if dump_dir is not None:
_dump_function_outputs(dump_dir, result)
if _KERNEL_API_LOG_LEVEL >= 3:
_log_section("Output:", {"return": result})
return result
return wrapper
if func is None:
return decorator
return decorator(func)
def debug_torch_op(op_name: str, *, namespace: str = "sglang") -> Callable:
def call(*args: Any, **kwargs: Any) -> Any:
return getattr(getattr(torch.ops, namespace), op_name)(*args, **kwargs)
return debug_kernel_api(call, op_name=f"{namespace}.custom_op.{op_name}")
def wrap_method_with_debug_kernel_once(
obj: Any,
method_name: str,
*,
op_name: str,
marker_attr: str | None = None,
) -> Any:
if marker_attr is None:
marker_attr = f"_debug_kernel_{method_name}_wrapped"
if getattr(obj, marker_attr, False):
return obj
setattr(
obj,
method_name,
debug_kernel_api(getattr(obj, method_name), op_name=op_name),
)
setattr(obj, marker_attr, True)
return obj
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
import torch
from sglang.kernel_api_logging import wrap_method_with_debug_kernel_once
from sglang.multimodal_gen.runtime.platforms import AttentionBackendEnum
@@ -168,3 +169,11 @@ class AttentionImpl(ABC, Generic[T]):
attn_metadata: T,
) -> torch.Tensor:
raise NotImplementedError
def wrap_attention_impl_forward(attn_impl: AttentionImpl) -> AttentionImpl:
return wrap_method_with_debug_kernel_once(
attn_impl,
"forward",
op_name=f"diffusion.attn_impl.{attn_impl.__class__.__name__}.forward",
)
@@ -20,6 +20,7 @@ from sglang.multimodal_gen.runtime.distributed.parallel_state import (
)
from sglang.multimodal_gen.runtime.layers.attention.backends.attention_backend import (
AttentionImpl,
wrap_attention_impl_forward,
)
from sglang.multimodal_gen.runtime.layers.attention.selector import get_attn_backend
from sglang.multimodal_gen.runtime.layers.usp import (
@@ -73,6 +74,7 @@ class UlyssesAttention(nn.Module):
prefix=f"{prefix}.impl",
**extra_impl_args,
)
wrap_attention_impl_forward(self.attn_impl)
self.num_heads = num_heads
self.head_size = head_size
self.num_kv_heads = num_kv_heads
@@ -252,6 +254,7 @@ class LocalAttention(nn.Module):
causal=causal,
**extra_impl_args,
)
wrap_attention_impl_forward(self.attn_impl)
self.num_heads = num_heads
self.head_size = head_size
self.num_kv_heads = num_kv_heads
@@ -338,6 +341,7 @@ class USPAttention(nn.Module):
prefix=f"{prefix}.impl",
**extra_impl_args,
)
wrap_attention_impl_forward(self.attn_impl)
self.num_heads = num_heads
self.head_size = head_size
self.num_kv_heads = num_kv_heads
@@ -8,6 +8,7 @@ from typing import Any
import torch.nn as nn
from sglang.kernel_api_logging import debug_kernel_api
from sglang.multimodal_gen.runtime.platforms import current_platform
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
@@ -25,6 +26,7 @@ class CustomOp(nn.Module):
super().__init__()
self._forward_method = self.dispatch_forward()
@debug_kernel_api
def forward(self, *args, **kwargs) -> Any:
return self._forward_method(*args, **kwargs)
@@ -10,6 +10,7 @@ import torch.distributed as dist
import torch.nn.functional as F
from torch.nn.parameter import Parameter
from sglang.kernel_api_logging import wrap_method_with_debug_kernel_once
from sglang.multimodal_gen.runtime.distributed import (
divide,
get_tp_group,
@@ -195,6 +196,13 @@ class LinearBase(torch.nn.Module):
else:
self.quant_method = quant_config.get_quant_method(self, prefix=prefix)
if self.quant_method is not None:
wrap_method_with_debug_kernel_once(
self.quant_method,
"apply",
op_name=f"diffusion.quant_method.{self.quant_method.__class__.__name__}.apply",
)
def forward(self, x: torch.Tensor) -> tuple[torch.Tensor, Parameter | None]:
raise NotImplementedError
@@ -5,6 +5,7 @@ from typing import Optional, Tuple
import torch
from sglang.jit_kernel.diffusion.triton.rotary import apply_rotary_embedding
from sglang.kernel_api_logging import debug_kernel_api
from sglang.multimodal_gen.runtime.platforms import current_platform
from sglang.srt.utils.custom_op import register_custom_op_from_extern
@@ -61,6 +62,7 @@ def _apply_rotary_emb(
return apply_rotary_embedding(x, cos, sin, interleaved)
@debug_kernel_api
def apply_flashinfer_rope_qk_inplace(
q: torch.Tensor,
k: torch.Tensor,
@@ -10,6 +10,7 @@ from typing import Any, Callable, List, Optional
import torch
from torch.library import Library
from sglang.kernel_api_logging import debug_torch_op
from sglang.multimodal_gen.runtime.platforms import current_platform
@@ -155,7 +156,7 @@ class CustomOpWrapper:
mutates_args=self.mutates_args,
fake_impl=self.fake_impl,
)
self._impl = getattr(torch.ops.sglang, self.op_name)
self._impl = debug_torch_op(self.op_name)
assert self._impl is not None
return self._impl
@@ -621,6 +621,9 @@ class SGLangAttentionWrapper(torch.nn.Module):
[nn.Linear(self.inner_dim, query_dim, bias=out_bias), nn.Dropout(dropout)]
)
from sglang.multimodal_gen.runtime.layers.attention.backends.attention_backend import (
wrap_attention_impl_forward,
)
from sglang.multimodal_gen.runtime.layers.attention.selector import (
get_attn_backend,
)
@@ -636,6 +639,7 @@ class SGLangAttentionWrapper(torch.nn.Module):
num_kv_heads=heads,
causal=False,
)
wrap_attention_impl_forward(self.attn_impl)
self._attn_backend_name = attn_backend.get_enum().name
def forward(
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Optional
import torch
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.utils.common import is_npu
if TYPE_CHECKING:
@@ -76,6 +77,7 @@ class AttentionBackend(ABC):
"""
raise NotImplementedError()
@debug_kernel_api
def forward(
self,
q: torch.Tensor,
@@ -16,6 +16,7 @@ from typing import TYPE_CHECKING, Callable, List, Optional, Union
import torch
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.compilation.piecewise_context_manager import is_in_piecewise_cuda_graph
from sglang.srt.dllm.config import DllmConfig
from sglang.srt.environ import envs
@@ -748,6 +749,7 @@ class FlashInferAttnBackend(AttentionBackend):
def get_cuda_graph_seq_len_fill_value(self):
return 1
@debug_kernel_api
def forward_extend(
self,
q: torch.Tensor,
@@ -862,6 +864,7 @@ class FlashInferAttnBackend(AttentionBackend):
return o.view(-1, layer.tp_q_head_num * layer.head_dim)
@debug_kernel_api
def forward_decode(
self,
q: torch.Tensor,
+8
View File
@@ -10,6 +10,7 @@ import torch
from torch import nn
from torch.nn.parameter import Parameter, UninitializedParameter
from sglang.kernel_api_logging import wrap_method_with_debug_kernel_once
from sglang.srt.distributed import (
divide,
get_tensor_model_parallel_rank,
@@ -176,6 +177,13 @@ class LinearBase(torch.nn.Module):
else:
self.quant_method = quant_config.get_quant_method(self, prefix=prefix)
if self.quant_method is not None:
wrap_method_with_debug_kernel_once(
self.quant_method,
"apply",
op_name=f"sglang.quant_method.{self.quant_method.__class__.__name__}.apply",
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
raise NotImplementedError
@@ -9,6 +9,7 @@ from torch.nn.parameter import Parameter
# Import to register custom ops for torch.compile compatibility
import sglang.srt.layers.moe.flashinfer_trtllm_moe # noqa: F401
from sglang.kernel_api_logging import debug_torch_op
from sglang.srt.distributed import get_tp_group
from sglang.srt.distributed.device_communicators.pynccl_allocator import (
use_symmetric_memory,
@@ -44,6 +45,16 @@ elif is_cuda_alike():
else:
fp4_quantize = None
_trtllm_fp8_block_scale_routed_moe_wrapper = debug_torch_op(
"trtllm_fp8_block_scale_routed_moe_wrapper"
)
_trtllm_fp8_block_scale_moe_wrapper = debug_torch_op(
"trtllm_fp8_block_scale_moe_wrapper"
)
_trtllm_fp8_per_tensor_scale_moe = debug_torch_op(
"trtllm_fp8_per_tensor_scale_moe_wrapper"
)
def align_fp8_moe_weights_for_flashinfer_trtllm(
layer: Module, swap_w13_halves: bool = False
@@ -375,7 +386,7 @@ def fused_experts_none_to_flashinfer_trtllm_fp8(
topk_weights=topk_output.topk_weights,
)
output = torch.ops.sglang.trtllm_fp8_block_scale_routed_moe_wrapper(
output = _trtllm_fp8_block_scale_routed_moe_wrapper(
topk_ids=packed_topk_ids,
routing_bias=None,
hidden_states=a_q,
@@ -408,7 +419,7 @@ def fused_experts_none_to_flashinfer_trtllm_fp8(
else:
assert TopKOutputChecker.format_is_bypassed(topk_output)
output = torch.ops.sglang.trtllm_fp8_block_scale_moe_wrapper(
output = _trtllm_fp8_block_scale_moe_wrapper(
routing_logits=(
router_logits.to(torch.float32)
if routing_method_type == RoutingMethodType.DeepSeekV3
@@ -465,7 +476,7 @@ def fused_experts_none_to_flashinfer_trtllm_fp8(
# Move kernel call outside context manager to avoid graph breaks
# during torch.compile for piecewise cuda graph.
# Use custom op wrapper for torch.compile compatibility.
output = torch.ops.sglang.trtllm_fp8_per_tensor_scale_moe_wrapper(
output = _trtllm_fp8_per_tensor_scale_moe(
routing_logits=router_logits.to(torch.bfloat16),
routing_bias=routing_bias_cast,
hidden_states=a_q,
@@ -5,6 +5,7 @@ from typing import NamedTuple, Optional
import torch
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.environ import envs
from sglang.srt.layers.dp_attention import get_dp_global_num_tokens
from sglang.srt.layers.moe.token_dispatcher import (
@@ -167,6 +168,7 @@ class FlashinferDispatcher(BaseDispatcher):
(1, self.router_topk), dtype=torch.float32, device="cuda"
)
@debug_kernel_api
def dispatch(
self, hidden_states: torch.Tensor, topk_output: TopKOutput
) -> FlashinferDispatchOutput:
@@ -243,6 +245,7 @@ class FlashinferDispatcher(BaseDispatcher):
moe_output,
)
@debug_kernel_api
def combine(self, combine_input: FlashinferCombineInput) -> torch.Tensor:
hidden_states = combine_input.hidden_states
output_hidden_size = hidden_states.shape[-1]
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Optional
import torch
from packaging import version
from sglang.kernel_api_logging import debug_torch_op
from sglang.srt.layers.linear import LinearBase
from sglang.srt.layers.quantization.base_config import (
FusedMoEMethodBase,
@@ -431,7 +432,7 @@ try:
mutates_args=["out"],
fake_impl=_apply_bnb_4bit_fake,
)
apply_bnb_4bit = torch.ops.sglang.apply_bnb_4bit
apply_bnb_4bit = debug_torch_op("apply_bnb_4bit")
except AttributeError as error:
raise error
+4 -1
View File
@@ -10,6 +10,7 @@ import torch.nn.functional as F
from torch.nn import Module
from torch.nn.parameter import Parameter
from sglang.kernel_api_logging import debug_torch_op
from sglang.srt.distributed import get_tensor_model_parallel_world_size, get_tp_group
from sglang.srt.distributed.device_communicators.pynccl_allocator import (
use_symmetric_memory,
@@ -110,6 +111,8 @@ ACTIVATION_SCHEMES = ["static", "dynamic"]
logger = logging.getLogger(__name__)
_apply_fp8_marlin_linear = debug_torch_op("apply_fp8_marlin_linear")
class Fp8Config(QuantizationConfig):
"""Config class for FP8."""
@@ -643,7 +646,7 @@ class Fp8LinearMethod(LinearMethodBase):
bias: Optional[torch.Tensor] = None,
) -> torch.Tensor:
if self.use_marlin:
return torch.ops.sglang.apply_fp8_marlin_linear(
return _apply_fp8_marlin_linear(
input=x,
weight=layer.weight,
weight_scale=layer.weight_scale,
@@ -2,6 +2,7 @@ from typing import Callable
from torch import nn
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.utils import (
cpu_has_amx_support,
is_cpu,
@@ -67,6 +68,7 @@ class MultiPlatformOp(nn.Module):
self.is_torch_compile = False
# Please do not override this method, because `self._forward_method` can change when in torch compile mode
@debug_kernel_api
def forward(self, *args, **kwargs):
return self._forward_method(*args, **kwargs)
+5 -1
View File
@@ -37,6 +37,7 @@ import triton
import triton.language as tl
from sglang.jit_kernel.kvcache import can_use_store_cache, store_cache
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.configs.mamba_utils import BaseLinearStateParams
from sglang.srt.constants import GPU_MEMORY_TYPE_KV_CACHE
from sglang.srt.environ import envs
@@ -63,7 +64,10 @@ from sglang.srt.utils import (
from sglang.srt.utils.custom_op import register_custom_op
from sglang.srt.utils.torch_memory_saver_adapter import TorchMemorySaverAdapter
store_cache = register_custom_op(store_cache, mutates_args=["k_cache", "v_cache"])
store_cache = register_custom_op(
debug_kernel_api(store_cache, op_name="jit_kernel.kvcache.store_cache"),
mutates_args=["k_cache", "v_cache"],
)
if TYPE_CHECKING:
from sglang.srt.managers.cache_controller import LayerDoneCounter
@@ -74,17 +74,19 @@ def awq_dequantize_func():
return awq_dequantize
elif _is_hip:
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.layers.quantization.awq_triton import (
awq_dequantize_triton as awq_dequantize,
)
return awq_dequantize
return debug_kernel_api(awq_dequantize, op_name="DeepseekCommon.awq_dequantize")
elif _is_npu:
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.layers.quantization.awq_triton import (
awq_dequantize_decomposition as awq_dequantize,
)
return awq_dequantize
return debug_kernel_api(awq_dequantize, op_name="DeepseekCommon.awq_dequantize")
else:
return None
@@ -52,6 +52,8 @@ import torch.nn.functional as F
from transformers.activations import ACT2FN
from transformers.modeling_utils import PreTrainedModel
from sglang.kernel_api_logging import debug_kernel_api
try:
from flash_attn.flash_attn_interface import flash_attn_varlen_func
except ImportError:
@@ -65,6 +67,7 @@ from sglang.srt.layers.quantization.modelslim.modelslim import ModelSlimConfig
from sglang.srt.utils import add_prefix
@debug_kernel_api
def multihead_attention(
q: torch.Tensor,
k: torch.Tensor,
+3
View File
@@ -25,6 +25,7 @@ import triton.language as tl
from torch import nn
from transformers import PretrainedConfig
from sglang.kernel_api_logging import debug_kernel_api
from sglang.srt.batch_overlap.two_batch_overlap import model_forward_maybe_tbo
from sglang.srt.distributed import (
get_moe_expert_parallel_world_size,
@@ -158,6 +159,7 @@ def rmsnorm_apply_kernel_serial(
tl.store(out2_row + offsets2, out2, mask=mask2)
@debug_kernel_api
def rms_sumsq_serial(x1: torch.Tensor, x2: torch.Tensor) -> torch.Tensor:
assert x1.is_cuda and x2.is_cuda
B, D1 = x1.shape
@@ -196,6 +198,7 @@ def rms_sumsq_serial(x1: torch.Tensor, x2: torch.Tensor) -> torch.Tensor:
return sum_sq
@debug_kernel_api
def rms_apply_serial(
x1: torch.Tensor,
x2: torch.Tensor,
+4 -2
View File
@@ -6,6 +6,8 @@ from typing import Any, Callable, List, Optional, TypeVar, Union, overload
import torch
import torch.library
from sglang.kernel_api_logging import debug_torch_op
F = TypeVar("F", bound=Callable)
@@ -159,7 +161,7 @@ class CustomOpWrapper:
mutates_args=self.mutates_args,
fake_impl=self.fake_impl,
)
self._impl = getattr(torch.ops.sglang, self.op_name)
self._impl = debug_torch_op(self.op_name)
assert self._impl is not None
return self._impl
@@ -332,4 +334,4 @@ def register_custom_op_from_extern(
fake_impl=fake_impl,
)
return getattr(torch.ops.sglang, name)
return debug_torch_op(name)