A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 2, 18:15 UTC
[ROCm][Perf] Expose AITER MoE sorting dispatch policy via env var (#39177)
Signed-off-by: nholmber <nholmber@users.noreply.github.com>
Nico Holmberg committed
May 26, 2026 at 22:11 UTC
7b546902447c695c3a555a81352719710d4f1783
3 files changed
+32
vllm/_aiter_ops.py
+17
@@ -144,6 +144,7 @@ def _rocm_aiter_fused_moe_impl(
144
intermediate_pad: int = 0,
145
bias1: torch.Tensor | None = None,
146
bias2: torch.Tensor | None = None,
147
+ moe_sorting_dispatch_policy: int = 0,
148
) -> torch.Tensor:
149
from aiter import ActivationType, QuantType
150
from aiter.fused_moe import fused_moe
@@ -171,6 +172,7 @@ def _rocm_aiter_fused_moe_impl(
172
intermediate_pad=intermediate_pad,
173
bias1=bias1,
174
bias2=bias2,
175
+ moe_sorting_dispatch_policy=moe_sorting_dispatch_policy,
176
)
177
178
@@ -194,6 +196,7 @@ def _rocm_aiter_fused_moe_fake(
196
intermediate_pad: int = 0,
197
bias1: torch.Tensor | None = None,
198
bias2: torch.Tensor | None = None,
199
+ moe_sorting_dispatch_policy: int = 0,
200
) -> torch.Tensor:
201
if output_dtype is not None:
202
return torch.empty_like(hidden_states, dtype=output_dtype)
@@ -1282,6 +1285,18 @@ class rocm_aiter_ops:
1285
- Triton ops: triton_rotary_embed, triton_fp8_bmm, triton_gemm_a8w8_blockscale
1286
"""
1287
1288
+ _MOE_DISPATCH_POLICY: int | None = None
1289
+
1290
+ @classmethod
1291
+ @if_aiter_supported
1292
+ def get_moe_dispatch_policy(cls) -> int:
1293
+ """Cached MoE sorting dispatch policy."""
1294
+ if cls._MOE_DISPATCH_POLICY is None:
1295
+ import vllm.envs as envs
1296
+
1297
+ cls._MOE_DISPATCH_POLICY = envs.VLLM_ROCM_AITER_MOE_DISPATCH_POLICY
1298
+ return cls._MOE_DISPATCH_POLICY
1299
+
1300
# Check if the env variable is set
1301
_AITER_ENABLED = envs.VLLM_ROCM_USE_AITER
1302
_LINEAR_ENABLED = envs.VLLM_ROCM_USE_AITER_LINEAR
@@ -1890,6 +1905,7 @@ class rocm_aiter_ops:
1905
intermediate_pad: int = 0,
1906
bias1: torch.Tensor | None = None,
1907
bias2: torch.Tensor | None = None,
1908
+ moe_sorting_dispatch_policy: int = 0,
1909
) -> torch.Tensor:
1910
return torch.ops.vllm.rocm_aiter_fused_moe(
1911
hidden_states,
@@ -1911,6 +1927,7 @@ class rocm_aiter_ops:
1927
intermediate_pad,
1928
bias1,
1929
bias2,
1930
+ moe_sorting_dispatch_policy,
1931
)
1932
1933
@staticmethod
vllm/envs.py
+12
@@ -116,6 +116,7 @@ if TYPE_CHECKING:
116
VLLM_ROCM_USE_AITER_PAGED_ATTN: bool = False
117
VLLM_ROCM_USE_AITER_LINEAR: bool = True
118
VLLM_ROCM_USE_AITER_MOE: bool = True
119
+ VLLM_ROCM_AITER_MOE_DISPATCH_POLICY: int = 0
120
VLLM_ROCM_USE_AITER_RMSNORM: bool = True
121
VLLM_ROCM_USE_AITER_MLA: bool = True
122
VLLM_ROCM_USE_AITER_MHA: bool = True
@@ -1103,6 +1104,17 @@ environment_variables: dict[str, Callable[[], Any]] = {
1104
"VLLM_ROCM_USE_AITER_MOE": lambda: (
1105
os.getenv("VLLM_ROCM_USE_AITER_MOE", "True").lower() in ("true", "1")
1106
),
1107
+ # MoE sorting dispatch policy for AITER fused MoE kernels.
1108
+ # 0 = auto (default): single-pass for small batches, multi-pass
1109
+ # for large batches
1110
+ # 1 = always single-pass: one kernel launch, no workspace,
1111
+ # may be preferred for low-concurrency decode workloads
1112
+ # 2 = always multi-pass: can be faster for MoE-heavy models
1113
+ # (e.g., +2-5% on Qwen3-Next, +1.5% on DeepSeek-V3 at TP4,
1114
+ # see PR #39177 for benchmarks)
1115
+ "VLLM_ROCM_AITER_MOE_DISPATCH_POLICY": lambda: int(
1116
+ os.getenv("VLLM_ROCM_AITER_MOE_DISPATCH_POLICY", "0")
1117
+ ),
1118
# use aiter rms norm op if aiter ops are enabled.
1119
"VLLM_ROCM_USE_AITER_RMSNORM": lambda: (
1120
os.getenv("VLLM_ROCM_USE_AITER_RMSNORM", "True").lower() in ("true", "1")
vllm/model_executor/layers/fused_moe/experts/rocm_aiter_moe.py
+3
@@ -246,6 +246,7 @@ def rocm_aiter_fused_experts(
246
a1q_scale: torch.Tensor | None = None,
247
num_local_tokens: torch.Tensor | None = None,
248
output_dtype: torch.dtype | None = None,
249
+ moe_sorting_dispatch_policy: int = 0,
250
) -> torch.Tensor:
251
"""ROCm AITER fused MoE expert computation."""
252
if quant_config is None:
@@ -361,6 +362,7 @@ def rocm_aiter_fused_experts(
362
intermediate_pad=intermediate_pad // 64 * 64 * 2,
363
bias1=quant_config.w1_bias if quant_config.use_mxfp4_w4a16 else None,
364
bias2=quant_config.w2_bias if quant_config.use_mxfp4_w4a16 else None,
365
+ moe_sorting_dispatch_policy=moe_sorting_dispatch_policy,
366
)
367
368
@@ -504,6 +506,7 @@ class AiterExperts(mk.FusedMoEExpertsModular):
506
a1q_scale=a1q_scale,
507
num_local_tokens=num_local_tokens,
508
output_dtype=output.dtype,
509
+ moe_sorting_dispatch_policy=rocm_aiter_ops.get_moe_dispatch_policy(),
510
)
511
# avoid redundant copy when output is a view of the result
512
if (