[ROCm][CI] Add quantized MoE serving test for gfx950 (#58748)
Signed-off-by: Stefan Koncarevic <Stefan.Koncarevic@amd.com> Co-authored-by: Andreas Karatzas <Andreas.Karatzas@amd.com> Co-authored-by: Andreas Karatzas <akaratza@amd.com>
stefankoncarevic committed
Sep 25, 2026 at 20:02 UTC
1b922ffcbe75cd411fab98a773f47b8f0294e43b
3 files changed
+206
-4
.buildkite/test-amd.yaml
+32
-2
@@ -2579,7 +2579,7 @@ steps:
2579
- unset VLLM_USE_V2_MODEL_RUNNER
2580
- uv pip install --system torchao==0.18.0
2581
- uv pip install --system conch-triton-kernels
2582
- - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
2582
+ - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --ignore quantization/test_rocm_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
2583
- if [ "$$BUILDKITE_PARALLEL_JOB" = "0" ]; then pytest -v -s rocm/test_moe_weight_replay.py; fi
2584
2585
#--------------------------------------------------------- mi300 · samplers ----------------------------------------------------------#
@@ -4943,7 +4943,7 @@ steps:
4943
- unset VLLM_USE_V2_MODEL_RUNNER
4944
- uv pip install --system torchao==0.17.0
4945
- uv pip install --system conch-triton-kernels
4946
- - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
4946
+ - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --ignore quantization/test_rocm_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
4947
- if [ "$$BUILDKITE_PARALLEL_JOB" = "0" ]; then pytest -v -s rocm/test_moe_weight_replay.py; fi
4948
4949
# - label: Quantized MoE Test (B200-MI355) # TBD
@@ -5445,6 +5445,36 @@ steps:
5445
- pip install 'modelscope<1.38'
5446
- pytest -v -s test_regression.py
5447
5448
+- label: ':amd: (MI355) Quantized MoE'
5449
+ timeout_in_minutes: 45
5450
+ working_dir: /vllm-workspace/
5451
+ source_file_dependencies:
5452
+ - tests/quantization/test_rocm_moe.py
5453
+ - tests/utils.py
5454
+ - vllm/model_executor/models/deepseek_v2.py
5455
+ - vllm/model_executor/models/qwen3_moe.py
5456
+ - vllm/model_executor/models/gpt_oss.py
5457
+ - vllm/model_executor/model_loader/
5458
+ - vllm/model_executor/layers/fused_moe/
5459
+ - vllm/model_executor/layers/quantization/
5460
+ - vllm/model_executor/kernels/linear/
5461
+ - vllm/v1/attention/
5462
+ - vllm/v1/worker/gpu/
5463
+ - vllm/_aiter_ops.py
5464
+ - vllm/platforms/rocm.py
5465
+ - vllm/envs.py
5466
+ commands:
5467
+ - pytest -v -s tests/quantization/test_rocm_moe.py
5468
+ dind: false
5469
+ agent_pool: mi355_1
5470
+ num_gpus: 1
5471
+ mirror_hardwares:
5472
+ - amdexperimental
5473
+ - amdproduction
5474
+ - amdgfx950nightly
5475
+ - amdmi355
5476
+ optional: true
5477
+
5478
- label: ':amd: (MI355) Fusion E2E TP2 AsyncTP BF16 Config Sweep'
5479
timeout_in_minutes: 30
5480
working_dir: /vllm-workspace/
.buildkite/test_areas/quantization.yaml
+28
-2
@@ -19,7 +19,7 @@ steps:
19
- uv pip install --system conch-triton-kernels
20
# The SM90-only checkpoint currently contains a removed weight_chan_scale
21
# parameter. It was not exercised by the previous L4 job.
22
- - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py -k 'not test_compressed_tensors_w4a8_fp8' --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
22
+ - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --ignore quantization/test_rocm_moe.py -k 'not test_compressed_tensors_w4a8_fp8' --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
23
mirror:
24
amd:
25
label: ":amd: (MI355) Quantization Shard %N"
@@ -43,7 +43,7 @@ steps:
43
- unset VLLM_USE_V2_MODEL_RUNNER
44
- uv pip install --system torchao==0.17.0
45
- uv pip install --system conch-triton-kernels
46
- - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
46
+ - VLLM_TEST_FORCE_LOAD_FORMAT=auto pytest -v -s quantization/ --ignore quantization/test_blackwell_moe.py --ignore quantization/test_rocm_moe.py --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT
47
- if [ "$$BUILDKITE_PARALLEL_JOB" = "0" ]; then pytest -v -s rocm/test_moe_weight_replay.py; fi
48
49
- label: ":nvidia: (H200 MIG 35GB) Quantized Fusions"
@@ -76,6 +76,32 @@ steps:
76
- vllm/v1/attention/backends/flashinfer.py
77
commands:
78
- pytest -s -v tests/quantization/test_blackwell_moe.py
79
+ mirror:
80
+ amd:
81
+ label: ":amd: (MI355) Quantized MoE"
82
+ dind: false
83
+ device: mi355_1
84
+ timeout_in_minutes: 45
85
+ working_dir: "/vllm-workspace/"
86
+ depends_on:
87
+ - image-build-amd
88
+ source_file_dependencies:
89
+ - tests/quantization/test_rocm_moe.py
90
+ - tests/utils.py
91
+ - vllm/model_executor/models/deepseek_v2.py
92
+ - vllm/model_executor/models/qwen3_moe.py
93
+ - vllm/model_executor/models/gpt_oss.py
94
+ - vllm/model_executor/model_loader/
95
+ - vllm/model_executor/layers/fused_moe/
96
+ - vllm/model_executor/layers/quantization/
97
+ - vllm/model_executor/kernels/linear/
98
+ - vllm/v1/attention/
99
+ - vllm/v1/worker/gpu/
100
+ - vllm/_aiter_ops.py
101
+ - vllm/platforms/rocm.py
102
+ - vllm/envs.py
103
+ commands:
104
+ - pytest -v -s tests/quantization/test_rocm_moe.py
105
106
- label: ":nvidia: (H200 MIG 35GB) Quantized Models"
107
device: h200_35gb
tests/quantization/test_rocm_moe.py
new
+146
@@ -0,0 +1,146 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+"""ROCm equivalents of the quantized-MoE model startup/generation contract.
4
+
5
+Like test_blackwell_moe.py, these tests use reduced models and dummy weights.
6
+They validate model/backend integration, not trained-model accuracy.
7
+"""
8
+
9
+import math
10
+
11
+import pytest
12
+
13
+from tests.utils import RemoteOpenAIServer
14
+from vllm.platforms import current_platform
15
+from vllm.platforms.rocm import on_gfx950
16
+
17
+pytestmark = pytest.mark.skipif(
18
+ not current_platform.is_rocm() or not on_gfx950(),
19
+ reason="ROCm FP8/MXFP4 model integration requires gfx950",
20
+)
21
+
22
+COMMON_OVERRIDES = {
23
+ "num_hidden_layers": 4,
24
+ "hidden_size": 512,
25
+ "intermediate_size": 1024,
26
+ "num_attention_heads": 8,
27
+ "num_key_value_heads": 2,
28
+}
29
+
30
+CASES = [
31
+ pytest.param(
32
+ "RedHatAI/DeepSeek-Coder-V2-Lite-Instruct-FP8",
33
+ "efe1ced428db63e7ccbcf367334596f77e9af140",
34
+ "triton",
35
+ "TRITON_MLA",
36
+ {
37
+ "n_routed_experts": 8,
38
+ "n_shared_experts": 1,
39
+ "num_experts_per_tok": 2,
40
+ "moe_intermediate_size": 512,
41
+ },
42
+ ["--code-revision", "e434a23f91ba5b4923cf6c9d9a238eb4a08e3a11"],
43
+ id="deepseek-fp8-per-tensor-triton",
44
+ ),
45
+ pytest.param(
46
+ "Qwen/Qwen3-30B-A3B-FP8",
47
+ "d206ba732169f29bb77fbf80fc2c4b81d4d30782",
48
+ "triton",
49
+ "TRITON_ATTN",
50
+ {
51
+ "num_experts": 8,
52
+ "num_experts_per_tok": 2,
53
+ "moe_intermediate_size": 512,
54
+ "head_dim": 64,
55
+ },
56
+ [],
57
+ id="qwen3-fp8-block-triton",
58
+ ),
59
+ pytest.param(
60
+ "openai/gpt-oss-20b",
61
+ "6cee5e81ee83917806bbde320786a8fb61efebee",
62
+ "aiter",
63
+ "TRITON_ATTN",
64
+ {
65
+ "num_local_experts": 8,
66
+ "num_experts_per_tok": 2,
67
+ "experts_per_token": 2,
68
+ "layer_types": ["sliding_attention", "full_attention"] * 2,
69
+ },
70
+ [],
71
+ id="gptoss-mxfp4-aiter",
72
+ ),
73
+]
74
+
75
+
76
+@pytest.mark.parametrize("enforce_eager", [True, False], ids=["eager", "compiled"])
77
+@pytest.mark.parametrize(
78
+ "model,revision,moe_backend,attention_backend,overrides,extra_args", CASES
79
+)
80
+def test_rocm_quantized_moe_generation(
81
+ model,
82
+ revision,
83
+ moe_backend,
84
+ attention_backend,
85
+ overrides,
86
+ extra_args,
87
+ enforce_eager,
88
+):
89
+ """Quantized MoE models warm up and return finite logits through serving."""
90
+ args = [
91
+ "--revision",
92
+ revision,
93
+ "--load-format",
94
+ "dummy",
95
+ "--trust-remote-code",
96
+ "--dtype",
97
+ "bfloat16",
98
+ "--max-model-len",
99
+ "2048",
100
+ "--max-num-batched-tokens",
101
+ "256",
102
+ "--max-num-seqs",
103
+ "8",
104
+ "--gpu-memory-utilization",
105
+ "0.02",
106
+ "--kv-cache-memory-bytes",
107
+ str(256 * 1024 * 1024),
108
+ "--moe-backend",
109
+ moe_backend,
110
+ "--attention-backend",
111
+ attention_backend,
112
+ *extra_args,
113
+ ]
114
+ if enforce_eager:
115
+ args.append("--enforce-eager")
116
+
117
+ with RemoteOpenAIServer(
118
+ model,
119
+ args,
120
+ env_dict={"VLLM_ROCM_USE_AITER": "1", "VLLM_USE_V2_MODEL_RUNNER": "1"},
121
+ override_hf_configs={**COMMON_OVERRIDES, **overrides},
122
+ max_wait_seconds=1200,
123
+ ) as server:
124
+ prompts = [[1, 2, 3], [1, 2, 3, 4] * 4 + [5]]
125
+ completion = server.get_client().completions.create(
126
+ model=model,
127
+ prompt=prompts,
128
+ temperature=0,
129
+ max_tokens=2,
130
+ logprobs=1,
131
+ extra_body={"ignore_eos": True, "skip_special_tokens": False},
132
+ )
133
+ assert len(completion.choices) == len(prompts)
134
+ assert completion.usage is not None
135
+ assert completion.usage.prompt_tokens == sum(map(len, prompts))
136
+ assert completion.usage.completion_tokens == 2 * len(prompts)
137
+ for choice in completion.choices:
138
+ assert choice.finish_reason == "length"
139
+ assert choice.text
140
+ assert choice.logprobs is not None
141
+ assert choice.logprobs.token_logprobs is not None
142
+ assert len(choice.logprobs.token_logprobs) == 2
143
+ assert all(
144
+ p is not None and math.isfinite(p)
145
+ for p in choice.logprobs.token_logprobs
146
+ )