use burn_std::DType;
pub use burn_std::{ExecutionError, backtrace::BackTrace};
use crate::distributed::DistributedOps;
pub use crate::element::Element;
use crate::ops::*;
use crate::tensor::{BoolTensor, FloatTensor, IntTensor, QuantizedTensor};
use crate::{TensorData, TensorMetadata};
use alloc::string::String;
use enumset::{EnumSet, EnumSetType};
use crate::distributed::{DistributedParamId, DistributedParams};
use super::DeviceOps;
pub trait BackendTypes: Clone + Send + Sync + core::fmt::Debug + 'static {
type Device: DeviceOps;
type FloatTensorPrimitive: TensorMetadata<Device = Self::Device> + 'static;
type IntTensorPrimitive: TensorMetadata<Device = Self::Device> + 'static;
type BoolTensorPrimitive: TensorMetadata<Device = Self::Device> + 'static;
type QuantizedTensorPrimitive: TensorMetadata<Device = Self::Device> + 'static;
type GraphPrimitive: Clone + Send + Sync + core::fmt::Debug + 'static;
}
pub type BackendGraph<B> = <B as BackendTypes>::GraphPrimitive;
#[derive(Debug, Clone, Copy)]
pub enum GraphUnsupported {}
fn graph_unsupported() -> ExecutionError {
ExecutionError::Generic {
reason: alloc::string::String::from("graph capture is not supported by this backend"),
backtrace: BackTrace::capture(),
}
}
#[cfg_attr(doc, doc = crate::doc_tensor!())]
#[cfg_attr(not(doc), doc = "`Tensor`")]
pub trait Backend:
BackendTypes
+ FloatTensorOps<Self>
+ BoolTensorOps<Self>
+ IntTensorOps<Self>
+ ModuleOps<Self>
+ ActivationOps<Self>
+ QTensorOps<Self>
+ TransactionOps<Self>
+ DistributedOps<Self>
+ Clone
+ Default
+ Sized
+ Send
+ Sync
+ core::fmt::Debug
+ 'static
{
fn ad_enabled(_device: &Self::Device) -> bool {
false
}
#[allow(unused_variables)]
fn memory_persistent_allocations<
Output: Send,
Input: Send,
Func: Fn(Input) -> Output + Send,
>(
device: &Self::Device,
input: Input,
func: Func,
) -> Output {
func(input)
}
#[allow(unused_variables)]
fn memory_cleanup(device: &Self::Device) {}
fn name(device: &Self::Device) -> String;
fn seed(device: &Self::Device, seed: u64);
fn sync(_device: &Self::Device) -> Result<(), ExecutionError> {
Ok(())
}
fn graph_prepare(_device: &Self::Device) -> Result<(), ExecutionError> {
Ok(())
}
fn graph_start_capture(_device: &Self::Device) -> Result<(), ExecutionError> {
Err(graph_unsupported())
}
fn graph_stop_capture(_device: &Self::Device) -> Result<BackendGraph<Self>, ExecutionError> {
Err(graph_unsupported())
}
unsafe fn graph_replay(
_device: &Self::Device,
_graph: &BackendGraph<Self>,
) -> Result<(), ExecutionError> {
Err(graph_unsupported())
}
fn flush(_device: &Self::Device);
fn staging<'a, Iter>(_data: Iter, _device: &Self::Device)
where
Iter: Iterator<Item = &'a mut TensorData>,
{
}
fn supports_dtype(device: &Self::Device, dtype: DType) -> bool {
Self::dtype_usage(device, dtype).is_superset(DTypeUsage::general())
}
fn dtype_usage(device: &Self::Device, dtype: DType) -> DTypeUsageSet;
fn device_count(type_id: u16) -> usize;
}
pub trait AutodiffBackend: Backend {
type InnerBackend: Backend<Device = Self::Device>;
type Gradients: Send;
fn backward(tensor: FloatTensor<Self>) -> Self::Gradients;
fn grad(
tensor: &FloatTensor<Self>,
grads: &Self::Gradients,
) -> Option<FloatTensor<Self::InnerBackend>>;
fn grad_remove(
tensor: &FloatTensor<Self>,
grads: &mut Self::Gradients,
) -> Option<FloatTensor<Self::InnerBackend>>;
fn grad_replace(
tensor: &FloatTensor<Self>,
grads: &mut Self::Gradients,
grad: FloatTensor<Self::InnerBackend>,
);
fn inner(tensor: FloatTensor<Self>) -> FloatTensor<Self::InnerBackend>;
fn int_inner(tensor: IntTensor<Self>) -> IntTensor<Self::InnerBackend>;
fn bool_inner(tensor: BoolTensor<Self>) -> BoolTensor<Self::InnerBackend>;
fn q_inner(tensor: QuantizedTensor<Self>) -> QuantizedTensor<Self::InnerBackend>;
fn from_inner(tensor: FloatTensor<Self::InnerBackend>) -> FloatTensor<Self>;
fn int_from_inner(tensor: IntTensor<Self::InnerBackend>) -> IntTensor<Self>;
fn bool_from_inner(tensor: BoolTensor<Self::InnerBackend>) -> BoolTensor<Self>;
fn q_from_inner(tensor: QuantizedTensor<Self::InnerBackend>) -> QuantizedTensor<Self>;
fn set_distributed_params(
tensor: FloatTensor<Self>,
_param_id: DistributedParamId,
) -> FloatTensor<Self> {
tensor
}
fn distributed_params(_tensor: &FloatTensor<Self>) -> Option<DistributedParams> {
None
}
fn is_distributed(_tensor: &FloatTensor<Self>) -> bool {
false
}
}
#[derive(Debug, EnumSetType)]
pub enum DTypeUsage {
Storage,
Arithmetic,
Accelerated,
}
pub type DTypeUsageSet = EnumSet<DTypeUsage>;
impl DTypeUsage {
pub fn general() -> DTypeUsageSet {
DTypeUsage::Storage | DTypeUsage::Arithmetic
}
}