[Kimi] Support kimi-k3 (#32541)
Co-authored-by: DarkSharpness <76582120+DarkSharpness@users.noreply.github.com> Co-authored-by: Xiaoyu Zhang <1182563586@qq.com> Co-authored-by: Mick <mickjagger19@icloud.com> Co-authored-by: Yuhao Yang <47235274+yhyang201@users.noreply.github.com> Co-authored-by: Cheng Wan <54331508+ch-wan@users.noreply.github.com> Co-authored-by: Ke Bao <ispobaoke@gmail.com> Co-authored-by: Baizhou Zhang <sobereddiezhang@gmail.com> Co-authored-by: Chunan Zeng <zcnrex@gmail.com> Co-authored-by: Khoa Pham <khoa.pham@radixark.ai> Co-authored-by: Ziyi Xu <ziyi.xu@radixark.ai> Co-authored-by: Zijie Xia <37504505+zijiexia@users.noreply.github.com> Co-authored-by: Yuwei An <ayw.sirius19@gmail.com> Co-authored-by: zhangxiaohao <1024393531@qq.com> Co-authored-by: Yangmin Li <yangminl@nvidia.com> Co-authored-by: Julien Lin <jullin@nvidia.com> Co-authored-by: Hao Phan <htphan@nvidia.com> Co-authored-by: Thomas Wang <1am9trash@gmail.com> Co-authored-by: RolaoDenthu <xinyisong0111@gmail.com> Co-authored-by: pigeonsoup <32922982+pigeonsoup@users.noreply.github.com> Co-authored-by: HaiShaw <hixiao@gmail.com> Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com> Co-authored-by: Pranjal Shankhdhar <pranjal.ssh@gmail.com> Co-authored-by: Lee Nau <lee.nau@gmail.com> Co-authored-by: HMING <126185151+Hearum@users.noreply.github.com> Co-authored-by: elvischenv <219235043+elvischenv@users.noreply.github.com> Co-authored-by: Byron Hsu <byronhsu1230@gmail.com> Co-authored-by: Byron Hsu <byron+per@periodiclabs.ai> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Thomas Wang <thomawan@amd.com> Co-authored-by: Xinyi Song <86638975+RolaoDenthu@users.noreply.github.com> Co-authored-by: Mohammad Miadh Angkad <176301910+mmangkad@users.noreply.github.com> Co-authored-by: Cheng Wan <cheng.wan@radixark.ai> Co-authored-by: BBuf <xiaoyu.zhang@radixark.ai> Co-authored-by: Hanming Lu <hanminglu@meta.com> Co-authored-by: Xinyi Song <xinyis10@illinois.edu>
This commit is contained in:
co-authored by
DarkSharpness
Xiaoyu Zhang
Mick
Yuhao Yang
Cheng Wan
Ke Bao
Baizhou Zhang
Chunan Zeng
Khoa Pham
Ziyi Xu
Zijie Xia
Yuwei An
zhangxiaohao
Yangmin Li
Julien Lin
Hao Phan
Thomas Wang
RolaoDenthu
pigeonsoup
HaiShaw
Xinyuan Tong
Pranjal Shankhdhar
Lee Nau
HMING
elvischenv
Byron Hsu
Byron Hsu
Claude Opus 5
Thomas Wang
Xinyi Song
Mohammad Miadh Angkad
Cheng Wan
BBuf
Hanming Lu
Xinyi Song
parent
0753663b8e
commit
abddb1c7e9
@@ -344,7 +344,7 @@ class MambaPool:
|
||||
# replayssm_rawv: [num_layers, num_slots, HV, L, V] (conv/activation dtype)
|
||||
# replayssm_rawk: [num_layers, num_slots, H, L, K] (conv/activation dtype)
|
||||
# replayssm_beta: [num_layers, num_slots, HV, L] (fp32)
|
||||
# The raw rings + beta exist only under --enable-gdn-replayssm-spec: the
|
||||
# The raw rings + beta exist only under --enable-linear-replayssm-spec: the
|
||||
# closed-loop exact fold sequentially replays them through the recurrent
|
||||
# update at flush -- bit-identical to the recurrent baseline -- instead
|
||||
# of folding the chunked `d` records open-loop (which accumulates error
|
||||
@@ -380,7 +380,7 @@ class MambaPool:
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class SpeculativeState(State):
|
||||
# None under --enable-gdn-replayssm-spec: the spec ring owns rollback
|
||||
# None under --enable-linear-replayssm-spec: the spec ring owns rollback
|
||||
# (verify writes ring records, commit moves cursors), so the per-draft
|
||||
# full-state snapshots are never produced or consumed.
|
||||
intermediate_ssm: Optional[torch.Tensor]
|
||||
@@ -468,7 +468,7 @@ class MambaPool:
|
||||
enable_linear_replayssm: bool = False,
|
||||
linear_replayssm_cache_len: int = 16,
|
||||
envelope_layout: bool = False,
|
||||
enable_gdn_replayssm_spec: bool = False,
|
||||
enable_linear_replayssm_spec: bool = False,
|
||||
):
|
||||
conv_state_shape = cache_params.shape.conv
|
||||
temporal_state_shape = cache_params.shape.temporal
|
||||
@@ -487,12 +487,13 @@ class MambaPool:
|
||||
self.linear_replayssm_cache_len = linear_replayssm_cache_len
|
||||
# ReplaySSM: the decode ring (--enable-linear-replayssm) allocates the
|
||||
# chunked (d, k) records + write_pos; the spec-verify flag
|
||||
# (--enable-gdn-replayssm-spec) always uses fold-every-commit and
|
||||
# (--enable-linear-replayssm-spec) always uses fold-every-commit and
|
||||
# allocates only the raw (v, k, g, beta) window -- no chunked records,
|
||||
# no cursors. The shared g allocation gates on `_replayssm_on`.
|
||||
self.enable_gdn_replayssm_spec = enable_gdn_replayssm_spec
|
||||
self.replayssm_spec_fold = bool(enable_gdn_replayssm_spec)
|
||||
_replayssm_on = enable_linear_replayssm or enable_gdn_replayssm_spec
|
||||
# no cursors (KDA additionally keeps d/k, see the allocation below).
|
||||
# The shared g allocation gates on `_replayssm_on`.
|
||||
self.enable_linear_replayssm_spec = enable_linear_replayssm_spec
|
||||
self.replayssm_spec_fold = bool(enable_linear_replayssm_spec)
|
||||
_replayssm_on = enable_linear_replayssm or enable_linear_replayssm_spec
|
||||
|
||||
# for disagg with nvlink
|
||||
self.enable_custom_mem_pool, self.custom_mem_pool, _ = (
|
||||
@@ -570,7 +571,7 @@ class MambaPool:
|
||||
# flag is on; otherwise left as None so the legacy State is
|
||||
# byte-identical. temporal_state_shape == (HV, V, K). Either the decode
|
||||
# ring (--enable-linear-replayssm) or the spec-verify ring
|
||||
# (--enable-gdn-replayssm-spec) shares this allocation.
|
||||
# (--enable-linear-replayssm-spec) shares this allocation.
|
||||
replayssm_d = replayssm_k = replayssm_g = None
|
||||
replayssm_rawv = replayssm_rawk = replayssm_beta = None
|
||||
if _replayssm_on:
|
||||
@@ -580,16 +581,23 @@ class MambaPool:
|
||||
num_slots = size + 1
|
||||
# Ring dtype. DECODE ring (--enable-linear-replayssm): records
|
||||
# follow the SSM dtype -- its flush folds `d` directly into the
|
||||
# state. SPEC-verify ring (--enable-gdn-replayssm-spec): d/k feed
|
||||
# state. SPEC-verify ring (--enable-linear-replayssm-spec): d/k feed
|
||||
# ONLY the one-shot output reconstruction (the closed-loop exact
|
||||
# fold replays the raw rings for state instead), so their
|
||||
# quantization noise stays below the bf16 output cast; keep them
|
||||
# in the conv/activation dtype instead of the (fp32-enforced)
|
||||
# SSM dtype to halve the ring traffic. g stays fp32 everywhere
|
||||
# (exact-fold input). The two flags are mutually exclusive.
|
||||
ring_dtype = conv_dtype if enable_gdn_replayssm_spec else ssm_dtype
|
||||
# Fold-every-commit: one verify window, no chunked (d, k) records.
|
||||
if self.replayssm_spec_fold:
|
||||
ring_dtype = conv_dtype if enable_linear_replayssm_spec else ssm_dtype
|
||||
# Fold-every-commit: one verify window, no chunked (d, k)
|
||||
# records. KDA is the exception on both counts: its window
|
||||
# stays L-sized (the fused verify ring-write drops
|
||||
# absorb-inflated rows past L), and d/k stay allocated --
|
||||
# forward_decode routes on `replayssm_d is None` (fused vs
|
||||
# decode-ring), so skipping them would flip KDA decode to the
|
||||
# fused path, a behavior change needing its own validation
|
||||
# (memory follow-up).
|
||||
if self.replayssm_spec_fold and not cache_params.is_kda:
|
||||
record_len = (
|
||||
speculative_num_draft_tokens
|
||||
if speculative_num_draft_tokens is not None
|
||||
@@ -597,6 +605,7 @@ class MambaPool:
|
||||
)
|
||||
else:
|
||||
record_len = L
|
||||
if not self.replayssm_spec_fold or cache_params.is_kda:
|
||||
replayssm_d = torch.zeros(
|
||||
size=(num_mamba_layers, num_slots, hv, L, v_dim),
|
||||
dtype=ring_dtype,
|
||||
@@ -626,7 +635,22 @@ class MambaPool:
|
||||
# flush replays these through the recurrent update sequentially
|
||||
# (bit-identical to the recurrent baseline) instead of folding
|
||||
# the chunked `d` records open-loop.
|
||||
if enable_gdn_replayssm_spec:
|
||||
if enable_linear_replayssm_spec:
|
||||
if cache_params.is_kda:
|
||||
# Backstop for the KDA ring invariants; this pool is
|
||||
# sized with the final adaptive-aware draft maximum.
|
||||
if L & (L - 1) != 0:
|
||||
raise ValueError(
|
||||
f"spec-verify ring length must be a power of two, got {L}"
|
||||
)
|
||||
if (
|
||||
speculative_num_draft_tokens is not None
|
||||
and L < 2 * speculative_num_draft_tokens
|
||||
):
|
||||
raise ValueError(
|
||||
f"spec-verify ring too small: {L} < "
|
||||
f"2 * {speculative_num_draft_tokens} (early-flush margin)"
|
||||
)
|
||||
replayssm_rawv = torch.zeros(
|
||||
size=(num_mamba_layers, num_slots, hv, record_len, v_dim),
|
||||
dtype=conv_dtype,
|
||||
@@ -662,7 +686,11 @@ class MambaPool:
|
||||
# The recurrent-verify fallback cannot be reached under the flag
|
||||
# (GDN + linear chain + triton enforced in server_args; the
|
||||
# backend asserts loudly if it ever is).
|
||||
if enable_gdn_replayssm_spec:
|
||||
# ReplaySSM skips this dominant scratch (~9GB @ K3 dspark γ=7): the
|
||||
# KDA verify kernel takes intermediate_states_buffer=None (skips the
|
||||
# per-step write, CACHE_INTERMEDIATE_STATES=False) and the commit
|
||||
# replays the ring into the checkpoint instead. This is the memory win.
|
||||
if enable_linear_replayssm_spec:
|
||||
intermediate_ssm_state_cache = None
|
||||
else:
|
||||
intermediate_ssm_state_cache = torch.zeros(
|
||||
@@ -795,7 +823,7 @@ class MambaPool:
|
||||
f"rawv={get_tensor_size_bytes(replayssm_rawv) / GB:.3f}GB, "
|
||||
f"rawk={get_tensor_size_bytes(replayssm_rawk) / GB:.3f}GB, "
|
||||
f"beta={get_tensor_size_bytes(replayssm_beta) / GB:.3f}GB "
|
||||
if enable_gdn_replayssm_spec
|
||||
if enable_linear_replayssm_spec
|
||||
else ""
|
||||
)
|
||||
)
|
||||
@@ -818,12 +846,12 @@ class MambaPool:
|
||||
# all GDN layers of one verify step; advanced by commit_gdn_replayssm_spec.
|
||||
self.replayssm_cache_base = (
|
||||
torch.zeros((size + 1,), dtype=torch.int32, device=device)
|
||||
if enable_gdn_replayssm_spec and not self.replayssm_spec_fold
|
||||
if enable_linear_replayssm_spec and not self.replayssm_spec_fold
|
||||
else None
|
||||
)
|
||||
self.replayssm_is_flush = (
|
||||
torch.zeros((size + 1,), dtype=torch.int8, device=device)
|
||||
if enable_gdn_replayssm_spec and not self.replayssm_spec_fold
|
||||
if enable_linear_replayssm_spec and not self.replayssm_spec_fold
|
||||
else None
|
||||
)
|
||||
mem_usage_bytes = self.mamba_cache.mem_usage_bytes()
|
||||
@@ -1130,7 +1158,7 @@ class HybridReqToTokenPool(ReqToTokenPool):
|
||||
enable_linear_replayssm: bool = False,
|
||||
linear_replayssm_cache_len: int = 16,
|
||||
mamba_envelope_layout: bool = False,
|
||||
enable_gdn_replayssm_spec: bool = False,
|
||||
enable_linear_replayssm_spec: bool = False,
|
||||
):
|
||||
super().__init__(
|
||||
size=size,
|
||||
@@ -1157,7 +1185,7 @@ class HybridReqToTokenPool(ReqToTokenPool):
|
||||
enable_linear_replayssm=enable_linear_replayssm,
|
||||
linear_replayssm_cache_len=linear_replayssm_cache_len,
|
||||
mamba_envelope_layout=mamba_envelope_layout,
|
||||
enable_gdn_replayssm_spec=enable_gdn_replayssm_spec,
|
||||
enable_linear_replayssm_spec=enable_linear_replayssm_spec,
|
||||
)
|
||||
|
||||
def _init_mamba_pool(
|
||||
@@ -1173,7 +1201,7 @@ class HybridReqToTokenPool(ReqToTokenPool):
|
||||
enable_linear_replayssm: bool = False,
|
||||
linear_replayssm_cache_len: int = 16,
|
||||
mamba_envelope_layout: bool = False,
|
||||
enable_gdn_replayssm_spec: bool = False,
|
||||
enable_linear_replayssm_spec: bool = False,
|
||||
):
|
||||
self.mamba_pool = self.mamba_pool_cls(
|
||||
size=mamba_size,
|
||||
@@ -1187,7 +1215,7 @@ class HybridReqToTokenPool(ReqToTokenPool):
|
||||
enable_linear_replayssm=enable_linear_replayssm,
|
||||
linear_replayssm_cache_len=linear_replayssm_cache_len,
|
||||
envelope_layout=mamba_envelope_layout,
|
||||
enable_gdn_replayssm_spec=enable_gdn_replayssm_spec,
|
||||
enable_linear_replayssm_spec=enable_linear_replayssm_spec,
|
||||
)
|
||||
self.mamba_allocator = MambaSlotAllocator(
|
||||
size=mamba_size,
|
||||
@@ -3663,7 +3691,7 @@ class HybridLinearKVPool(KVCache):
|
||||
|
||||
def get_kv_buffer_shape(self) -> Tuple[torch.Size, torch.Size]:
|
||||
# Hybrid layer ids are global model-layer ids, while the backing pool
|
||||
# is dense over only full-attention layers. Shape discovery does not
|
||||
# is dense over only full-attention layers. Shape discovery does not
|
||||
# need a global layer lookup, so delegate it to that backing pool.
|
||||
return self.full_kv_pool.get_kv_buffer_shape()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user