metrale_circuit/venn/
mod.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-29: The kernel Venn diagram of a target model against the models we already support
4//! (`met circuit venn`): every target node, in every mode and row count asked for, classified
5//! against the kernel families the compared models run, ranked by estimated share of step time.
6//!
7//! Classes, decided per node from the family manifest ([`families`]):
8//! - **Shared**: a family the compared models run, at the same compile-time and policy point,
9//!   with a microbench record at that point and row count.
10//! - **Shared, unmeasured**: the same, without the record. Also a point the family already
11//!   realises by an instantiation or a runtime branch while the compared models run another
12//!   (the differing parameters are still listed).
13//! - **Parameterization opportunity**: the same family where declared parameters differ and
14//!   one of them is compile-time; the target point is missing or exists only as a file copy.
15//! - **Policy variant**: the same, where every differing parameter is a policy.
16//! - **Novel**: no family implements the op with the node's formats at that row count.
17//!
18//! Owner: metrale-circuit (venn).
19//! Invariants:
20//! - Pure: no I/O. The caller passes the circuits, plans, manifest and measurements.
21//! - Deterministic: ties break by family order in the manifest, then by circuit order.
22//! - A compared node whose plan kernel belongs to no family, and a parameter a node cannot
23//!   supply, are typed errors: the report is never built from a guess.
24
25pub mod checkpoint;
26pub mod classify;
27mod cli_args;
28pub mod compute;
29pub mod discover;
30pub mod families;
31pub mod measurements;
32mod render;
33mod render_summary;
34pub mod repo;
35pub mod report;
36pub mod roofline;
37
38use std::collections::BTreeMap;
39
40use crate::fuser::FusionPlan;
41use crate::ir::Circuit;
42use crate::rules::Mode;
43
44pub use cli_args::VennArgs;
45pub use families::{Families, FamilyError, ParamKind, parse_families};
46pub use measurements::{Measurements, parse_measurements};
47pub use render::render;
48pub use repo::{Repo, checkpoint_id_of, report_text, resolve};
49pub use report::{VennInputs, VennReport, build};
50
51/// 2026-09-29: One model on either side of the diagram, at one mode and row count.
52#[derive(Debug, Clone, Copy)]
53pub struct Subject<'a> {
54    /// 2026-09-29: Recipe id.
55    pub recipe: &'a str,
56    /// 2026-09-29: The instantiated circuit.
57    pub circuit: &'a Circuit,
58    /// 2026-09-29: The instance's policy settings (`kv_cache_dtype`, ...).
59    pub settings: &'a BTreeMap<String, String>,
60    /// 2026-09-29: Its fused plan at this mode and row count; `None` for a target no rule set
61    /// covers yet, whose nodes are matched to families by op.
62    pub plan: Option<&'a FusionPlan>,
63}
64
65/// 2026-09-29: A node's class.
66#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
67pub enum Class {
68    /// 2026-09-29: Reuse; optimized at this point.
69    Shared,
70    /// 2026-09-29: Reuse, then microbench.
71    SharedUnmeasured,
72    /// 2026-09-29: A policy template (or a split).
73    PolicyVariant,
74    /// 2026-09-29: A template parameter (or a split), with the stability gate.
75    ParameterizationOpportunity,
76    /// 2026-09-29: Build it.
77    Novel,
78}
79
80impl Class {
81    /// 2026-09-29: The report spelling.
82    pub fn name(self) -> &'static str {
83        match self {
84            Class::Shared => "Shared",
85            Class::SharedUnmeasured => "Shared, unmeasured",
86            Class::PolicyVariant => "Policy variant",
87            Class::ParameterizationOpportunity => "Param. opportunity",
88            Class::Novel => "Novel",
89        }
90    }
91}
92
93/// 2026-09-29: A parameter whose value differs from the compared point.
94#[derive(Debug, Clone, PartialEq, Eq)]
95pub struct Diff {
96    /// 2026-09-29: Parameter.
97    pub param: String,
98    /// 2026-09-29: Its kind.
99    pub kind: ParamKind,
100    /// 2026-09-29: The target's value.
101    pub target: String,
102    /// 2026-09-29: The compared value.
103    pub other: String,
104}
105
106/// 2026-09-29: What a target node was compared with.
107#[derive(Debug, Clone, PartialEq, Eq)]
108pub enum Compared {
109    /// 2026-09-29: A node a compared model runs, and the kernels its plan group launches.
110    Model {
111        /// 2026-09-29: Recipe.
112        recipe: String,
113        /// 2026-09-29: Node id.
114        node: String,
115        /// 2026-09-29: `module::function` list, or the emitter of a kernel-less group.
116        kernels: String,
117    },
118    /// 2026-09-29: An instantiated point no compared model runs.
119    Point {
120        /// 2026-09-29: How it is realised.
121        how: families::How,
122        /// 2026-09-29: Its sources.
123        files: Vec<String>,
124    },
125}
126
127/// 2026-09-29: A node's classification against one family.
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct Finding {
130    /// 2026-09-29: Family id.
131    pub family: String,
132    /// 2026-09-29: Class.
133    pub class: Class,
134    /// 2026-09-29: The target's point in the family.
135    pub point: families::Values,
136    /// 2026-09-29: The comparison.
137    pub compared: Compared,
138    /// 2026-09-29: Parameters that differ from the comparison, runtime ones included.
139    pub diffs: Vec<Diff>,
140    /// 2026-09-29: How the target point is realised when the family already has it.
141    pub instantiated: Option<families::How>,
142    /// 2026-09-29: Evidence records at the target point and row count.
143    pub evidence: Vec<families::EvidenceSource>,
144}
145
146/// 2026-09-29: Why a Venn table could not be built.
147#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
148pub enum VennError {
149    /// 2026-09-29: A compared node whose plan group's kernels no family lists.
150    #[error("{recipe}: node `{node}` ({op}) runs {kernels}, which no family in the manifest lists")]
151    UnmappedKernel {
152        /// 2026-09-29: Recipe.
153        recipe: String,
154        /// 2026-09-29: Node id.
155        node: String,
156        /// 2026-09-29: Op name.
157        op: String,
158        /// 2026-09-29: Kernels.
159        kernels: String,
160    },
161    /// 2026-09-29: A parameter a node cannot supply, and no stated `absent` value.
162    #[error("family `{family}` parameter `{param}`: node `{node}` gives no value")]
163    MissingValue {
164        /// 2026-09-29: Family id.
165        family: String,
166        /// 2026-09-29: Parameter.
167        param: String,
168        /// 2026-09-29: Node id.
169        node: String,
170    },
171    /// 2026-09-29: An evidence record naming a measurements.toml row that does not exist.
172    #[error("family `{family}` cites measurement `{key}`, which measurements.toml does not have")]
173    UnknownMeasurement {
174        /// 2026-09-29: Family id.
175        family: String,
176        /// 2026-09-29: The key.
177        key: String,
178    },
179    /// 2026-09-29: A node the roofline cannot estimate.
180    #[error(transparent)]
181    Cost(#[from] roofline::CostError),
182    /// 2026-09-29: A mode the target circuit has no section for, or a row count it cannot run.
183    #[error("{0}")]
184    Run(String),
185    /// 2026-09-29: Loading or fusing a subject.
186    #[error("{0}")]
187    Load(String),
188    /// 2026-09-29: The family manifest disagrees with the kernel sources.
189    #[error("KERNEL_FAMILIES.toml has drifted from the sources:\n  {}", .0.join("\n  "))]
190    Drift(Vec<String>),
191    /// 2026-09-29: The target instance disagrees with the checkpoint directory it was named by.
192    #[error("{0}")]
193    Checkpoint(String),
194}
195
196/// 2026-09-29: One mode and row count.
197#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
198pub struct Run {
199    /// 2026-09-29: Mode.
200    pub mode: Mode,
201    /// 2026-09-29: Padded rows.
202    pub rows: u64,
203}
204
205#[cfg(test)]
206mod venn_tests;