[ROCm][Bugfix] Explicitly reject FSE=1 with DPA+ETP deployment for DeepSeek-V4 (#57919)

Signed-off-by: Shanshan Shen <87969357+shen-shanshan@users.noreply.github.com>

Shanshan Shen committed Sep 22, 2026 at 12:45 UTC 42a85a49761921fe5965e28eb971d863d9759503
2 files changed +43 -5
tests/models/test_deepseek_v4_vl_rocm.py
+22 -1
@@ -7,6 +7,7 @@ import pytest
7 import torch
8 from torch import nn
9
10 +from vllm.config import ParallelConfig
11 from vllm.model_executor.models.utils import WeightsMapper
12 from vllm.platforms import current_platform
13
@@ -100,7 +101,9 @@ def test_rocm_moe_wires_vision_routing_on_hash_and_regular_layers(
101 n_shared_experts=None,
102 )
103 vllm_config = SimpleNamespace(
103 - model_config=SimpleNamespace(hf_config=config), quant_config=None
104 + model_config=SimpleNamespace(hf_config=config),
105 + quant_config=None,
106 + parallel_config=ParallelConfig(),
107 )
108
109 hash_moe = rocm_model.DeepseekV4MoE(vllm_config, prefix="model.layers.0.ffn")
@@ -115,6 +118,24 @@ def test_rocm_moe_wires_vision_routing_on_hash_and_regular_layers(
118 assert factory_kwargs["image_sentinel_lo"] == IMAGE_SENTINEL_BASE_ID
119
120
121 +def test_rocm_fse_rejects_data_parallel_deployment(
122 + monkeypatch: pytest.MonkeyPatch,
123 +) -> None:
124 + from vllm.models.deepseek_v4.amd.model import _fuse_shared_experts_enabled
125 +
126 + config = SimpleNamespace(n_shared_experts=1)
127 +
128 + monkeypatch.setenv("VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS", "1")
129 + with pytest.raises(ValueError, match="data parallelism"):
130 + _fuse_shared_experts_enabled(config, ParallelConfig(data_parallel_size=2))
131 +
132 + # Expert parallelism already disables FSE: no raise, FSE stays off.
133 + assert not _fuse_shared_experts_enabled(
134 + config, ParallelConfig(data_parallel_size=2, enable_expert_parallel=True)
135 + )
136 + assert _fuse_shared_experts_enabled(config, ParallelConfig())
137 +
138 +
139 def test_rocm_mtp_forwards_input_ids_for_vision_routing(
140 monkeypatch: pytest.MonkeyPatch,
141 ) -> None:
vllm/models/deepseek_v4/amd/model.py
+21 -4
@@ -12,7 +12,7 @@ import torch.nn as nn
12
13 import vllm.envs as envs
14 from vllm._aiter_ops import rocm_aiter_ops
15 -from vllm.config import VllmConfig, get_current_vllm_config
15 +from vllm.config import ParallelConfig, VllmConfig
16 from vllm.distributed import (
17 get_pp_group,
18 get_tensor_model_parallel_rank,
@@ -504,11 +504,28 @@ class DeepseekV4HeterogeneousSharedRoutedExperts(RoutedExperts):
504 return routed + shared_out
505
506
507 -def _fuse_shared_experts_enabled(config) -> bool:
507 +def _fuse_shared_experts_enabled(config, parallel_config: ParallelConfig) -> bool:
508 + if (
509 + getattr(config, "n_shared_experts", None)
510 + and envs.VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS
511 + and not parallel_config.enable_expert_parallel
512 + and parallel_config.data_parallel_size > 1
513 + ):
514 + # Fused shared experts are not supported under data parallelism:
515 + # the fused path cannot load the FP8 shared expert into the MXFP4
516 + # routed slot, which fails obscurely during weight loading. Fail
517 + # fast with an actionable message instead.
518 + raise ValueError(
519 + "DeepSeek-V4 fused shared experts "
520 + "(VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1) are not supported "
521 + "with data parallelism (data_parallel_size > 1). Set "
522 + "VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=0 to run the shared "
523 + "expert as an unfused FP8 MLP."
524 + )
525 return bool(
526 getattr(config, "n_shared_experts", None)
527 and envs.VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS
511 - and not get_current_vllm_config().parallel_config.enable_expert_parallel
528 + and not parallel_config.enable_expert_parallel
529 )
530
531
@@ -586,7 +603,7 @@ class DeepseekV4MoE(nn.Module):
603 # This should be cleaned up and use `resolve_layer_fused_shared_expert`.
604 self.fuse_heterogeneous_shared_expert = fuse_heterogeneous_shared_expert
605 fse_requested = (
589 - _fuse_shared_experts_enabled(config)
606 + _fuse_shared_experts_enabled(config, vllm_config.parallel_config)
607 and not self.fuse_heterogeneous_shared_expert
608 )
609 fse_compatible = False