Module plan

Module plan 

Source
Expand description

2026-10-04: The measured planner of --spec-cost-model measured: draft depth by expected accepted tokens per joule, with tok/s as a constraint. Pure and deterministic: its output depends only on the table, the calibration, the batch width and the drafter’s confidences; no clock is read. It chooses how many drafts are proposed and verified, never which token is emitted, so greedy output is unchanged on row-invariant tiers.

  • propose_depth: before drafting, the depth K for width n that maximises E[tokens] / E[joules] over 0..=max_k, among the depths whose E[tokens] / E[ms] is at least (1 - slack) times depth 1’s. E[tokens] per sequence is 1 + Σ_{j<=K} Π_{t<=j} prior(t); a step costs verify(n, K) + draft(n, K) from the table. Above the serve’s own mtp_max_seqs (the width beyond which the scheduler plain-decodes every sequence regardless, sched.levers.mtp_max_seqs), it returns 0 by construction: there is nothing to search, since the scheduler will not dispatch a draft there no matter what this picks (2026-10-04, found measuring the published throughput recipe at C=64/128: with the default cap of 32, metrale_sched_phase_seconds_count{phase="step_mtp"} fired once across a 91 s, 32129-token run — the batch plain-decoded almost throughout).
  • sequence_depths: after drafting, how many of each sequence’s drafts to verify. Every sequence starts at one draft (none when K = 0). Which sequence a further row goes to is still decided greedily (by chained P(accept): a sequence’s own marginal token gain is non-increasing in its depth, since it is a running product of probabilities <= 1, so for any total row count the globally-largest-gain-first order is the tokens-maximising allocation — an exchange argument, not an approximation). But the total number of rows R the batch spends is chosen by scanning every reachable R, not by stopping at the first one whose tokens per joule does not improve: the pilot measured verify cost as non-monotone in rows per sequence (n=1 cost MORE at 3 rows than at 4, on the dense 27B, 2026-10-04), so a row that does not pay can still be worth adding when a cheaper row lies beyond it. The drafts are already paid for, so a row’s marginal cost is verify cost only; the table is uniform in depth, so a batch of R rows costs the width’s cells interpolated in R / n.

Owner: speculative. Invariants:

  • sequence_depths never gives a sequence more drafts than it has, more than k_max, or the batch more than row_budget draft rows; a batch with more sequences than row_budget verifies no drafts at all (a plain decode step).
  • Ties keep the shallower choice (propose_depth) or the earlier sequence (the caller’s order, which is slot order).

Functions§

propose_depth
2026-10-04: The propose depth for a batch of n sequences: see the module doc. slack is --spec-cost-slack, in 0..1. A table without depth 1 has no reference rate, so its constraint is against depth 0. mtp_max_seqs is the serve’s own dispatch cap (sched.levers.mtp_max_seqs, SSOT — never a restated default here); n > mtp_max_seqs returns 0 without consulting the table (see the module doc). Within the cap the search can also return 0 on its own terms (a draft row that costs a whole step — see the no_drafting_when_it_is_neither_faster_nor_cheaper test) — the two 0s mean different things to a caller that is not wired to suspend MTP from the table’s energy preference alone: it must re-check the cap itself to tell them apart (mtp_step.rs does).
sequence_depths
2026-10-04: Drafts to verify per sequence: see the module doc. drafts[i] is sequence i’s draft confidences (top-1 log-probabilities, in draft order; its length is how many drafts it has; an empty slice with known_drafts[i] > 0 means drafts without confidences).