Skip to main content

KernelRegistry

Struct KernelRegistry 

Source
pub struct KernelRegistry { /* private fields */ }
Expand description

Registry mapping OpKind to runtime-executable Kernel implementations.

This type is used by the execution engine to dispatch operations to the correct kernel at runtime.

Implementations§

Source§

impl KernelRegistry

Source

pub fn new() -> Self

Creates an empty kernel registry.

§Examples
use tensor_forge::registry::KernelRegistry;
use tensor_forge::op::OpKind;

let reg = KernelRegistry::new();

assert!(reg.get(&OpKind::Add).is_none());
assert!(reg.get(&OpKind::MatMul).is_none());
assert!(reg.get(&OpKind::ReLU).is_none());
Examples found in repository?
examples/custom_kernel.rs (line 100)
78fn main() {
79    // Build a tiny graph:
80    //
81    //   out = add(a, b)
82    //
83    // The graph describes *what* should be computed, not how.
84    let mut graph = Graph::new();
85
86    let a = graph.input_node(vec![2, 2]);
87    let b = graph.input_node(vec![2, 2]);
88    let out = graph
89        .add(a, b)
90        .expect("Adding valid input nodes should succeed");
91
92    graph
93        .set_output_node(out)
94        .expect("Setting output node should succeed");
95
96    // Create a custom registry.
97    //
98    // Start from an empty registry and explicitly register only the kernel(s)
99    // needed by this graph.
100    let mut registry = KernelRegistry::new();
101
102    // Register our custom Add kernel.
103    //
104    // `register(...)` returns the previous mapping if one existed.
105    let old = registry.register(OpKind::Add, Box::new(CustomAddKernel));
106    assert!(
107        old.is_none(),
108        "First Add registration should not replace an existing kernel"
109    );
110
111    // Construct the executor with the custom registry.
112    let exec = Executor::new(registry);
113
114    // Bind runtime inputs.
115    //
116    // These are ordinary tensors supplied for the graph input nodes.
117    let a_tensor = Tensor::from_vec(vec![2, 2], vec![1.0, 2.0, 3.0, 4.0])
118        .expect("Tensor construction should succeed");
119    let b_tensor = Tensor::from_vec(vec![2, 2], vec![10.0, 20.0, 30.0, 40.0])
120        .expect("Tensor construction should succeed");
121
122    // Execute the graph.
123    //
124    // During execution:
125    // - the executor validates input bindings,
126    // - walks the graph in topological order,
127    // - sees an `OpKind::Add` node,
128    // - looks up `OpKind::Add` in the registry,
129    // - dispatches to `CustomAddKernel::compute(...)`.
130    let outputs = exec
131        .execute(&graph, vec![(a, a_tensor), (b, b_tensor)])
132        .expect("Execution should succeed");
133
134    let result = outputs
135        .get(&out)
136        .expect("Declared output should be present in executor results");
137
138    println!("Computed output for node {:?}: {:?}", out, result);
139}
Source

pub fn register( &mut self, op: OpKind, kernel: Box<dyn Kernel>, ) -> Option<Box<dyn Kernel>>

Registers kernel as the implementation for op.

Returns the previously registered kernel if one existed.

§Examples
use tensor_forge::kernel::{AddKernel, MatMulKernel};
use tensor_forge::op::OpKind;
use tensor_forge::registry::KernelRegistry;

let mut reg = KernelRegistry::new();

let old_kernel = reg.register(OpKind::Add, Box::new(AddKernel));
assert!(old_kernel.is_none());
assert!(reg.get(&OpKind::Add).is_some());

// Add conflicting mapping
let old_kernel = reg.register(OpKind::Add, Box::new(MatMulKernel));
assert!(old_kernel.is_some());             // returns old AddKernel Mapping.
assert!(reg.get(&OpKind::Add).is_some());  // `OpKind::Add` now maps to MatMulKernel.
Examples found in repository?
examples/custom_kernel.rs (line 105)
78fn main() {
79    // Build a tiny graph:
80    //
81    //   out = add(a, b)
82    //
83    // The graph describes *what* should be computed, not how.
84    let mut graph = Graph::new();
85
86    let a = graph.input_node(vec![2, 2]);
87    let b = graph.input_node(vec![2, 2]);
88    let out = graph
89        .add(a, b)
90        .expect("Adding valid input nodes should succeed");
91
92    graph
93        .set_output_node(out)
94        .expect("Setting output node should succeed");
95
96    // Create a custom registry.
97    //
98    // Start from an empty registry and explicitly register only the kernel(s)
99    // needed by this graph.
100    let mut registry = KernelRegistry::new();
101
102    // Register our custom Add kernel.
103    //
104    // `register(...)` returns the previous mapping if one existed.
105    let old = registry.register(OpKind::Add, Box::new(CustomAddKernel));
106    assert!(
107        old.is_none(),
108        "First Add registration should not replace an existing kernel"
109    );
110
111    // Construct the executor with the custom registry.
112    let exec = Executor::new(registry);
113
114    // Bind runtime inputs.
115    //
116    // These are ordinary tensors supplied for the graph input nodes.
117    let a_tensor = Tensor::from_vec(vec![2, 2], vec![1.0, 2.0, 3.0, 4.0])
118        .expect("Tensor construction should succeed");
119    let b_tensor = Tensor::from_vec(vec![2, 2], vec![10.0, 20.0, 30.0, 40.0])
120        .expect("Tensor construction should succeed");
121
122    // Execute the graph.
123    //
124    // During execution:
125    // - the executor validates input bindings,
126    // - walks the graph in topological order,
127    // - sees an `OpKind::Add` node,
128    // - looks up `OpKind::Add` in the registry,
129    // - dispatches to `CustomAddKernel::compute(...)`.
130    let outputs = exec
131        .execute(&graph, vec![(a, a_tensor), (b, b_tensor)])
132        .expect("Execution should succeed");
133
134    let result = outputs
135        .get(&out)
136        .expect("Declared output should be present in executor results");
137
138    println!("Computed output for node {:?}: {:?}", out, result);
139}
Source

pub fn get(&self, op: &OpKind) -> Option<&dyn Kernel>

Returns the kernel registered for op, if present.

§Examples
use tensor_forge::kernel::AddKernel;
use tensor_forge::op::OpKind;
use tensor_forge::registry::KernelRegistry;

let mut reg = KernelRegistry::new();
reg.register(OpKind::Add, Box::new(AddKernel));

assert!(reg.get(&OpKind::Add).is_some());
assert!(reg.get(&OpKind::MatMul).is_none());

Trait Implementations§

Source§

impl Default for KernelRegistry

Source§

fn default() -> Self

Creates a registry populated with the built-in kernels.

Registers:

§Examples
use tensor_forge::op::OpKind;
use tensor_forge::registry::KernelRegistry;

let reg = KernelRegistry::default();
assert!(reg.get(&OpKind::Add).is_some());
assert!(reg.get(&OpKind::MatMul).is_some());
assert!(reg.get(&OpKind::ReLU).is_some());

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.