Files
wehub-resource-sync 94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

320 lines
11 KiB
Python

"""
Conv2d/Conv3d layers with unfold+linear optimization for patch embeddings.
When kernel_size == stride, padding == 0, dilation == 1, groups == 1, the conv
is equivalent to unfold + F.linear, which is significantly faster on CUDA and
also avoids the PyTorch 2.9.1 + CuDNN < 9.15 Conv3d bug
(https://github.com/pytorch/pytorch/issues/168167).
"""
import math
from typing import Tuple, Union
import torch
import torch.nn as nn
import torch.nn.functional as F
from sglang.srt.layers.amx_utils import PackWeightMethod
from sglang.srt.layers.utils.multi_platform import MultiPlatformOp
from sglang.srt.utils import cpu_has_amx_support, is_cpu, use_intel_amx_backend
_is_cpu = is_cpu()
_is_cpu_amx_available = cpu_has_amx_support()
if _is_cpu and _is_cpu_amx_available:
conv3d_embed = torch.ops.sgl_kernel.conv3d_embed_cpu
_VALID_PADDING_STRINGS = {"same", "valid"}
_VALID_PADDING_MODES = {"zeros", "reflect", "replicate", "circular"}
def _tuplify(val, n: int) -> tuple:
if isinstance(val, (list, tuple)):
assert len(val) == n
return tuple(val)
return (val,) * n
def _check_enable_linear(
kernel_size: tuple,
stride: tuple,
padding: tuple,
dilation: tuple,
groups: int,
) -> bool:
"""Check if conv can be replaced with unfold + F.linear."""
return (
kernel_size == stride
and all(p == 0 for p in padding)
and all(d == 1 for d in dilation)
and groups == 1
)
def _reverse_repeat_tuple(t: tuple) -> tuple:
"""(1, 2, 3) -> (3, 3, 2, 2, 1, 1). Used for F.pad with non-zeros padding_mode."""
return tuple(x for x in reversed(t) for _ in range(2))
def _compute_same_padding_for_pad(kernel_size: tuple, dilation: tuple) -> tuple:
"""Compute _reversed_padding_repeated_twice for padding='same'.
This mirrors PyTorch's nn.Conv*d behavior: pre-compute the exact pad
amounts so that F.pad can be called before F.conv*d(padding=0).
"""
pad = []
for k, d in zip(reversed(kernel_size), reversed(dilation)):
total = d * (k - 1)
pad.append(total // 2)
pad.append(total - total // 2)
return tuple(pad)
def _validate_conv_args(
in_channels: int,
out_channels: int,
groups: int,
padding,
padding_mode: str,
stride: tuple,
) -> None:
if in_channels % groups != 0:
raise ValueError(
f"in_channels ({in_channels}) must be divisible by groups ({groups})"
)
if out_channels % groups != 0:
raise ValueError(
f"out_channels ({out_channels}) must be divisible by groups ({groups})"
)
if padding_mode not in _VALID_PADDING_MODES:
raise ValueError(
f"padding_mode must be one of {_VALID_PADDING_MODES}, got '{padding_mode}'"
)
if isinstance(padding, str):
if padding not in _VALID_PADDING_STRINGS:
raise ValueError(
f"padding must be one of {_VALID_PADDING_STRINGS}, got '{padding}'"
)
if padding == "same" and any(s != 1 for s in stride):
raise ValueError("padding='same' is not supported for strided convolutions")
class Conv2dLayer(MultiPlatformOp):
"""Drop-in replacement for nn.Conv2d. Linear optimization disabled by default."""
def __init__(
self,
in_channels: int,
out_channels: int,
kernel_size: Union[int, Tuple[int, int]],
stride: Union[int, Tuple[int, int]] = 1,
padding: Union[int, Tuple[int, int], str] = 0,
dilation: Union[int, Tuple[int, int]] = 1,
groups: int = 1,
bias: bool = True,
padding_mode: str = "zeros",
disable_linear: bool = True,
):
super().__init__()
self.in_channels = in_channels
self.out_channels = out_channels
self.kernel_size = _tuplify(kernel_size, 2)
self.stride = _tuplify(stride, 2)
self.dilation = _tuplify(dilation, 2)
self.groups = groups
self.padding_mode = padding_mode
_validate_conv_args(
in_channels, out_channels, groups, padding, padding_mode, self.stride
)
if isinstance(padding, str):
self.padding = (0, 0) if padding == "valid" else padding
else:
self.padding = _tuplify(padding, 2)
# Pre-compute pad tuple for padding_mode != "zeros" (mirrors nn.Conv2d).
# When padding="same", we need numeric values for F.pad;
# when padding is already numeric, _reverse_repeat_tuple handles it.
if isinstance(self.padding, str):
self._reversed_padding_repeated_twice = _compute_same_padding_for_pad(
self.kernel_size, self.dilation
)
else:
self._reversed_padding_repeated_twice = _reverse_repeat_tuple(self.padding)
padding_tuple = self.padding if isinstance(self.padding, tuple) else (1, 1)
self.enable_linear = not disable_linear and _check_enable_linear(
self.kernel_size, self.stride, padding_tuple, self.dilation, groups
)
self.weight = nn.Parameter(
torch.empty(out_channels, in_channels // groups, *self.kernel_size)
)
if bias:
self.bias = nn.Parameter(torch.empty(out_channels))
else:
self.register_parameter("bias", None)
self._reset_parameters()
def _reset_parameters(self):
nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
if self.bias is not None:
fan_in = nn.init._calculate_correct_fan(self.weight, "fan_in")
bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
nn.init.uniform_(self.bias, -bound, bound)
def _forward_mulmat(self, x: torch.Tensor) -> torch.Tensor:
K1, K2 = self.kernel_size
x = x.unfold(2, K1, K1).unfold(3, K2, K2)
N, _, Hp, Wp = x.shape[:4]
x = x.permute(0, 2, 3, 1, 4, 5).reshape(N, Hp, Wp, -1)
x = F.linear(x, self.weight.reshape(self.out_channels, -1), self.bias)
return x.permute(0, 3, 1, 2)
def _forward_conv(self, x: torch.Tensor) -> torch.Tensor:
if self.padding_mode != "zeros":
return F.conv2d(
F.pad(x, self._reversed_padding_repeated_twice, mode=self.padding_mode),
self.weight,
self.bias,
self.stride,
(0, 0),
self.dilation,
self.groups,
)
return F.conv2d(
x,
self.weight,
self.bias,
self.stride,
self.padding,
self.dilation,
self.groups,
)
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
if self.enable_linear:
return self._forward_mulmat(x)
return self._forward_conv(x)
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
if self.enable_linear:
return self._forward_mulmat(x)
return self._forward_conv(x)
class Conv3dLayer(MultiPlatformOp):
"""Drop-in replacement for nn.Conv3d with automatic linear optimization."""
def __init__(
self,
in_channels: int,
out_channels: int,
kernel_size: Union[int, Tuple[int, int, int]],
stride: Union[int, Tuple[int, int, int]] = 1,
padding: Union[int, Tuple[int, int, int], str] = 0,
dilation: Union[int, Tuple[int, int, int]] = 1,
groups: int = 1,
bias: bool = True,
padding_mode: str = "zeros",
disable_linear: bool = False,
):
super().__init__()
self.in_channels = in_channels
self.out_channels = out_channels
self.kernel_size = _tuplify(kernel_size, 3)
self.stride = _tuplify(stride, 3)
self.dilation = _tuplify(dilation, 3)
self.groups = groups
self.padding_mode = padding_mode
_validate_conv_args(
in_channels, out_channels, groups, padding, padding_mode, self.stride
)
if isinstance(padding, str):
self.padding = (0, 0, 0) if padding == "valid" else padding
else:
self.padding = _tuplify(padding, 3)
if isinstance(self.padding, str):
self._reversed_padding_repeated_twice = _compute_same_padding_for_pad(
self.kernel_size, self.dilation
)
else:
self._reversed_padding_repeated_twice = _reverse_repeat_tuple(self.padding)
padding_tuple = self.padding if isinstance(self.padding, tuple) else (1, 1, 1)
self.enable_linear = not disable_linear and _check_enable_linear(
self.kernel_size, self.stride, padding_tuple, self.dilation, groups
)
self.weight = nn.Parameter(
torch.empty(out_channels, in_channels // groups, *self.kernel_size)
)
if bias:
self.bias = nn.Parameter(torch.empty(out_channels))
else:
self.register_parameter("bias", None)
if _is_cpu and _is_cpu_amx_available and self.bias is not None:
self.quant_method = PackWeightMethod(weight_names=["weight"])
self._reset_parameters()
def _reset_parameters(self):
nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
if self.bias is not None:
fan_in = nn.init._calculate_correct_fan(self.weight, "fan_in")
bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
nn.init.uniform_(self.bias, -bound, bound)
def _forward_mulmat(self, x: torch.Tensor) -> torch.Tensor:
K1, K2, K3 = self.kernel_size
x = x.unfold(2, K1, K1).unfold(3, K2, K2).unfold(4, K3, K3)
N, Dp, Hp, Wp = x.shape[0], x.shape[2], x.shape[3], x.shape[4]
x = x.permute(0, 2, 3, 4, 1, 5, 6, 7).reshape(N, Dp, Hp, Wp, -1)
x = F.linear(x, self.weight.reshape(self.out_channels, -1), self.bias)
return x.permute(0, 4, 1, 2, 3)
def _forward_conv(self, x: torch.Tensor) -> torch.Tensor:
if self.padding_mode != "zeros":
return F.conv3d(
F.pad(x, self._reversed_padding_repeated_twice, mode=self.padding_mode),
self.weight,
self.bias,
self.stride,
(0, 0, 0),
self.dilation,
self.groups,
)
return F.conv3d(
x,
self.weight,
self.bias,
self.stride,
self.padding,
self.dilation,
self.groups,
)
def forward_cpu(self, x: torch.Tensor) -> torch.Tensor:
if use_intel_amx_backend(self):
return conv3d_embed(
x,
self.weight,
self.bias,
is_vnni=True,
)
return self.forward_native(x)
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
if self.enable_linear:
return self._forward_mulmat(x)
return self._forward_conv(x)
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
if self.enable_linear:
return self._forward_mulmat(x)
return self._forward_conv(x)