sgl-project--sglang
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
478 行
18 KiB
Python
478 行
18 KiB
Python
"""Test memory release and resume operations for SGLang engine in hybrid RL training.
|
|
|
|
This test suite evaluates the SGLang engine's memory management capabilities, focusing
|
|
on releasing and resuming memory occupation for KV cache and model weights. It simulates
|
|
an RL workflow where the SGLang engine acts as a rollout engine for experience collection.
|
|
The process involves initializing the engine, sending a small number of requests to simulate
|
|
rollout, releasing memory to mimic offloading during RL training, resuming memory occupation,
|
|
updating weights with a trained HuggingFace model, and verifying the updated weights.
|
|
|
|
Detailed in our proposal (https://github.com/sgl-project/sglang/pull/7099), two test cases
|
|
are included:
|
|
|
|
1. Basic Release and Resume: Uses a lower mem_fraction_static (0.6) to control memory allocation
|
|
and avoid OOM errors carefully. This test simulates a scenario without multi-stage memory management,
|
|
ensuring the engine can release and resume memory occupation while maintaining functionality after
|
|
weight updates.
|
|
|
|
2. Multi-Stage Release and Resume: Employs a higher mem_fraction_static (0.85) to simulate higher
|
|
memory pressure, leveraging multi-stage memory management. It sequentially releases and resumes
|
|
KV cache and model weights, verifying memory deallocation and reallocation at each stage, and
|
|
ensuring correct weight updates and text generation.
|
|
|
|
3. Tensor Parallel Tests: Tests memory release and resume operations with different tensor parallel
|
|
configurations (tp=1, tp=2) to ensure proper memory management in distributed settings. For different
|
|
data parallel size, we test it in verl.
|
|
|
|
NOTE: This test is temporarily disabled.
|
|
"""
|
|
|
|
import os
|
|
import time
|
|
import unittest
|
|
|
|
from transformers import AutoModelForCausalLM
|
|
|
|
import sglang as sgl
|
|
from sglang.srt.constants import (
|
|
GPU_MEMORY_TYPE_CUDA_GRAPH,
|
|
GPU_MEMORY_TYPE_KV_CACHE,
|
|
GPU_MEMORY_TYPE_WEIGHTS,
|
|
)
|
|
from sglang.srt.utils import get_device
|
|
from sglang.test.ci.ci_register import register_cuda_ci
|
|
from sglang.test.test_utils import (
|
|
DEFAULT_HYBRID_MAMBA_MODEL_NAME_FOR_TEST,
|
|
DEFAULT_SMALL_MODEL_NAME_FOR_TEST,
|
|
DEFAULT_SMALL_MODEL_NAME_FOR_TEST_BASE,
|
|
DEFAULT_SMALL_MOE_MODEL_NAME_FOR_TEST_BASE,
|
|
DEFAULT_SMALL_MOE_MODEL_NAME_FOR_TEST_CHAT,
|
|
CustomTestCase,
|
|
empty_gpu_cache,
|
|
get_gpu_count,
|
|
get_gpu_memory_gb,
|
|
)
|
|
|
|
register_cuda_ci(
|
|
est_time=200,
|
|
stage="base-c",
|
|
runner_config="4-gpu-h100",
|
|
disabled="Temporarily disabled - needs investigation",
|
|
)
|
|
|
|
# (temporarily) set to true to observe memory usage in nvidia-smi more clearly
|
|
_DEBUG_EXTRA = False
|
|
|
|
|
|
class TestReleaseMemoryOccupation(CustomTestCase):
|
|
def _setup_engine(
|
|
self,
|
|
model_name,
|
|
mem_fraction_static=0.8,
|
|
tp_size=1,
|
|
ep_size=1,
|
|
enable_weights_cpu_backup=False,
|
|
):
|
|
"""Common setup for engine and HF model."""
|
|
|
|
os.environ["SGLANG_MEMORY_SAVER_CUDA_GRAPH"] = "1"
|
|
engine = sgl.Engine(
|
|
model_path=model_name,
|
|
random_seed=42,
|
|
enable_memory_saver=True,
|
|
mem_fraction_static=mem_fraction_static,
|
|
tp_size=tp_size,
|
|
ep_size=ep_size,
|
|
enable_weights_cpu_backup=enable_weights_cpu_backup,
|
|
# disable_cuda_graph=True, # for debugging only
|
|
)
|
|
|
|
return engine
|
|
|
|
def _common_test_params(self):
|
|
"""Common test parameters."""
|
|
return {
|
|
"prompt": "Today is a sunny day and I like",
|
|
"sampling_params": {"temperature": 0, "max_new_tokens": 8},
|
|
"expect_output_before_update_weights": " to spend it outdoors. I decided to",
|
|
"expect_output_after_update_weights": " to go for a walk. I like",
|
|
"prompt_moe": "The weather is nice today, and I want to",
|
|
"sampling_params_moe": {"temperature": 0, "max_new_tokens": 16},
|
|
"expect_output_before_update_weights_moe": " go to the park. I have a picnic basket, a book, and a",
|
|
"expect_output_after_update_weights_moe": " go to the park. I have a lot of things to do, but I",
|
|
"prompt_hybrid_mamba": "The weather is nice today, and I want to",
|
|
"sampling_params_hybrid_mamba": {"temperature": 0, "max_new_tokens": 16},
|
|
"expect_output_before_update_weights_hybrid_mamba": " go out for a walk. But I don't know what to wear. Can",
|
|
"expect_output_after_update_weights_hybrid_mamba": " go out for a walk. But I don't know what to wear. Can",
|
|
}
|
|
|
|
def _test_initial_generation(
|
|
self, engine, prompt, sampling_params, expect_output_before_update_weights
|
|
):
|
|
"""Test initial generation and memory allocation."""
|
|
print("generate (#1)")
|
|
outputs = engine.generate(prompt, sampling_params)["text"]
|
|
self.assertEqual(outputs, expect_output_before_update_weights)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
def test_release_and_resume_occupation(self):
|
|
# Without multi-stage release and resume, we need to carefully control the memory fraction to avoid OOM
|
|
model_name = DEFAULT_SMALL_MODEL_NAME_FOR_TEST
|
|
assert get_gpu_count() >= 2, "Need at least 2 GPUs for tensor parallel tests"
|
|
|
|
for tp_size in [1, 2]:
|
|
|
|
print(f"Testing tp_size={tp_size} for test_release_and_resume_occupation")
|
|
engine = self._setup_engine(
|
|
model_name=model_name, mem_fraction_static=0.6, tp_size=tp_size
|
|
)
|
|
params = self._common_test_params()
|
|
|
|
self._test_initial_generation(
|
|
engine,
|
|
params["prompt"],
|
|
params["sampling_params"],
|
|
params["expect_output_before_update_weights"],
|
|
)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_release = get_gpu_memory_gb()
|
|
engine.release_memory_occupation()
|
|
gpu_memory_usage_after_release = get_gpu_memory_gb()
|
|
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release,
|
|
gpu_memory_usage_before_release,
|
|
)
|
|
|
|
print(
|
|
f"Release took {time.perf_counter() - t:.2f}s, memory: {gpu_memory_usage_before_release:.1f} GB → {gpu_memory_usage_after_release:.1f} GB"
|
|
)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
t = time.perf_counter()
|
|
engine.resume_memory_occupation()
|
|
print(
|
|
f"Resume took {time.perf_counter() - t:.2f}s, memory: {get_gpu_memory_gb():.1f} GB"
|
|
)
|
|
|
|
hf_model_new = AutoModelForCausalLM.from_pretrained(
|
|
DEFAULT_SMALL_MODEL_NAME_FOR_TEST_BASE,
|
|
torch_dtype="bfloat16",
|
|
device_map=get_device(),
|
|
)
|
|
engine.update_weights_from_tensor(list(hf_model_new.named_parameters()))
|
|
|
|
# destroy the hf model
|
|
del hf_model_new
|
|
empty_gpu_cache()
|
|
|
|
print("generate (#2)")
|
|
outputs = engine.generate(params["prompt"], params["sampling_params"])[
|
|
"text"
|
|
]
|
|
self.assertEqual(outputs, params["expect_output_after_update_weights"])
|
|
engine.shutdown()
|
|
|
|
def test_release_and_resume_occupation_with_weights_cpu_backup(self):
|
|
# Test release and resume occupation with weights CPU backup
|
|
model_name = DEFAULT_SMALL_MODEL_NAME_FOR_TEST
|
|
|
|
print("Testing test_release_and_resume_occupation_with_weights_cpu_backup")
|
|
engine = self._setup_engine(
|
|
model_name=model_name,
|
|
mem_fraction_static=0.6,
|
|
enable_weights_cpu_backup=True,
|
|
)
|
|
params = self._common_test_params()
|
|
|
|
self._test_initial_generation(
|
|
engine,
|
|
params["prompt"],
|
|
params["sampling_params"],
|
|
params["expect_output_before_update_weights"],
|
|
)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_release = get_gpu_memory_gb()
|
|
engine.release_memory_occupation()
|
|
gpu_memory_usage_after_release = get_gpu_memory_gb()
|
|
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release,
|
|
gpu_memory_usage_before_release,
|
|
)
|
|
|
|
print(
|
|
f"Release took {time.perf_counter() - t:.2f}s, memory: {gpu_memory_usage_before_release:.1f} GB → {gpu_memory_usage_after_release:.1f} GB"
|
|
)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
t = time.perf_counter()
|
|
engine.resume_memory_occupation()
|
|
print(
|
|
f"Resume took {time.perf_counter() - t:.2f}s, memory: {get_gpu_memory_gb():.1f} GB"
|
|
)
|
|
|
|
print("generate post resume")
|
|
outputs = engine.generate(params["prompt"], params["sampling_params"])["text"]
|
|
self.assertEqual(outputs, params["expect_output_before_update_weights"])
|
|
engine.shutdown()
|
|
|
|
def test_multi_stage_release_and_resume(self):
|
|
# With multi-stage release and resume, we can set the memory fraction to 0.85 without concern of OOM
|
|
model_name = DEFAULT_SMALL_MODEL_NAME_FOR_TEST
|
|
|
|
for tp_size in [1, 2]:
|
|
if tp_size == 2 and get_gpu_count() < 2:
|
|
continue
|
|
|
|
print(f"Testing tp_size={tp_size} for test_multi_stage_release_and_resume")
|
|
os.environ["SGLANG_MEMORY_SAVER_CUDA_GRAPH"] = "1"
|
|
engine = sgl.Engine(
|
|
model_path=model_name,
|
|
random_seed=42,
|
|
enable_memory_saver=True,
|
|
mem_fraction_static=0.85, # Higher memory pressure
|
|
tp_size=tp_size,
|
|
)
|
|
params = self._common_test_params()
|
|
|
|
self._test_initial_generation(
|
|
engine,
|
|
params["prompt"],
|
|
params["sampling_params"],
|
|
params["expect_output_before_update_weights"],
|
|
)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_release = get_gpu_memory_gb()
|
|
engine.release_memory_occupation(tags=[GPU_MEMORY_TYPE_KV_CACHE])
|
|
|
|
gpu_memory_usage_after_release_kv_cache = get_gpu_memory_gb()
|
|
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release_kv_cache,
|
|
gpu_memory_usage_before_release,
|
|
)
|
|
|
|
engine.release_memory_occupation(tags=[GPU_MEMORY_TYPE_WEIGHTS])
|
|
gpu_memory_usage_after_release_weights = get_gpu_memory_gb()
|
|
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release_weights,
|
|
gpu_memory_usage_after_release_kv_cache,
|
|
)
|
|
|
|
engine.release_memory_occupation(tags=[GPU_MEMORY_TYPE_CUDA_GRAPH])
|
|
gpu_memory_usage_after_release_cuda_graph = get_gpu_memory_gb()
|
|
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release_cuda_graph,
|
|
gpu_memory_usage_after_release_weights,
|
|
)
|
|
|
|
print(f"Release took {time.perf_counter() - t:.2f}s")
|
|
print(
|
|
f"Memory: {gpu_memory_usage_before_release:.1f} → {gpu_memory_usage_after_release_kv_cache:.1f} → {gpu_memory_usage_after_release_weights:.1f} → {gpu_memory_usage_after_release_cuda_graph:.1f} GB"
|
|
)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_resume = get_gpu_memory_gb()
|
|
|
|
# gpu_memory_usage_after_release_weights and gpu_memory_usage_before_resume should be close
|
|
|
|
self.assertAlmostEqual(
|
|
gpu_memory_usage_after_release_weights,
|
|
gpu_memory_usage_before_resume,
|
|
delta=3.0,
|
|
)
|
|
print(f"Resume weights took {time.perf_counter() - t:.2f}s")
|
|
|
|
engine.resume_memory_occupation(tags=[GPU_MEMORY_TYPE_CUDA_GRAPH])
|
|
gpu_memory_usage_after_resume_cuda_graph = get_gpu_memory_gb()
|
|
|
|
self.assertGreater(
|
|
gpu_memory_usage_after_resume_cuda_graph,
|
|
gpu_memory_usage_before_resume,
|
|
)
|
|
|
|
engine.resume_memory_occupation(tags=[GPU_MEMORY_TYPE_WEIGHTS])
|
|
gpu_memory_usage_after_resume_weights = get_gpu_memory_gb()
|
|
|
|
self.assertGreater(
|
|
gpu_memory_usage_after_resume_weights,
|
|
gpu_memory_usage_after_resume_cuda_graph,
|
|
)
|
|
|
|
# Update weights from a trained model to serving engine, and then destroy the trained model
|
|
hf_model_new = AutoModelForCausalLM.from_pretrained(
|
|
DEFAULT_SMALL_MODEL_NAME_FOR_TEST_BASE,
|
|
torch_dtype="bfloat16",
|
|
device_map=get_device(),
|
|
)
|
|
gpu_memory_usage_after_loaded_hf_model = get_gpu_memory_gb()
|
|
engine.update_weights_from_tensor(list(hf_model_new.named_parameters()))
|
|
|
|
# destroy the hf model
|
|
del hf_model_new
|
|
empty_gpu_cache()
|
|
engine.resume_memory_occupation(tags=[GPU_MEMORY_TYPE_KV_CACHE])
|
|
|
|
gpu_memory_usage_after_resume_kv_cache = get_gpu_memory_gb()
|
|
self.assertGreater(
|
|
gpu_memory_usage_after_resume_kv_cache,
|
|
gpu_memory_usage_after_resume_weights,
|
|
)
|
|
|
|
print(f"Resume + update took {time.perf_counter() - t:.2f}s")
|
|
print(
|
|
f"Memory: {gpu_memory_usage_before_resume:.1f} → {gpu_memory_usage_after_resume_cuda_graph:.1f} → {gpu_memory_usage_after_resume_weights:.1f} → {gpu_memory_usage_after_loaded_hf_model:.1f} → {gpu_memory_usage_after_resume_kv_cache:.1f} GB"
|
|
)
|
|
|
|
print("generate (#2)")
|
|
outputs = engine.generate(params["prompt"], params["sampling_params"])[
|
|
"text"
|
|
]
|
|
self.assertEqual(outputs, params["expect_output_after_update_weights"])
|
|
engine.shutdown()
|
|
|
|
def test_moe_model_release_and_resume(self):
|
|
# Test with MoE model
|
|
model_name = DEFAULT_SMALL_MOE_MODEL_NAME_FOR_TEST_CHAT
|
|
|
|
tp_size = ep_size = 2
|
|
|
|
print(
|
|
f"Testing tp_size={tp_size} and ep_size={ep_size} for test_moe_model_release_and_resume"
|
|
)
|
|
engine = sgl.Engine(
|
|
model_path=model_name,
|
|
random_seed=42,
|
|
enable_memory_saver=True,
|
|
mem_fraction_static=0.5,
|
|
tp_size=tp_size,
|
|
ep_size=ep_size,
|
|
)
|
|
params = self._common_test_params()
|
|
|
|
self._test_initial_generation(
|
|
engine,
|
|
params["prompt_moe"],
|
|
params["sampling_params_moe"],
|
|
params["expect_output_before_update_weights_moe"],
|
|
)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_release = get_gpu_memory_gb()
|
|
engine.release_memory_occupation()
|
|
gpu_memory_usage_after_release = get_gpu_memory_gb()
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release,
|
|
gpu_memory_usage_before_release,
|
|
)
|
|
|
|
print(
|
|
f"Release took {time.perf_counter() - t:.2f}s, memory: {gpu_memory_usage_before_release:.1f} GB → {gpu_memory_usage_after_release:.1f} GB"
|
|
)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
t = time.perf_counter()
|
|
engine.resume_memory_occupation()
|
|
print(
|
|
f"Resume took {time.perf_counter() - t:.2f}s, memory: {get_gpu_memory_gb():.1f} GB"
|
|
)
|
|
|
|
hf_model_new = AutoModelForCausalLM.from_pretrained(
|
|
DEFAULT_SMALL_MOE_MODEL_NAME_FOR_TEST_BASE,
|
|
torch_dtype="bfloat16",
|
|
device_map=get_device(),
|
|
)
|
|
engine.update_weights_from_tensor(list(hf_model_new.named_parameters()))
|
|
|
|
# destroy the hf model
|
|
del hf_model_new
|
|
empty_gpu_cache()
|
|
|
|
print("generate (#2)")
|
|
outputs = engine.generate(params["prompt_moe"], params["sampling_params_moe"])[
|
|
"text"
|
|
]
|
|
self.assertEqual(outputs, params["expect_output_after_update_weights_moe"])
|
|
engine.shutdown()
|
|
|
|
def test_hybrid_mamba_model_release_and_resume(self):
|
|
# Test with Hybrid Mamba model
|
|
model_name = DEFAULT_HYBRID_MAMBA_MODEL_NAME_FOR_TEST
|
|
|
|
tp_size = 4
|
|
|
|
print(
|
|
f"Testing tp_size={tp_size} for test_hybrid_mamba_model_release_and_resume"
|
|
)
|
|
engine = sgl.Engine(
|
|
model_path=model_name,
|
|
random_seed=42,
|
|
enable_memory_saver=True,
|
|
tp_size=tp_size,
|
|
)
|
|
params = self._common_test_params()
|
|
|
|
self._test_initial_generation(
|
|
engine,
|
|
params["prompt_hybrid_mamba"],
|
|
params["sampling_params_hybrid_mamba"],
|
|
params["expect_output_before_update_weights_hybrid_mamba"],
|
|
)
|
|
|
|
t = time.perf_counter()
|
|
gpu_memory_usage_before_release = get_gpu_memory_gb()
|
|
engine.release_memory_occupation()
|
|
gpu_memory_usage_after_release = get_gpu_memory_gb()
|
|
self.assertLess(
|
|
gpu_memory_usage_after_release,
|
|
gpu_memory_usage_before_release,
|
|
)
|
|
|
|
print(
|
|
f"Release took {time.perf_counter() - t:.2f}s, memory: {gpu_memory_usage_before_release:.1f} GB → {gpu_memory_usage_after_release:.1f} GB"
|
|
)
|
|
|
|
if _DEBUG_EXTRA:
|
|
time.sleep(3)
|
|
|
|
t = time.perf_counter()
|
|
engine.resume_memory_occupation()
|
|
print(
|
|
f"Resume took {time.perf_counter() - t:.2f}s, memory: {get_gpu_memory_gb():.1f} GB"
|
|
)
|
|
|
|
engine.update_weights_from_disk(model_name)
|
|
|
|
# destroy the hf model
|
|
empty_gpu_cache()
|
|
|
|
print("generate (#2)")
|
|
outputs = engine.generate(
|
|
params["prompt_hybrid_mamba"], params["sampling_params_hybrid_mamba"]
|
|
)["text"]
|
|
self.assertEqual(
|
|
outputs, params["expect_output_after_update_weights_hybrid_mamba"]
|
|
)
|
|
engine.shutdown()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|