[Unified Cache][6/N]: Add UMBP external linker (#37578)
Co-authored-by: Zhangheng <hzh0425@apache.org>
This commit is contained in:
@@ -336,6 +336,57 @@ class TestDefaultRadixCacheFactory(CustomTestCase):
|
||||
ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once()
|
||||
self.assertIs(result, fake_radix.UnifiedRadixCache.return_value)
|
||||
|
||||
def test_unified_radix_cache_with_mori_external_linker(self):
|
||||
from sglang.srt.mem_cache.storage.umbp import umbp_direct_linker
|
||||
|
||||
ctx = _make_ctx(self)
|
||||
object.__setattr__(
|
||||
ctx.server_args, "enable_unified_cache_external_linker", True
|
||||
)
|
||||
object.__setattr__(
|
||||
ctx.server_args, "unified_cache_external_linker_backend", "mori"
|
||||
)
|
||||
self.assertTrue(ctx.server_args.enable_unified_cache_external_linker)
|
||||
self.assertEqual(ctx.server_args.unified_cache_external_linker_backend, "mori")
|
||||
fake_components = MagicMock()
|
||||
fake_components.ComponentType.FULL = "full"
|
||||
fake_radix = MagicMock()
|
||||
cache = fake_radix.UnifiedRadixCache.return_value
|
||||
cache.components = ("full",)
|
||||
counter = MagicMock(name="layer_done_counter")
|
||||
cache.linker.layer_done_counter = counter
|
||||
linker = MagicMock(name="linker")
|
||||
|
||||
with (
|
||||
patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"sglang.srt.mem_cache.unified_cache.components": fake_components,
|
||||
"sglang.srt.mem_cache.unified_radix_cache": fake_radix,
|
||||
},
|
||||
),
|
||||
patch.object(
|
||||
umbp_direct_linker,
|
||||
"UMBPDirectLinker",
|
||||
return_value=linker,
|
||||
) as linker_cls,
|
||||
):
|
||||
result = default_radix_cache_factory(ctx)
|
||||
|
||||
linker_cls.assert_called_once_with(
|
||||
ctx.server_args,
|
||||
ctx.params,
|
||||
components={"full"},
|
||||
)
|
||||
cache.init_cache_linker.assert_called_once_with(linker)
|
||||
ctx.params.token_to_kv_pool_allocator.get_kvcache.return_value.register_layer_transfer_counter.assert_called_once_with(
|
||||
counter
|
||||
)
|
||||
ctx.tp_worker.register_hicache_layer_transfer_counter.assert_called_once_with(
|
||||
counter
|
||||
)
|
||||
self.assertIs(result, cache)
|
||||
|
||||
def test_swa_radix_cache_when_hybrid_swa(self):
|
||||
ctx = _make_ctx(self, is_hybrid_swa=True)
|
||||
# SWA hybrid models now default to the unified radix tree.
|
||||
|
||||
@@ -21,6 +21,8 @@ register_cpu_ci(est_time=5, suite="base-a-test-cpu")
|
||||
class FakeBacking(Enum):
|
||||
Anonymous = 0
|
||||
AnonymousHugetlb = 1
|
||||
AnonymousShm = 2
|
||||
AnonymousShmHugetlb = 3
|
||||
|
||||
|
||||
class FakeHandle:
|
||||
@@ -64,7 +66,10 @@ class FakeHostMemAllocator:
|
||||
mapped_size=size,
|
||||
actual_backing=backing,
|
||||
actual_alignment=(
|
||||
hugepage_size if backing == FakeBacking.AnonymousHugetlb else 4096
|
||||
hugepage_size
|
||||
if backing
|
||||
in (FakeBacking.AnonymousHugetlb, FakeBacking.AnonymousShmHugetlb)
|
||||
else 4096
|
||||
),
|
||||
)
|
||||
self.alloc_calls.append(
|
||||
@@ -142,6 +147,37 @@ class TestUMBPHostAllocator(unittest.TestCase):
|
||||
tensor.fill_(3.0)
|
||||
self.assertEqual(float(tensor[0, 0]), 3.0)
|
||||
|
||||
def test_standalone_process_uses_shareable_backing(self):
|
||||
self._install_fake_mori()
|
||||
|
||||
from sglang.srt.mem_cache.storage.umbp.umbp_host_allocator import (
|
||||
UMBPHostTensorAllocator,
|
||||
)
|
||||
|
||||
cases = (
|
||||
("0", FakeBacking.AnonymousShm),
|
||||
("1", FakeBacking.AnonymousShmHugetlb),
|
||||
)
|
||||
for use_hugepage, expected in cases:
|
||||
with (
|
||||
self.subTest(use_hugepage=use_hugepage),
|
||||
mock.patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"UMBP_STANDALONE_ADDRESS": "unix:///tmp/umbp-test.sock",
|
||||
"SGLANG_HICACHE_HOST_HUGEPAGE": use_hugepage,
|
||||
},
|
||||
),
|
||||
):
|
||||
allocator = UMBPHostTensorAllocator()
|
||||
tensor = allocator.allocate((16,), dtype=torch.uint8, device="cpu")
|
||||
|
||||
self.assertEqual(
|
||||
allocator._allocator.alloc_calls[0]["backing"], expected
|
||||
)
|
||||
del tensor
|
||||
allocator.__del__()
|
||||
|
||||
def test_umbp_allocator_del_calls_free_once(self):
|
||||
self._install_fake_mori()
|
||||
|
||||
|
||||
@@ -119,6 +119,55 @@ def make_indices(indices):
|
||||
|
||||
|
||||
class TestUMBPStore(unittest.TestCase):
|
||||
def test_standalone_process_configuration(self):
|
||||
from sglang.srt.mem_cache.storage.umbp import umbp_store
|
||||
|
||||
imported = list(umbp_store._import_umbp_client())
|
||||
captured = []
|
||||
|
||||
def make_client(config):
|
||||
captured.append(config)
|
||||
client = MagicMock()
|
||||
client.flush.return_value = True
|
||||
return client
|
||||
|
||||
imported[0] = make_client
|
||||
config = MockStorageConfig(
|
||||
extra_config={
|
||||
"standalone_address": "unix:///tmp/umbp-test.sock",
|
||||
"standalone_auto_start": False,
|
||||
"standalone_startup_timeout_ms": 1234,
|
||||
"ssd_enabled": False,
|
||||
"extra_backend_tag": "tenant-a",
|
||||
}
|
||||
)
|
||||
with patch.object(
|
||||
umbp_store, "_import_umbp_client", return_value=tuple(imported)
|
||||
):
|
||||
store = umbp_store.UMBPStore(config, mem_pool_host=None)
|
||||
|
||||
self.assertEqual(len(captured), 1)
|
||||
self.assertIsNone(captured[0].distributed)
|
||||
self.assertEqual(
|
||||
captured[0].standalone_process.address, "unix:///tmp/umbp-test.sock"
|
||||
)
|
||||
self.assertFalse(captured[0].standalone_process.auto_start)
|
||||
self.assertEqual(captured[0].standalone_process.startup_timeout_ms, 1234)
|
||||
self.assertEqual(store.config_prefix, "tenant-a_test-model")
|
||||
store.close()
|
||||
|
||||
def test_standalone_and_distributed_addresses_are_mutually_exclusive(self):
|
||||
from sglang.srt.mem_cache.storage.umbp import umbp_store
|
||||
|
||||
config = MockStorageConfig(
|
||||
extra_config={
|
||||
"master_address": "127.0.0.1:1234",
|
||||
"standalone_address": "unix:///tmp/umbp-test.sock",
|
||||
}
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, "mutually exclusive"):
|
||||
umbp_store.UMBPStore(config, mem_pool_host=None)
|
||||
|
||||
def test_basic_set_get(self):
|
||||
from sglang.srt.mem_cache.storage.umbp.umbp_store import UMBPStore
|
||||
|
||||
@@ -326,6 +375,7 @@ class TestUMBPStoreDefensiveSemantics(unittest.TestCase):
|
||||
store.is_mla_backend = True
|
||||
store.mla_suffix = ""
|
||||
store.mha_suffix = "0"
|
||||
store.config_prefix = None
|
||||
store.register_mem_host_pool_v2(MockHybridSidePool(), PoolName.DEEPSEEK_V4_C4)
|
||||
return store
|
||||
|
||||
@@ -345,6 +395,7 @@ class TestUMBPStoreDefensiveSemantics(unittest.TestCase):
|
||||
spdk_proxy_tenant_quota_bytes=0,
|
||||
)
|
||||
self.distributed = None
|
||||
self.standalone_process = None
|
||||
|
||||
@classmethod
|
||||
def from_environment(cls):
|
||||
@@ -366,6 +417,8 @@ class TestUMBPStoreDefensiveSemantics(unittest.TestCase):
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
config = MockStorageConfig(
|
||||
extra_config={"dram_capacity_bytes": 1024, "ssd_enabled": False}
|
||||
|
||||
Reference in New Issue
Block a user