Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
748f342
Fix HunyuanImage3 NPU MoE effective TP size
Celeste-jq Jun 12, 2026
aa6755a
Map HunyuanImage3 diffusion SP to vLLM PCP
Celeste-jq Jun 15, 2026
85854d9
Limit diffusion PCP mapping to MoE models
Celeste-jq Jun 16, 2026
fbb3a96
Gate diffusion MoE PCP mapping on EP
Celeste-jq Jun 16, 2026
7007897
Avoid PCP lookup when HunyuanImage3 EP is disabled
Celeste-jq Jun 16, 2026
7e7f15a
Trigger PR checks
Celeste-jq Jun 16, 2026
32904c9
Avoid EP error for non-MoE diffusion models
Celeste-jq Jun 16, 2026
e75ce28
Add diffusion MoE EP rank layout test
Celeste-jq Jun 17, 2026
ba56fe9
Align HunyuanImage3 MC2 with MoE EP layout
Celeste-jq Jun 17, 2026
59137de
Test HunyuanImage3 MC2 EP rank layout
Celeste-jq Jun 17, 2026
dbcdd24
Remove redundant HunyuanImage3 EP sync
Celeste-jq Jun 17, 2026
660357f
Apply ruff formatting
Celeste-jq Jun 17, 2026
3a7cd19
Remove obsolete diffusion EP rank shortcut
Celeste-jq Jun 17, 2026
683aa65
Store diffusion group ranks on coordinators
Celeste-jq Jun 17, 2026
c2b7e0f
Keep EP group ranks scoped to EP group
Celeste-jq Jun 17, 2026
0b37c8b
Keep MoE EP rank layout as metadata
Celeste-jq Jun 17, 2026
5a29484
Map CFG parallelism into vLLM DP groups
Celeste-jq Jun 17, 2026
265553b
Use EP flag for diffusion MoE rank mapping
Celeste-jq Jun 17, 2026
fdf4b06
Inline EP flag checks in diffusion parallel state
Celeste-jq Jun 17, 2026
038afb9
Rename expert parallel rank metadata
Celeste-jq Jun 17, 2026
d0c143e
Limit vLLM group remapping to expert parallel
Celeste-jq Jun 18, 2026
50d4bc8
Move NPU MC2 layout test to platform tests
Celeste-jq Jun 24, 2026
e166a69
Remove vllm-ascend specific layout test
Celeste-jq Jun 24, 2026
a43c7e1
Clarify Hunyuan NPU MC2 group size naming
Celeste-jq Jun 24, 2026
a73f9ce
Limit Hunyuan NPU MC2 init to EP
Celeste-jq Jun 24, 2026
defb9f2
Remove redundant EP sync in Hunyuan MC2 setup
Celeste-jq Jun 24, 2026
9cd1e08
Merge branch 'main' into npu-hunyuanimage3-dit-ep-sp-fix
hsliuustc0106 Jun 29, 2026
0ba0223
Merge branch 'main' into npu-hunyuanimage3-dit-ep-sp-fix
hsliuustc0106 Jun 29, 2026
639b5c7
Merge remote-tracking branch 'upstream/main' into npu-hunyuanimage3-d…
Celeste-jq Jun 30, 2026
6002deb
Merge remote-tracking branch 'fork/npu-hunyuanimage3-dit-ep-sp-fix' i…
Celeste-jq Jun 30, 2026
24fc059
Gate diffusion EP remap to MoE models
Celeste-jq Jul 1, 2026
2209dfe
Merge remote-tracking branch 'upstream/main' into npu-hunyuanimage3-d…
Celeste-jq Jul 1, 2026
7ed32af
Merge branch 'main' into npu-hunyuanimage3-dit-ep-sp-fix
Gaohan123 Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 282 additions & 0 deletions tests/diffusion/distributed/test_expert_parallel_layout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project

from types import SimpleNamespace

import pytest

import vllm_omni.diffusion.distributed.parallel_state as parallel_state


class _FakeGroup:
def __init__(
self,
group_ranks: list[list[int]],
local_rank: int,
parallel_mode: str,
**kwargs,
) -> None:
self.group_ranks = group_ranks
self.parallel_mode = parallel_mode
self.device_group = object()
self.ulysses_group = kwargs.get("ulysses_group")
self.ring_group = kwargs.get("ring_group")
self.local_group = next(group for group in group_ranks if local_rank in group)
self.world_size = len(self.local_group)
self.rank_in_group = self.local_group.index(local_rank)

def destroy(self) -> None:
pass


