1use std::borrow::Borrow;
2use std::fmt::{Debug, Display};
3
4use multithread::Executor;
5
6use crate::internal::*;
7use crate::model::{Fact, Graph, OutletId};
8use crate::ops::konst::Const;
9use crate::runtime::RunOptions;
10
11use self::order::{build_flush_list, eval_order_for_nodes, eval_order_opt_ram_for_nodes};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub struct SessionId(u64);
19
20static NEXT_SESSION_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
21
22impl SessionId {
23 pub const NONE: SessionId = SessionId(u64::MAX);
26
27 fn next() -> SessionId {
28 SessionId(NEXT_SESSION_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
35pub struct LaneId(pub usize);
36
37#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct Seating {
52 lanes: Vec<LaneId>,
53 max_lanes: usize,
54}
55
56impl Seating {
57 pub fn new(max_lanes: usize, lanes: impl IntoIterator<Item = LaneId>) -> TractResult<Seating> {
58 let lanes: Vec<LaneId> = lanes.into_iter().collect();
59 for (seat, lane) in lanes.iter().enumerate() {
60 ensure!(lane.0 < max_lanes, "Seat {seat} takes lane {} of {max_lanes}", lane.0);
61 ensure!(!lanes[..seat].contains(lane), "Lane {} takes two seats in one turn", lane.0);
62 }
63 Ok(Seating { lanes, max_lanes })
64 }
65
66 pub fn single() -> Seating {
69 Seating { lanes: vec![LaneId(0)], max_lanes: 1 }
70 }
71
72 pub fn max_lanes(&self) -> usize {
73 self.max_lanes
74 }
75
76 pub fn lanes(&self) -> &[LaneId] {
77 &self.lanes
78 }
79
80 pub fn occupancy(&self) -> usize {
83 self.lanes.len()
84 }
85
86 pub fn address(&self, ix: usize) -> (Option<usize>, Option<usize>) {
91 if self.max_lanes == 1 { (None, None) } else { (Some(ix), Some(self.lanes[ix].0)) }
92 }
93}
94
95pub type TurnShared = anymap3::Map<dyn std::any::Any + Send>;
99
100#[derive(Debug, Clone, Copy)]
106pub struct EvalContext<'a> {
107 pub session: SessionId,
108 pub node_id: usize,
109 pub symbols: &'a SymbolValues,
110 pub scenario: Option<usize>,
111 pub shared: Option<&'a TurnShared>,
112 pub seating: &'a Seating,
115}
116
117pub struct TurnState {
118 pub resolved_symbols: SymbolValues,
119 pub scenario: Option<usize>,
120 pub values: Vec<Option<TVec<TValue>>>,
121 pub shared: TurnShared,
126 pub seating: Seating,
129}
130
131impl EvalContext<'static> {
132 pub fn out_of_plan() -> EvalContext<'static> {
136 static SYMBOLS: std::sync::OnceLock<SymbolValues> = std::sync::OnceLock::new();
137 static SEATING: std::sync::OnceLock<Seating> = std::sync::OnceLock::new();
138 EvalContext {
139 session: SessionId::NONE,
140 node_id: usize::MAX,
141 symbols: SYMBOLS.get_or_init(SymbolValues::default),
142 scenario: None,
143 shared: None,
144 seating: SEATING.get_or_init(Seating::single),
145 }
146 }
147}
148
149impl TurnState {
150 pub fn context(&self, session: SessionId, node_id: usize) -> EvalContext<'_> {
151 EvalContext {
152 session,
153 node_id,
154 symbols: &self.resolved_symbols,
155 scenario: self.scenario,
156 shared: Some(&self.shared),
157 seating: &self.seating,
158 }
159 }
160}
161
162impl Default for TurnState {
163 fn default() -> Self {
164 TurnState {
165 resolved_symbols: SymbolValues::default(),
166 scenario: None,
167 values: vec![],
168 shared: TurnShared::new(),
169 seating: Seating::single(),
170 }
171 }
172}
173
174impl Clone for TurnState {
175 fn clone(&self) -> Self {
176 TurnState {
177 resolved_symbols: self.resolved_symbols.clone(),
178 scenario: self.scenario,
179 values: vec![],
180 shared: TurnShared::new(),
181 seating: self.seating.clone(),
182 }
183 }
184}
185
186pub trait TurnStateHandler: Send + Sync + Debug {
187 fn before_plan_eval(&self, turn: &mut TurnState) -> TractResult<()>;
188 fn after_plan_eval(&self, turn: &mut TurnState) -> TractResult<()>;
189}
190
191impl Debug for TurnState {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 write!(f, "TurnState({:?})", self.resolved_symbols)
194 }
195}
196
197#[derive(Debug, Clone)]
198pub struct SimplePlan<F, O>
199where
200 F: Fact + Clone + 'static,
201 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
202{
203 pub(crate) model: Arc<Graph<F, O>>,
204 outputs: Vec<OutletId>,
205 order: Vec<usize>,
206 flush_lists: Vec<TVec<usize>>,
207 has_unresolved_symbols: bool,
208 symbols: Vec<Symbol>,
209 executor: Option<Executor>,
210 turn_handler: Option<Arc<dyn TurnStateHandler + 'static>>,
211}
212
213impl<F, O> SimplePlan<F, O>
214where
215 F: Fact + Clone + 'static,
216 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
217{
218 pub fn new(model: impl Into<Arc<Graph<F, O>>>) -> TractResult<Arc<SimplePlan<F, O>>> {
220 let model = model.into();
221 Self::build(model, &RunOptions::default()).map(Arc::new)
222 }
223
224 pub fn new_with_options(
226 model: impl Into<Arc<Graph<F, O>>>,
227 options: &RunOptions,
228 ) -> TractResult<Arc<SimplePlan<F, O>>> {
229 let model = model.into();
230 Self::build(model, options).map(Arc::new)
231 }
232
233 #[deprecated]
235 pub fn new_for_output(
236 model: Graph<F, O>,
237 output: OutletId,
238 ) -> TractResult<Arc<SimplePlan<F, O>>> {
239 #[allow(deprecated)]
240 Self::build_with_outputs_and_deps(model, &[output], &[], &RunOptions::default())
241 .map(Arc::new)
242 }
243
244 #[deprecated]
246 pub fn new_for_outputs(
247 model: impl Into<Arc<Graph<F, O>>>,
248 outputs: &[OutletId],
249 ) -> TractResult<Arc<SimplePlan<F, O>>> {
250 #[allow(deprecated)]
251 Self::build_with_outputs_and_deps(model, outputs, &[], &RunOptions::default()).map(Arc::new)
252 }
253
254 pub fn with_turn_handler<H: TurnStateHandler + 'static>(mut self, turn_handler: H) -> Self {
255 self.turn_handler = Some(Arc::new(turn_handler));
256 self
257 }
258
259 #[deprecated]
260 pub fn new_for_outputs_and_deps(
261 model: impl Into<Arc<Graph<F, O>>>,
262 outputs: &[OutletId],
263 deps: &[(usize, usize)],
264 ) -> TractResult<Arc<SimplePlan<F, O>>> {
265 #[allow(deprecated)]
266 Self::build_with_outputs_and_deps(model, outputs, deps, &RunOptions::default())
267 .map(Arc::new)
268 }
269
270 pub fn build(
271 model: impl Into<Arc<Graph<F, O>>>,
272 options: &RunOptions,
273 ) -> TractResult<SimplePlan<F, O>> {
274 let model = model.into();
275 let outputs = model.outputs.clone();
276 #[allow(deprecated)]
277 Self::build_with_outputs_and_deps(model, &outputs, &[], options)
278 }
279
280 #[deprecated]
281 pub fn build_with_outputs_and_deps(
282 model: impl Into<Arc<Graph<F, O>>>,
283 outputs: &[OutletId],
284 deps: &[(usize, usize)],
285 options: &RunOptions,
286 ) -> TractResult<SimplePlan<F, O>> {
287 let model = model.into();
288 let inputs = model.input_outlets()?.iter().map(|n| n.node).collect::<Vec<usize>>();
289 let outputs_nodes = outputs.iter().map(|n| n.node).collect::<Vec<usize>>();
290 let mut order = if options.skip_order_opt_ram {
291 eval_order_for_nodes(model.nodes(), &inputs, &outputs_nodes, deps)?
292 } else {
293 eval_order_opt_ram_for_nodes(model.nodes(), &inputs, &outputs_nodes, deps)?
294 };
295 order.retain(|node| !model.node(*node).op_is::<Const>());
296 let flush_lists = build_flush_list(&*model, &order, outputs, |n| !n.op_is::<Const>());
297
298 #[allow(clippy::mutable_key_type)]
299 let mut symbols: std::collections::HashSet<Symbol> = Default::default();
300 for node in &model.nodes {
301 for output in &node.outputs {
302 if let Ok(fact) = output.fact.to_typed_fact() {
303 symbols.extend(fact.shape.iter().flat_map(|d| d.symbols()))
304 }
305 }
306 }
307 Ok(SimplePlan {
308 model,
309 order,
310 flush_lists,
311 outputs: outputs.to_vec(),
312 has_unresolved_symbols: !symbols.is_empty(),
313 symbols: symbols.into_iter().collect(),
314 executor: options.executor.clone(),
315 turn_handler: None,
316 })
317 }
318
319 pub fn order_without_consts(&self) -> &[usize] {
320 &self.order
321 }
322
323 pub fn run(self: &Arc<Self>, inputs: TVec<TValue>) -> TractResult<TVec<TValue>> {
324 let mut state = self.spawn()?;
325 state.run(inputs)
326 }
327
328 pub fn model(&self) -> &Graph<F, O> {
329 self.model.borrow()
330 }
331
332 pub fn spawn(self: &Arc<Self>) -> TractResult<SimpleState<F, O>> {
333 SimpleState::new(self)
334 }
335}
336
337#[derive(Debug)]
338pub struct SimpleState<F, O>
339where
340 F: Fact + Clone + 'static,
341 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
342{
343 pub(crate) plan: Arc<SimplePlan<F, O>>,
344 pub op_states: Vec<Option<Box<dyn OpState>>>,
345 pub turn_state: TurnState,
346 session: SessionId,
347}
348
349impl<F, O> Clone for SimpleState<F, O>
352where
353 F: Fact + Clone + 'static,
354 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
355{
356 fn clone(&self) -> Self {
357 SimpleState {
358 plan: self.plan.clone(),
359 op_states: self.op_states.clone(),
360 turn_state: self.turn_state.clone(),
361 session: SessionId::next(),
362 }
363 }
364}
365
366impl<F, O> Drop for SimpleState<F, O>
367where
368 F: Fact + Clone + 'static,
369 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
370{
371 fn drop(&mut self) {
372 for (ix, node) in self.plan.model.nodes.iter().enumerate() {
373 node.op().drop_session(self.session, ix);
374 }
375 }
376}
377
378impl<F, O> SimpleState<F, O>
379where
380 F: Fact + Clone + 'static,
381 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
382{
383 pub fn new(plan: &Arc<SimplePlan<F, O>>) -> TractResult<SimpleState<F, O>> {
384 let plan = Arc::clone(plan);
385 let turn = TurnState::default();
386 let model = plan.model();
387 let states: Vec<Option<Box<dyn OpState>>> = vec![None; model.nodes.len()];
388 let mut state =
389 SimpleState { plan, op_states: states, turn_state: turn, session: SessionId::next() };
390 state.reset_op_states()?;
391 Ok(state)
392 }
393
394 pub fn new_from_inputs(
395 plan: &Arc<SimplePlan<F, O>>,
396 inputs: TVec<TValue>,
397 ) -> TractResult<SimpleState<F, O>> {
398 let mut state = SimpleState::new(plan)?;
399 state.set_inputs(inputs)?;
400 state.resolve_symbols_with_states()?;
401
402 Ok(state)
403 }
404
405 fn ready_turn(&mut self) {
406 if self.turn_state.values.len() == 0 {
407 self.turn_state.values = vec![None; self.plan.model.nodes().len()];
408 for node in &self.plan.model.nodes {
409 if let Some(k) = node.op_as::<Const>() {
410 self.turn_state.values[node.id] = Some(tvec!(k.val().clone().into_tvalue()));
411 }
412 }
413 }
414 }
415 pub fn reset_turn(&mut self) -> TractResult<()> {
417 self.reset_turn_keep_symbols();
418 self.turn_state.resolved_symbols = SymbolValues::default();
419 Ok(())
420 }
421
422 pub(crate) fn reset_turn_keep_symbols(&mut self) {
427 for node in &self.plan.order {
428 self.turn_state.values[*node] = None;
429 }
430 }
431
432 pub(crate) fn clear_resolved_symbols(&mut self) {
436 self.turn_state.resolved_symbols = SymbolValues::default();
437 self.turn_state.scenario = None;
438 }
439
440 pub fn seat(&mut self, seating: Seating) {
443 self.turn_state.seating = seating;
444 }
445
446 pub fn reset_lanes(&mut self, lanes: &[LaneId]) -> TractResult<()> {
448 for op_state in self.op_states.iter_mut().flatten() {
449 op_state.reset_lanes(lanes)?;
450 }
451 Ok(())
452 }
453
454 fn reset_op_states(&mut self) -> TractResult<()> {
456 let &mut SimpleState {
457 ref plan, ref turn_state, op_states: ref mut states, session, ..
458 } = self;
459 for (ix, n) in plan.model.nodes.iter().enumerate() {
460 states[ix] = n.op().state(&turn_state.context(session, ix))?;
461 }
462 Ok(())
463 }
464
465 pub(crate) fn resolve_symbols_with_states(&mut self) -> TractResult<()> {
466 for state in self
467 .op_states
468 .iter_mut()
469 .filter_map(Option::as_mut)
470 .filter(|s| s.has_init_tensor_fact())
471 {
472 state.resolve_symbols(&mut self.turn_state)?;
473 }
474 Ok(())
475 }
476
477 pub fn run(&mut self, inputs: TVec<TValue>) -> TractResult<TVec<TValue>> {
478 self.run_plan_with_eval(inputs, self::eval)
479 }
480
481 pub fn exec(&mut self) -> TractResult<()> {
482 self.exec_plan_with_eval(self::eval)
483 }
484
485 pub fn run_plan_with_eval<Eval, E>(
486 &mut self,
487 inputs: TVec<TValue>,
488 eval: Eval,
489 ) -> TractResult<TVec<TValue>>
490 where
491 Eval: for<'a, 'b, 'c> FnMut(
492 &'a EvalContext<'a>,
493 Option<&'b mut (dyn OpState + 'static)>,
494 &'c Node<F, O>,
495 TVec<TValue>,
496 ) -> Result<TVec<TValue>, E>,
497 E: Into<anyhow::Error> + Send + Sync + 'static,
498 {
499 self.set_inputs(inputs)?;
500 self.resolve_symbols_with_states()?;
501 self.exec_plan_with_eval(eval)?;
502 let outputs = self.outputs()?;
503 self.reset_turn()?;
504 Ok(outputs)
505 }
506
507 pub fn exec_plan_with_eval<Eval, E>(&mut self, eval: Eval) -> TractResult<()>
508 where
509 Eval: for<'a, 'b, 'c> FnMut(
510 &'a EvalContext<'a>,
511 Option<&'b mut (dyn OpState + 'static)>,
512 &'c Node<F, O>,
513 TVec<TValue>,
514 ) -> Result<TVec<TValue>, E>,
515 E: Into<anyhow::Error> + Send + Sync + 'static,
516 {
517 if let Some(executor) = self.plan().executor.as_ref() {
518 tract_linalg::multithread::multithread_tract_scope(executor.clone(), || {
519 self.do_exec_plan_with_eval(eval)
520 })
521 } else {
522 self.do_exec_plan_with_eval(eval)
523 }
524 }
525
526 fn do_exec_plan_with_eval<Eval, E>(&mut self, mut eval: Eval) -> TractResult<()>
527 where
528 Eval: for<'a, 'b, 'c> FnMut(
529 &'a EvalContext<'a>,
530 Option<&'b mut (dyn OpState + 'static)>,
531 &'c Node<F, O>,
532 TVec<TValue>,
533 ) -> Result<TVec<TValue>, E>,
534 E: Into<anyhow::Error> + Send + Sync + 'static,
535 {
536 {
537 self.ready_turn();
538 self.plan
539 .turn_handler
540 .as_ref()
541 .map(|it| it.before_plan_eval(&mut self.turn_state))
542 .transpose()?;
543
544 let mut syms_done = !self.plan.has_unresolved_symbols
545 || self
546 .plan
547 .symbols
548 .iter()
549 .all(|s| self.turn_state.resolved_symbols.get(s).is_some());
550
551 for (step, n) in self.plan.order.iter().enumerate() {
552 let node = self.plan.model.node(*n);
553 trace!("Running step {step}, node {node}");
554 let mut inputs: TVec<TValue> = tvec![];
555 for i in &node.inputs {
556 trace!(" use input {i:?}");
557 let prec_node = self.plan.model.node(i.node);
558 let prec = self.turn_state.values[i.node].as_ref().ok_or_else(|| {
559 format_err!("Computing {}, precursor {} not done:", node, prec_node)
560 })?;
561 inputs.push(prec[i.slot].clone())
562 }
563 for flush in &self.plan.flush_lists[step] {
564 trace!(" Ran {} can now flush {}", node, self.plan.model.node(*flush));
565 self.turn_state.values[*flush] = None;
566 }
567
568 if cfg!(debug_assertions) {
569 let facts = self.plan.model.node_input_facts(node.id)?;
570 if facts.len() != inputs.len() {
571 bail!(
572 "Evaluating {}: expected {} inputs, got {}",
573 node,
574 facts.len(),
575 inputs.len()
576 );
577 }
578 for (ix, (v, f)) in inputs.iter().zip(facts.iter()).enumerate() {
579 if !f.matches(v, Some(&self.turn_state.resolved_symbols))? {
580 bail!(
581 "Evaluating {}: input {:?}, expected {:?}, got {:?}",
582 node,
583 ix,
584 f,
585 v
586 );
587 }
588 }
589 }
590
591 if node.inputs.is_empty()
597 && let Some(preset) = self.turn_state.values[*n].as_ref()
598 {
599 inputs = preset.clone();
600 }
601
602 let ctx = self.turn_state.context(self.session, node.id);
603 let vs = eval(&ctx, self.op_states[node.id].as_deref_mut(), node, inputs)
604 .map_err(|e| e.into())?;
605
606 if !syms_done && self.plan.has_unresolved_symbols {
607 for (o, v) in node.outputs.iter().zip(vs.iter()) {
608 if let Ok(f) = o.fact.to_typed_fact() {
609 for (dim_abstract, dim_concrete) in f.shape.iter().zip(v.shape()) {
610 Self::resolve(
611 &mut self.turn_state,
612 dim_abstract,
613 *dim_concrete as i64,
614 )?;
615 }
616 }
617 }
618 if self
619 .plan
620 .symbols
621 .iter()
622 .all(|s| self.turn_state.resolved_symbols.get(s).is_some())
623 {
624 syms_done = true;
625 }
626 }
627 if cfg!(debug_assertions) {
628 let facts = self.plan.model.node_output_facts(node.id)?;
629 if facts.len() != vs.len() {
630 bail!(
631 "Evaluating {}: expected {} outputs, got {}",
632 node,
633 facts.len(),
634 vs.len()
635 );
636 }
637 for (ix, (v, f)) in vs.iter().zip(facts.iter()).enumerate() {
638 if node.outputs[ix].successors.len() == 0 {
639 continue;
640 }
641 if !f.matches(v, Some(&self.turn_state.resolved_symbols))? {
642 bail!(
643 "Evaluating {}: output {:?}, expected {:?}, got {:?}",
644 node,
645 ix,
646 f,
647 v
648 );
649 }
650 }
651 }
652
653 self.turn_state.values[node.id] = Some(vs);
654 }
655 self.plan
656 .turn_handler
657 .as_ref()
658 .map(|it| it.after_plan_eval(&mut self.turn_state))
659 .transpose()?;
660 }
661 Ok(())
662 }
663
664 pub fn set_inputs(&mut self, inputs: TVec<TValue>) -> TractResult<()> {
665 ensure!(
666 inputs.len() == self.model().inputs.len(),
667 "Wrong number of inputs for model. Expected {} got {}",
668 self.model().inputs.len(),
669 inputs.len()
670 );
671
672 for (ix, t) in inputs.into_iter().enumerate() {
673 self.set_input(ix, t)?
674 }
675 Ok(())
676 }
677
678 pub(crate) fn set_inputs_drain(&mut self, inputs: &mut TVec<TValue>) -> TractResult<()> {
682 ensure!(
683 inputs.len() == self.model().inputs.len(),
684 "Wrong number of inputs for model. Expected {} got {}",
685 self.model().inputs.len(),
686 inputs.len()
687 );
688 for (ix, t) in inputs.drain(..).enumerate() {
689 self.set_input(ix, t)?
690 }
691 Ok(())
692 }
693
694 fn resolve(state: &mut TurnState, expression: &TDim, provided: i64) -> TractResult<()> {
695 if let TDim::Sym(sym) = expression
696 && state.resolved_symbols.get(sym).is_none()
697 {
698 state.resolved_symbols.set(sym, provided);
699 if state.scenario.is_none() {
700 let scope = sym.scope().with_context(|| {
701 format!(
702 "Symbol {sym:?} points to an invalid (dead ?) SymbolScope. \
703 Make sure to create symbols using the model-managed SymbolScope."
704 )
705 })?;
706 state.scenario = scope.guess_scenario(&state.resolved_symbols)?;
707 }
708 return Ok(());
709 }
710 let expected = expression.eval(&state.resolved_symbols);
711 if let Some(x) = expected.as_i64()
712 && x != provided
713 {
714 bail!("Clashing resolution for expression. {expression}={x} != {provided}. ({state:?})")
715 }
716 if expected.symbols().len() == 1 {
717 let sym = expected.symbols().into_iter().next().unwrap();
718 if let Some(v) = solve_for(&sym, &expected, &provided.to_dim()) {
719 debug!("Determined symbol {sym}={v}");
720 state.resolved_symbols.set(&sym, v.to_i64().unwrap());
721 }
722 if state.scenario.is_none() {
723 let scope = sym
724 .scope()
725 .with_context(|| format!("Symbol {sym:?} points to an invalid (dead ?) SymbolScope. Make sure to create symbols using the model-managed SymbolScope."))?;
726 state.scenario = scope.guess_scenario(&state.resolved_symbols)?;
727 }
728 }
729 Ok(())
730 }
731
732 pub fn set_input(&mut self, input: usize, t: TValue) -> TractResult<()> {
733 let outlet: OutletId = *self
734 .model()
735 .input_outlets()?
736 .get(input)
737 .with_context(|| format!("Invalid input id for model ({input})."))?;
738 if let Ok(fact) = self.plan.model.outlet_fact(outlet)?.to_typed_fact() {
739 for (expected, provided) in fact.shape.iter().zip(t.shape()) {
740 Self::resolve(&mut self.turn_state, expected, *provided as i64)?;
741 }
742 }
743 let fact = self.plan.model.outlet_fact(outlet)?;
744 ensure!(
745 fact.matches(&t, Some(&self.turn_state.resolved_symbols))
746 .with_context(|| format!("Setting input {input}"))?,
747 "Input at index {input} has incorrect dtype or shape (got {t:?}, expected to match fact {fact:?})",
748 );
749 self.ready_turn();
750 self.turn_state.values[outlet.node] = Some(tvec!(t));
751 Ok(())
752 }
753
754 pub fn output(&self, id: usize) -> TractResult<&TValue> {
755 let outlet = self.model().output_outlets()?.get(id).with_context(|| {
756 format!(
757 "Required output {}, only have {}",
758 id,
759 self.model().output_outlets().unwrap().len()
760 )
761 })?;
762 let value: &TValue = self
763 .turn_state
764 .values
765 .get(outlet.node)
766 .context("node id for output beyond node values array")?
767 .as_ref()
768 .context("node is not an output")?
769 .get(outlet.slot)
770 .context("slot id too high")?;
771 Ok(value)
772 }
773
774 pub fn outputs(&mut self) -> TractResult<TVec<TValue>> {
775 let &mut SimpleState { ref plan, ref mut turn_state, .. } = self;
776 let mut v = tvec![];
777 for o in plan.outputs.iter() {
778 let vs = turn_state.values[o.node].as_mut().ok_or_else(|| {
779 format_err!("Outputs of {:?} are not computed", plan.model.nodes()[o.node])
780 })?;
781 v.push(vs[o.slot].clone())
782 }
783 Ok(v)
784 }
785
786 pub fn set_values(&mut self, id: usize, values: TVec<TValue>) -> TractResult<()> {
787 self.turn_state.values[id] = Some(values);
788 Ok(())
789 }
790
791 pub fn set_value(&mut self, id: usize, value: TValue) -> TractResult<()> {
792 self.set_values(id, tvec!(value))
793 }
794
795 pub fn prepare_inputs(&self, node: usize) -> TractResult<TVec<TValue>> {
796 let SimpleState { plan, turn_state, .. } = self;
797 let nodes = plan.model.nodes();
798 let node = &nodes[node];
799 let mut inputs: TVec<TValue> = tvec![];
800 for i in &node.inputs {
801 let prec_node = &nodes[i.node];
802 let prec = turn_state.values[i.node].as_ref().ok_or_else(|| {
803 format_err!("Computing {}, precursor {} not done.", node, prec_node)
804 })?;
805 inputs.push(prec[i.slot].clone())
806 }
807 if node.inputs.is_empty()
808 && let Some(preset) = turn_state.values[node.id].as_ref()
809 {
810 inputs = preset.clone();
811 }
812 Ok(inputs)
813 }
814
815 pub fn compute_one(&mut self, node: usize) -> TractResult<()> {
816 let inputs = self.prepare_inputs(node)?;
817 self.compute_one_with_inputs(node, inputs)
818 }
819
820 pub fn compute_one_with_inputs(
821 &mut self,
822 node: usize,
823 inputs: TVec<TValue>,
824 ) -> TractResult<()> {
825 let &mut SimpleState {
826 ref plan,
827 ref mut turn_state,
828 op_states: ref mut states,
829 session,
830 ..
831 } = self;
832 let nodes = plan.model.nodes();
833 let node = &nodes[node];
834 let ctx = turn_state.context(session, node.id);
835 let vs = eval(&ctx, states[node.id].as_deref_mut(), node, inputs)?;
836 turn_state.values[node.id] = Some(vs);
837 Ok(())
838 }
839
840 pub fn compute_recursively(&mut self, node: usize) -> TractResult<&[TValue]> {
841 let values = {
842 #[allow(clippy::needless_collect)] let precs: Vec<usize> =
844 self.model().nodes()[node].inputs.iter().map(|i| i.node).collect();
845 for i in precs.into_iter() {
846 if self.turn_state.values[i].is_none() {
847 let _ = self.compute_recursively(i)?;
848 }
849 }
850 let mut inputs: TVec<TValue> = tvec![];
851 {
852 let node = &self.model().nodes()[node];
853 for i in &node.inputs {
854 inputs.push(self.turn_state.values[i.node].as_ref().unwrap()[i.slot].clone())
855 }
856 if node.inputs.is_empty()
857 && let Some(preset) = self.turn_state.values[node.id].as_ref()
858 {
859 inputs = preset.clone();
860 }
861 }
862 let &mut Self {
863 op_states: ref mut states,
864 turn_state: ref mut turn,
865 ref plan,
866 session,
867 ..
868 } = self;
869 let ctx = turn.context(session, node);
870 eval(&ctx, states[node].as_deref_mut(), &plan.model().nodes[node], inputs)?
871 };
872 self.turn_state.values[node] = Some(values);
873 Ok(self.turn_state.values[node].as_ref().unwrap())
874 }
875
876 pub fn take_by_name(&mut self, name: &str) -> TractResult<TVec<Tensor>> {
877 let id = self.model().node_by_name(name)?.id;
878 Self::take(self, id)
879 }
880
881 pub fn take(&mut self, id: usize) -> TractResult<TVec<Tensor>> {
882 Ok(self.turn_state.values[id]
883 .take()
884 .ok_or_else(|| format_err!("Node is not computed"))?
885 .into_iter()
886 .map(|v| v.into_tensor())
887 .collect())
888 }
889
890 pub fn plan(&self) -> &Arc<SimplePlan<F, O>> {
891 &self.plan
892 }
893
894 pub fn model(&self) -> &Graph<F, O> {
895 &self.plan.model
896 }
897}
898
899pub fn eval<F, O>(
900 ctx: &EvalContext,
901 mut state: Option<&mut (dyn OpState + 'static)>,
902 node: &Node<F, O>,
903 input: TVec<TValue>,
904) -> TractResult<TVec<TValue>>
905where
906 F: Fact + Clone + 'static,
907 O: Debug + Display + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static,
908{
909 match state {
910 Some(ref mut state) => state.eval(ctx, node.op(), input),
911 None => node.op().eval(ctx, input),
912 }
913 .with_context(|| format!("Evaluating {node}"))
914}
915
916#[cfg(test)]
917mod test {
918 use super::*;
919 fn is_send<T: Send>() {}
920 fn is_sync<T: Sync>() {}
921
922 #[test]
923 fn type_model_is_sync() {
924 is_sync::<TypedModel>();
925 }
926
927 #[test]
928 fn type_model_is_send() {
929 is_send::<TypedModel>();
930 }
931
932 #[test]
933 fn type_plan_is_send() {
934 is_send::<TypedSimplePlan>();
935 }
936
937 #[test]
938 fn type_plan_is_sync() {
939 is_sync::<TypedSimplePlan>();
940 }
941
942 #[test]
943 fn type_state_is_send() {
944 is_send::<TypedSimpleState>();
945 }
946}