[ROCm][aiter] officially supporting aiter Triton kernels+dsv4 on RDNA3 (#52970)

Signed-off-by: xawang <xawang@amd.com>
Signed-off-by: skysnow2001 <skysnow9285@gmail.com>
Co-authored-by: skysnow2001 <skysnow9285@gmail.com>
Co-authored-by: keneoneth <keneoneth18@gmail.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-10-27 17:01:13 +00:00
1 parent 94ad4dfbae
commit eaf1627c01
8 files changed
+45 -33

No files matched your search

+23 -14
View File
@@ -238,6 +238,15 @@ def is_aiter_found_and_supported_on_rdna4() -> bool:
return False
def is_aiter_found_and_supported_on_rdna() -> bool:
"""RDNA (gfx11 + gfx12) analog of `is_aiter_found_and_supported()`."""
if current_platform.is_rocm() and IS_AITER_FOUND:
from vllm.platforms.rocm import on_rdna
return on_rdna()
return False
def _triton_gemm_config_is_tuned(config_name: str, N: int, K: int) -> bool:
from aiter.ops.triton.utils.gemm_config_utils import get_gemm_config
@@ -2290,20 +2299,20 @@ class rocm_aiter_ops:
@classmethod
def is_rdna_aiter_enabled(cls) -> bool:
"""AITER on RDNA4 (gfx12): library present, arch is rdna4, and the user
enabled aiter. Only aiter's Triton kernels exist on gfx12 (no CK build),
so this deliberately stays off the gfx9/CK `@if_aiter_supported` umbrella
and gates only the Triton paths rdna4 uses. The gfx12 analog of
"""AITER on RDNA: library present, arch is RDNA, and the user enabled
aiter. Only aiter's Triton kernels exist on RDNA (no CK build), so this
deliberately stays off the gfx9/CK `@if_aiter_supported` umbrella and
gates only the Triton paths RDNA uses. The RDNA analog of
`is_enabled()`."""
if not current_platform.is_rocm() or not IS_AITER_FOUND:
return False
from vllm.platforms.rocm import on_rdna4
from vllm.platforms.rocm import on_rdna
return on_rdna4() and cls._AITER_ENABLED
return on_rdna() and cls._AITER_ENABLED
@classmethod
def is_rdna_linear_enabled(cls) -> bool:
"""RDNA4 (gfx12) analog of is_linear_enabled() (aiter Triton blockscale)."""
"""RDNA analog of is_linear_enabled() (aiter Triton blockscale)."""
return cls.is_rdna_aiter_enabled() and cls._LINEAR_ENABLED
@classmethod
@@ -2840,8 +2849,8 @@ class rocm_aiter_ops:
)
@classmethod
def is_rdna_gdn_triton_kernels_available(cls) -> bool:
"""RDNA4 (gfx12) analog of are_gdn_triton_kernels_available()."""
def are_rdna_gdn_triton_kernels_available(cls) -> bool:
"""RDNA analog of are_gdn_triton_kernels_available()."""
return cls.is_rdna_aiter_enabled() and cls._gdn_triton_kernels_importable()
@classmethod
@@ -3024,16 +3033,16 @@ class rocm_aiter_ops:
global _OPS_REGISTERED
if not (
is_aiter_found_and_supported() or is_aiter_found_and_supported_on_rdna4()
is_aiter_found_and_supported() or is_aiter_found_and_supported_on_rdna()
):
if not current_platform.is_rocm():
return
from vllm.platforms.rocm import on_gfx11, on_gfx950
from vllm.platforms.rocm import on_gfx950
# This op has self-contained Triton/C++ implementations on gfx11
# and gfx950. Only its optional top-k fast path comes from aiter.
if (on_gfx11() or on_gfx950()) and not _OPS_REGISTERED:
# This op has self-contained Triton/C++ implementations on gfx950.
# Only its optional top-k fast path comes from aiter.
if on_gfx950() and not _OPS_REGISTERED:
direct_register_custom_op(
op_name="rocm_aiter_sparse_attn_indexer",
op_func=rocm_aiter_sparse_attn_indexer,
@@ -733,7 +733,7 @@ class RocmAiterRMSNormQuantFusionPass(VllmPatternMatcherPass):
gated_norm_shapes.add((num_v_heads // layer.tp_size, head_v_dim))
# RDNA4 uses native quant ops and supports only Triton replacements.
# RDNA uses native quant ops and supports only Triton replacements.
match_aiter_quant_op = not rocm_aiter_ops.is_rdna_aiter_enabled()
# Make sure fused add patterns are before simple rms norm,
@@ -804,7 +804,7 @@ class RocmAiterRMSNormQuantFusionPass(VllmPatternMatcherPass):
# an aiter version that includes the GDN triton kernel renames.
if gated_norm_shapes and (
rocm_aiter_ops.are_gdn_triton_kernels_available()
or rocm_aiter_ops.is_rdna_gdn_triton_kernels_available()
or rocm_aiter_ops.are_rdna_gdn_triton_kernels_available()
):
for num_heads, head_dim in gated_norm_shapes:
if head_dim != 128:
@@ -464,9 +464,9 @@ class AiterFp8BlockScaledMMKernel(Fp8BlockScaledMMLinearKernel):
"quantization with group_shape=(1,128).",
)
# RDNA4 (gfx12) only has the aiter Triton blockscale backend, which
# needs a per-(N,K) tune. Reject untuned shapes so the dispatcher falls
# through to the generic backend.
# RDNA only has the aiter Triton blockscale backend, which needs a
# per-(N,K) tune. Reject untuned shapes so the dispatcher falls through
# to the generic backend.
if rocm_aiter_ops.is_rdna_linear_enabled():
n, k = config.weight_shape
if not rocm_aiter_ops.is_triton_gemm_w8a8_tuned(n, k):
@@ -93,7 +93,7 @@ from vllm.v1.worker.workspace import current_workspace_manager
# import overhead.
GDN_AITER_TRITON_AVAILABLE = (
rocm_aiter_ops.are_gdn_triton_kernels_available()
or rocm_aiter_ops.is_rdna_gdn_triton_kernels_available()
or rocm_aiter_ops.are_rdna_gdn_triton_kernels_available()
)
if GDN_AITER_TRITON_AVAILABLE:
@@ -1171,12 +1171,11 @@ class SparseAttnIndexer(CustomOp):
assert isinstance(q_quant, torch.Tensor), (
"AMD sparse_attn_indexer expects a single FP8 q_quant tensor"
)
from vllm.platforms.rocm import on_gfx11, on_gfx950
from vllm.platforms.rocm import on_gfx950
if (
rocm_aiter_ops.is_enabled()
or rocm_aiter_ops.is_rdna_aiter_enabled()
or on_gfx11()
# The so-called AITER sparse indexer op has a native gfx950 path:
# its cache insert, MQA logits, and top-k fallbacks are implemented
# by local Triton/C++ kernels and do not require the aiter package.
@@ -1204,7 +1203,7 @@ class SparseAttnIndexer(CustomOp):
)
raise RuntimeError(
"Sparse attention indexer ROCm path requires AITER or a supported "
"native architecture (gfx950/gfx11)."
"native architecture (gfx950)."
)
def forward_cpu(
+2 -2
View File
@@ -35,7 +35,7 @@ from vllm.models.deepseek_v4.sparse_mla import (
DeepseekV4SparseMLAMetadataBuilder,
)
from vllm.platforms import current_platform
from vllm.platforms.rocm import _ON_GFX950, on_gfx1250
from vllm.platforms.rocm import _ON_GFX950, on_gfx1250, on_rdna
from vllm.triton_utils import tl, triton
from vllm.utils.multi_stream_utils import execute_in_parallel
from vllm.v1.attention.backend import (
@@ -1489,7 +1489,7 @@ class DeepseekV4ROCMAiterMLAAttention(DeepseekV4Attention):
)
rotated = 0
if num_decodes > 0:
fuse_decode_inv_rope = fuse_inv_rope and not on_gfx1250()
fuse_decode_inv_rope = fuse_inv_rope and not on_gfx1250() and not on_rdna()
rotated = self._forward_decode(
q=q[:num_decode_tokens],
positions=(
+5 -3
View File
@@ -559,8 +559,11 @@ def _get_backend_priorities(
backends.append(AttentionBackendEnum.ROCM_AITER_FA)
if is_aiter_found_and_supported():
backends.append(AttentionBackendEnum.ROCM_AITER_UNIFIED_ATTN)
elif rocm_aiter_ops.is_rdna_aiter_enabled():
backends.insert(0, AttentionBackendEnum.ROCM_AITER_UNIFIED_ATTN)
if rocm_aiter_ops.is_rdna_aiter_enabled():
if on_rdna4():
backends.insert(0, AttentionBackendEnum.ROCM_AITER_UNIFIED_ATTN)
else:
backends.append(AttentionBackendEnum.ROCM_AITER_UNIFIED_ATTN)
backends.append(AttentionBackendEnum.TRITON_ATTN)
backends.append(AttentionBackendEnum.TURBOQUANT)
backends.append(AttentionBackendEnum.ROCM_OCTAVE)
@@ -1422,7 +1425,6 @@ class RocmPlatform(Platform):
cc.cudagraph_mode != CUDAGraphMode.NONE
and envs.VLLM_ROCM_USE_AITER
and envs.VLLM_ROCM_USE_AITER_RMSNORM
and not on_rdna4()
and not on_gfx90a() # AITER not built for gfx90a, rmsnorm -> SEGV.
):
rms_norm = ["aiter"] + default
@@ -23,10 +23,12 @@ from vllm.v1.attention.ops.common import pack_seq_triton, unpack_seq_triton
from vllm.v1.worker.workspace import current_workspace_manager
if current_platform.is_rocm():
from vllm.platforms.rocm import _ON_GFX942, _ON_GFX950
from vllm.platforms.rocm import _ON_GFX942, _ON_GFX950, _ON_GFX1151, _ON_RDNA
else:
_ON_GFX942 = False
_ON_GFX950 = False
_ON_GFX1151 = False
_ON_RDNA = False
logger = init_logger(__name__)
@@ -709,7 +711,7 @@ def paged_mqa_logits_module():
str(error),
)
return None
if _ON_GFX942 or _ON_GFX950:
if _ON_GFX942 or _ON_GFX950 or (_ON_RDNA and not _ON_GFX1151):
function_name = "deepgemm_fp8_paged_mqa_logits"
required_parameters = {
"Preshuffle",
@@ -812,7 +814,7 @@ def rocm_fp8_paged_mqa_logits(
aiter_paged_mqa_logits_module = paged_mqa_logits_module()
if aiter_paged_mqa_logits_module is not None:
if _ON_GFX942 or _ON_GFX950:
if _ON_GFX942 or _ON_GFX950 or (_ON_RDNA and not _ON_GFX1151):
logger.info_once(
"Using AITER paged-MQA logits from %s.",
aiter_paged_mqa_logits_module.__name__,
@@ -833,7 +835,7 @@ def rocm_fp8_paged_mqa_logits(
block_tables,
max_model_len,
ChunkK=256,
Preshuffle=block_size > 1,
Preshuffle=block_size > 1 and not _ON_RDNA,
KVBlockSize=block_size,
WavePerEU=2,
)
@@ -1339,7 +1341,7 @@ def rocm_aiter_sparse_attn_indexer(
# Decode logits buffer, used by rocm_fp8_paged_mqa_logits.
decode_rows = _max_decode_logits_rows(hidden_states.shape[0])
if _ON_GFX942 or _ON_GFX950:
if _ON_GFX942 or _ON_GFX950 or _ON_RDNA:
workspace_manager.get_simultaneous(
((decode_rows, max_model_len), torch.float32),
)