@pytest.mark.cpu
@pytest.mark.core_model
def test_moe_ep_maps_diffusion_sp_cfg_dp_to_vllm_groups(monkeypatch):
"""MoE+EP rank layout should map SP->PCP, CFG*DP->DP, and TP*SP*CFG*DP->EP."""
local_rank = 0
world_size = 32
created_groups: list[_FakeGroup] = []

def fake_init_model_parallel_group(
group_ranks,
local_rank,
backend,
parallel_mode=None,
group_name=None,
**kwargs,
):
del backend, group_name
group = _FakeGroup(
[list(ranks) for ranks in group_ranks],
local_rank,
parallel_mode or "",
**kwargs,
)
created_groups.append(group)
return group

fake_world_group = SimpleNamespace(
rank_in_group=local_rank,
local_rank=local_rank,
device_group=object(),
)
fake_forward_context = SimpleNamespace(omni_diffusion_config=SimpleNamespace(is_moe=True))
monkeypatch.setattr(parallel_state.torch.distributed, "is_initialized", lambda: True)
monkeypatch.setattr(parallel_state.torch.distributed, "get_world_size", lambda: world_size)
monkeypatch.setattr(parallel_state.torch.distributed, "get_backend", lambda *_args, **_kwargs: "gloo")
monkeypatch.setattr(parallel_state.torch.distributed, "new_group", lambda ranks: tuple(ranks))
monkeypatch.setattr(parallel_state, "get_world_group", lambda: fake_world_group)
monkeypatch.setattr(parallel_state, "get_forward_context", lambda: fake_forward_context)
monkeypatch.setattr(parallel_state, "init_model_parallel_group", fake_init_model_parallel_group)
monkeypatch.setattr(parallel_state, "init_dit_group", lambda *_args, **_kwargs: None)

for name in ("_DP", "_CFG", "_SP", "_PP", "_FS", "_EXPERT_PARALLEL_GROUP_RANKS"):
monkeypatch.setattr(parallel_state, name, None)
for name in ("_TP", "_PCP", "_DP", "_EP", "_PP"):
monkeypatch.setattr(parallel_state.vllm_parallel_state, name, None, raising=False)

parallel_state.initialize_model_parallel(
tensor_parallel_size=2,
sequence_parallel_size=2,
ulysses_degree=2,
ring_degree=1,
pipeline_parallel_size=2,
cfg_parallel_size=2,
data_parallel_size=2,
enable_expert_parallel=True,
backend="gloo",
)

assert parallel_state.vllm_parallel_state._PCP is parallel_state._SP
assert parallel_state.vllm_parallel_state._PCP.world_size == 2
assert parallel_state._DP.world_size == 2
assert parallel_state.vllm_parallel_state._DP is not parallel_state._DP
assert parallel_state.vllm_parallel_state._DP.world_size == 4
assert parallel_state.vllm_parallel_state._EP.world_size == 16
assert parallel_state.vllm_parallel_state._TP.world_size == 2
assert parallel_state._PP.world_size == 2

assert parallel_state.vllm_parallel_state._PCP.local_group == [0, 2]
assert parallel_state.vllm_parallel_state._DP.local_group == [0, 8, 16, 24]
assert parallel_state.vllm_parallel_state._EP.local_group == [
0,
1,
2,
3,
8,
9,
10,
11,
16,
17,
18,
19,
24,
25,
26,
27,
]
assert parallel_state.get_expert_parallel_group_ranks() == [
[
0,
1,
2,
3,
8,
9,
10,
11,
16,
17,
18,
19,
24,
25,
26,
27,
],
[
4,
5,
6,
7,
12,
13,
14,
15,
20,
21,
22,
23,
28,
29,
30,
31,
],
]

ep_groups = [group.local_group for group in created_groups if group.parallel_mode == "expert"]
assert ep_groups == [parallel_state.vllm_parallel_state._EP.local_group]


@pytest.mark.cpu
@pytest.mark.core_model
def test_cfg_parallel_keeps_diffusion_dp_without_ep(monkeypatch):
"""vLLM DP should keep diffusion DP when expert parallelism is not enabled."""
local_rank = 0
world_size = 8

def fake_init_model_parallel_group(
group_ranks,
local_rank,
backend,
parallel_mode=None,
group_name=None,
**kwargs,
):
del backend, group_name
return _FakeGroup(
[list(ranks) for ranks in group_ranks],
local_rank,
parallel_mode or "",
**kwargs,
)

