fix(load-snapshot): avoid duplicate zmq bind in multi-tokenizer mode (#27145)

Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
This commit is contained in:
ybyang
2026-06-03 18:24:56 -07:00
committed by GitHub
co-authored by Lianmin Zheng
parent 14ed9b448e
commit 687baf9471
5 changed files with 157 additions and 19 deletions
@@ -16,6 +16,7 @@ from sglang.srt.managers.load_snapshot import (
create_load_snapshot_reader,
create_load_snapshot_writer,
should_use_zmq,
zmq_reader_owner,
)
from sglang.test.ci.ci_register import register_cpu_ci
from sglang.test.test_utils import CustomTestCase, maybe_stub_sgl_kernel
@@ -217,13 +218,16 @@ class TestFactoryFunctions(CustomTestCase):
dp_size=1,
load_balance_method="round_robin",
node_rank=0,
tokenizer_worker_num=1,
)
port_args = SimpleNamespace(instance_id="test_shm_factory")
writer = create_load_snapshot_writer(
server_args, port_args, dp_size=1, dp_rank=0
)
self.assertIsInstance(writer, ShmLoadSnapshotWriter)
reader = create_load_snapshot_reader(server_args, port_args, caller="tokenizer")
reader = create_load_snapshot_reader(
server_args, port_args, caller="TokenizerManager"
)
self.assertIsInstance(reader, ShmLoadSnapshotReader)
reader.close()
writer.close()
@@ -240,6 +244,7 @@ class TestFactoryFunctions(CustomTestCase):
dp_size=1,
load_balance_method="round_robin",
node_rank=0,
tokenizer_worker_num=1,
)
port_args = SimpleNamespace(instance_id="test_zmq_factory")
os.environ["SGLANG_LOAD_SNAPSHOT_USE_ZMQ"] = "1"
@@ -249,7 +254,7 @@ class TestFactoryFunctions(CustomTestCase):
)
self.assertIsInstance(writer, ZmqLoadSnapshotWriter)
reader = create_load_snapshot_reader(
server_args, port_args, caller="tokenizer"
server_args, port_args, caller="TokenizerManager"
)
self.assertIsInstance(reader, ZmqShmLoadSnapshotReader)
reader.close()
@@ -270,6 +275,71 @@ class TestFactoryFunctions(CustomTestCase):
self.assertFalse(should_use_zmq(args))
class TestZmqReaderOwner(CustomTestCase):
"""At most one process binds the zmq PULL socket across all callers."""
CALLERS = ("TokenizerManager", "MultiTokenizerRouter", "DataParallelController")
@staticmethod
def _args(**overrides):
base = dict(
enable_dp_attention=True,
nnodes=2,
node_rank=0,
dp_size=1,
load_balance_method="round_robin",
tokenizer_worker_num=1,
)
base.update(overrides)
return SimpleNamespace(**base)
def _owners(self, args):
return {c for c in self.CALLERS if zmq_reader_owner(args, c)}
def test_zmq_disabled_no_owner(self):
args = self._args(enable_dp_attention=False, nnodes=1)
self.assertEqual(self._owners(args), set())
def test_non_zero_node_rank_no_owner(self):
args = self._args(node_rank=1, dp_size=4, tokenizer_worker_num=8)
self.assertEqual(self._owners(args), set())
def test_tokenizer_manager_owns_when_dp1(self):
self.assertEqual(self._owners(self._args(dp_size=1)), {"TokenizerManager"})
def test_multi_tokenizer_router_owns_in_multi_tokenizer_dp1(self):
args = self._args(dp_size=1, tokenizer_worker_num=8)
self.assertEqual(self._owners(args), {"MultiTokenizerRouter"})
def test_multi_tokenizer_router_owns_in_multi_tokenizer_round_robin(self):
args = self._args(dp_size=4, tokenizer_worker_num=8)
self.assertEqual(self._owners(args), {"MultiTokenizerRouter"})
def test_data_parallel_controller_owns_load_aware(self):
for method in ("total_tokens", "total_requests"):
args = self._args(
dp_size=4, tokenizer_worker_num=8, load_balance_method=method
)
self.assertEqual(self._owners(args), {"DataParallelController"})
def test_tokenizer_manager_owns_dp4_round_robin(self):
args = self._args(dp_size=4, tokenizer_worker_num=1)
self.assertEqual(self._owners(args), {"TokenizerManager"})
def test_at_most_one_owner_across_configs(self):
for dp_size in (1, 4):
for tw in (1, 8):
for method in ("round_robin", "total_tokens", "total_requests"):
for node_rank in (0, 1):
args = self._args(
dp_size=dp_size,
tokenizer_worker_num=tw,
load_balance_method=method,
node_rank=node_rank,
)
self.assertLessEqual(len(self._owners(args)), 1, args)
class TestZmqAddr(CustomTestCase):
def test_ipc_for_single_node(self):
port_args = SimpleNamespace(instance_id="myinstance")