[MoE] Plumb gemm1_alpha/beta/clamp_limit into TRT-LLM FP8 MoE

The FlashInfer FP8 block-scale MoE kernels (trtllm_fp8_block_scale_moe
and trtllm_fp8_block_scale_routed_moe) accept optional per-expert SwiGLU
parameters gemm1_alpha, gemm1_beta, gemm1_clamp_limit that realize the
OAI SwiGLU variant for MXFP8. The FP8 experts did not pass them.

- Build per-expert alpha/beta/clamp tensors in TrtLlmFp8ExpertsBase and
  pass them to the block-scale (monolithic) and routed (modular) kernels,
  mirroring the existing MXFP4 experts.
- Forward gemm1_alpha/gemm1_beta from layer.swiglu_alpha/beta in the
  MXFP8-capable FP8 quant-config builders (fp8, online mxfp8,
  compressed-tensors mxfp8). Previously only swiglu_limit was forwarded;
  only ModelOptMxfp8 forwarded all three, so other paths silently dropped
  alpha/beta.
- Add swigluoai_uninterleave to the supported activations (maps to
  FlashInfer Swiglu; the OAI behavior comes from the gemm1_* params).

Signed-off-by: Yongye Zhu <zyy1102000@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit f4b8540570)
This commit is contained in:
Yongye Zhu
2026-06-20 13:51:49 -07:00
committed by Roger Wang
parent 985d00a751
commit ef762c26e5
4 changed files with 52 additions and 3 deletions
@@ -56,6 +56,35 @@ class TrtLlmFp8ExpertsBase:
self.moe_config = moe_config
self.quant_config = quant_config
# Per-expert SwiGLU parameters from quant_config (MXFP8 + Swiglu only).
device = torch.accelerator.current_device_index()
if quant_config.gemm1_alpha is not None:
self.gemm1_alpha = torch.tensor(
[quant_config.gemm1_alpha] * self.local_num_experts,
dtype=torch.float32,
device=device,
)
else:
self.gemm1_alpha = None
if quant_config.gemm1_beta is not None:
self.gemm1_beta = torch.tensor(
[quant_config.gemm1_beta] * self.local_num_experts,
dtype=torch.float32,
device=device,
)
else:
self.gemm1_beta = None
if quant_config.gemm1_clamp_limit is not None:
self.gemm1_clamp_limit = torch.tensor(
[quant_config.gemm1_clamp_limit] * self.local_num_experts,
dtype=torch.float32,
device=device,
)
else:
self.gemm1_clamp_limit = None
@staticmethod
def activation_format() -> mk.FusedMoEActivationFormat:
return mk.FusedMoEActivationFormat.Standard
@@ -77,8 +106,12 @@ class TrtLlmFp8ExpertsBase:
@staticmethod
def _supports_activation(activation: MoEActivation) -> bool:
"""Supports only SiLU and RELU^2 non-gated activation."""
return activation in [MoEActivation.SILU, MoEActivation.RELU2_NO_MUL]
"""Supports SiLU, SwiGLU-OAI (uninterleaved), and RELU^2 non-gated."""
return activation in [
MoEActivation.SILU,
MoEActivation.SWIGLUOAI_UNINTERLEAVE,
MoEActivation.RELU2_NO_MUL,
]
@staticmethod
def _supports_parallel_config(moe_parallel_config: FusedMoEParallelConfig) -> bool:
@@ -198,6 +231,9 @@ class TrtLlmFp8ExpertsModular(TrtLlmFp8ExpertsBase, mk.FusedMoEExpertsModular):
hidden_states_scale=hidden_states_scale,
gemm1_weights=w1,
gemm1_weights_scale=self.quant_config.w1_scale,
gemm1_alpha=self.gemm1_alpha,
gemm1_beta=self.gemm1_beta,
gemm1_clamp_limit=self.gemm1_clamp_limit,
gemm2_weights=w2,
gemm2_weights_scale=self.quant_config.w2_scale,
num_experts=global_num_experts,
@@ -327,7 +363,11 @@ class TrtLlmFp8ExpertsMonolithic(TrtLlmFp8ExpertsBase, mk.FusedMoEExpertsMonolit
from flashinfer.fused_moe import Fp8QuantizationType, WeightLayout
assert not apply_router_weight_on_input
assert activation in [MoEActivation.SILU, MoEActivation.RELU2_NO_MUL]
assert activation in [
MoEActivation.SILU,
MoEActivation.SWIGLUOAI_UNINTERLEAVE,
MoEActivation.RELU2_NO_MUL,
]
activation_type = activation_to_flashinfer_int(activation)
assert self.topk <= global_num_experts
assert global_num_experts % 4 == 0
@@ -362,6 +402,9 @@ class TrtLlmFp8ExpertsMonolithic(TrtLlmFp8ExpertsBase, mk.FusedMoEExpertsMonolit
hidden_states_scale=hidden_states_scale,
gemm1_weights=w1,
gemm1_weights_scale=self.quant_config.w1_scale,
gemm1_alpha=self.gemm1_alpha,
gemm1_beta=self.gemm1_beta,
gemm1_clamp_limit=self.gemm1_clamp_limit,
gemm2_weights=w2,
gemm2_weights_scale=self.quant_config.w2_scale,
num_experts=global_num_experts,
@@ -153,6 +153,8 @@ class CompressedTensorsW8A8Mxfp8MoEMethod(CompressedTensorsMoEMethod):
a2_scale=layer.w2_input_scale,
block_shape=self.weight_block_size,
swiglu_limit=getattr(layer, "swiglu_limit", None),
gemm1_alpha=getattr(layer, "swiglu_alpha", None),
gemm1_beta=getattr(layer, "swiglu_beta", None),
)
def maybe_make_prepare_finalize(
@@ -224,6 +224,8 @@ class Mxfp8OnlineMoEMethod(OnlineMoEMethodBase):
w2_bias=getattr(layer, "w2_bias", None),
block_shape=self.weight_block_size,
swiglu_limit=getattr(layer, "swiglu_limit", None),
gemm1_alpha=getattr(layer, "swiglu_alpha", None),
gemm1_beta=getattr(layer, "swiglu_beta", None),
)
def process_weights_after_loading(self, layer: Module) -> None:
@@ -33,6 +33,8 @@ def activation_to_flashinfer_type(activation: MoEActivation) -> "ActivationType"
MoEActivation.SILU_NO_MUL: ActivationType.Silu,
MoEActivation.GELU_NO_MUL: ActivationType.Gelu,
MoEActivation.SILU: ActivationType.Swiglu,
# SwiGLU-OAI uses Swiglu; the OAI alpha/beta/clamp come from gemm1_* args.
MoEActivation.SWIGLUOAI_UNINTERLEAVE: ActivationType.Swiglu,
MoEActivation.GELU: ActivationType.Geglu,
MoEActivation.GELU_TANH: ActivationType.Geglu,
MoEActivation.RELU2_NO_MUL: ActivationType.Relu2,