Support symmetric memory pre-allocation to avoid fragmentation (#17089)

This commit is contained in:
Nicolas Castet
2026-01-23 03:57:04 -06:00
committed by GitHub
parent b23470e95a
commit 48e9daadff
7 changed files with 100 additions and 1 deletions

View File

@@ -453,6 +453,9 @@ class Envs:
# TokenizerManager
SGLANG_REQUEST_STATE_WAIT_TIMEOUT = EnvInt(4)
# Symmetric Memory
SGLANG_SYMM_MEM_PREALLOC_GB_SIZE = EnvInt(-1)
# Aiter
SGLANG_USE_AITER_FP8_PER_TOKEN = EnvBool(False)
# fmt: on

View File

@@ -551,6 +551,7 @@ class Scheduler(
self.max_req_input_len,
self.random_seed,
self.device,
self.forward_stream,
_,
_,
_,
@@ -971,7 +972,6 @@ class Scheduler(
if self.device == "cpu":
self.default_stream.synchronize = lambda: None # No-op for CPU
self.forward_stream: CudaStream = self.device_module.Stream()
self.forward_stream_ctx: CudaStreamContext = self.device_module.stream(
self.forward_stream
)

View File

@@ -400,6 +400,7 @@ class TpModelWorker(BaseTpWorker):
self.max_req_input_len,
self.random_seed,
self.device,
self.model_runner.forward_stream,
self.model_runner.req_to_token_pool.size,
self.model_runner.req_to_token_pool.max_context_len,
self.model_runner.token_to_kv_pool.size,

View File

@@ -58,6 +58,9 @@ from sglang.srt.distributed import (
set_mscclpp_all_reduce,
set_torch_symm_mem_all_reduce,
)
from sglang.srt.distributed.device_communicators.pynccl_allocator import (
use_symmetric_memory,
)
from sglang.srt.distributed.parallel_state import monkey_patch_vllm_parallel_state
from sglang.srt.elastic_ep.elastic_ep import ElasticEPStateManager
from sglang.srt.environ import envs
@@ -365,6 +368,9 @@ class ModelRunner(ModelRunnerKVCacheMixin):
# Get memory before model loading
min_per_gpu_memory = self.init_torch_distributed()
# Init forward stream for overlap schedule
self.forward_stream = torch.get_device_module(self.device).Stream()
# CPU offload
set_offloader(create_offloader_from_server_args(server_args, dp_rank=dp_rank))
@@ -593,6 +599,8 @@ class ModelRunner(ModelRunnerKVCacheMixin):
# Initialize piecewise CUDA graph
self.init_piecewise_cuda_graphs()
self.prealloc_symmetric_memory_pool()
def init_routed_experts_capturer(self):
if not self.server_args.disable_shared_experts_fusion and hasattr(
self.model, "num_fused_shared_experts"
@@ -2483,6 +2491,27 @@ class ModelRunner(ModelRunnerKVCacheMixin):
logger.error(f"IPC weight update failed: {e}")
return False, str(e)
def prealloc_symmetric_memory_pool(self):
# PyTorch mempools never de-fragment memory in OOM scenarios, so we need to pre-allocate a large chunk of memory to limit fragmentation.
if (
self.is_draft_worker
or not self.server_args.enable_symm_mem
or envs.SGLANG_SYMM_MEM_PREALLOC_GB_SIZE.get() <= 0
):
return
# Memory allocation is tied to a cuda stream, use the forward stream
with torch.get_device_module(self.device).stream(self.forward_stream):
logger.info(
f"Pre-allocating symmetric memory pool with {envs.SGLANG_SYMM_MEM_PREALLOC_GB_SIZE.get()} GiB"
)
with use_symmetric_memory(get_tp_group()):
torch.empty(
(envs.SGLANG_SYMM_MEM_PREALLOC_GB_SIZE.get() * 1024 * 1024 * 1024,),
dtype=torch.uint8,
device=self.device,
)
def _model_load_weights_direct(model, named_tensors: List[Tuple[str, torch.Tensor]]):
params_dict = dict(model.named_parameters())

View File

@@ -1036,6 +1036,17 @@ class ServerArgs:
if model_config.is_multimodal:
self.adjust_mem_fraction_for_vlm(model_config)
# If symm mem is enabled and prealloc size is not set, set it to 4GB
if (
self.enable_symm_mem
and not envs.SGLANG_SYMM_MEM_PREALLOC_GB_SIZE.is_set()
):
envs.SGLANG_SYMM_MEM_PREALLOC_GB_SIZE.set(4)
logger.warning(
"Symmetric memory is enabled, setting symmetric memory prealloc size to 4GB as default."
"Use environment variable SGLANG_SYMM_MEM_PREALLOC_GB_SIZE to change the prealloc size."
)
def _generate_cuda_graph_batch_sizes(self):
"""
Generate the list of batch sizes for CUDA graph capture based on cuda_graph_max_bs.