[NPU] add zbal support for npu (#24575)
This commit is contained in:
@@ -1598,7 +1598,7 @@ _DEVICE_TO_DISTRIBUTED_BACKEND = {
|
|||||||
"xpu": "xccl",
|
"xpu": "xccl",
|
||||||
"hpu": "hccl",
|
"hpu": "hccl",
|
||||||
"cpu": "gloo",
|
"cpu": "gloo",
|
||||||
"npu": "hccl",
|
"npu": "hccl" if not envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() > 0 else "zbal",
|
||||||
"musa": "mccl",
|
"musa": "mccl",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -558,6 +558,10 @@ class Envs:
|
|||||||
# TokenizerManager
|
# TokenizerManager
|
||||||
SGLANG_REQUEST_STATE_WAIT_TIMEOUT = EnvInt(4)
|
SGLANG_REQUEST_STATE_WAIT_TIMEOUT = EnvInt(4)
|
||||||
|
|
||||||
|
# ZBAL, zero buffer accelerate library, currently worked only in npu
|
||||||
|
SGLANG_ZBAL_LOCAL_MEM_SIZE = EnvInt(0)
|
||||||
|
SGLANG_ZBAL_BOOTSTRAP_URL = EnvStr("")
|
||||||
|
|
||||||
SGLANG_DEFAULT_THINKING = EnvBool(False)
|
SGLANG_DEFAULT_THINKING = EnvBool(False)
|
||||||
|
|
||||||
# ====================================================================
|
# ====================================================================
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ if TYPE_CHECKING:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
_is_npu = is_npu()
|
_is_npu = is_npu()
|
||||||
indexer_weight_stream = None
|
indexer_weight_stream = None
|
||||||
|
gva_is_inited = False
|
||||||
|
|
||||||
|
|
||||||
class NPUACLFormat(IntEnum):
|
class NPUACLFormat(IntEnum):
|
||||||
@@ -184,6 +186,96 @@ def get_indexer_weight_stream():
|
|||||||
return indexer_weight_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(f"[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(f"[ZBAL] zbal lazy init failed!")
|
||||||
|
sys.exit(-1)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
share_stream = None
|
share_stream = None
|
||||||
routed_stream = None
|
routed_stream = None
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,11 @@ if TYPE_CHECKING:
|
|||||||
from sglang.srt.batch_overlap.single_batch_overlap import CombineOverlapArgs
|
from sglang.srt.batch_overlap.single_batch_overlap import CombineOverlapArgs
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from deep_ep import Buffer, Config
|
if _is_npu and envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() > 0:
|
||||||
|
from zbal.zbal.deepep_adaptor import Config
|
||||||
|
from zbal.zbal_buffer import Buffer
|
||||||
|
else:
|
||||||
|
from deep_ep import Buffer, Config
|
||||||
|
|
||||||
if not _is_npu:
|
if not _is_npu:
|
||||||
from sglang.srt.layers.quantization.fp8_kernel import (
|
from sglang.srt.layers.quantization.fp8_kernel import (
|
||||||
|
|||||||
@@ -417,6 +417,9 @@ class Scheduler(
|
|||||||
# Init inter-process communication
|
# Init inter-process communication
|
||||||
self.init_ipc_channels(port_args)
|
self.init_ipc_channels(port_args)
|
||||||
|
|
||||||
|
# Init ZBAL, switch allocator should before any torch alloc action
|
||||||
|
self.init_zbal_on_npu()
|
||||||
|
|
||||||
# Init PD-multiplexing context
|
# Init PD-multiplexing context
|
||||||
if self.enable_pdmux:
|
if self.enable_pdmux:
|
||||||
self.init_pdmux()
|
self.init_pdmux()
|
||||||
@@ -496,6 +499,16 @@ class Scheduler(
|
|||||||
|
|
||||||
self.is_initializing = False
|
self.is_initializing = False
|
||||||
|
|
||||||
|
def init_zbal_on_npu(self):
|
||||||
|
if _is_npu:
|
||||||
|
from sglang.srt.hardware_backend.npu.utils import init_zbal
|
||||||
|
|
||||||
|
if self.pp_size > 1:
|
||||||
|
logger.error(f"only zbal mix mode support pp_size > 1!")
|
||||||
|
init_zbal(
|
||||||
|
self.tp_size, self.gpu_id, self.tp_rank
|
||||||
|
) # only switch allocator if is mix mode
|
||||||
|
|
||||||
def init_model_config(self):
|
def init_model_config(self):
|
||||||
self.model_config = ModelConfig.from_server_args(self.server_args)
|
self.model_config = ModelConfig.from_server_args(self.server_args)
|
||||||
if _is_npu:
|
if _is_npu:
|
||||||
|
|||||||
@@ -785,9 +785,23 @@ class ModelRunner(ModelRunnerKVCacheMixin):
|
|||||||
)
|
)
|
||||||
self._pre_initialize_flashinfer_allreduce_workspace()
|
self._pre_initialize_flashinfer_allreduce_workspace()
|
||||||
self.init_device_graphs()
|
self.init_device_graphs()
|
||||||
elif self.device in ["npu", "cpu"]:
|
elif self.device == "cpu":
|
||||||
self.init_attention_backend()
|
self.init_attention_backend()
|
||||||
self.init_device_graphs()
|
self.init_device_graphs()
|
||||||
|
elif self.device == "npu":
|
||||||
|
self.init_attention_backend()
|
||||||
|
# lazy init for zbal with mix mode(before graph capture when enable_cuda_graph)
|
||||||
|
if envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() > 0 and not self.is_draft_worker:
|
||||||
|
from sglang.srt.hardware_backend.npu.utils import lazy_init_zbal_gva_mem
|
||||||
|
|
||||||
|
lazy_init_zbal_gva_mem(
|
||||||
|
self.device,
|
||||||
|
self.gpu_id,
|
||||||
|
get_world_group().rank_in_group,
|
||||||
|
get_world_group().world_size,
|
||||||
|
get_world_group().cpu_group,
|
||||||
|
)
|
||||||
|
self.init_device_graphs()
|
||||||
elif current_platform.is_out_of_tree():
|
elif current_platform.is_out_of_tree():
|
||||||
self.init_attention_backend()
|
self.init_attention_backend()
|
||||||
if current_platform.support_cuda_graph():
|
if current_platform.support_cuda_graph():
|
||||||
|
|||||||
@@ -587,7 +587,16 @@ def get_available_gpu_memory(
|
|||||||
)
|
)
|
||||||
if empty_cache:
|
if empty_cache:
|
||||||
empty_device_cache(torch.npu)
|
empty_device_cache(torch.npu)
|
||||||
free_gpu_memory, total_gpu_memory = torch.npu.mem_get_info()
|
if envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() > 0:
|
||||||
|
import zbal
|
||||||
|
|
||||||
|
if not zbal.is_mix_alloc():
|
||||||
|
free_gpu_memory, total_gpu_memory = zbal.zbal_module.mem_get_info()
|
||||||
|
else:
|
||||||
|
# mix mode fall back into npu mem info since gva may not inited yet
|
||||||
|
free_gpu_memory, total_gpu_memory = torch.npu.mem_get_info()
|
||||||
|
else:
|
||||||
|
free_gpu_memory, total_gpu_memory = torch.npu.mem_get_info()
|
||||||
elif device == "musa":
|
elif device == "musa":
|
||||||
num_gpus = torch.musa.device_count()
|
num_gpus = torch.musa.device_count()
|
||||||
assert gpu_id < num_gpus
|
assert gpu_id < num_gpus
|
||||||
@@ -1689,7 +1698,10 @@ def get_npu_memory_capacity():
|
|||||||
try:
|
try:
|
||||||
import torch_npu # noqa: F401
|
import torch_npu # noqa: F401
|
||||||
|
|
||||||
return torch.npu.mem_get_info()[1] // 1024 // 1024 # unit: MB
|
if envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() > 0:
|
||||||
|
return envs.SGLANG_ZBAL_LOCAL_MEM_SIZE.get() # unit: MB
|
||||||
|
else:
|
||||||
|
return torch.npu.mem_get_info()[1] // 1024 // 1024 # unit: MB
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError("torch_npu is required when run on npu device.")
|
raise ImportError("torch_npu is required when run on npu device.")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user