fake_world_group = SimpleNamespace(
rank_in_group=local_rank,
local_rank=local_rank,
device_group=object(),
)
monkeypatch.setattr(parallel_state.torch.distributed, "is_initialized", lambda: True)
monkeypatch.setattr(parallel_state.torch.distributed, "get_world_size", lambda: world_size)
monkeypatch.setattr(parallel_state.torch.distributed, "get_backend", lambda *_args, **_kwargs: "gloo")
monkeypatch.setattr(parallel_state.torch.distributed, "new_group", lambda ranks: tuple(ranks))
monkeypatch.setattr(parallel_state, "get_world_group", lambda: fake_world_group)
monkeypatch.setattr(parallel_state, "init_model_parallel_group", fake_init_model_parallel_group)
monkeypatch.setattr(parallel_state, "init_dit_group", lambda *_args, **_kwargs: None)

for name in ("_DP", "_CFG", "_SP", "_PP", "_FS", "_EXPERT_PARALLEL_GROUP_RANKS"):
monkeypatch.setattr(parallel_state, name, None)
for name in ("_TP", "_PCP", "_DP", "_EP", "_PP"):
monkeypatch.setattr(parallel_state.vllm_parallel_state, name, None, raising=False)

parallel_state.initialize_model_parallel(
tensor_parallel_size=2,
sequence_parallel_size=1,
ulysses_degree=1,
ring_degree=1,
pipeline_parallel_size=1,
cfg_parallel_size=2,
data_parallel_size=2,
enable_expert_parallel=False,
backend="gloo",
)

assert parallel_state._DP.world_size == 2
assert parallel_state.vllm_parallel_state._DP is parallel_state._DP
assert parallel_state.vllm_parallel_state._DP.world_size == 2
assert parallel_state.vllm_parallel_state._DP.local_group == [0, 4]
assert parallel_state.vllm_parallel_state._PCP is None
assert parallel_state.vllm_parallel_state._EP is None
assert parallel_state._EXPERT_PARALLEL_GROUP_RANKS is None


@pytest.mark.cpu
@pytest.mark.core_model
def test_non_moe_ep_fails_before_vllm_ep_remap(monkeypatch):
"""Non-MoE diffusion configs should not create vLLM PCP/DP/EP remap state."""
local_rank = 0
world_size = 8

def fake_init_model_parallel_group(
group_ranks,
local_rank,
backend,
parallel_mode=None,
group_name=None,
**kwargs,
):
del backend, group_name
return _FakeGroup(
[list(ranks) for ranks in group_ranks],
local_rank,
parallel_mode or "",
**kwargs,
)

fake_world_group = SimpleNamespace(
rank_in_group=local_rank,
local_rank=local_rank,
device_group=object(),
)
fake_forward_context = SimpleNamespace(omni_diffusion_config=SimpleNamespace(is_moe=False))
monkeypatch.setattr(parallel_state.torch.distributed, "is_initialized", lambda: True)
monkeypatch.setattr(parallel_state.torch.distributed, "get_world_size", lambda: world_size)
monkeypatch.setattr(parallel_state.torch.distributed, "get_backend", lambda *_args, **_kwargs: "gloo")
monkeypatch.setattr(parallel_state.torch.distributed, "new_group", lambda ranks: tuple(ranks))
monkeypatch.setattr(parallel_state, "get_world_group", lambda: fake_world_group)
monkeypatch.setattr(parallel_state, "get_forward_context", lambda: fake_forward_context)
monkeypatch.setattr(parallel_state, "init_model_parallel_group", fake_init_model_parallel_group)
monkeypatch.setattr(parallel_state, "init_dit_group", lambda *_args, **_kwargs: None)

for name in ("_DP", "_CFG", "_SP", "_PP", "_FS", "_EXPERT_PARALLEL_GROUP_RANKS"):
monkeypatch.setattr(parallel_state, name, None)
for name in ("_TP", "_PCP", "_DP", "_EP", "_PP"):
monkeypatch.setattr(parallel_state.vllm_parallel_state, name, None, raising=False)

with pytest.raises(RuntimeError, match="Expert parallelism enabled for a non-MoE model"):
parallel_state.initialize_model_parallel(
tensor_parallel_size=2,
sequence_parallel_size=2,
ulysses_degree=2,
ring_degree=1,
pipeline_parallel_size=1,
cfg_parallel_size=2,
data_parallel_size=1,
enable_expert_parallel=True,
backend="gloo",
)

assert parallel_state.vllm_parallel_state._PCP is None
assert parallel_state.vllm_parallel_state._EP is None
assert parallel_state._EXPERT_PARALLEL_GROUP_RANKS is None
Loading
Loading