From 2f4a6addf3101342498b4528289c6fd053622530 Mon Sep 17 00:00:00 2001 From: Yibo Cai Date: Sun, 11 Jan 2026 20:27:19 +0800 Subject: [PATCH] [cpu/arm64] support run sglang on arm64 cpu (#14867) --- python/sglang/srt/layers/activation.py | 12 ------------ python/sglang/srt/layers/layernorm.py | 9 --------- python/sglang/srt/layers/rotary_embedding.py | 2 +- python/sglang/srt/model_executor/model_runner.py | 6 ++++-- python/sglang/srt/utils/common.py | 14 ++++++++++++-- 5 files changed, 17 insertions(+), 26 deletions(-) diff --git a/python/sglang/srt/layers/activation.py b/python/sglang/srt/layers/activation.py index 8fde6b80f..4b6f0f18d 100644 --- a/python/sglang/srt/layers/activation.py +++ b/python/sglang/srt/layers/activation.py @@ -378,15 +378,3 @@ def get_cross_encoder_activation_function(config: PretrainedConfig): else: # adapt bge-reranker return nn.Identity() - - -if not ( - _is_cuda or _is_npu or (_is_cpu and _is_cpu_amx_available) or _is_hip or _is_xpu -): - logger.info( - "sgl-kernel is not available on Non-NV, Non-AMD platforms or Non-AMX CPUs. Fallback to other kernel libraries." - ) - from vllm.model_executor.layers.activation import ( # noqa: F401 - GeluAndMul, - SiluAndMul, - ) diff --git a/python/sglang/srt/layers/layernorm.py b/python/sglang/srt/layers/layernorm.py index 7bef9d2ab..9f4c77a76 100644 --- a/python/sglang/srt/layers/layernorm.py +++ b/python/sglang/srt/layers/layernorm.py @@ -502,12 +502,3 @@ class Gemma3RMSNorm(MultiPlatformOp): def extra_repr(self): return f"{tuple(self.weight.shape)}, eps={self.eps}" - - -if not ( - _is_cuda or _is_hip or _is_npu or (_is_cpu and _is_cpu_amx_available) or _is_xpu -): - logger.info( - "sgl-kernel layernorm implementation is not available on current platform. Fallback to other kernel libraries." - ) - from vllm.model_executor.layers.layernorm import GemmaRMSNorm, RMSNorm # noqa: F401 diff --git a/python/sglang/srt/layers/rotary_embedding.py b/python/sglang/srt/layers/rotary_embedding.py index faa35d3c0..8fbdf3160 100644 --- a/python/sglang/srt/layers/rotary_embedding.py +++ b/python/sglang/srt/layers/rotary_embedding.py @@ -116,7 +116,7 @@ class RotaryEmbedding(MultiPlatformOp): if ( (not (_is_cuda or _is_npu) or self.head_size not in [64, 128, 256, 512]) - and not (_is_cpu and _is_cpu_amx_available) + and not (_is_cpu) and not (_is_xpu) ): if _is_cuda or _is_hip: diff --git a/python/sglang/srt/model_executor/model_runner.py b/python/sglang/srt/model_executor/model_runner.py index f3ce8cf4a..07e0cf7f5 100644 --- a/python/sglang/srt/model_executor/model_runner.py +++ b/python/sglang/srt/model_executor/model_runner.py @@ -148,6 +148,7 @@ from sglang.srt.utils import ( get_local_ip_auto, init_custom_process_group, is_hip, + is_host_cpu_arm64, is_npu, log_info_on_rank0, monkey_patch_p2p_access_check, @@ -178,6 +179,7 @@ from sglang.srt.weight_sync.tensor_bucket import ( _is_hip = is_hip() _is_npu = is_npu() _is_cpu_amx_available = cpu_has_amx_support() +_is_cpu_arm64 = is_host_cpu_arm64() if _is_npu: from sglang.srt.hardware_backend.npu.utils import init_npu_backend @@ -729,7 +731,7 @@ class ModelRunner(ModelRunnerKVCacheMixin): if not self.is_draft_worker: if self.device == "cpu": - if _is_cpu_amx_available: + if _is_cpu_amx_available or _is_cpu_arm64: # Bind OpenMP threads to CPU cores torch.ops.sgl_kernel.init_cpu_threads_env(self.local_omp_cpuid) @@ -743,7 +745,7 @@ class ModelRunner(ModelRunnerKVCacheMixin): else: logger.warning( - "init_cpu_threads_env and shared memory based AllReduce is disabled since intel amx backend is not available" + "init_cpu_threads_env and shared memory based AllReduce is disabled, only intel amx backend and arm64 are supported" ) # Only initialize the distributed environment on the target model worker. diff --git a/python/sglang/srt/utils/common.py b/python/sglang/srt/utils/common.py index 4b2110ed8..ad8217116 100644 --- a/python/sglang/srt/utils/common.py +++ b/python/sglang/srt/utils/common.py @@ -165,9 +165,19 @@ def is_host_cpu_x86() -> bool: ) +def is_host_cpu_arm64() -> bool: + machine = platform.machine().lower() + return ( + machine in ("aarch64", "arm64") + and hasattr(torch, "cpu") + and torch.cpu.is_available() + ) + + @lru_cache(maxsize=1) def is_cpu() -> bool: - return os.getenv("SGLANG_USE_CPU_ENGINE", "0") == "1" and is_host_cpu_x86() + is_host_cpu_supported = is_host_cpu_x86() or is_host_cpu_arm64() + return os.getenv("SGLANG_USE_CPU_ENGINE", "0") == "1" and is_host_cpu_supported def is_float4_e2m1fn_x2(dtype) -> bool: @@ -3166,7 +3176,7 @@ def get_cpu_ids_by_node(): def is_shm_available(dtype, world_size, local_size): return ( - cpu_has_amx_support() + (cpu_has_amx_support() or is_host_cpu_arm64()) and dtype in [torch.bfloat16, torch.float16, torch.float] and world_size >= 1 and world_size == local_size