metrale_circuit/memory/
workspace.rs1use std::collections::BTreeMap;
15
16use super::MemoryError;
17use crate::fuser::FusionPlan;
18use crate::ir::{Circuit, NodeIdx};
19use crate::venn::families::Families;
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct WorkspaceTerm {
24 pub family: String,
26 pub name: String,
28 pub bytes: u64,
30 pub arena: bool,
32 pub nodes: Vec<NodeIdx>,
34}
35
36pub(crate) fn widest(plans: Vec<Vec<WorkspaceTerm>>) -> Vec<WorkspaceTerm> {
39 let mut by: BTreeMap<(String, String), WorkspaceTerm> = BTreeMap::new();
40 for t in plans.into_iter().flatten() {
41 let key = (t.family.clone(), t.name.clone());
42 match by.get(&key) {
43 Some(old) if old.bytes >= t.bytes => {}
44 _ => {
45 by.insert(key, t);
46 }
47 }
48 }
49 by.into_values().collect()
50}
51
52pub(crate) fn workspace_terms(
54 c: &Circuit,
55 plan: &FusionPlan,
56 fams: &Families,
57 rows: u64,
58 sm_count: u64,
59) -> Result<Vec<WorkspaceTerm>, MemoryError> {
60 let mut dims = c.dims.clone();
61 dims.insert("n".into(), rows);
62 dims.insert("sm_count".into(), sm_count);
63 let mut terms: BTreeMap<(String, String), WorkspaceTerm> = BTreeMap::new();
64 for g in &plan.groups {
65 for &n in &g.nodes {
66 let node = &c.nodes[n];
67 let Some(f) = fams.of_group(&g.kernels, &g.emitter, &node.op) else {
68 continue;
69 };
70 dims.insert(
71 "k".into(),
72 node.inputs.first().map_or(0, |&e| c.edges[e].dim_value),
73 );
74 for w in &f.workspace {
75 let mut bytes = 0;
76 for e in &w.bytes {
77 bytes = bytes.max(e.eval(&dims).map_err(|e| MemoryError::Workspace {
78 family: f.id.clone(),
79 name: w.name.clone(),
80 detail: e.to_string(),
81 })?);
82 }
83 let t = terms
84 .entry((f.id.clone(), w.name.clone()))
85 .or_insert_with(|| WorkspaceTerm {
86 family: f.id.clone(),
87 name: w.name.clone(),
88 bytes: 0,
89 arena: w.arena,
90 nodes: Vec::new(),
91 });
92 t.bytes = t.bytes.max(bytes);
93 t.nodes.push(n);
94 }
95 }
96 }
97 Ok(terms.into_values().collect())
98}