Expand description
Ranked dispatch tables — Phase 6b’s O(1) runtime lookup.
Moved here from fuel-tensor/src/judge/cache.rs (board #109 PR-D
follow-up). docs/restructure-migration-design.md §5.1 Row 3 (RULED
2026-09-02) called this move clean, but that was measured before board
#109 landed judge/mod.rs itself in fuel-tensor (it needs Tensor to
realize profiling ops). The ORIGINAL cache.rs had exactly one
Tensor-dependent call (populate_dispatch_table ran judge::Judge::run
directly) blocking a bare move — moving it as-is would have recreated
the fuel-dispatch -> fuel-tensor cycle #305 avoided. The fix inverts
that one write path: this module no longer RUNS the judge, it only
STORES an already-computed ProfileReport via store.
fuel-tensor/src/judge/cache.rs keeps a thin populate_dispatch_table
that runs Judge::run (needs Tensor) and hands the result to store
— a downward call, no cycle.
Judge (mentioned above) is fuel_tensor::judge::Judge — plain text,
not a doc link, since this crate cannot resolve a path in a crate above
it in the dependency graph. This module has no dependency on it.
§Criteria
- Fastest — pick the backend with the lowest median latency. Excludes the reference backend by default (it’s the oracle, not a production path — pathologically slow by design).
- MostAccurate — pick the backend with the lowest
max_rel_erroragainst the reference backend. Also excludes reference (reference vs reference is by definition 0, but dispatching to it defeats the purpose of having an optimized backend at all). Ties broken by latency. - Balanced — minimise
latency_ns * (1 + accuracy_penalty * rel_error). Penalty coefficient defaults to 100 so a 1% rel-error bump is equivalent to a 2× latency penalty — steep enough that numerically-unsound fast paths don’t win by default.
§Process-wide cache
The dispatch table is hardware-determined: it doesn’t depend on the app, only on the CPU/GPU configuration. So a single process-wide instance is the right granularity, with three states:
- In-memory — populated by an explicit
storecall this process. Authoritative. - On-disk — persisted from a prior process; the same hardware was
profiled previously. Lazy-loaded on first
cachedcall. - Absent — no profile yet, or hardware changed since the persisted
profile was taken. Routed ops fall through to the Router’s default
backend until
storeruns successfully.
Structs§
- Dispatch
Options - Options for building a
DispatchTable. - Dispatch
Table - O(1) runtime dispatch table, constructed once from a
ProfileReportand then queried at realize time. - Pick
- Where the dispatch table decided an op should run, and which kernel sibling won at that decision point.
- Profile
Entry - Single (op_kind, dtype, size_class) × (backend, device_index, kernel_source) datum produced by one measurement run.
- Profile
Report - A persistable table of every profile measurement the Judge produced in one run.
- Size
Class - Dispatch size bucket. One
u32field carries two representations, disambiguated by theOpKindthat always sits beside it in the dispatch key (a matmul key is only ever compared to matmul keys):
Enums§
- Criterion
- A selection criterion — what “best” means for a lookup.
- OpKind
- Op kinds the Judge profiles. Adding a variant + a Judge match
arm extends the profile matrix; existing reports parse forward
thanks to
#[non_exhaustive].
Constants§
- DEFAULT_
ACCURACY_ PENALTY - Default weight applied to
max_rel_errorin the Balanced criterion’s cost function.
Functions§
- cached
- The currently-active dispatch table, if any.
- cached_
oracle - The currently-active
ProfileJudgeOracle, if any — same lifecycle and data source ascached, but exposing EVERY raw measurement (losing alternatives included) instead of winners only. The pipelined bridge attaches it tocrate::plan::PlanOptions::with_judgesocompile_planrefines Layer-1 static costs with measured latencies. - invalidate
- Drop the in-memory cache and delete the persisted profile on disk. The
next populate call (fuel-tensor’s
populate_dispatch_table, which runs the Judge and callsstore) will re-run the probe + judge from scratch. - store
- Populate the dispatch table from an already-computed
ProfileReportand persist it to disk. The caller runs the actual Judge measurement (that needsTensor, hence lives infuel-tensor) and hands the finished report here — this function only stores and serves it.