use crate::{BatchNormTask, GemmTask, MapOperation, Normalized};
#[cfg(all(feature = "accelerate", target_os = "macos"))]
use super::accelerate;
use super::backend::Backend;
#[cfg(all(feature = "cuda", target_os = "linux"))]
use super::cuda;
use super::formula::{Formula, Precision};
#[cfg(all(feature = "metal", target_os = "macos"))]
use super::metal;
#[cfg(feature = "simd")]
use super::simd;
pub(crate) trait Task: Sized {
type Product;
const FORMULA: Formula;
const PRECISION: Precision;
fn offer(&self, backend: Backend) -> Option<Self::Product>;
}
#[derive(Debug)]
pub struct MapTask<'buffers, Element> {
operation: MapOperation,
elements: &'buffers [Element],
}
impl<'buffers, Element> MapTask<'buffers, Element> {
pub fn new(operation: MapOperation, elements: &'buffers [Element]) -> Self {
Self {
operation,
elements,
}
}
pub fn operation(&self) -> MapOperation {
self.operation
}
pub fn elements(&self) -> &'buffers [Element] {
self.elements
}
}
impl Task for GemmTask<'_, f32> {
type Product = Vec<f32>;
const FORMULA: Formula = Formula::Gemm;
const PRECISION: Precision = Precision::F32;
fn offer(&self, backend: Backend) -> Option<Vec<f32>> {
match backend {
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::gemm_f32(self),
#[cfg(all(feature = "metal", target_os = "macos"))]
Backend::Metal => metal::gemm_f32(self),
#[cfg(all(feature = "cuda", target_os = "linux"))]
Backend::Cuda => cuda::gemm_f32(self),
#[cfg(feature = "simd")]
Backend::Simd => simd::gemm_f32(self),
_ => None,
}
}
}
impl Task for GemmTask<'_, f64> {
type Product = Vec<f64>;
const FORMULA: Formula = Formula::Gemm;
const PRECISION: Precision = Precision::F64;
fn offer(&self, backend: Backend) -> Option<Vec<f64>> {
match backend {
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::gemm_f64(self),
#[cfg(all(feature = "cuda", target_os = "linux"))]
Backend::Cuda => cuda::gemm_f64(self),
#[cfg(feature = "simd")]
Backend::Simd => simd::gemm_f64(self),
_ => None,
}
}
}
impl Task for MapTask<'_, f32> {
type Product = Vec<f32>;
const FORMULA: Formula = Formula::Map;
const PRECISION: Precision = Precision::F32;
fn offer(&self, backend: Backend) -> Option<Vec<f32>> {
match backend {
#[cfg(all(feature = "metal", target_os = "macos"))]
Backend::Metal => metal::map_f32(self.operation, self.elements),
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::map_f32(self.operation, self.elements),
_ => {
let _ = (self.operation, self.elements);
None
}
}
}
}
impl Task for MapTask<'_, f64> {
type Product = Vec<f64>;
const FORMULA: Formula = Formula::Map;
const PRECISION: Precision = Precision::F64;
fn offer(&self, backend: Backend) -> Option<Vec<f64>> {
match backend {
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::map_f64(self.operation, self.elements),
_ => {
let _ = (self.operation, self.elements);
None
}
}
}
}
impl Task for BatchNormTask<'_, f32> {
type Product = Normalized<f32>;
const FORMULA: Formula = Formula::BatchNormTraining;
const PRECISION: Precision = Precision::F32;
fn offer(&self, backend: Backend) -> Option<Normalized<f32>> {
match backend {
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::batch_norm_f32(self),
_ => None,
}
}
}
impl Task for BatchNormTask<'_, f64> {
type Product = Normalized<f64>;
const FORMULA: Formula = Formula::BatchNormTraining;
const PRECISION: Precision = Precision::F64;
fn offer(&self, backend: Backend) -> Option<Normalized<f64>> {
match backend {
#[cfg(all(feature = "accelerate", target_os = "macos"))]
Backend::Accelerate => accelerate::batch_norm_f64(self),
_ => None,
}
}
}