Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/asap-aware-mapping/src/explanation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
//! | Catalog entry | Status | Where a future `ExplanationKind` would come from |
//! |---|---|---|
//! | Semantic-equivalent rewriting (e.g. `avg` → `sum`/`count`) | No `ReplacementStrategy` implementation in this codebase yet (tracked separately, issue #253) | Once wired into `default_strategies()`: any `Replacement::Rewrite` candidate that strategy proposes |
//! | Roll-ups (fine-to-coarse group-by reuse) | No `ReplacementStrategy` implementation in this codebase yet (tracked separately, issue #254) | Once wired into `default_strategies()`: any `Replacement::Rewrite` candidate that strategy proposes |
//! | Roll-ups (fine-to-coarse group-by reuse) | [`RollupStrategy`](crate::rollup::RollupStrategy), derived from workload siblings after CSE/target discovery (issue #254) | Any `Replacement::Rewrite` candidate that rolls a coarse aggregate up from a compatible finer aggregate |
//! | Wavelets/OMP | Params type exists (`WaveletKind`/`WaveletParams`), reachable only via a deployment `CostModel::realize_extension` (no core `AggIntent` dispatch picks it) | A `ReplacementStrategy` that inspects a deployment's own `CostModel`, once some intent shape actually maps to `Implementation::Wavelet` |
//! | Sampling | Same story as Wavelets: `SamplingKind`/`SamplingParams` exist, unreachable from core dispatch | Same hook as Wavelets, for `Implementation::Sample` |
//! | Deep generative compression | No representation at all — no `Implementation`/`SummaryFamilyType` variant | Needs a new summary family added to `asap_types::post_asap` first |
Expand Down
12 changes: 12 additions & 0 deletions crates/asap-aware-mapping/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@
//! #247's own rule-based traversal, which re-walked the tree once per
//! optimization before [`replacement::search_workload`] existed to read
//! from instead — see that module's docs for the full reframing.
//! - [`rollup`] — [`rollup::RollupStrategy`] wraps group-by-lattice roll-up
//! reuse (issue #254, part of #33) as a [`ReplacementStrategy`]: given a
//! coarser `Aggregate` target and a caller-supplied sibling set, proposes
//! re-deriving it from an already-computed, strictly finer sibling
//! `Aggregate` over identical child IR instead of an independent pass
//! over the raw source — the cross-aggregate sibling of
//! `pre_asap::cse::share_common_subtrees`'s identical-subtree sharing.
//! [`rollup::is_legal_rollup_source`] is the standalone legality predicate
//! other axes (e.g. issue #256's `GroupingStrategy`) are expected to
//! consult directly, so it and this module's `RollupStrategy` can never
//! disagree about which siblings qualify.
//! - [`rewrite`] — the "semantic-equivalent rewriting (e.g. `avg` →
//! `sum`/`count`) to increase how often the [sharing/sketch] optimizations
//! above apply" degree of freedom `docs/design_docs/asap_aware_mapping.md`
Expand Down Expand Up @@ -156,6 +167,7 @@ pub mod cost_model;
pub mod explanation;
pub mod replacement;
pub mod rewrite;
pub mod rollup;

pub use cost_model::{CostModel, DefaultCostModel};
pub use explanation::{
Expand Down
38 changes: 31 additions & 7 deletions crates/asap-aware-mapping/src/replacement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ use std::rc::Rc;
use thiserror::Error;

use crate::cost_model::{CostModel, CseCandidate, DefaultCostModel, ShareDecision};
use crate::rollup::RollupStrategy;

/// Errors from the pre-ASAP → post-ASAP replacement/construction path
/// ([`realize_child`] and [`keep_pre_asap`]). Moved here from the former
Expand Down Expand Up @@ -1776,9 +1777,10 @@ fn sketch_kind_of(node: &SummaryNode) -> Option<SketchAlgorithm> {

// ── default_strategies ──────────────────────────────────────────────────

/// The strategies [`search_workload`] runs, in the built-in
/// [`DefaultCostModel`] configuration — mirrors this module's own two
/// shipped [`ReplacementStrategy`] impls.
/// The context-free strategies [`search_workload`] runs in the built-in
/// [`DefaultCostModel`] configuration. Workload-dependent strategies such as
/// [`RollupStrategy`] are added by [`search_workload`] after CSE and target
/// discovery, when their sibling context exists.
/// [`crate::explanation::explain_replacements`] (issue #257) uses
/// this same set (via [`search_workload`]) rather than keeping a second,
/// explanation-specific list to stay in sync with. Use
Expand Down Expand Up @@ -1817,9 +1819,11 @@ pub fn search_workload<Id>(roots: Vec<(Id, Rc<QueryExpr>)>) -> PlanSpace<Id> {
search_workload_with(roots, &default_strategies())
}

/// Like [`search_workload`], but with an explicit `strategies` set (see
/// [`default_strategies_with`] to plug in a deployment-specific
/// [`CostModel`] for candidate generation).
/// Like [`search_workload`], but with an explicit set of context-free
/// `strategies` (see [`default_strategies_with`] to plug in a
/// deployment-specific [`CostModel`]). The workload-dependent
/// [`RollupStrategy`] is derived and added automatically after CSE for both
/// entry points, because only this function owns the post-CSE sibling set.
///
/// Runs [`share_common_subtrees`] once over `roots` first — so every
/// strategy (and, transitively, every
Expand All @@ -1837,6 +1841,10 @@ pub fn search_workload_with<'s, Id>(
roots: Vec<(Id, Rc<QueryExpr>)>,
strategies: &[Box<dyn ReplacementStrategy + 's>],
) -> PlanSpace<Id> {
search_cse_workload_with(cse_workload(roots), strategies)
}

fn cse_workload<Id>(roots: Vec<(Id, Rc<QueryExpr>)>) -> Vec<(Id, Rc<QueryExpr>)> {
// `share_common_subtrees` wants owned `QueryExpr`s, not already-`Rc`
// roots — the same `Rc::try_unwrap`-with-clone-fallback pattern
// `asap_types::pre_asap::cse::intern_child` itself uses to recover an
Expand All @@ -1848,12 +1856,25 @@ pub fn search_workload_with<'s, Id>(
(id, expr)
})
.collect();
let cse_roots = share_common_subtrees(owned_roots);
share_common_subtrees(owned_roots)
}

fn search_cse_workload_with<'s, Id>(
cse_roots: Vec<(Id, Rc<QueryExpr>)>,
strategies: &[Box<dyn ReplacementStrategy + 's>],
) -> PlanSpace<Id> {
let mut order = Vec::new();
let mut nodes = HashMap::new();
let mut counts: HashMap<*const QueryExpr, usize> = HashMap::new();
discover_targets(&cse_roots, &mut order, &mut nodes, &mut counts);
let siblings: Vec<Rc<QueryExpr>> = order
.iter()
.filter_map(|ptr| {
let node = &nodes[ptr];
matches!(node.as_ref(), QueryExpr::Aggregate { .. }).then(|| Rc::clone(node))
})
.collect();
let rollup_strategy = RollupStrategy::new(&siblings);

let mut groups: HashMap<*const QueryExpr, MemoGroup> = HashMap::new();
for ptr in &order {
Expand Down Expand Up @@ -1894,6 +1915,9 @@ pub fn search_workload_with<'s, Id>(
proposed.extend(strategy.replacements(&target));
}
}
if rollup_strategy.matches(&target) {
proposed.extend(rollup_strategy.replacements(&target));
}

for candidate in &proposed {
if let Replacement::Rewrite(rc) = &candidate.replacement {
Expand Down
Loading
Loading