use std::sync::Arc;
use crate::skeleton::Skeleton;
use crate::tensor::backend::{Backend, ComputeFor, DefaultBackend};
use crate::{Composable, Dimension, Layout, OpError, Tensor};
use super::cache::{BuildFunction, EvictionPolicy, LRUPolicy, SkeletonCache, UnboundedPolicy};
use super::frame::BakedPromise;
pub struct DynamicSkeleton<T, B: Backend = DefaultBackend, P: EvictionPolicy = LRUPolicy> {
cache: SkeletonCache<Box<[Layout]>, P, T, B>,
build: BuildFunction<T, B>,
}
impl<T, B: Backend, P: EvictionPolicy> std::fmt::Debug for DynamicSkeleton<T, B, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DynamicSkeleton")
.field("cache", &self.cache)
.finish_non_exhaustive()
}
}
impl<P: EvictionPolicy, T, B: Backend> DynamicSkeleton<T, B, P>
where
T: ComputeFor<B>,
B: Backend,
{
#[inline]
pub fn new(cache_size: usize, build: BuildFunction<T, B>) -> Self {
Self {
cache: SkeletonCache::new(cache_size),
build,
}
}
#[inline]
pub fn run(&self, inputs: &[&Tensor<T, B>]) -> Result<Tensor<T, B>, OpError> {
self.cache.run(inputs, &self.build)
}
#[inline]
pub fn compose<C>(&self, inputs: &[&C]) -> Result<BakedPromise<T, B>, OpError>
where
C: Composable<T, B>,
{
self.cache.compose(inputs, &self.build)
}
#[inline]
pub fn remove(&self, key: &[&Tensor<T, B>]) -> Option<Arc<Skeleton<T, B>>> {
let layouts: Box<[Layout]> = key.iter().map(|&x| x.layout().clone()).collect();
self.cache.remove(&layouts)
}
#[inline]
pub fn remove_by_layout(&self, key: &[Layout]) -> Option<Arc<Skeleton<T, B>>> {
self.cache.remove(key)
}
#[inline]
pub fn contains_key(&self, key: &[&Tensor<T, B>]) -> bool {
let layouts: Box<[Layout]> = key.iter().map(|&x| x.layout().clone()).collect();
self.cache.contains_key(&layouts)
}
#[inline]
pub fn contains_key_by_layout(&self, key: &[Layout]) -> bool {
self.cache.contains_key(key)
}
}
pub type UnboundedDynamicSkeleton<T, B = DefaultBackend> = DynamicSkeleton<T, B, UnboundedPolicy>;