Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
656550c
feat: add ReplaySSM state modes for GDN and KDA
sufubao Nov 7, 2026
398cc21
refactor: remove retired ReplaySSM modes
sufubao Nov 8, 2026
ead7d04
refactor: name the SSM executor explicitly
sufubao Nov 8, 2026
fec53e8
style: modernize ReplaySSM Python interfaces
sufubao Nov 8, 2026
f88e7ba
style: document ReplaySSM Python functions
sufubao Nov 8, 2026
8720368
refactor: split GDN and KDA replay into standalone state modules
hiworldwzj Nov 8, 2026
ed4f140
refactor: move GDN and KDA replay off the native attention path
hiworldwzj Nov 9, 2026
7948824
refactor: make replay KDA and GDN backends standalone
hiworldwzj Nov 9, 2026
cb6f6f8
refactor: move replay decode onto GDN and KDA step modules
hiworldwzj Nov 9, 2026
98957a4
refactor: keep GDN and KDA replay history on the state
hiworldwzj Nov 9, 2026
93d7249
refactor: fold replay history when decode accepts
hiworldwzj Nov 9, 2026
3f9f313
refactor: drop the SSM slot property and keyword-only arguments
hiworldwzj Nov 9, 2026
8d6308c
refactor: keep replay page layout on the state
hiworldwzj Nov 9, 2026
c3075fe
refactor: let replay state commit accepted lengths directly
hiworldwzj Nov 9, 2026
4f5f3f5
refactor: name the replay decode kernel helpers
hiworldwzj Nov 9, 2026
91ec748
refactor: place private helpers after the public interfaces
hiworldwzj Nov 9, 2026
5e7a285
refactor: tune replay on a one-layer scratch state
hiworldwzj Nov 9, 2026
0e08843
refactor: drop replay decode wrappers and restore native backends
hiworldwzj Nov 9, 2026
476cfdc
refactor: keep replay history as one accepted prefix
hiworldwzj Nov 9, 2026
8374064
refactor: compress replay prefixes inside the materialize kernel
hiworldwzj Nov 9, 2026
0ead21c
refactor: close replay tokens in-kernel and drop tuning OOM bypass
hiworldwzj Nov 9, 2026
8f3681f
refactor: honor replay precompute for single-token decode
hiworldwzj Nov 9, 2026
b399522
style: restore the blank line in Autotuner initialization
hiworldwzj Nov 9, 2026
b1a78bb
refactor: inline one-use replay helpers
hiworldwzj Nov 9, 2026
a8cb33b
refactor: put replay entry points ahead of their helpers
hiworldwzj Nov 9, 2026
833cf51
refactor: restore the original MTP state-params layout
hiworldwzj Nov 9, 2026
eb91e42
refactor: name replay kernels by decode, cursor, and fold
hiworldwzj Nov 9, 2026
2f117c6
feat: reconstruct GDN and KDA replay outputs on tensor cores
hiworldwzj Nov 10, 2026
fea39d6
fix: fold replay prefixes inside the decode kernel
hiworldwzj Nov 11, 2026
c63ad74
refactor: share the accepted-prefix fold between replay and compress
hiworldwzj Nov 11, 2026
244c986
refactor: remove the unused full-prefix replay path
hiworldwzj Nov 11, 2026
3a8540b
refactor: drop the unused replay prepare_decode hook
hiworldwzj Nov 11, 2026
e73ae2e
refactor: fill replay kernel defaults at launch
hiworldwzj Nov 11, 2026
5b8623a
refactor: copy the prefill baseline into replay pages
hiworldwzj Nov 11, 2026
8bfc2cc
refactor: drop the empty prefill fold from replay state
hiworldwzj Nov 11, 2026
28db987
refactor: advance the replay cursor after the whole window is accepted
hiworldwzj Nov 11, 2026
69c2518
fix: wait for every value tile before a folded replay writes history
hiworldwzj Nov 11, 2026
5dc284e
refactor: require cursor prefixes at decode setup
hiworldwzj Nov 11, 2026
1d9162a
refactor: keep one MTP index path and commit only when MTP is enabled
hiworldwzj Nov 11, 2026
64b6f1f
refactor: fold replay prefixes only back into the canonical SSM
hiworldwzj Nov 11, 2026
e97fce7
refactor: drop unused replay kernel exports and the dense stride fall…
hiworldwzj Nov 11, 2026
664d543
refactor: name replay inputs by the tensors they address
hiworldwzj Nov 12, 2026
88b886e
refactor: require one packed layout for replay decode
hiworldwzj Nov 12, 2026
7bd612f
refactor: tune GDN and KDA replay on their own kernels
hiworldwzj Nov 12, 2026
bc474ff
refactor: pass replay tile configs as arguments
hiworldwzj Nov 12, 2026
ba78baa
refactor: give GDN and KDA separate linear backend entries.
hiworldwzj Nov 12, 2026
85f0f22
refactor: pass KDA replay tensors instead of the state object.
hiworldwzj Nov 12, 2026
c79a062
chore: record Cursor rules for new code.
hiworldwzj Nov 12, 2026
1567491
refactor: name replay kernel arguments and pass tile configs explicitly.
hiworldwzj Nov 12, 2026
7bcedef
refactor: move SSM config validation to the end of startup.
hiworldwzj Nov 12, 2026
5a441ba
fix: ignore reused replay history and store deltas in fp32
hiworldwzj Nov 12, 2026
6fb01a0
fix: wait for every value head sharing a key before replay overwrites it
hiworldwzj Nov 12, 2026
59adc05
refactor: launch replay value heads before requests
hiworldwzj Nov 12, 2026
083ac58
test: fix replay padding and restore grouped-head coverage
sufubao Nov 12, 2026
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
12 changes: 12 additions & 0 deletions .cursor/rules/named-args-and-types.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: 新代码的函数调用使用参数名,参数带类型标注
alwaysApply: true
---

# 新代码的调用和类型

新写的函数调用使用 `param_name=value`。不要用 `*args`、`*activations`、`**kwargs` 把一组参数展开传进去。

新写的函数参数带类型标注。

修改旧代码时,原有调用和原有签名保持不动,避免把风格调整混进 review。这次改动里新加的函数、新加的调用按上面两条写。
10 changes: 10 additions & 0 deletions .cursor/rules/no-test-only-production-api.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
description: 测试专用的实现和接口只放在测试里,不留在正式代码中
alwaysApply: true
---

# 测试代码不进正式实现

正式路径不保留只为测试、benchmark 或对照方便而存在的函数、参数和分支。

需要这类行为时,在测试或 benchmark 自己实现,并调用正式接口。正式接口的参数对应真实推理会传入的数据,不为测试场景增加可选参数。
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,24 @@ def create_gdn_state(
request_capacity: int,
mtp_step: int = 0,
device: str | torch.device = "cuda",
ssm_state_mode: str = "native",
ssm_replay_config: dict | None = None,
gate_lower_bound: float = -5.0,
) -> GDNState:
"""创建 GDN 请求运行态,大小页池由后续容量分配流程初始化。"""
"""创建 GDN 请求运行态。replay 模式使用独立的 ReplayGDNState。"""
if ssm_state_mode == "replay":
from .replay_gdn_state import ReplayGDNState

return ReplayGDNState(
config=config,
request_capacity=request_capacity,
mtp_step=mtp_step,
device=device,
ssm_replay_config=ssm_replay_config,
gate_lower_bound=gate_lower_bound,
)
if ssm_state_mode != "native":
raise ValueError(f"unknown GDN state mode: {ssm_state_mode}")
return GDNState(
config=config,
request_capacity=request_capacity,
Expand Down
14 changes: 8 additions & 6 deletions lightllm/common/attention_state/bounded_att/gdn/gdn_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def __init__(
self.state_name: str | None = None # 由 AttentionStateManager.register_state() 绑定时设置。
self.request_capacity = request_capacity # 包含预留的 HOLD 请求槽位。
self.mtp_step = mtp_step
self.mtp_enabled = mtp_step > 0
self._logical_to_storage_layer = {
logical_layer_id: storage_layer_index
for storage_layer_index, logical_layer_id in enumerate(config.logical_layer_ids)
Expand All @@ -67,7 +68,7 @@ def __init__(
dtype=config.ssm_dtype,
device=device,
)
self.mtp_state_index = torch.zeros(request_capacity, dtype=torch.int32, device=device) if mtp_step else None
self.mtp_state_index = torch.zeros(request_capacity, dtype=torch.int32, device=device)
self.big_pages_pool = None
self.small_pages_pool = None

Expand Down Expand Up @@ -126,7 +127,7 @@ def reset_bounded_att_state(self, req_indices: List[int]) -> None:
self.conv_state[:, req_idx].zero_()
start = req_idx * (self.mtp_step + 1)
self.ssm_state[:, start : start + self.mtp_step + 1].zero_()
if self.mtp_state_index is not None:
if self.mtp_enabled:
self.mtp_state_index[req_idx].fill_(0)

def save_bounded_att_runtime_to_pages(
Expand Down Expand Up @@ -170,18 +171,19 @@ def restore_bounded_att_runtime_from_pages(
ssm_copies.append((pool.ssm_state[slot_id], self.ssm_state[:, req_idx * (self.mtp_step + 1)]))
copy_bounded_att_tensors(copies=conv_copies)
copy_bounded_att_tensors(copies=ssm_copies)
if self.mtp_state_index is not None:
if self.mtp_enabled:
for req_idx in req_indices:
self.mtp_state_index[req_idx].fill_(0)

def commit_bounded_att_state(
self,
req_indices: torch.Tensor,
accepted_steps: torch.Tensor,
req_verify_width: torch.Tensor,
) -> None:
"""用 CUDA 请求索引和 int32 接受步数选择 SSM 候选位置;步数包含基准输入步。"""
assert req_indices.is_cuda and accepted_steps.is_cuda, "commit inputs must be CUDA tensors"
if self.mtp_state_index is not None:
if self.mtp_enabled:
self.mtp_state_index[req_indices] = accepted_steps - 1

# ========================================================================
Expand Down Expand Up @@ -320,7 +322,7 @@ def copy_runtime_state_from_dp(
)
copy_bounded_att_tensors(copies=conv_copies)
copy_bounded_att_tensors(copies=ssm_copies)
if self.mtp_state_index is not None:
if self.mtp_enabled:
for dst_req in dst_req_indices:
self.mtp_state_index[dst_req].fill_(0)

Expand Down Expand Up @@ -375,7 +377,7 @@ def read_from_pd_page(
write=False,
):
copy_bounded_att_tensors(copies=copies)
if self.mtp_state_index is not None:
if self.mtp_enabled:
self.mtp_state_index[req_idx].fill_(0)

# ========================================================================
Expand Down
Loading
Loading