Expand description
Batch lane policy: the shared vocabulary and the one decision function.
Three libraries decide how a batch of independent problems is split over a
thread budget (tcontract’s packed driver and faer strategy, cpueinsum’s
grouped GEMM, tlinalg’s lane plan). This module gives them one vocabulary
and one pure function, batch_decision, so a caller can force a route and
two crates cannot drift on the same decision. The types are plain data with
no rayon dependency; they live apart from Exec so moving
them later is a re-export, not a redesign.
§Strategies
BatchStrategy::Auto is the only heuristic. Every other variant forces a
route and never falls back: the route either honors it (clamped to the
items and the budget) or the library reports
ExecError::StrategyUnavailable.
BatchStrategy::WholeBatchVendor is the one forced route that may be
unavailable, and it is refused from the query’s vendor capability alone,
before any output write.
Forced strategies are evaluated against the original host budget. Only
Auto narrows, because the packed driver narrows its Exec twice (see
below).
§What Auto computes
Auto has two forms, chosen by the query. This is how one formula serves
both the shared work model and the packed driver’s legacy rule:
- Without
balanced_lanes, the issue’s generic formula: estimateitem_nsandtotal_ns, cap the lanes attotal_ns / min_work_per_lane_ns, and fan out only whenlanes >= 2,items >= min_itemsanditems >= lanes * min_items_per_lane. Each lane runs items serially; with one lane,item_threadsis the width of one item, so a route that permits it (faer) can parallelize inside the item. - With
balanced_lanes, the packed two-stage rule below, which the defaultWorkModelreproduces to the lane.
§The legacy rules and how Auto expresses them
This step lands the vocabulary with defaults that reproduce today’s tcontract packed decision; the sweep that fits one shared default to all three libraries is a later step. The three legacy rules and their mapping:
| Legacy rule | Source | Encoding here |
|---|---|---|
| packed balanced lanes | crates/tcontract/src/driver/batch.rs:38, plan/mod.rs:641, driver/route.rs:49 | Auto + balanced_lanes + the default WorkModel (its width is the existing WidthPolicy, its item cost is NS_PER_FLOP) |
| faer item-width-1 | crates/tcontract/src/strategy/faer.rs:243 | Auto + item_parallel; a decision with item_threads > 1 is the inner route, lanes > 1 with item threads one is the outer route |
contract_batched item count | crates/tcontract/src/batch.rs:140 | forced strategies, not Auto: BatchStrategy::Outer when the items fill the budget; below that one lane, the caller running each item on the whole budget (Sequential/Inner). It has no work threshold. |
The packed rule is two-stage. plan/mod.rs:641 first narrows the Exec to
width_for(total_ns) over the whole batch, and driver/batch.rs:38
recomputes the width against that narrowed budget and only then applies its
tiny (one item already below the serial threshold) and balanced (every
lane non-empty, the split near-even, the batch alone fills the budget)
tests. Auto reproduces exactly that: it narrows budget with
model.width, then applies the tiny/balanced tests when the query says
balanced_lanes, and reports the narrowed width as item_threads when it
keeps one lane. The test auto_matches_legacy_packed_table pins this on a
table.
§Examples
use std::num::NonZeroUsize;
use tcontract_exec::batch::{batch_decision, BatchPolicy, BatchQuery, BatchStrategy};
use tcontract_exec::ExecError;
let budget = NonZeroUsize::new(8).unwrap();
let query = BatchQuery::new(16, 64.0);
// A forced route is clamped, never a fallback.
let outer = BatchPolicy::new(BatchStrategy::Outer);
let d = batch_decision(&outer, budget, &query).unwrap();
assert_eq!((d.lanes, d.item_threads, d.vendor_batch), (8, 1, false));
// The vendor route needs the caller to say it exists.
let vendor = BatchPolicy::new(BatchStrategy::WholeBatchVendor);
assert!(matches!(
batch_decision(&vendor, budget, &query),
Err(ExecError::StrategyUnavailable { .. })
));Structs§
- Batch
Decision - The route
batch_decisionselected. - Batch
Policy - A strategy and the model its
Autoarm applies. - Batch
Query - What one batch of one route looks like to
batch_decision. - Work
Model - The cost and fan-out model
BatchStrategy::Autoapplies.
Enums§
- Batch
Strategy - How the items of a batch are split over a thread budget.
Functions§
- batch_
decision - Decide the route for one batch on
budgetthreads underpolicy.