Skip to content

feat(scheduler): live-tail allocation for sliding groups - #694

Draft
nperrin-fr wants to merge 7 commits into
mainfrom
dev/live-tail
Draft

feat(scheduler): live-tail allocation for sliding groups#694
nperrin-fr wants to merge 7 commits into
mainfrom
dev/live-tail

Conversation

@nperrin-fr

Copy link
Copy Markdown
Collaborator

Summary

Chunked prefill previously allocated the FULL chunk range in every
paged-cache group and punched the slid-out pages one chunk later. For
tiny-window conv-state groups (Inkling hiddenconv: block 16, wide
columns) that transient is ~9 GB/GPU per 8k in-flight chunk — the
documented admission transient that evicts every retained prefix entry
under concurrency.

This adds opt-in live-tail allocation for sliding-window groups
(PagedCacheGroupConfig.live_tail_alloc): SwaManager::Acquire appends
null holes for new slots the retention can never read back and real
blocks only for
(a) slots not fully slid out at the post-acquire frontier, and
(b) the pagesNeededToResume() slots behind every LCM-aligned restore
boundary (the pages the engine's lcm_align persist set writes and
a future prefix-cache restore must find registered).
MakeCoordinator wires the groups' LCM block size as the alignment;
BlocksNeededFor mirrors the clipped math so admission stops charging
the transient; ReclaimExpired/BlocksReclaimableAt walk through the
interleaved holes instead of early-breaking on the first null.

Safe only for groups whose in-flight reads never come from the pool
(conv kernels read the chunk from packed activations); SWA attention
groups keep full allocation. hiddenconv math: 2 of every 32 slots stay
real once slid out -> the transient drops ~16x.

10 new unit tests (manager + coordinator lcm wiring); full scheduler
suite: failure set identical to the parent commit (the 103 known
radix-oriented failures under -DTOKENSPEED_FLAT_KVCACHE=ON).

Test Plan

@nperrin-fr
nperrin-fr requested a review from wangbo981016 July 16, 2026 02:29
Base automatically changed from inkling to main July 16, 2026 17:26
Opt-in live_tail_alloc for sliding-window paged-cache groups: SwaManager
allocates real pages only for the live tail and the resume pages behind
each LCM-aligned restore boundary, appending null holes for slots the
retention can never read back. This clips the full-chunk admission
transient at allocation time instead of punching pages a chunk later.

Safe only for groups whose in-flight reads never come from the pool
(conv kernels read the chunk from packed activations); SWA attention
groups keep full allocation. MakeCoordinator wires the groups' LCM block
size as the alignment; BlocksNeededFor mirrors the clipped math so
admission stops charging the transient; reclaim walks the interleaved
holes instead of early-breaking on the first null. Adds 10 unit tests.

Signed-off-by: nperrin-fr <nperrin.ai@gmail.com>
kvconv/hiddenconv specs opt into the scheduler's allocate-time window
clipping, removing the ~17 GB/GPU chunked-prefill admission transient
for the tiny-window conv-state groups (second-wave shared-prefix hit
rate recovers under concurrency with no workaround).

Signed-off-by: nperrin-fr <nperrin.ai@gmail.com>
@nperrin-fr nperrin-fr changed the title [WIP] feat(scheduler): live-tail allocation for sliding groups feat(scheduler): live-tail allocation for sliding groups Jul 22, 2026
@nperrin-fr
nperrin-fr marked this pull request as ready for review July 22, 2026 01:26
@nperrin-fr
nperrin-fr requested a review from a team as a code owner July 22, 2026 01:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 626ea7c8c2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +148 to +152
// Live-tail interleaves holes with real checkpoint pages, so don't early-break.
if (live_alloc_alignment_ == 0) {
break; // already null -> earlier slots are null too
}
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track reclaimed live-tail holes

With live_tail_alloc enabled, continuing after every null makes each ReclaimExpired call walk from the current slide bound back to slot 0, even though almost all earlier slots were already punched on prior decode steps. For Inkling hiddenconv's 8/16-token pages, long-context decoding scans tens or hundreds of thousands of holes per group per token (and BlocksReclaimableAt repeats the same pattern gate-side), which can dominate scheduler latency; keep a reclaimed cursor or skip directly to possible checkpoint residues instead of rescanning the entire sparse history.

Useful? React with 👍 / 👎.

Signed-off-by: Nicolas <nperrin.ai@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75439f6a11

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (num_tokens <= tail_avail) {
return 0;
}
const std::int32_t end = TableExtentTokens(table, block_size_) + num_tokens;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make live-tail admission charge the peak pages

For live-tail groups this prediction is not monotonic because it classifies all new slots against the final frontier. For example with block_size=8/window=12, a fresh BlocksNeededFor(19) returns 2 while the actual first Acquire(17) needs 3 pages (the later frontier turns slot 0 into a hole). flatAdmitFirstChunk gates on BlocksNeededFor(chunk + decode_reserve) before the C slice actually acquires only chunk_tokens, so under page pressure admission can succeed with two free blocks and then hit the allocation-failure assert when the chunk needs three. Please charge the peak/sequential acquire demand, not just the final table shape.

Useful? React with 👍 / 👎.

@nperrin-fr
nperrin-fr marked this pull request as draft July 22, 2026 01:43
Two review findings on the live-tail allocation path:

BlocksNeededFor is non-monotonic for live-tail groups (a later frontier
holes early slots: BlocksNeededFor(17)=3 but BlocksNeededFor(19)=2 at
block 8 / window 12), so gating chunk + decode-reserve on the combined
query could under-charge the chunk's own Acquire and compute a negative
reserve that the >0 guard silently dropped. Admission now charges
BlocksNeededForSequential (first batch at its own frontier + extra batch
at the final frontier), which equals the sequential acquires' peak pin
and makes the recorded reserve exactly the second acquire's demand.

ReclaimExpired walked from the slide bound back to slot 0 every call
(holes forbid the early break), rescanning the entire punched history
per decode step -- O(N^2) over a long generation, twice per token with
the BlocksReclaimableAt gate. A reclaim floor on BlockTable now bounds
both scans to the newly-expired band; EvictToNull is permanent, so slots
below the floor can never re-materialize.

Signed-off-by: Nicolas <nperrin.ai@gmail.com>
…ent coupling

Adversarial review of the floor invariant found the "known-null" claim
false on reachable tables: SwaManager::Match emits holes below
hits_begin and AppendHostExtension appends null slots, so an
alignment==0 early break can advance the floor over stranded real pages
(the pre-floor scan stranded the exact same pages; Free releases them).
State the comment as the scan-bound guarantee it actually is.

Also record why flatAdmitFirstChunk's fresh-table sequential charge is
exact: SweepThenConverge pins claim extents to the same lcm
MakeCoordinator wires as the live alignment. slotIsLive is not
shift-invariant, so decoupling those would silently under-charge.

Signed-off-by: Nicolas <nperrin.ai@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant