Step Planner#
-
class StepPlanner#
Chooses the work of one IFB step from the residents’ ledger state.
order(x) = (priority, arrival) under SchedulingPolicy::kPriority, else arrival.
mixed: decode rows take one token each first; with any decode row the step budget is maxNumTokens and the per-sequence chunk cap maxChunkTokens, otherwise T_max and S_in. prefillFirst: with any prompt-incomplete resident only prefill is scheduled (budget T_max, cap S_in), else every resident decodes; under kPriority that prefill step holds only the prompts of the best (lowest) pending priority value, and the others wait for a later prefill step. Prefills are then filled in order: n = min(remaining, cap, S_in, budget); a non-final chunk is trimmed back to a page boundary of committed + n; a resident left with n <= 0 is skipped so a later, shorter prompt may still fit. The first prompt in order is never skipped: admission bounds a prompt by S_in, and beside decode rows the budget and maxChunkTokens are at least P, so its chunk completes the prompt or reaches the next page boundary.
Pause (mixed, priority policy, preemption=pause): h is the prompt-incomplete resident first in order; residents with a larger priority value than h are paused and the plan is made over the rest, so when no active resident decodes h gets the whole-prompt budget. The pause set is recomputed from the ledger on every call and empties once h’s final chunk commits. With maxPauseSteps > 0, a resident whose consecutivePausedSteps has reached it is not paused in this plan. Under kFcfs every request counts as priority 0, so nothing is paused.
plan() allocates nothing: the buffers are sized for maxBatchSize at construction and the returned plan is overwritten by the next call.
Public Functions
- StepPlanner(
- ResolvedSchedulingPolicy const &policy,
- StepPlannerLimits const &limits
policycomes from resolveSchedulingPolicy() for an engine withlimits, which validates its budgets.- Throws:
std::runtime_error – when its mode is not mixed or prefillFirst.
-
StepPlan const &plan(ResidentState const *residents, int32_t count)#
- Throws:
std::invalid_argument – when
countexceeds maxBatchSize or a prompt-incomplete resident has no remaining prompt.
- inline StepPlan const &plan(
- std::vector<ResidentState> const &residents
-
struct ResidentState#
The ledger view of one resident that plan() reads.
Public Members
-
int32_t priority = {0}#
Lower value = higher priority. Ignored under SchedulingPolicy::kFcfs.
-
uint64_t arrival = {0}#
Monotonic admission-queue arrival stamp; unique per request.
-
int32_t promptLength = {0}#
-
int32_t committed = {0}#
Tokens already in KV and recurrent state (the frontier).
-
bool contextCommitted = {false}#
The final prompt chunk has committed: the resident decodes. While false, the remaining prompt promptLength - committed must be positive.
-
int32_t consecutivePausedSteps = {0}#
Steps in a row that withheld this resident under preemption=pause, up to the step being planned.
-
int32_t priority = {0}#
-
struct StepPlannerLimits#
Engine build limits the planner budgets against.
-
struct PlannedSequence#
Public Members
-
int32_t resident = {0}#
Index of the resident in the array passed to plan().
-
SequenceWork work = {SequenceWork::kDecode}#
kContext for a prompt chunk, kDecode for one decode token.
-
int32_t pastLength = {0}#
Equals the resident’s committed.
-
int32_t queryLength = {0}#
-
bool selectLastTokenLogits = {false}#
True for decode rows and for the chunk that completes the prompt; a non-final chunk only advances committed.
-
int32_t resident = {0}#
-
struct StepPlan#
A planned step. With residents it always names at least one of them: the first unpaused resident in order gets a decode row or a chunk of at least one token (see StepPlanner). The session decides how a plan runs.
Public Members
-
std::vector<PlannedSequence> sequences#
All prefill chunks in scheduling order, then all decode rows in scheduling order (the compact layout).
-
std::vector<int32_t> paused#
Residents withheld by preemption=pause, ascending index. Residents left out for any other reason (prefill-first decodes, prefills that got no budget) are simply absent from sequences.
-
int32_t numPrefill = {0}#
Np, Nd, T_p and T.
-
int32_t numDecode = {0}#
-
int32_t prefillTokens = {0}#
-
int32_t totalTokens = {0}#
-
std::vector<PlannedSequence> sequences#