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

367 lines
11 KiB
Python

import functools
import logging
import sys
from enum import IntEnum
from typing import TYPE_CHECKING, Callable
import torch
from sglang.srt.environ import envs
from sglang.srt.utils import get_npu_memory_capacity, is_npu
if TYPE_CHECKING:
from sglang.srt.server_args import ServerArgs
logger = logging.getLogger(__name__)
_is_npu = is_npu()
indexer_weight_stream = None
gva_is_inited = False
class NPUACLFormat(IntEnum):
ACL_FORMAT_UNDEFINED = -1
ACL_FORMAT_ND = 2
ACL_FORMAT_FRACTAL_NZ = 29
class FusedMoEMode(IntEnum):
FUSED_DEEP_MOE = 1
DISPATCH_FFN_COMBINE = 2
def _call_once(fn: Callable):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
if getattr(fn, "_has_been_called", False):
logger.debug("Function {} has already been called.", fn.__name__)
return
fn._has_been_called = True
return fn(*args, **kwargs)
return wrapper
def set_default_server_args(args: "ServerArgs"):
"""
Set default server arguments for NPU backend.
"""
# NPU only works with "ascend" attention backend for now
args.attention_backend = "ascend"
args.prefill_attention_backend = "ascend"
args.decode_attention_backend = "ascend"
if args.page_size is None:
args.page_size = 128
# NPU memory settings
decode = args.cuda_graph_config.decode
npu_mem = get_npu_memory_capacity()
if npu_mem <= 32 * 1024:
# Ascend 910B4,910B4_1
# (chunked_prefill_size 4k, max_bs 16 if tp < 4 else 64)
if args.chunked_prefill_size is None:
args.chunked_prefill_size = 4 * 1024
if decode.max_bs is None:
if args.tp_size < 4:
decode.max_bs = 16
else:
decode.max_bs = 64
elif npu_mem <= 64 * 1024:
# Ascend 910B1,910B2,910B2C,910B3,910_9391,910_9392,910_9381,910_9382,910_9372,910_9362
# (chunked_prefill_size 8k, max_bs 64 if tp < 4 else 256)
if args.chunked_prefill_size is None:
args.chunked_prefill_size = 8 * 1024
if decode.max_bs is None:
if args.tp_size < 4:
decode.max_bs = 64
else:
decode.max_bs = 256
# NPU does not support CustomAllReduce
args.disable_custom_all_reduce = True
# handles hierarchical cache configs
if args.enable_hierarchical_cache:
args.hicache_io_backend = "kernel_ascend"
if args.use_mla_backend():
args.hicache_mem_layout = "page_first_kv_split"
else:
args.hicache_mem_layout = "page_first_direct"
@_call_once
def init_npu_backend():
"""
Initialize NPU backend. This function should be called only once.
"""
assert _is_npu, "NPU backend initialization called on non-NPU device."
try:
import custom_ops # noqa: F401
import sgl_kernel_npu # noqa: F401
except ImportError as e:
logger.warning("NPU custom kernel packages unavailable: %s", e)
import torch_npu
from torch_npu.contrib import transfer_to_npu # noqa: F401
# Re-mock torch.cuda.is_available cuz transfer_to_npu mocks it True
torch.cuda.is_available = lambda: False
torch_npu.npu.config.allow_internal_format = True
torch_npu.npu.set_compile_mode(jit_compile=False)
def _is_nz_aligned(tensor: torch.Tensor) -> bool:
"""Check whether the last two dims satisfy FRACTAL_NZ alignment rules.
Ascend FRACTAL_NZ requires:
BF16 / FP16 : both dims divisible by 16
INT8 : k % 16 == 0 and n % 32 == 0
INT4 : k % 16 == 0 and n % 64 == 0
FP4 : both dims divisible by 64
"""
if tensor.dim() < 2:
return False
k, n = tensor.shape[-2], tensor.shape[-1]
if tensor.dtype in (torch.bfloat16, torch.float16):
return k % 16 == 0 and n % 16 == 0
if tensor.dtype == torch.int8:
return k % 16 == 0 and n % 32 == 0
if tensor.dtype in (torch.uint8, torch.int32):
# INT4 is typically packed into uint8/int32; be conservative
return k % 16 == 0 and n % 64 == 0
return True
def npu_format_cast(
tensor: torch.Tensor,
acl_format: NPUACLFormat = NPUACLFormat.ACL_FORMAT_FRACTAL_NZ,
*,
customize_dtype=None,
input_dtype=None,
) -> torch.Tensor:
"""
Cast a tensor to a specific NPU ACL format.
Args:
tensor (torch.Tensor): The input tensor.
acl_format (NPUACLFormat): The target NPU ACL format.
customize_dtype / input_dtype: packed-FP4 unpack kwargs (e.g.
``customize_dtype=torch.float8_e4m3fn``,
``input_dtype=torch.float4_e2m1fn_x2``). When either is set the unpack
kwargs are forwarded to the op and the ``_is_nz_aligned`` ND fallback
is skipped: the FP4 matmul strictly requires FRACTAL_NZ, so a silent
ND fallback would corrupt results.
Returns:
torch.Tensor: The tensor cast to the specified NPU ACL format.
"""
if not _is_npu:
return tensor
if envs.SGLANG_NPU_DISABLE_ACL_FORMAT_WEIGHT.get():
return tensor
if tensor.device == torch.device("cpu"):
logger.warning_once(
"Warning: The conversion from 'ND' to 'NZ' does not work on the CPU. "
"Please disable offloading, otherwise the performance will be "
"significantly reduced. --dit-cpu-offload false"
)
return tensor
# Skip format cast for meta tensors (used in offloader)
if tensor.device.type == "meta":
return tensor
# Packed-FP4 → FRACTAL_NZ: forward the unpack kwargs to the op, and skip the
# _is_nz_aligned ND fallback — the FP4 matmul strictly requires NZ, so a
# silent ND fallback would corrupt results.
if customize_dtype is not None or input_dtype is not None:
return torch.ops.npu.npu_format_cast(
tensor,
int(acl_format),
customize_dtype=customize_dtype,
input_dtype=input_dtype,
)
if acl_format == NPUACLFormat.ACL_FORMAT_FRACTAL_NZ and not _is_nz_aligned(tensor):
k, n = tensor.shape[-2], tensor.shape[-1]
logger.warning_once(
"Skipping FRACTAL_NZ format cast: tensor shape (%d, %d) dtype %s "
"is not aligned to NZ requirements. Falling back to 'ND' format, "
"which may reduce NPU performance.",
k,
n,
tensor.dtype,
)
return tensor
return torch.ops.npu.npu_format_cast(tensor, acl_format.value)
def get_indexer_weight_stream():
global indexer_weight_stream
if indexer_weight_stream is None:
indexer_weight_stream = torch.npu.Stream()
return indexer_weight_stream
def init_zbal(world_size, gpu_id, world_rank, do_check=True):
"""
init zbal, if is mix alloc mode, only register for sma & comm
"""
zbal_mem_size = envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get()
if not zbal_mem_size > 0:
return 1
global gva_is_inited
from zbal import is_mix_alloc, switch_to_allocator, zbal_init
if is_mix_alloc():
switch_to_allocator()
# use lazy init for mix alloc
return 1
else:
if envs.SGLANG_ZBAL_BOOTSTRAP_URL.get():
ret = zbal_init(
world_size,
gpu_id,
world_rank,
zbal_mem_size * (1024**2),
ip_port=envs.SGLANG_ZBAL_BOOTSTRAP_URL.get(),
)
else:
ret = zbal_init(world_size, gpu_id, world_rank, zbal_mem_size * (1024**2))
gva_is_inited = True
if do_check and not ret:
logger.error("[ZBAL] zbal init failed!")
sys.exit(-1)
return ret
def lazy_init_zbal_gva_mem(
device, gpu_id, world_rank, world_size, cpu_group=None, do_check=True
):
"""
lazy init zbal gva mem, keep weights and kv remains alloc by dma vmm to avoid memory fragment
"""
from zbal import is_mix_alloc, zbal_init
if not is_mix_alloc():
logger.info(
"lazy init is supported only in mix alloc mode, this action will be passed"
)
return 1
global gva_is_inited
from sglang.srt.utils.common import get_available_gpu_memory
# TODO need to use allgather if you want use total_memory stats from mem_get_info as unbalance os
total_memory = 61.2 # 2.5GB for other (workspace & os) outside torch
free_gpu_memory = get_available_gpu_memory(
device,
gpu_id,
distributed=world_size > 1,
cpu_group=cpu_group,
empty_cache=True,
)
used_memory = total_memory - free_gpu_memory
used_memory_in_mb = int(used_memory * 1024)
gva_in_mb = envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() - used_memory_in_mb
gva_in_mb = gva_in_mb - gva_in_mb % 128 # align to 128MB
print(f"[ZBAL] rank {world_rank} allocated {gva_in_mb} MB gva space.")
assert not gva_is_inited, "zbal gva should be inited only once"
# zbal_set_logger_level(0)
if envs.SGLANG_ZBAL_BOOTSTRAP_URL.get():
res = zbal_init(
world_size,
gpu_id,
world_rank,
gva_in_mb * (1024**2),
ip_port=envs.SGLANG_ZBAL_BOOTSTRAP_URL.get(),
)
else:
res = zbal_init(world_size, gpu_id, world_rank, gva_in_mb * (1024**2))
gva_is_inited = True
if do_check and not res:
logger.error("[ZBAL] zbal lazy init failed!")
sys.exit(-1)
return res
share_stream = None
routed_stream = None
def get_share_stream():
global share_stream
return share_stream
def set_share_stream(stream):
global share_stream
share_stream = stream
# TODO LKL: set stream limit has impact on precision
# torch.npu.set_stream_limit(share_stream, 8, 16)
def get_routed_stream():
global routed_stream
return routed_stream
def set_routed_stream(stream):
global routed_stream
routed_stream = stream
# TODO LKL: set stream limit has impact on precision
# torch.npu.set_stream_limit(routed_stream, 16, 32)
def wait_share_stream():
stream = get_share_stream()
if stream is not None:
cur_stream = torch.get_device_module().current_stream()
cur_stream.wait_stream(stream)
def wait_routed_stream():
stream = get_routed_stream()
if stream is not None:
cur_stream = torch.get_device_module().current_stream()
cur_stream.wait_stream(stream)
def process_shared_expert(hidden_states, forward_func):
stream = get_share_stream()
if stream is None:
stream = torch.get_device_module().Stream()
set_share_stream(stream)
stream.wait_stream(torch.get_device_module().current_stream())
with torch.get_device_module().stream(stream):
shared_output = forward_func(hidden_states)
return shared_output
def process_routed_expert(hidden_states, topk_output, forward_func):
stream = get_routed_stream()
if stream is None:
stream = torch.get_device_module().Stream()
set_routed_stream(stream)
stream.wait_stream(torch.get_device_module().current_stream())
with torch.get_device_module().stream(stream):
shared_output = forward_func(hidden_states, topk_output)
return shared_output