Skip to main content

Module batch

Module batch 

Source
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 scheduler 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 crate::ExecError::StrategyUnavailable.

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: estimate item_ns and total_ns, cap the lanes at total_ns / min_work_per_lane_ns, and fan out only when lanes >= 2, items >= min_items and items >= lanes * min_items_per_lane. Each lane runs items serially; with one lane, item_threads is 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 default WorkModel reproduces to the lane.

§Widths come from the token

Auto never owns a width model. Every width it needs is the token’s: Exec::width_for turns the estimated serial time of the region and the number of sections (dispatches) it performs into the width at which the region pays, using the dispatch cost of the token’s kind (team, plain token inside its pool, plain token outside it; threadteam owns the table and the PAYS multiple). A batch has two such regions: the whole batch spread over lanes (one section) and one item on a team (BatchQuery::item_sections sections). The rules below combine them:

RuleSourceEncoding here
packed balanced lanescrates/tcontract/src/driver/batch.rs:38, plan/mod.rs:641, driver/route.rs:49Auto + balanced_lanes + the default WorkModel (its item cost is ns_per_flop())
faer item-width-1crates/tcontract/src/strategy/faer.rs:243Auto + 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 countcrates/tcontract/src/batch.rs:140forced 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 first narrows the Exec to the width the whole batch pays for, and driver/batch.rs recomputes the width against that narrowed budget and only then applies its tiny (one item alone does not pay a team) 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 the token, 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.

§Examples

use tcontract_exec::batch::{batch_decision, BatchPolicy, BatchQuery, BatchStrategy};
use tcontract_exec::{Exec, Pool};

let sp = threadteam::Pool::builder().threads(8).build().unwrap();
let pool = Pool::borrow(&sp);
let exec = Exec::new(&pool, 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, &exec, &query);
assert_eq!(d.lanes, exec.budget().min(8));
assert_eq!(d.item_threads, 1);

Structs§

BatchDecision
The route batch_decision selected.
BatchPolicy
A strategy and the model its Auto arm applies.
BatchQuery
What one batch of one route looks like to batch_decision.
WorkModel
The cost and fan-out model BatchStrategy::Auto applies.

Enums§

BatchStrategy
How the items of a batch are split over a thread budget.

Functions§

batch_decision
Decide the route for one batch on the budget and the dispatch costs of exec under policy.
batch_decision_within
batch_decision for a stage that was narrowed to budget slots (at most the token’s own) without narrowing the token: the widths minimise over 1..=budget with the token’s dispatch costs (Exec::width_for_within).