pub struct AlternativeSet { /* private fields */ }Expand description
Bounded collection of Candidates at one decision point. The
optimizer ranker constructs one of these per kernel-bearing graph
node, runs the filter chain, ranks survivors by composite cost,
and retains the per-ending-device Pareto frontier (capped at
KEEP_PER_DEVICE/device by crowding distance) for storage on the
optimized graph — see Self::retain_per_device_frontier.
Stored as a SmallVec because:
- Inline capacity 4 covers every decision point that exists today (CPU + CUDA + Vulkan + one cuBLAS/CUTLASS sibling once that registers).
- Spilling to heap only happens when a decision point genuinely has more than 4 alternatives — rare, and the cost is amortized over a one-time enumeration anyway.
Implementations§
Source§impl AlternativeSet
impl AlternativeSet
Sourcepub fn empty() -> Self
pub fn empty() -> Self
Build an empty set. Tests + the candidate enumerator both use
this. Retention (the per-device Pareto frontier + crowding cap)
is applied later via Self::retain_per_device_frontier, not
at construction.
Sourcepub fn from_candidates(candidates: Vec<Candidate>) -> Self
pub fn from_candidates(candidates: Vec<Candidate>) -> Self
Build a set from a pre-collected list of candidates. The
enumerator path; retention (per-device Pareto frontier +
crowding cap) happens after the filter chain + cost rank via
Self::retain_per_device_frontier, not here.
Sourcepub fn set_context(&mut self, ctx: DecisionContext)
pub fn set_context(&mut self, ctx: DecisionContext)
Stamp the decision-point identity. compile_plan calls this
once per kernel-bearing node; the context survives filtering,
ranking, and truncation untouched (it describes the decision
point, not the candidates).
Sourcepub fn context(&self) -> Option<&DecisionContext>
pub fn context(&self) -> Option<&DecisionContext>
The decision-point identity, if stamped. Dispatch-time
selectors use this to key super::JudgeOracle lookups.
Sourcepub fn push(&mut self, c: Candidate)
pub fn push(&mut self, c: Candidate)
Append one candidate. Used by the enumerator as it walks
(backend, device) combinations.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
How many alternatives remain. Drives the filter chain’s hard-vs-soft decision and (in later phases) the executor’s “we have N to choose from” telemetry.
Sourcepub fn alternatives(&self) -> &[Candidate]
pub fn alternatives(&self) -> &[Candidate]
Borrow the full candidate list. Read-only — the filter chain uses this to compute the keep-mask without mutating.
Sourcepub fn retain_indices(&mut self, indices: &[usize])
pub fn retain_indices(&mut self, indices: &[usize])
Retain only the entries at indices (must be sorted ascending,
distinct, and in-range). The filter-chain pipeline produces a
Vec<usize> from each filter and calls this to apply it.
Panics in debug builds if indices is mis-shaped (out-of-range
or unsorted). Release builds skip the check — the producer is
always internal to the ranker.
Sourcepub fn retain_per_device_frontier(&mut self, keep: usize)
pub fn retain_per_device_frontier(&mut self, keep: usize)
Retain the per-ending-device Pareto frontier, backstopped by
an NSGA-II crowding-distance cap of keep/device — Phase B
PR-B2’s retention policy, replacing the retired fixed top-N
truncation.
Production callers pass KEEP_PER_DEVICE. The set is expected
to have been ranked (Self::rank_by_cost) so the arm-0 winner
(lowest central time) is at index 0; this method preserves
that winner and re-ranks the survivors so the winner stays at
index 0 (realize follows arm-0, so its identity must not change).
§Algorithm
- Bucket by ending device (
Candidate::device). - Per-device Pareto frontier: within each bucket keep the
candidates not
dominatedby any other candidate in the same bucket; drop the dominated. - Never strand the last
(device, backend): for every distinct(device, backend)present in the input, if the Pareto filter dropped all of its candidates, re-admit its time-best one. A(device, backend)with a single candidate therefore always survives, even if globally dominated. - Crowding cap: if a device bucket still exceeds
keep, drop the lowest-crowding-distance entries (NSGA-II: boundary points per axis getf64::INFINITY, interior points the sum of normalized neighbor gaps over theCostVectoraxes) until the bucket is≤ keep— but never drop a candidate that is the sole survivor of its(device, backend), and never drop the global arm-0 winner.
§Invariants (asserted)
- ≥1 path per device survives (each device bucket is non-empty after retention).
- Total ≤
keep × devices. - The arm-0 winner is retained.
A keep of 0 is treated as 1 (a device bucket can never be
emptied — that would strand the device).
Sourcepub fn rank_by_cost(&mut self)
pub fn rank_by_cost(&mut self)
Rank candidates by the per-path cost vector
(super::cost_vector::CostVector) — Phase B PR-B1.
The vector’s axes are one central time metric, per-tier
memory, and discrete precision/accuracy (see the cost_vector
module docs). Ranking uses
CostVector::total_order_key, which keeps the winner
time-first: the lowest-central-time candidate sorts to
index 0 (arm-0), exactly preserving the old composite_ns
winner, with ties broken precision → accuracy → memory
(the constitution’s order).
Why time-first for the winner while CostVector::dominates
exists: realize follows arm-0, so the winner must stay the
lowest-time candidate to preserve realize behavior. Pareto
dominance is the relation the frontier retention
(Self::retain_per_device_frontier, PR-B2) uses — that
retired the top-N truncation for a per-device Pareto frontier +
crowding cap.
Stable sort — equal-key candidates keep their relative order, which matters when registration order is the residual tie-breaker (and, post-Stage-2, when decision-device candidates are enumerated ahead of off-device ones).
Sourcepub fn rank_by_composite_cost(&mut self)
pub fn rank_by_composite_cost(&mut self)
Sort candidates ascending by their composite static cost
(Layer-1 score; see super::cost::composite_ns) plus the
Stage-2 inbound-transfer term
(Candidate::inbound_transfer_ns).
As of Phase B PR-B1 this delegates to Self::rank_by_cost:
the cost VECTOR is now the ranking primitive, and its
total_order_key is time-first, so for a single-device,
single-precision candidate set (the common case + the entire
CPU --lib suite) the winner is unchanged — lowest central
time is exactly the old composite_ns winner. Retained as a
named alias so existing callers (compile_plan,
compile_run_view) and tests don’t churn.
Phase 1.4 of the picker-work arc. Composite cost is
max(compute_ns, memory_ns) + overhead_ns, treating
compute and memory as parallel (roofline model). Layer-2
Judge data refines static_cost before this call
(compute_static_costs); the transfer term is added
serially — the bytes must land before the kernel can run.
Sourcepub fn set_static_cost(&mut self, index: usize, cost: CostEstimate)
pub fn set_static_cost(&mut self, index: usize, cost: CostEstimate)
Set the static_cost field of the candidate at index.
Used by super::cost::compute_static_costs to populate
the field after enumeration. Panics in debug builds if
index >= len.
Sourcepub fn set_inbound_transfer_ns(&mut self, index: usize, ns: u64)
pub fn set_inbound_transfer_ns(&mut self, index: usize, ns: u64)
Set the Stage-2 inbound-transfer term of the candidate at
index. Used by
super::cost::apply_inbound_transfer_costs. Panics in
debug builds if index >= len.
Trait Implementations§
Source§impl Clone for AlternativeSet
impl Clone for AlternativeSet
Auto Trait Implementations§
impl Freeze for AlternativeSet
impl RefUnwindSafe for AlternativeSet
impl Send for AlternativeSet
impl Sync for AlternativeSet
impl Unpin for AlternativeSet
impl UnsafeUnpin for AlternativeSet
impl UnwindSafe for AlternativeSet
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more