Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 46 additions & 68 deletions aiter/fused_moe.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import re
from collections.abc import Callable
from dataclasses import dataclass
from enum import Enum

import torch

Expand All @@ -32,20 +31,7 @@
)
from aiter.jit.utils.torch_guard import torch_compile_guard
from aiter.ops.flydsl.kernels.mega_moe_gfx1250.types import Stage2ScatterContext

try:
from aiter.ops.flydsl.moe_common import GateMode
from aiter.ops.flydsl.utils import is_flydsl_available
except ImportError:

class GateMode(Enum):
SEPARATED = "separated"
INTERLEAVE = "interleave"

def is_flydsl_available():
return False


from aiter.ops.flydsl.moe_common import GateMode
from aiter.ops.flydsl.mxfp4_kname import (
_is_mxfp4_kname,
_parse_mxfp4_g1_kname,
Expand Down Expand Up @@ -368,7 +354,6 @@ def moe_sorting(
if (
not _USE_CK_MOE_SORTING
and _USE_FLYDSL_MOE_SORTING
and is_flydsl_available()
and not return_local_topk_ids
and not flat
and not output_aux
Expand Down Expand Up @@ -824,47 +809,46 @@ def _fused_moe_impl(
q_dtype_a = _q_dtype_a

grouped_a8w4_out = None
if is_flydsl_available():
try:
from aiter.ops.flydsl.grouped_moe_gfx1250 import (
grouped_gemm_gfx1250_a8w4,
)
except ImportError:
grouped_gemm_gfx1250_a8w4 = None

# grouped_gemm_gfx1250_a8w4 reads GUGU (gate/up row-interleaved) w1 only,
# so it is reachable exclusively from GateMode.INTERLEAVE. SEPARATED
# weights fall through to the generic MoE below.
if grouped_gemm_gfx1250_a8w4 is not None and gate_mode == GateMode.INTERLEAVE:
grouped_a8w4_out = grouped_gemm_gfx1250_a8w4(
hidden_states,
w1,
w2,
topk_weight,
topk_ids,
E=E,
model_dim=model_dim,
inter_dim=inter_dim,
dtype=dtype,
activation=activation,
quant_type=quant_type,
q_dtype_a=q_dtype_a,
q_dtype_w=q_dtype_w,
isG1U1=isG1U1,
doweight_stage1=doweight_stage1,
w1_scale=w1_scale,
w2_scale=w2_scale,
expert_mask=expert_mask,
hidden_pad=hidden_pad,
intermediate_pad=intermediate_pad,
bias1=bias1,
bias2=bias2,
swiglu_limit=swiglu_limit,
num_local_tokens=num_local_tokens,
situ_beta=1.0 if beta is None else float(beta),
situ_linear_beta=1.0 if linear_beta is None else float(linear_beta),
stage2_scatter=stage2_scatter,
)
try:
from aiter.ops.flydsl.grouped_moe_gfx1250 import (
grouped_gemm_gfx1250_a8w4,
)
except ImportError:
grouped_gemm_gfx1250_a8w4 = None

# grouped_gemm_gfx1250_a8w4 reads GUGU (gate/up row-interleaved) w1 only,
# so it is reachable exclusively from GateMode.INTERLEAVE. SEPARATED
# weights fall through to the generic MoE below.
if grouped_gemm_gfx1250_a8w4 is not None and gate_mode == GateMode.INTERLEAVE:
grouped_a8w4_out = grouped_gemm_gfx1250_a8w4(
hidden_states,
w1,
w2,
topk_weight,
topk_ids,
E=E,
model_dim=model_dim,
inter_dim=inter_dim,
dtype=dtype,
activation=activation,
quant_type=quant_type,
q_dtype_a=q_dtype_a,
q_dtype_w=q_dtype_w,
isG1U1=isG1U1,
doweight_stage1=doweight_stage1,
w1_scale=w1_scale,
w2_scale=w2_scale,
expert_mask=expert_mask,
hidden_pad=hidden_pad,
intermediate_pad=intermediate_pad,
bias1=bias1,
bias2=bias2,
swiglu_limit=swiglu_limit,
num_local_tokens=num_local_tokens,
situ_beta=1.0 if beta is None else float(beta),
situ_linear_beta=1.0 if linear_beta is None else float(linear_beta),
stage2_scatter=stage2_scatter,
)

if grouped_a8w4_out is not None:
return grouped_a8w4_out
Expand All @@ -879,10 +863,10 @@ def _fused_moe_impl(
if _is_a16w4_situv2:
for _bad, _why in (
(
get_gfx() not in ("gfx942", "gfx950") or not is_flydsl_available(),
get_gfx() not in ("gfx942", "gfx950"),
(
f"requires the FlyDSL kernel on CDNA gfx942/gfx950 "
f"(gfx={get_gfx()!r}, flydsl_available={is_flydsl_available()})"
f"(gfx={get_gfx()!r})"
),
),
(bias1 is not None or bias2 is not None, "per-expert bias"),
Expand Down Expand Up @@ -2562,7 +2546,7 @@ def get_block_m() -> int:
is_opus1 = isinstance(kernelName1, str) and kernelName1.startswith("opus_moe1_")
is_cktile2 = isinstance(kernelName2, str) and kernelName2.startswith("cktile_")
is_opus2 = _opus_a8w4.is_opus_a8w4_stage2_kernel(kernelName2)
if is_opus1 or ((is_flydsl1 or is_flydsl2) and is_flydsl_available()):
if is_opus1 or is_flydsl1 or is_flydsl2:
enable_bias = (
_needs_swiglu_bias_support(dtype, q_type) and q_dtype_w == dtypes.fp4x2
)
Expand Down Expand Up @@ -2690,11 +2674,7 @@ def get_block_m() -> int:
and q_dtype_w == dtypes.fp4x2
and is_shuffled
)
if (
q_type == QuantType.per_1x32
and q_dtype_w == dtypes.i4x2
and is_flydsl_available()
):
if q_type == QuantType.per_1x32 and q_dtype_w == dtypes.i4x2:
# Untuned a16wi4 fallback: one shape-safe config on the shared a16w-mix port.
# Tiles belong in the tuned CSV, not in a heuristic here. ksplit is 0 because
# the port has no grid split-K (it uses intra-block k_wave); asking for it
Expand Down Expand Up @@ -2743,7 +2723,6 @@ def get_block_m() -> int:
and is_shuffled
and use_g1u1
and not doweight_stage1
and is_flydsl_available()
)
use_mxfp4_flydsl = _is_a16w4_situv2 or (
dtype in [dtypes.bf16, dtypes.fp16]
Expand All @@ -2759,7 +2738,6 @@ def get_block_m() -> int:
and is_shuffled
and use_g1u1
and not doweight_stage1
and is_flydsl_available()
)
if use_mxfp4_flydsl:
from aiter.ops.flydsl.moe_kernels import (
Expand Down Expand Up @@ -2926,7 +2904,7 @@ def get_block_m() -> int:
]
)
):
if kernelName2 and kernelName2.startswith("flydsl_") and is_flydsl_available():
if kernelName2 and kernelName2.startswith("flydsl_"):
stage2_func = functools.partial(
_flydsl_stage2_wrapper,
kernelName=kernelName2,
Expand Down
9 changes: 9 additions & 0 deletions aiter/jit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ def mp_lock(
f"{AITER_ROOT_DIR}/aiter/configs/bf16_tuned_gemm.csv",
)

AITER_CONFIG_GDR_DECODE = os.getenv(
"AITER_CONFIG_GDR_DECODE",
f"{AITER_ROOT_DIR}/aiter/configs/gdr_decode_tuned.csv",
)

# K5 opt BV tuned config. Per-model tuned rows live under model_configs/
# (qwen3_5_*_chunk_gdn_h_opt_tuned.csv) and get merged into this canonical file by
# get_config_file. It ships header-only: with no per-model table present
Expand Down Expand Up @@ -247,6 +252,10 @@ def AITER_CONFIG_GEMM_BF16_FILE(self):
"AITER_CONFIG_GEMM_BF16", AITER_CONFIG_GEMM_BF16, "bf16_tuned_gemm"
)

@property
def AITER_CONFIG_GDR_DECODE_FILE(self):
return AITER_CONFIG_GDR_DECODE

@property
def AITER_CONFIG_GDN_K5_OPT_FILE(self):
return self.get_config_file(
Expand Down
9 changes: 2 additions & 7 deletions aiter/mla.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@

@functools.lru_cache(maxsize=1)
def _flydsl_mla_reduce_available() -> bool:
"""Whether the optional FlyDSL package is available on this device."""
try:
from aiter.ops.flydsl import is_flydsl_available

return is_flydsl_available()
except (ImportError, OSError, RuntimeError):
return False
"""Whether FlyDSL MLA reduce is supported on this device."""
return get_gfx() in _FLYDSL_MLA_REDUCE_TARGET_GFX


def _flydsl_mla_reduce_supported(
Expand Down
120 changes: 53 additions & 67 deletions aiter/ops/flydsl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,67 @@
# SPDX-License-Identifier: MIT
# Copyright (C) 2024-2026, Advanced Micro Devices, Inc. All rights reserved.

"""FlyDSL -- high-performance GPU kernels implemented using FlyDSL.

Kernel compilation and public APIs are only available when a compatible
``flydsl`` package is installed. Use ``is_flydsl_available()`` to check
whether the optional dependency exists before relying on FlyDSL kernels.
"""
"""FlyDSL -- high-performance GPU kernels implemented using FlyDSL."""

import flydsl as _flydsl
from packaging.version import Version

from .moe_common import GateMode
from .utils import is_flydsl_available

_MIN_FLYDSL_VERSION = Version("0.2.4")

__all__ = [
"GateMode",
"is_flydsl_available",
]

if is_flydsl_available():
import flydsl as _flydsl

installed_flydsl_version = getattr(_flydsl, "__version__", None)
if installed_flydsl_version is None:
raise ImportError(
"`flydsl` is importable but its version cannot be determined."
)
installed_flydsl_version = getattr(_flydsl, "__version__", None)
if installed_flydsl_version is None:
raise ImportError("`flydsl` is importable but its version cannot be determined.")

_base_version = Version(installed_flydsl_version.split("+")[0])
if _base_version < _MIN_FLYDSL_VERSION:
raise ImportError(
"Unsupported `flydsl` version: "
f"expected >=`{_MIN_FLYDSL_VERSION}`, "
f"got `{installed_flydsl_version}`."
)

from .fmha_kernels import flydsl_flash_attn_func
from .gemm_kernels import flydsl_hgemm, flydsl_preshuffle_gemm_a8
from .kernels.mqa_logits.fp8_mqa_logits import (
DEFAULT_VARIANT as FP8_MQA_LOGITS_DEFAULT_VARIANT,
)
from .kernels.mqa_logits.fp8_mqa_logits import (
KERNEL_VARIANTS as FP8_MQA_LOGITS_VARIANTS,
_base_version = Version(installed_flydsl_version.split("+")[0])
if _base_version < _MIN_FLYDSL_VERSION:
raise ImportError(
"Unsupported `flydsl` version: "
f"expected >=`{_MIN_FLYDSL_VERSION}`, "
f"got `{installed_flydsl_version}`."
)
from .kernels.mqa_logits.fp8_mqa_logits import (
flydsl_fp8_mqa_logits,
)
from .kernels.mqa_logits.pa_mqa_logits_fp4 import (
flydsl_pa_mqa_logits_fp4,
)
from .kernels.mqa_logits.pa_mqa_logits_fp4_prefill import (
compute_varqlen_windows,
flydsl_pa_mqa_logits_fp4_prefill,
flydsl_pa_mqa_logits_fp4_varqlen,
)
from .kernels.qk_norm_rope_quant import flydsl_qk_norm_rope_quant
from .mla_reduce_kernels import flydsl_mla_reduce_v1
from .moe_kernels import flydsl_moe_stage1, flydsl_moe_stage2

# from .linear_attention_kernels import flydsl_gdr_decode
from .fmha_kernels import flydsl_flash_attn_func
from .gemm_kernels import flydsl_hgemm, flydsl_preshuffle_gemm_a8
from .kernels.mqa_logits.fp8_mqa_logits import (
DEFAULT_VARIANT as FP8_MQA_LOGITS_DEFAULT_VARIANT,
)
from .kernels.mqa_logits.fp8_mqa_logits import (
KERNEL_VARIANTS as FP8_MQA_LOGITS_VARIANTS,
)
from .kernels.mqa_logits.fp8_mqa_logits import (
flydsl_fp8_mqa_logits,
)
from .kernels.mqa_logits.pa_mqa_logits_fp4 import (
flydsl_pa_mqa_logits_fp4,
)
from .kernels.mqa_logits.pa_mqa_logits_fp4_prefill import (
compute_varqlen_windows,
flydsl_pa_mqa_logits_fp4_prefill,
flydsl_pa_mqa_logits_fp4_varqlen,
)
from .kernels.qk_norm_rope_quant import flydsl_qk_norm_rope_quant
from .mla_reduce_kernels import flydsl_mla_reduce_v1
from .moe_kernels import flydsl_moe_stage1, flydsl_moe_stage2

# from .linear_attention_kernels import flydsl_gdr_decode

__all__ += [
"FP8_MQA_LOGITS_DEFAULT_VARIANT",
"FP8_MQA_LOGITS_VARIANTS",
"compute_varqlen_windows",
"flydsl_flash_attn_func",
"flydsl_fp8_mqa_logits",
"flydsl_hgemm",
"flydsl_mla_reduce_v1",
"flydsl_moe_stage1",
"flydsl_moe_stage2",
"flydsl_pa_mqa_logits_fp4",
"flydsl_pa_mqa_logits_fp4_prefill",
"flydsl_pa_mqa_logits_fp4_varqlen",
"flydsl_preshuffle_gemm_a8",
"flydsl_qk_norm_rope_quant",
# "flydsl_gdr_decode",
]
__all__ = [
"FP8_MQA_LOGITS_DEFAULT_VARIANT",
"FP8_MQA_LOGITS_VARIANTS",
"GateMode",
"compute_varqlen_windows",
"flydsl_flash_attn_func",
"flydsl_fp8_mqa_logits",
"flydsl_hgemm",
"flydsl_mla_reduce_v1",
"flydsl_moe_stage1",
"flydsl_moe_stage2",
"flydsl_pa_mqa_logits_fp4",
"flydsl_pa_mqa_logits_fp4_prefill",
"flydsl_pa_mqa_logits_fp4_varqlen",
"flydsl_preshuffle_gemm_a8",
"flydsl_qk_norm_rope_quant",
# "flydsl_gdr_decode",
]
Loading