A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 05:30 UTC
fix[DP][v1]: Prevent hangs from mismatched worker configurations (#26218)
Signed-off-by: Ayush Satyam <ayushsatyam146@gmail.com>
Ayush Satyam committed
Oct 8, 2025 at 11:25 UTC
5e65d6b2adf64d1548c3b25ccc52ad55fcfe8044
3 files changed
+46
-11
vllm/config/parallel.py
+9
@@ -336,6 +336,9 @@ class ParallelConfig:
336
graph from input ids/embeddings to the final hidden states,
337
excluding anything before input ids/embeddings and after
338
the final hidden states.
339
+
340
+ This hash is also used for DP worker configuration validation
341
+ to prevent hangs from mismatched collective communication patterns.
342
"""
343
factors: list[Any] = []
344
factors.append(self.pipeline_parallel_size)
@@ -343,6 +346,12 @@ class ParallelConfig:
346
factors.append(self.enable_expert_parallel)
347
factors.append(self.data_parallel_size)
348
factors.append(envs.VLLM_ALL2ALL_BACKEND)
349
+ factors.append(self.enable_eplb)
350
+ if self.enable_eplb:
351
+ factors.append(self.eplb_config.log_balancedness)
352
+ factors.append(self.eplb_config.window_size)
353
+ factors.append(self.eplb_config.step_interval)
354
+ factors.append(self.eplb_config.num_redundant_experts)
355
return hashlib.sha256(str(factors).encode()).hexdigest()
356
357
def __post_init__(self) -> None:
vllm/v1/engine/core.py
+14
-10
@@ -681,17 +681,21 @@ class EngineCoreProc(EngineCore):
681
# external LB case for our colocated front-end to use (coordinator
682
# only runs with rank 0).
683
dp_stats_address = self.frontend_stats_publish_address
684
- handshake_socket.send(
685
- msgspec.msgpack.encode(
686
- {
687
- "status": "READY",
688
- "local": local_client,
689
- "headless": headless,
690
- "num_gpu_blocks": num_gpu_blocks,
691
- "dp_stats_address": dp_stats_address,
692
- }
684
+
685
+ # Include config hash for DP configuration validation
686
+ ready_msg = {
687
+ "status": "READY",
688
+ "local": local_client,
689
+ "headless": headless,
690
+ "num_gpu_blocks": num_gpu_blocks,
691
+ "dp_stats_address": dp_stats_address,
692
+ }
693
+ if vllm_config.parallel_config.data_parallel_size > 1:
694
+ ready_msg["parallel_config_hash"] = (
695
+ vllm_config.parallel_config.compute_hash()
696
)
694
- )
697
+
698
+ handshake_socket.send(msgspec.msgpack.encode(ready_msg))
699
700
@staticmethod
701
def startup_handshake(
vllm/v1/engine/utils.py
+23
-1
@@ -73,6 +73,7 @@ class EngineHandshakeMetadata:
73
74
addresses: EngineZmqAddresses
75
parallel_config: dict[str, Union[int, str, list[int]]]
76
+ parallel_config_hash: Optional[str] = None
77
78
79
class CoreEngineProcManager:
@@ -867,7 +868,8 @@ def wait_for_engine_startup(
868
)
869
870
if status == "HELLO" and engine.state == CoreEngineState.NEW:
870
- # Send init message with DP config info.
871
+ # Send init message with DP config info and config hash.
872
+ # The config hash ensures all DP workers have compatible configs.
873
init_message = msgspec.msgpack.encode(
874
EngineHandshakeMetadata(
875
addresses=addresses,
@@ -880,6 +882,9 @@ def wait_for_engine_startup(
882
"data_parallel_size",
883
)
884
},
885
+ parallel_config_hash=parallel_config.compute_hash()
886
+ if parallel_config.data_parallel_size > 1
887
+ else None,
888
)
889
)
890
handshake_socket.send_multipart((eng_identity, init_message), copy=False)
@@ -900,6 +905,23 @@ def wait_for_engine_startup(
905
if addresses.frontend_stats_publish_address is None:
906
addresses.frontend_stats_publish_address = msg.get("dp_stats_address")
907
908
+ # Validate config hash consistency across DP workers
909
+ if parallel_config.data_parallel_size > 1:
910
+ worker_config_hash = msg.get("parallel_config_hash")
911
+ expected_hash = parallel_config.compute_hash()
912
+ if worker_config_hash != expected_hash:
913
+ raise RuntimeError(
914
+ f"Configuration mismatch detected for engine "
915
+ f"{eng_index}. All DP workers must have identical "
916
+ f"configurations for parameters that affect collective "
917
+ f"communication (e.g., enable_eplb, "
918
+ f"eplb_config.log_balancedness). "
919
+ f"Worker hash: {worker_config_hash}, "
920
+ f"Expected hash: {expected_hash}. "
921
+ f"Please ensure all workers are started with the same "
922
+ f"command-line arguments."
923
+ )
924
+
925
start_pending[0 if local else 1] -= 1
926
engine.state = CoreEngineState.READY
927
else: