[Kimi-K3] Use explicit SiTU activation for MegaMoE (#34883)
This commit is contained in:
@@ -69,7 +69,7 @@ dependencies = [
|
|||||||
"sentencepiece",
|
"sentencepiece",
|
||||||
"setproctitle",
|
"setproctitle",
|
||||||
"sgl-deep-ep==0.1.0",
|
"sgl-deep-ep==0.1.0",
|
||||||
"sgl-deep-gemm==0.1.5.post2",
|
"sgl-deep-gemm==0.1.5.post3",
|
||||||
"sglang-kernel==0.4.6.post1",
|
"sglang-kernel==0.4.6.post1",
|
||||||
"smg-grpc-servicer>=0.5.0",
|
"smg-grpc-servicer>=0.5.0",
|
||||||
"soundfile==0.13.1",
|
"soundfile==0.13.1",
|
||||||
|
|||||||
@@ -342,6 +342,10 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
# Weights stay MXFP4 (e2m1 + ue8m0 g32, zero requantization);
|
# Weights stay MXFP4 (e2m1 + ue8m0 g32, zero requantization);
|
||||||
# activations are quantized to fp8 per-token-group-128.
|
# activations are quantized to fp8 per-token-group-128.
|
||||||
self.use_deep_gemm = get_moe_runner_backend().is_deep_gemm()
|
self.use_deep_gemm = get_moe_runner_backend().is_deep_gemm()
|
||||||
|
# MegaMoE calls DeepGEMM directly instead of going through the selected
|
||||||
|
# MoE runner, so it needs the same unpadded checkpoint layout and
|
||||||
|
# DeepGEMM scale preparation even when the runner is flashinfer_mxfp4.
|
||||||
|
self.use_mega_moe = get_moe_a2a_backend().is_megamoe()
|
||||||
self.flashinfer_mxfp4_moe_precision = (
|
self.flashinfer_mxfp4_moe_precision = (
|
||||||
get_exec().moe.flashinfer_mxfp4_moe_precision
|
get_exec().moe.flashinfer_mxfp4_moe_precision
|
||||||
)
|
)
|
||||||
@@ -392,7 +396,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
# pad the intermediate size to be a multiple of 2 * mxfp4_block
|
# pad the intermediate size to be a multiple of 2 * mxfp4_block
|
||||||
# for to hold non-uniform sharded tensor as well as swizzling
|
# for to hold non-uniform sharded tensor as well as swizzling
|
||||||
intermediate_size_per_partition_after_pad = intermediate_size_per_partition
|
intermediate_size_per_partition_after_pad = intermediate_size_per_partition
|
||||||
if self.use_marlin:
|
if self.use_marlin and not self.use_mega_moe:
|
||||||
intermediate_size_per_partition_after_pad = round_up(
|
intermediate_size_per_partition_after_pad = round_up(
|
||||||
intermediate_size_per_partition, 128
|
intermediate_size_per_partition, 128
|
||||||
)
|
)
|
||||||
@@ -402,7 +406,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
intermediate_size_per_partition_after_pad
|
intermediate_size_per_partition_after_pad
|
||||||
- layer.intermediate_size_per_partition
|
- layer.intermediate_size_per_partition
|
||||||
)
|
)
|
||||||
elif self.use_deep_gemm:
|
elif self.use_deep_gemm or self.use_mega_moe:
|
||||||
# DeepGEMM fp8_fp4 grouped GEMM consumes the checkpoint layout
|
# DeepGEMM fp8_fp4 grouped GEMM consumes the checkpoint layout
|
||||||
# directly (packed e2m1 K-major + ue8m0 g32 scales); no padding.
|
# directly (packed e2m1 K-major + ue8m0 g32 scales); no padding.
|
||||||
pass
|
pass
|
||||||
@@ -544,7 +548,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
set_weight_attrs(w2_weight_bias, extra_weight_attrs)
|
set_weight_attrs(w2_weight_bias, extra_weight_attrs)
|
||||||
|
|
||||||
def process_weights_after_loading(self, layer):
|
def process_weights_after_loading(self, layer):
|
||||||
if self.use_marlin:
|
if self.use_marlin and not self.use_mega_moe:
|
||||||
from sglang.srt.layers.quantization.marlin_utils import (
|
from sglang.srt.layers.quantization.marlin_utils import (
|
||||||
check_moe_marlin_supports_layer,
|
check_moe_marlin_supports_layer,
|
||||||
)
|
)
|
||||||
@@ -572,7 +576,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
layer._mxfp4_backend = "marlin"
|
layer._mxfp4_backend = "marlin"
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.use_deep_gemm:
|
if self.use_deep_gemm or self.use_mega_moe:
|
||||||
from deep_gemm import transform_sf_into_required_layout
|
from deep_gemm import transform_sf_into_required_layout
|
||||||
|
|
||||||
# Packed fp4 (e2m1 x2 per byte) weights: DeepGEMM expects int8.
|
# Packed fp4 (e2m1 x2 per byte) weights: DeepGEMM expects int8.
|
||||||
@@ -597,7 +601,7 @@ class Mxfp4MoEMethod(FusedMoEMethodBase):
|
|||||||
num_groups=num_experts,
|
num_groups=num_experts,
|
||||||
disable_ue8m0_cast=False,
|
disable_ue8m0_cast=False,
|
||||||
)
|
)
|
||||||
if get_moe_a2a_backend().is_megamoe():
|
if self.use_mega_moe:
|
||||||
# MegaMoE consumes the same transformed sf, plus its own
|
# MegaMoE consumes the same transformed sf, plus its own
|
||||||
# interleaved/UTCCP weight layout. K3 routes EVERY batch
|
# interleaved/UTCCP weight layout. K3 routes EVERY batch
|
||||||
# through mega (the megamoe backend has no a2a fallback), so
|
# through mega (the megamoe backend has no a2a fallback), so
|
||||||
|
|||||||
@@ -141,14 +141,6 @@ def _cdiv(a: int, b: int) -> int:
|
|||||||
return (a + b - 1) // b
|
return (a + b - 1) // b
|
||||||
|
|
||||||
|
|
||||||
# MegaMoE SiTU sentinel: DeepGEMM 0.1.5.post1+ selects the K3 SiTU
|
|
||||||
# activation when activation_clamp == 0.03125 (2^-5: exactly representable and
|
|
||||||
# unused by any legitimate swiglu clamp; the host asserts clamp >= 0 so a
|
|
||||||
# negative sentinel is impossible). beta=4.0 / linear_beta=25.0 are baked into
|
|
||||||
# the DeepGEMM kernel.
|
|
||||||
_K3_MEGA_SITU_SENTINEL_CLAMP = 0.03125
|
|
||||||
|
|
||||||
|
|
||||||
def _k3_bf16_gemm(
|
def _k3_bf16_gemm(
|
||||||
x: torch.Tensor,
|
x: torch.Tensor,
|
||||||
weight: torch.Tensor,
|
weight: torch.Tensor,
|
||||||
@@ -487,9 +479,8 @@ class KimiK3MoE(nn.Module):
|
|||||||
# through it when enabled — the megamoe backend's non-mega fallback is
|
# through it when enabled — the megamoe backend's non-mega fallback is
|
||||||
# a StandardDispatcher without a2a, which is wrong for scattered
|
# a StandardDispatcher without a2a, which is wrong for scattered
|
||||||
# tokens — so SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK must
|
# tokens — so SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK must
|
||||||
# cover the per-rank prefill chunk. SiTU is selected inside the
|
# cover the per-rank prefill chunk. The DeepGEMM MegaMoE SiTU kernel
|
||||||
# DeepGEMM mega kernel via a sentinel activation_clamp with the K3
|
# bakes in the K3 activation constants.
|
||||||
# constants baked in.
|
|
||||||
self._use_mega_moe = get_moe_a2a_backend().is_megamoe()
|
self._use_mega_moe = get_moe_a2a_backend().is_megamoe()
|
||||||
self._mega_intermediate_size = moe_intermediate_size
|
self._mega_intermediate_size = moe_intermediate_size
|
||||||
self._mega_top_k = config.num_experts_per_token
|
self._mega_top_k = config.num_experts_per_token
|
||||||
@@ -499,7 +490,7 @@ class KimiK3MoE(nn.Module):
|
|||||||
config.activation_situ_beta,
|
config.activation_situ_beta,
|
||||||
config.activation_situ_linear_beta,
|
config.activation_situ_linear_beta,
|
||||||
) == (4.0, 25.0), (
|
) == (4.0, 25.0), (
|
||||||
"mega SiTU kernel patch bakes beta=4.0/linear_beta=25.0; "
|
"MegaMoE SiTU kernel bakes beta=4.0/linear_beta=25.0; "
|
||||||
"got a checkpoint with different constants"
|
"got a checkpoint with different constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -802,10 +793,7 @@ class KimiK3MoE(nn.Module):
|
|||||||
self.experts.mega_l2_weights,
|
self.experts.mega_l2_weights,
|
||||||
buf,
|
buf,
|
||||||
recipe=(1, 1, 32),
|
recipe=(1, 1, 32),
|
||||||
activation="swiglu",
|
activation="situ",
|
||||||
# Sentinel: selects the K3 SiTU branch in the DeepGEMM mega kernel
|
|
||||||
# (beta=4.0 / linear_beta=25.0 baked in).
|
|
||||||
activation_clamp=_K3_MEGA_SITU_SENTINEL_CLAMP,
|
|
||||||
fast_math=True,
|
fast_math=True,
|
||||||
)
|
)
|
||||||
y = y[:num_tokens]
|
y = y[:num_tokens]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""B300 per-commit CI coverage for Kimi-K3 serving recipes.
|
"""B300 per-commit CI coverage for Kimi-K3 serving recipes.
|
||||||
|
|
||||||
Runs the Low Latency DSPARK recipe and the Balanced DCP/HiCache recipe on
|
Runs the Low Latency DSPARK, Balanced DCP/HiCache, and MegaMoE recipes on
|
||||||
eight B300 GPUs. Each server must preserve basic model quality on GSM8K, and
|
eight B300 GPUs. Each server must preserve basic model quality on GSM8K, and
|
||||||
the Low Latency recipe must also preserve single-request decode performance.
|
the Low Latency recipe must also preserve single-request decode performance.
|
||||||
"""
|
"""
|
||||||
@@ -18,13 +18,17 @@ from sglang.test.test_utils import (
|
|||||||
popen_launch_server,
|
popen_launch_server,
|
||||||
)
|
)
|
||||||
|
|
||||||
register_cuda_ci(est_time=900, stage="base-c", runner_config="8-gpu-b300")
|
register_cuda_ci(est_time=1200, stage="base-c", runner_config="8-gpu-b300")
|
||||||
|
|
||||||
MODEL_PATH = (
|
MODEL_PATH = (
|
||||||
"/data/radixark/model-cache/hub/models--moonshotai--Kimi-K3/"
|
"/data/radixark/model-cache/hub/models--moonshotai--Kimi-K3/"
|
||||||
"snapshots/9f62e4e9fffbd0a83ddd60e1c209d828994b3569"
|
"snapshots/9f62e4e9fffbd0a83ddd60e1c209d828994b3569"
|
||||||
)
|
)
|
||||||
DSPARK_DRAFT_MODEL = "RadixArk/Kimi-K3-DSpark"
|
DSPARK_DRAFT_MODEL = "RadixArk/Kimi-K3-DSpark"
|
||||||
|
MEGAMOE_URL = "http://0.0.0.0:30000"
|
||||||
|
MEGAMOE_ENV = {
|
||||||
|
"SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK": "8320",
|
||||||
|
}
|
||||||
SERVER_LAUNCH_TIMEOUT = 3600
|
SERVER_LAUNCH_TIMEOUT = 3600
|
||||||
GPU_IDLE_TIMEOUT = 120
|
GPU_IDLE_TIMEOUT = 120
|
||||||
|
|
||||||
@@ -124,5 +128,53 @@ class TestKimiK3B300Balanced(GSM8KMixin, CustomTestCase):
|
|||||||
_stop_server(getattr(cls, "process", None))
|
_stop_server(getattr(cls, "process", None))
|
||||||
|
|
||||||
|
|
||||||
|
class TestKimiK3B300MegaMoE(GSM8KMixin, CustomTestCase):
|
||||||
|
"""TP8/EP8/DCP8 MegaMoE recipe with DSPARK speculation."""
|
||||||
|
|
||||||
|
gsm8k_score_threshold = 0.95
|
||||||
|
gsm8k_num_examples = 200
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.model = MODEL_PATH
|
||||||
|
cls.base_url = MEGAMOE_URL
|
||||||
|
cls.process = popen_launch_server(
|
||||||
|
cls.model,
|
||||||
|
cls.base_url,
|
||||||
|
timeout=SERVER_LAUNCH_TIMEOUT,
|
||||||
|
other_args=[
|
||||||
|
"--trust-remote-code",
|
||||||
|
"--tp-size",
|
||||||
|
"8",
|
||||||
|
"--moe-a2a-backend",
|
||||||
|
"megamoe",
|
||||||
|
"--ep",
|
||||||
|
"8",
|
||||||
|
"--dcp-size",
|
||||||
|
"8",
|
||||||
|
"--mem-fraction-static",
|
||||||
|
"0.85",
|
||||||
|
"--reasoning-parser",
|
||||||
|
"kimi_k3",
|
||||||
|
"--tool-call-parser",
|
||||||
|
"kimi_k3",
|
||||||
|
"--mamba-full-memory-ratio",
|
||||||
|
"5.13",
|
||||||
|
"--speculative-algorithm",
|
||||||
|
"DSPARK",
|
||||||
|
"--speculative-draft-model-path",
|
||||||
|
DSPARK_DRAFT_MODEL,
|
||||||
|
"--speculative-dspark-block-size",
|
||||||
|
"7",
|
||||||
|
"--enable-linear-replayssm-spec",
|
||||||
|
],
|
||||||
|
env=MEGAMOE_ENV,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
_stop_server(getattr(cls, "process", None))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user