pub struct Skeleton<T, B: Backend = DefaultBackend> { /* private fields */ }Expand description
A precompiled execution plan, built once and run many times against new inputs.
§Examples
use candela::Tensor;
use std::error::Error;
// Creates tensors
let a = Tensor::from_scalar(0.3, &[4]);
let b = Tensor::from_scalar(0.3, &[8]);
// Creates a slot for a tensor with the same shape as a
let slot = a.to_slot();
// Create a skeleton with that slot
let skeleton = (&slot * 2.0 + 1.0).log2().into_skeleton(&[slot]).unwrap();
// Running the skeleton
let output_a = skeleton.run(&[&a]);
// Running the skeleton for an invalid shape
let output_b = skeleton.run(&[&b]);
// Check the output is ok
assert!(output_a.is_ok());
// Check the output is an error
assert!(output_b.is_err());Implementations§
Source§impl<T: Clone + PartialEq + ComputeFor<B>, B: Backend> Skeleton<T, B>
impl<T: Clone + PartialEq + ComputeFor<B>, B: Backend> Skeleton<T, B>
Sourcepub fn run(&self, inputs: &[&Tensor<T, B>]) -> Result<Tensor<T, B>, OpError>
pub fn run(&self, inputs: &[&Tensor<T, B>]) -> Result<Tensor<T, B>, OpError>
Executes the compiled plan against inputs and returns the result.
Runs the stored plan on the provided inputs without re-planning. The
inputs must be supplied in the same order they were declared to
into_skeleton.
§Errors
Returns OpError::IncorrectSlotAmount if inputs.len() differs from
the number of declared slots, or OpError::NotSameLayoutAtSlot if an
input’s Layout does not match the layout its slot was declared with.
§Examples
use candela::skeleton::SkeletonSlot;
use candela::{Layout, Tensor};
// The same compiled plan, executed against two different inputs.
let slot = SkeletonSlot::new(Layout::new(&[4]));
let skeleton = (&slot * 2.0 + 1.0).into_skeleton(std::slice::from_ref(&slot))?;
let a = skeleton.run(&[&Tensor::from_slice(&[0.0, 1.0, 2.0, 3.0], &[4])])?;
let b = skeleton.run(&[&Tensor::from_scalar(5.0, &[4])])?;
assert_eq!(a.data(), &[1.0, 3.0, 5.0, 7.0]);
assert_eq!(b.data(), &[11.0; 4]);Sourcepub fn compose<C: Composable<T, B>>(
&self,
inputs: &[&C],
) -> Result<BakedPromise<T, B>, OpError>
pub fn compose<C: Composable<T, B>>( &self, inputs: &[&C], ) -> Result<BakedPromise<T, B>, OpError>
Embeds the compiled plan as a node in a larger graph.
Embeds the Skeleton’s plan into a promise that must still be planned
and materialized to produce a Tensor. Unlike run, its inputs may
be any Composable operand except a slot - Tensor, TensorPromise,
or BakedPromise.
For all practical purposes, treat the output of this function as a
compressed representation of a TensorPromise.
§Errors
Returns OpError::IncorrectSlotAmount if inputs.len() differs from
the number of declared slots, or OpError::NotSameLayoutAtSlot if an
input’s Layout does not match the layout its slot was declared with.
§Examples
use candela::skeleton::SkeletonSlot;
use candela::{Layout, Tensor};
let lhs = Tensor::from_slice(&[1.0, 2.0, 3.0, 4.0], &[4]);
let rhs = Tensor::from_scalar(10.0, &[4]);
// Compile `a + b` over two slots, then splice it into a bigger expression.
let a = SkeletonSlot::new(Layout::new(&[4]));
let b = a.deep_clone();
let sum = (&a + &b).into_skeleton(&[a, b])?;
let baked = sum.compose(&[&lhs, &rhs])?;
// `baked` slots into a normal promise expression.
let result = (baked * 2.0).materialize();
assert_eq!(result.data(), &[22.0, 24.0, 26.0, 28.0]);Source§impl<T, B: Backend> Skeleton<T, B>
impl<T, B: Backend> Skeleton<T, B>
Sourcepub fn memory_report(&self) -> MemoryMetrics
pub fn memory_report(&self) -> MemoryMetrics
Reports memory allocations
Reports the memory that will be allocated during the execution of the Skeleton.
The report is correct at the moment this function was called, but changes to
cache state (filled vs empty) after it was run will change the metrics.
For the most accurate results rerun this function every time a cache part of this
Skeleton is changed (even by itself on the first run).
§Examples
use candela::skeleton::SkeletonSlot;
let slot = SkeletonSlot::from_shape(&[8]);
let skeleton = (&slot * 2.0).into_skeleton(&[slot])?;
let report = skeleton.memory_report();
assert!(report.total_number_of_allocations >= 1);
assert_eq!(report.output_memory_usage, 64); // [8] f64 = 64 bytes