[Unified Cache][6/N]: Add UMBP external linker (#37578)

Co-authored-by: Zhangheng <hzh0425@apache.org>
This commit is contained in:
Niko Ma
2026-09-05 09:21:43 +08:00
committed by GitHub
co-authored by Zhangheng
parent bc727bc4ee
commit f1f2380d2b
9 changed files with 1584 additions and 207 deletions
@@ -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}