[Bugfix] Surface all-rank diffusion RPC failures
Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
This commit is contained in:
1 parent
6506ed3d4d
commit
3805852a71
6 files changed
+278
-52
No files matched your search
@@ -17,8 +17,10 @@ from vllm.v1.engine.exceptions import EngineDeadError
|
||||
from vllm_omni.diffusion.data import DiffusionOutput
|
||||
from vllm_omni.diffusion.diffusion_engine import DiffusionEngine
|
||||
from vllm_omni.diffusion.executor.multiproc_executor import MultiprocDiffusionExecutor
|
||||
from vllm_omni.diffusion.ipc import DIFFUSION_RPC_RESULT_ENVELOPE
|
||||
from vllm_omni.diffusion.sched import RequestScheduler
|
||||
from vllm_omni.diffusion.stage_diffusion_proc import StageDiffusionProc
|
||||
from vllm_omni.diffusion.worker.diffusion_worker import WorkerProc
|
||||
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
|
||||
from vllm_omni.outputs import OmniRequestOutput
|
||||
|
||||
@@ -305,6 +307,51 @@ class TestSerialEngineOperations:
|
||||
assert len(results) == 1
|
||||
assert results[0].error == "rank0"
|
||||
|
||||
def test_collective_rpc_all_rank_status_error_propagation(self):
|
||||
engine, _, _, res_q = _make_engine(num_gpus=2)
|
||||
|
||||
res_q.put(
|
||||
{
|
||||
"type": DIFFUSION_RPC_RESULT_ENVELOPE,
|
||||
"method": "add_lora",
|
||||
"result": True,
|
||||
"rank_statuses": [
|
||||
{"rank": 0, "ok": True, "bool_result": True},
|
||||
{
|
||||
"rank": 1,
|
||||
"ok": False,
|
||||
"error": "rank1 boom",
|
||||
"error_type": "RuntimeError",
|
||||
"traceback": "rank1 traceback",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
engine.collective_rpc("add_lora")
|
||||
error = str(excinfo.value)
|
||||
assert "rank 1" in error
|
||||
assert "rank1 boom" in error
|
||||
assert "rank1 traceback" in error
|
||||
|
||||
def test_collective_rpc_all_rank_bool_false_is_aggregated(self):
|
||||
engine, _, _, res_q = _make_engine(num_gpus=2)
|
||||
|
||||
res_q.put(
|
||||
{
|
||||
"type": DIFFUSION_RPC_RESULT_ENVELOPE,
|
||||
"method": "remove_lora",
|
||||
"result": True,
|
||||
"rank_statuses": [
|
||||
{"rank": 0, "ok": True, "bool_result": True},
|
||||
{"rank": 1, "ok": True, "bool_result": False},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
assert engine.collective_rpc("remove_lora") == [False]
|
||||
|
||||
def test_serial_add_req_then_collective_rpc(self):
|
||||
engine, _, req_q, res_q = _make_engine()
|
||||
wt = _start_worker(req_q, res_q, count=2)
|
||||
@@ -348,6 +395,79 @@ class TestSerialEngineOperations:
|
||||
engine.collective_rpc("anything")
|
||||
|
||||
|
||||
class TestWorkerProcRpcRankStatus:
|
||||
def _make_worker_proc(self, has_result_mq: bool = True):
|
||||
proc = object.__new__(WorkerProc)
|
||||
proc.gpu_id = 0
|
||||
proc.result_mq = object() if has_result_mq else None
|
||||
proc.worker = SimpleNamespace(execute_method=Mock(return_value=True))
|
||||
return proc
|
||||
|
||||
def test_execute_rpc_returns_rank_status_envelope(self, monkeypatch):
|
||||
proc = self._make_worker_proc()
|
||||
|
||||
monkeypatch.setattr(torch.distributed, "is_initialized", lambda: True)
|
||||
monkeypatch.setattr(torch.distributed, "get_world_size", lambda: 2)
|
||||
|
||||
def _all_gather_object(out, local):
|
||||
out[0] = local
|
||||
out[1] = {
|
||||
"rank": 1,
|
||||
"ok": False,
|
||||
"error": "rank1 boom",
|
||||
"error_type": "RuntimeError",
|
||||
"traceback": "trace",
|
||||
"bool_result": None,
|
||||
}
|
||||
|
||||
monkeypatch.setattr(torch.distributed, "all_gather_object", _all_gather_object)
|
||||
|
||||
result, should_reply = proc.execute_rpc(
|
||||
{
|
||||
"method": "remove_lora",
|
||||
"args": (),
|
||||
"kwargs": {},
|
||||
"output_rank": 0,
|
||||
"exec_all_ranks": True,
|
||||
"collect_rank_status": True,
|
||||
}
|
||||
)
|
||||
|
||||
assert should_reply is True
|
||||
assert result["type"] == DIFFUSION_RPC_RESULT_ENVELOPE
|
||||
assert result["result"] is True
|
||||
assert result["rank_statuses"][0]["rank"] == 0
|
||||
assert result["rank_statuses"][1]["rank"] == 1
|
||||
assert result["rank_statuses"][1]["ok"] is False
|
||||
|
||||
def test_execute_rpc_local_exception_is_reported_in_envelope(self, monkeypatch):
|
||||
proc = self._make_worker_proc()
|
||||
proc.worker.execute_method = Mock(side_effect=RuntimeError("local boom"))
|
||||
monkeypatch.setattr(torch.distributed, "is_initialized", lambda: False)
|
||||
|
||||
result, should_reply = proc.execute_rpc(
|
||||
{
|
||||
"method": "add_lora",
|
||||
"args": (),
|
||||
"kwargs": {},
|
||||
"output_rank": 0,
|
||||
"exec_all_ranks": True,
|
||||
"collect_rank_status": True,
|
||||
}
|
||||
)
|
||||
|
||||
assert should_reply is True
|
||||
assert result["type"] == DIFFUSION_RPC_RESULT_ENVELOPE
|
||||
assert len(result["rank_statuses"]) == 1
|
||||
status = result["rank_statuses"][0]
|
||||
assert status["rank"] == 0
|
||||
assert status["ok"] is False
|
||||
assert status["error"] == "local boom"
|
||||
assert status["error_type"] == "RuntimeError"
|
||||
assert status["bool_result"] is None
|
||||
assert "local boom" in status["traceback"]
|
||||
|
||||
|
||||
# ───────── error handling: EngineDeadError propagation through layers ─────
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user