openinfer_simulator/runtime/executor/mod.rs
1//! Graph execution engine.
2//!
3//! The executor runs a validated graph against a model, managing runtime state
4//! and tensor storage. Use `Simulator` to validate and create an executor.
5mod fetch;
6mod iter;
7
8use std::sync::Arc;
9
10use anyhow::Result;
11
12use crate::graph::Graph;
13use crate::runtime::model_loader::ModelLoader;
14use crate::runtime::state::RuntimeState;
15use crate::runtime::trace::{TraceEvent, TraceEventKind};
16use crate::simulator::Device;
17use crate::tensor::{Tensor, TensorElement, TensorValue};
18
19pub use fetch::Fetchable;
20pub use iter::ExecutorIter;
21pub(crate) use iter::run_block;
22
23/// Executes a graph against a model and mutable runtime state.
24pub struct Executor {
25 state: RuntimeState,
26}
27
28impl Executor {
29 /// Create a new executor for a graph/model/device configuration.
30 pub fn new(
31 model: Arc<ModelLoader>,
32 graph: Graph,
33 device: Device,
34 trace_enabled: bool,
35 timer_enabled: bool,
36 ) -> Result<Self> {
37 Ok(Self {
38 state: RuntimeState::new(model, graph, device, trace_enabled, timer_enabled)?,
39 })
40 }
41
42 /// Insert a dynamic (runtime-provided) tensor value.
43 ///
44 /// # Example
45 /// ```no_run
46 /// # use openinfer::{ModelLoader, Simulator, Device, Tensor, graph};
47 /// # fn main() -> anyhow::Result<()> {
48 /// let model = ModelLoader::open("model.oinf")?;
49 /// let g = graph! { dynamic { x: f32[1]; } block entry { return; } };
50 /// let mut exec = Simulator::new(&model, &g, Device::Cpu)?.make_executor()?;
51 /// exec.insert_dynamic("x", Tensor::from_vec(vec![1.0f32])?)?;
52 /// # Ok(()) }
53 /// ```
54 pub fn insert_dynamic<T: Into<TensorValue>>(&mut self, name: &str, data: T) -> Result<()> {
55 self.state.insert_dynamic(name, data.into())
56 }
57
58 /// Fetch a named value using a `Fetchable` adapter.
59 ///
60 /// # Example
61 /// ```no_run
62 /// # use openinfer::{ModelLoader, Simulator, Device, graph};
63 /// # fn main() -> anyhow::Result<()> {
64 /// let model = ModelLoader::open("model.oinf")?;
65 /// let g = graph! { constant { alpha: f32; } block entry { return; } };
66 /// let mut exec = Simulator::new(&model, &g, Device::Cpu)?.make_executor()?;
67 /// let alpha: f32 = exec.fetch("alpha")?;
68 /// # Ok(()) }
69 /// ```
70 pub fn fetch<T: Fetchable>(&mut self, name: &str) -> Result<T> {
71 T::fetch(&mut self.state, name)
72 }
73
74 /// Fetch a tensor and convert it to a concrete element type.
75 pub fn fetch_typed<T: TensorElement>(&mut self, name: &str) -> Result<Tensor<T>> {
76 self.state.fetch_typed(name)
77 }
78
79 /// Fetch a tensor as a raw `TensorValue`.
80 pub fn fetch_raw(&mut self, name: &str) -> Result<TensorValue> {
81 self.state.get_tensor(name)
82 }
83
84 /// Execute the graph to completion, returning the last trace event.
85 ///
86 /// # Example
87 /// ```no_run
88 /// # use openinfer::{ModelLoader, Simulator, Device, graph};
89 /// # fn main() -> anyhow::Result<()> {
90 /// let model = ModelLoader::open("model.oinf")?;
91 /// let g = graph! { block entry { return; } };
92 /// let mut exec = Simulator::new(&model, &g, Device::Cpu)?.make_executor()?;
93 /// exec.step()?;
94 /// # Ok(()) }
95 /// ```
96 pub fn step(&mut self) -> Result<Option<TraceEvent>> {
97 let trace_enabled = self.state.trace_enabled();
98 let mut iter = self.iterate();
99 let mut last_event = None;
100 while let Some(step) = iter.next() {
101 let step = step?;
102 if trace_enabled {
103 log_trace_event(&step.event);
104 }
105 last_event = Some(step.event);
106 }
107 Ok(last_event)
108 }
109
110 /// Return the accumulated trace events.
111 pub fn trace(&self) -> Vec<TraceEvent> {
112 self.state.trace()
113 }
114
115 /// Iterate execution step-by-step, yielding `TraceStep` values.
116 ///
117 /// # Example
118 /// ```no_run
119 /// # use openinfer::{ModelLoader, Simulator, Device, graph};
120 /// # fn main() -> anyhow::Result<()> {
121 /// let model = ModelLoader::open("model.oinf")?;
122 /// let g = graph! { block entry { return; } };
123 /// let mut exec = Simulator::new(&model, &g, Device::Cpu)?.make_executor()?;
124 /// for step in exec.iterate() {
125 /// let _ = step?;
126 /// }
127 /// # Ok(()) }
128 /// ```
129 pub fn iterate(&mut self) -> ExecutorIter<'_> {
130 ExecutorIter::new(self)
131 }
132}
133
134fn log_trace_event(event: &TraceEvent) {
135 crate::log!(
136 "{} {} [{}] -- {} -- ({})",
137 event.node_index,
138 event.node_uuid,
139 event.block_name,
140 event.node_desc,
141 event.micros
142 );
143}