Template Struct PeakBatchedModel¶
Defined in File cost_model.hpp
Nested Relationships¶
Nested Types¶
Struct Documentation¶
-
template<typename IdxToSz>
struct PeakBatchedModel¶ Multi-mode batched peak-memory single-term cost model (DenseSpaceTimeBatched objective).
Implements the per-batchable-index all-co-resident pebble-game DP, factored into the CostModel hooks driven by run_single_term_opt. Follows the batch-aware cost model design (section 6.2, model A): each DP cell is indexed by both a subset
nand a sliced-set contextBover the batchable indices, so a model State is the[B]-vector of per-context BatchedRes. No CSE; persistence-gated batching.- Template Parameters:
IdxToSz – A callable mapping an Index to its extent.
Public Types
-
using State = container::vector<container::vector<BFrontPoint>>¶
Per-subset DP cell: a
[B]-vector (sizenB= 2^m) of Pareto frontiers, one non-dominated (peak, flops) set per sliced-set context B.
Public Functions
-
inline bool is_batchable(Index const &ix) const¶
Derived “batchable in any role”: true iff the index is batchable in the contracted or the external role. This is not a settable field; the DP’s role filters consume the individual building blocks, never this union. The building blocks default-decline, so both are always callable here.
-
template<typename TIdxs>
inline Context build_context(TensorNetwork const &network, TIdxs const &tidxs) const¶
-
inline void relax(Context &ctx, size_t n, size_t lp, size_t rp, State const &lp_st, State const &rp_st, State &acc) const¶
-
inline bool is_external_mode(Context const &ctx, std::size_t k) const¶
True iff batchable mode bit
kis a genuine external mode of this network: it is open on the root result and is contracted at no node.An external mode is carried unchanged from the leaves up to the root: whenever any tensor in a subset carries the mode, the mode stays open in that subset, so it never appears in any node’s contracted-at-node set (
contracted_here= (open_modes[lp]|open_modes[rp]) & ~open_modes[n]) and slicing it is purely a footprint change with identical work. This is whatContext::external_maskis built from: such a mode is a nestable cell mode only under batch_spectator_indices, and only then may the DP open its loop at a node (BFrontPoint::eopen).
-
inline int select_root(Context const &ctx, container::vector<State> const &st) const¶
Threshold-gated root-frontier selection shared by reconstruct and reconstruct_batched_modes: among points whose peak (bytes) fits peak_threshold, pick fewest flops (ties by lower peak). If none fit, pick min peak (best effort). peak_threshold == +inf => all feasible => min flops => the non-batched schedule. Returns the chosen index into
st[root][0] — the term root is always read at cell 0 (the empty sequence): every loop the schedule uses, contracted or external, is opened inside the tree by the DP, so the root has no enclosing nest.
-
inline EvalSequence reconstruct(Context const &ctx, container::vector<State> const &st) const¶
-
inline double subtree_peak(Context const &ctx, container::vector<State> const &st, std::size_t n, std::size_t Bsched, std::size_t Usize, int idx) const¶
Modeled peak (in elements) of the chosen back-pointer subtree rooted at subset
n, read at DP schedule cellBschedand sized under the explicit union maskUsize. This is the reusable, node-level re-price of the peak reconstruction in reconstructed_batched_peak: it follows the same back-pointer walk (children/order/aprime chosen by the DP) and the same staged-peak algebra (stage_first/stage_second/stage_formwith the resident-scanresand accumulationcontribterms), but sizes every subset fromUsizeinstead of from the schedule cell’s union. WithUsize==cell_union(Bsched)the two agree exactly.
-
inline std::pair<EvalSequence, container::vector<NodeBatchAnnotation>> reconstruct_batched_modes(Context const &ctx, container::vector<State> const &st, double *out_root_peak_bytes = nullptr) const¶
Companion to reconstruct that additionally reports, for each
-1(contraction) entry emitted in the returnedEvalSequencein emission order, the vector ofIndexsliced at that node (ctx.batchable_modes[bit] for each set bit of that node’saprime). Leaf entries contribute nothing. Does not change reconstruct’s own output; the two walks are kept in lock-step so the RPN order and the per-node modes line up.out_root_peak_bytes(when non-null) receives the term’s reported root peak in bytes: the selected root frontier point’s footprint, which already reflects every loop — contracted and external alike — the DP chose to open, since external opens are priced inside the DP (BFrontPoint::eopen) rather than stamped on afterwards.
Public Members
-
std::function<double(Index const&, std::size_t)> inner_pow = {}¶
k-aware inner (CSV/PNO composite) extent; see footprint_counter. Required whenever the network has composite indices (empty => inner_aware_volume throws); pass an explicit no-op only for composite-free networks. No default: omitting it silently mis-sized composites (4-PAO-integral bug).
-
double volatile_weight = 1.0¶
Replay weight applied to volatile contractions in the flop tie-break.
-
double machine_balance = 0.0¶
Roofline parameters for the secondary (tie-break) cost; see RooflineParams and roofline_op_cost. machine_balance == 0 (default) => pure-flop tie-break (no behavior change). Uses full (unsliced) operand+result footprints (total per-replay traffic; slicing reduces peak, not total work).
-
double fast_mem_elems = 0.0¶
-
double block_tiles = 3.0¶
-
double block_prefactor = 1.0¶
-
bool batch_persistent_only = false¶
If true, batch only persistent subtrees (decline any subset containing a volatile leaf). Default false = batch across the board. See BatchPolicy::persistent_only.
-
double peak_flops_tolerance = 0.0¶
Unused by reconstruct (superseded by the threshold-gated selection below, driven by peak_threshold / numeric_size); retained for source compatibility. See PeakModel::peak_flops_tolerance, which is still consulted by the (unbatched) DenseSpaceTime model.
-
double accumulation_factor = 0.0¶
In-flight batch-contribution footprint multiplier; see BatchPolicy::accumulation_factor. Charged only on nodes that contract a batchable index (Ap != 0), into the all-co-resident peak term, to price the accumulator + contribution co-residency of K += contribution.
-
double peak_threshold = std::numeric_limits<double>::infinity()¶
Peak-memory budget (bytes) for threshold-gated selection; see BatchPolicy::peak_threshold. +infinity (default) => min-flops (no batching).
-
double numeric_size = 8.0¶
Bytes per stored element, to compare the model’s element-count peak to peak_threshold (bytes). Default 8 (double / TensorD).
-
bool perf_first = false¶
Perf-first / peak-second selection: when true,
select_rootselects the root-frontier point by (flops, then peak) and does not consultpeak_thresholdas a feasibility gate, so the threshold cannot force a flops-catastrophic factorization for its sliceability. Default false = peak-first, threshold-gated selection.
-
bool charge_batch_recompute = true¶
If true (the default), charge the batch recomputation cost on the flops/ exec mode. The batched evaluator re-executes each contraction per tile of the ancestor batch modes its result does not carry (across-batch work is recomputed; within-batch sharing is cached — see eval.hpp
”replays the
build of every compatible persistent final”). A node at ancestor-sliced- set B is charged nbatches(b) for each b in B not open in the node, so a schedule that slices many modes it must recompute across pays for it. The alternative (false) assumes work parity (batching is free on flops), which under-costs heavily-sliced families and does not reflect the true cost of batching; kept only as an escape hatch for comparison.
The charge is order-aware: DP cells are ordered nests (see Context::ordered), so a node is billed only for the enclosing loops outer to its innermost-carried placement (Context::escaped_outer). Loops inner to that placement, and every loop when the node carries none of the enclosing modes, hoist above for free (rf == 1). An order-blind set charge would systematically over-bill the hoistable case.
-
bool charge_bound_persistence = true¶
If true (the default), a value bound to a batch loop is charged as often as the loop runs. A loop runs once per production of the value that closes it (the node contracting the mode in batches), so a non-volatile subtree sliced by a loop that a volatile node closes is rebuilt every replay — it cannot persist across evaluations (the runtime’s persistence rule, explicit-cells design section 12) — and takes volatile_weight exactly as an amplitude-dependent value does. A non-volatile nest closed by a non-volatile node (a persistent intermediate summed over the DF index from two persistent factors) runs once and is charged once, as before. Without this the model assumed every amplitude-independent subtree is computed once, ever, regardless of slicing, and priced slicing a persistent operand of an amplitude contraction as free — part of the water-20 occupied-batching cost gap (3x measured vs 1x modelled). Applied at the closing node, where its volatility is known: for each child subtree that is non-volatile and carries a mode sliced here, the child’s whole cost is scaled (an over-charge only for descendants of that child which do not carry the mode and hoist above the loop). An external loop the DP opens here (BFrontPoint::eopen) closes here too — the full result is assembled outside it, per production of this node — so it is charged the same way: the scale keys on the whole sliced set S (the contracted
aprimeor the external opens), not onaprimealone.
-
std::function<bool(Index const&)> is_batchable_contracted_index =
[](Index const&) { return false; }¶ Spaces batchable in the contracted role — i.e. a mode of such a space is batchable where it is summed at some node. Building block; companion to is_batchable_external_index. Declared here (outside the positionally-initialized prefix) and adjacent to its external companion so the two roles read together; set it by member assignment. Defaults to decline every index => no mode is batchable in the contracted role.
-
std::function<bool(Index const&)> is_batchable_external_index =
[](Index const&) { return false; }¶ Spaces batchable in the external role — i.e. a mode of such a space is batchable when it is open on the term root (a spectator carried to the result), not when it is contracted. Companion to is_batchable_contracted_index, which admits spaces batchable in the contracted role. Keeping the two roles as separate caller-supplied space sets is what lets this layer stay domain-generic: the caller decides which spaces are batchable in which role, and build_context drops every mode whose role’s predicate rejects it (so a space batchable only as external never bloats the 2^m search with its contracted occurrences). Defaults to decline every index; a caller that wants external batching sets it explicitly (there is no fallback to the contracted-role predicate). Declared here (outside the positionally-initialized prefix) so existing aggregate initializations are unaffected; set it by member assignment.
-
bool prune_outer_products = true¶
Prune disconnected (outer-product) subsets from the DP (see OptimizeOptions::prune_outer_products). Default true.
-
bool batch_spectator_indices = false¶
Term-level gate for reconstruct_batched_modes emitting
BatchModeType::Externalentries (genuine external modes; see is_external_mode), threaded from CostParams::batch_spectator_indices / BatchPolicy::batch_spectator_indices. Default false so every other PeakBatchedModel construction (peak_cost_batched, compute_external_batch_ axis’s own model, existing tests) is unaffected and emits no External entries. With it on, an external batch loop is a per-node DP choice (BFrontPoint::eopen): external bits become nestable cell modes and reconstruct_batched_modes stampsExternalexactly where the DP opened or inherited them. There is no post-DP placement pass.
-
struct BFrontPoint¶
One non-dominated (peak, flops) trade-off for a (subset, sliced-set
B) cell.aprimeis the sliced-set chosen at this node; the children are read at contextC= B | aprime, at frontier indiceslp_idx/rp_idx. See PeakModel::FrontPoint for why a frontier (not a single peak-min cell) is needed.Public Members
-
double peak = std::numeric_limits<double>::max()¶
-
double flops = std::numeric_limits<double>::max()¶
-
size_t lp = 0¶
-
size_t rp = 0¶
-
bool lp_first = true¶
-
std::size_t aprime = 0¶
-
int lp_idx = -1¶
-
int rp_idx = -1¶
-
std::size_t nsl = 0¶
Cumulative count of batchable modes sliced anywhere in this realization (this node’s
aprimepopcount plus both children’snsl). Used only by the perf-first ceiling’s threshold-aware frontier domination (pareto_insert_ceiling) to break peak-below-budget ties toward the least-sliced realization, so the unsliced schedule survives whenever it fits the budget. Zero for leaves and for the unbatched / peak-first paths, where it is never consulted.
-
std::size_t eopen = 0¶
External modes whose batch loop this node opens: carried by the node, absent from its enclosing set, nested outer of
aprime. The node is produced per batch and scattered into its full result outside the loop; the children see the mode in their enclosing set, non-carriers under it pay the recompute charge, and the opener is the loop’s closer for charge_bound_persistence. Children are read at descend(descend(B, eopen), aprime).
-
double peak = std::numeric_limits<double>::max()¶
-
struct Context¶
Precomputed tables and per-(subset, sliced-set) lookup parameters built once by build_context.
Public Functions
-
inline double fast_flops(std::size_t lp, std::size_t rp) const¶
Flop count of the binary contraction (subset
lp) x (subsetrp), equivalent to flops_of(idx[lp], idx[rp], idx[n]) with n = lp|rp, but reading precomputed atom-ID lists instead of rebuilding index sets per call. (idx[n] is a subset of idx[lp] U idx[rp], so it adds nothing.)
-
inline double sz_u(std::size_t U, std::size_t s) const¶
Footprint of subset s under an explicit sliced-set union mask (the order-independent bitmask, as returned by cell_union). Slicing is a pure footprint change, so the size depends only on which modes are in the union, never on the cell’s nesting order — this is the primitive that sz and the external-placement re-price (subtree_peak) share, so an external mode can be injected into the union directly without a precomputed ordered cell (external bits are excluded from build_cells).
-
inline double Lof_u(std::size_t U, std::size_t s) const¶
Per-context leaf-sum of subset s under an explicit union mask.
-
inline double sz(std::size_t s, std::size_t id) const¶
Context-restricted size of subset s under sliced-set ctx (the table is indexed by the part of ctx actually open in s; mirrors the oracle).
-
inline double Lof(std::size_t s, std::size_t id) const¶
Per-context leaf-sum of subset s (sum of singleton sizes under ctx).
-
inline std::size_t cell_union(std::size_t id) const¶
-
inline std::size_t descend(std::size_t id, std::size_t Ap) const¶
-
inline std::size_t descend_pt(std::size_t id, std::size_t eopen, std::size_t Ap) const¶
-
inline std::size_t escaped_outer(std::size_t id, std::size_t carried) const¶
-
inline void build_cells(bool ext_nestable)¶
Public Members
-
container::vector<Index> batchable_modes¶
Ordered, deduplicated batchable indices (bit
kmaps tobatchable_modes[k]).
-
std::size_t m = 0¶
Number of batchable indices (= batchable_modes.size()).
-
std::size_t nB = 1¶
Number of sliced-sets (= 2^m).
-
std::size_t nt = 0¶
Number of tensors in the network.
-
container::vector<container::vector<double>> tables¶
tables[B][n] = footprint of subset n under sliced-set B.
-
container::vector<std::size_t> open_modes¶
open_modes[n] = bitmask of batchable indices open in subset n.
-
std::size_t volatile_mask = 0¶
Bitmask of volatile leaf tensors.
-
std::function<double(IndexSet const&, IndexSet const&, IndexSet const&)> flops_of¶
flops_of(lhs, rhs, result) = flop count of one binary contraction. Retained as the reference for the fast_flops parity test; the relax hot loop uses fast_flops (see below).
-
container::vector<double> nbatches¶
nbatches[k] = number of batch tiles of batchable_modes[k] = ceil(extent / target), clamped to >= 1. Used to charge batch recomputation (see charge_batch_recompute): a node inside an ancestor batch loop over batchable_modes[k] that does not carry batchable_modes[k] is re-executed nbatches[k] times.
-
bool use_fast_flops = true¶
-
bool f_inner_engaged = false¶
-
bool ordered = true¶
-
std::size_t cap = 3¶
-
std::size_t nCells = 1¶
-
std::size_t external_mask = 0¶
-
inline double fast_flops(std::size_t lp, std::size_t rp) const¶