[ROCm][CI] skip the ROCm MRV1 default where MRV1 cannot serve the config (#58535)
Signed-off-by: Stefan Koncarevic <Stefan.Koncarevic@amd.com> Co-authored-by: Andreas Karatzas <akaratza@amd.com>
stefankoncarevic committed
Sep 24, 2026 at 22:36 UTC
e33de821c0df5c15d0fad990a754f3b69a6478e3
5 files changed
+91
-2
.buildkite/test_areas/lm_eval.yaml
+1
@@ -307,6 +307,7 @@ steps:
307
- csrc/
308
- tests/evals/gsm8k/configs/Kimi-K3-pruned75-DSpark-AITER-TP4.yaml
309
- tests/evals/gsm8k/configs/DeepSeek-V4-Flash-DSpark-AITER-TEP4.yaml
310
+ - tests/evals/gsm8k/configs/DeepSeek-V4-Flash-DSpark-FP8-TP4-ROCm.yaml
311
- tests/evals/gsm8k/configs/models-spec-decode-rocm.txt
312
- tests/evals/gsm8k/test_gsm8k_correctness.py
313
- tests/evals/gsm8k/gsm8k_eval.py
tests/evals/gsm8k/configs/DeepSeek-V4-Flash-DSpark-FP8-TP4-ROCm.yaml
new
+28
@@ -0,0 +1,28 @@
1
+model_name: "deepseek-ai/DeepSeek-V4-Flash-DSpark"
2
+accuracy_threshold: 0.92
3
+tolerance: 0.08
4
+min_acceptance_length: 1.2
5
+num_questions: 1319
6
+num_fewshot: 5
7
+startup_max_wait_seconds: 1800
8
+env:
9
+ VLLM_ROCM_USE_AITER: "1"
10
+server_args: >-
11
+ --tokenizer-mode deepseek_v4
12
+ --trust-remote-code
13
+ --max-model-len 8192
14
+ --tensor-parallel-size 4
15
+ --enable-expert-parallel
16
+ --all2all-backend allgather_reducescatter
17
+ --block-size 256
18
+ --gpu-memory-utilization 0.5
19
+ --kv-cache-dtype fp8
20
+ --attention_config.indexer_kv_dtype=fp8
21
+ --max-num-batched-tokens 16384
22
+ --max-num-seqs 128
23
+ --enforce-eager
24
+ --speculative-config '{"method":"dspark",
25
+ "model":"deepseek-ai/DeepSeek-V4-Flash-DSpark",
26
+ "num_speculative_tokens":7,
27
+ "draft_sample_method":"probabilistic",
28
+ "enable_adaptive_verification":false}'
tests/evals/gsm8k/configs/models-spec-decode-rocm.txt
+1
@@ -1,2 +1,3 @@
1
Kimi-K3-pruned75-DSpark-AITER-TP4.yaml
2
DeepSeek-V4-Flash-DSpark-AITER-TEP4.yaml
3
+DeepSeek-V4-Flash-DSpark-FP8-TP4-ROCm.yaml
tests/test_config.py
+47
@@ -550,11 +550,58 @@ def test_rocm_keeps_compiled_deepseek_defaults(monkeypatch):
550
model_config=SimpleNamespace(architectures=["DeepseekV32ForCausalLM"]),
551
attention_config=AttentionConfig(),
552
)
553
+ config._get_v1_model_runner_unsupported_features = lambda: []
554
assert VllmConfig.use_v2_model_runner.fget(config) is False
555
finally:
556
default_breakable_cudagraph_architectures.cache_clear()
557
558
559
+def test_rocm_mrv1_default_yields_to_v1_unsupported_config(monkeypatch):
560
+ """The ROCm V1 default is a speed preference, not a capability claim.
561
+
562
+ DSpark runs only on V2, so pinning DeepSeek V4 to V1 would fail config
563
+ validation instead of serving it. With nothing V1 refuses, it still holds.
564
+ """
565
+ from vllm.platforms import current_platform
566
+
567
+ monkeypatch.setattr(current_platform, "is_rocm", lambda: True)
568
+ monkeypatch.setattr(vllm_config_module, "HAS_TRITON", True)
569
+ monkeypatch.delenv("VLLM_USE_V2_MODEL_RUNNER", raising=False)
570
+
571
+ config = SimpleNamespace(
572
+ model_config=SimpleNamespace(
573
+ architectures=["DeepseekV4ForCausalLM"], is_diffusion=False
574
+ ),
575
+ attention_config=AttentionConfig(),
576
+ parallel_config=SimpleNamespace(
577
+ prefill_context_parallel_size=1,
578
+ pipeline_parallel_size=1,
579
+ enable_batch_sharded_sampling=False,
580
+ ),
581
+ scheduler_config=SimpleNamespace(async_scheduling=False),
582
+ speculative_config=None,
583
+ )
584
+ config._dflash_needs_multi_kv_group = lambda: False
585
+ config._is_dflash2_draft = lambda: False
586
+ config._get_v2_model_runner_unsupported_features = lambda: []
587
+ # The real predicate, so the test also pins where dspark lands in it.
588
+ config._get_v1_model_runner_unsupported_features = lambda: (
589
+ VllmConfig._get_v1_model_runner_unsupported_features(config)
590
+ )
591
+
592
+ assert VllmConfig.use_v2_model_runner.fget(config) is False
593
+
594
+ config.speculative_config = SimpleNamespace(
595
+ method="dspark", enable_adaptive_verification=False
596
+ )
597
+ assert VllmConfig.use_v2_model_runner.fget(config) is True
598
+
599
+ # Yielding is not the same as selecting V2: the later checks still run, so
600
+ # a config neither runner can serve lands on V1 and fails validation there.
601
+ config._get_v2_model_runner_unsupported_features = lambda: ["sequence parallelism"]
602
+ assert VllmConfig.use_v2_model_runner.fget(config) is False
603
+
604
+
605
@pytest.mark.parametrize(
606
("model", "architecture"),
607
[
vllm/config/vllm.py
+14
-2
@@ -722,11 +722,23 @@ class VllmConfig:
722
if model_config is not None and current_platform.is_rocm():
723
architectures = getattr(model_config, "architectures", ())
724
if any(arch in ROCM_DEFAULT_MRV1_ARCHITECTURES for arch in architectures):
725
+ # This default is a speed preference, not a claim that V1 can
726
+ # serve the config, so it yields where V1 cannot. It yields by
727
+ # falling through to the checks below, not by selecting V2.
728
+ v1_unsupported = self._get_v1_model_runner_unsupported_features()
729
+ if not v1_unsupported:
730
+ logger.warning_once(
731
+ "Defaulting to V1 model runner on ROCm for model "
732
+ "architectures: %s",
733
+ ", ".join(architectures),
734
+ )
735
+ return False
736
logger.warning_once(
726
- "Defaulting to V1 model runner on ROCm for model architectures: %s",
737
+ "Skipping the ROCm V1 model runner default for %s: V1 does "
738
+ "not support %s.",
739
", ".join(architectures),
740
+ ", ".join(v1_unsupported),
741
)
729
- return False
742
743
if not HAS_TRITON:
744
logger.warning_once(