use crate::defaults::backend as backend_defaults;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum GpuMode {
#[default]
Auto,
Hybrid,
Full,
}
impl GpuMode {
pub fn resolve(self, backend: BackendType) -> GpuMode {
match self {
GpuMode::Auto => match backend {
BackendType::Cuda => GpuMode::Full,
BackendType::Wgpu | BackendType::Rocm | BackendType::Metal => GpuMode::Hybrid,
_ => GpuMode::Hybrid,
},
other => other,
}
}
pub fn is_full(self, backend: BackendType) -> bool {
matches!(self.resolve(backend), GpuMode::Full)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum BackendType {
#[default]
Auto,
Scalar,
Wgpu,
Avx512,
Sve2,
Cuda,
Rocm,
Metal,
}
impl BackendType {
pub fn is_implemented(&self) -> bool {
matches!(self, BackendType::Auto | BackendType::Scalar)
}
pub fn is_tensor_tile(&self) -> bool {
matches!(
self,
BackendType::Wgpu
| BackendType::Avx512
| BackendType::Sve2
| BackendType::Cuda
| BackendType::Rocm
| BackendType::Metal
)
}
}
#[derive(Clone, Debug)]
pub struct BackendConfig {
pub preferred: BackendType,
pub gpu_mode: GpuMode,
pub fallback_to_scalar: bool,
pub tensor_tile_min_rows: usize,
pub gpu_batch_size: usize,
pub use_gpu_subgroups: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BackendPreset {
Auto,
CpuOnly,
GpuRequired,
GpuPreferred,
}
impl Default for BackendConfig {
fn default() -> Self {
Self {
preferred: BackendType::Auto,
gpu_mode: GpuMode::default(),
fallback_to_scalar: true,
tensor_tile_min_rows: backend_defaults::TENSOR_TILE_MIN_ROWS,
gpu_batch_size: backend_defaults::DEFAULT_GPU_BATCH_SIZE,
use_gpu_subgroups: false,
}
}
}
impl BackendConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_preset(mut self, preset: BackendPreset) -> Self {
match preset {
BackendPreset::Auto => {
self.preferred = BackendType::Auto;
self.fallback_to_scalar = true;
}
BackendPreset::CpuOnly => {
self.preferred = BackendType::Scalar;
self.fallback_to_scalar = true;
}
BackendPreset::GpuRequired => {
self.preferred = BackendType::Wgpu;
self.fallback_to_scalar = false;
self.gpu_mode = GpuMode::Auto;
}
BackendPreset::GpuPreferred => {
self.preferred = BackendType::Wgpu;
self.fallback_to_scalar = true;
self.gpu_mode = GpuMode::Auto;
}
}
self
}
pub fn scalar() -> Self {
Self {
preferred: BackendType::Scalar,
gpu_mode: GpuMode::Hybrid,
fallback_to_scalar: true,
tensor_tile_min_rows: usize::MAX,
gpu_batch_size: backend_defaults::DEFAULT_GPU_BATCH_SIZE,
use_gpu_subgroups: false,
}
}
pub fn prefer_gpu() -> Self {
Self {
preferred: BackendType::Wgpu,
gpu_mode: GpuMode::Auto,
fallback_to_scalar: true,
tensor_tile_min_rows: backend_defaults::TENSOR_TILE_MIN_ROWS,
gpu_batch_size: backend_defaults::DEFAULT_GPU_BATCH_SIZE,
use_gpu_subgroups: false,
}
}
pub fn with_backend(mut self, backend: BackendType) -> Self {
self.preferred = backend;
self
}
pub fn with_gpu_mode(mut self, mode: GpuMode) -> Self {
self.gpu_mode = mode;
self
}
pub fn with_gpu_batch_size(mut self, batch_size: usize) -> Self {
self.gpu_batch_size = batch_size;
self
}
pub fn with_gpu_subgroups(mut self, enabled: bool) -> Self {
self.use_gpu_subgroups = enabled;
self
}
}