#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Backend {
Scalar,
Sse2,
Avx2,
Avx512,
Neon,
Cuda,
Metal,
Vulkan,
WebGpu,
}
impl Backend {
pub fn name(&self) -> &'static str {
match self {
Self::Scalar => "Scalar",
Self::Sse2 => "SSE2",
Self::Avx2 => "AVX2",
Self::Avx512 => "AVX-512",
Self::Neon => "NEON",
Self::Cuda => "CUDA",
Self::Metal => "Metal",
Self::Vulkan => "Vulkan",
Self::WebGpu => "WebGPU",
}
}
pub fn is_gpu(&self) -> bool {
matches!(self, Self::Cuda | Self::Metal | Self::Vulkan | Self::WebGpu)
}
pub fn is_simd(&self) -> bool {
matches!(self, Self::Sse2 | Self::Avx2 | Self::Avx512 | Self::Neon)
}
pub fn theoretical_speedup(&self) -> f64 {
match self {
Self::Scalar => 1.0,
Self::Sse2 => 4.0, Self::Avx2 => 8.0, Self::Avx512 => 16.0, Self::Neon => 4.0, Self::Cuda => 100.0, Self::Metal => 50.0, Self::Vulkan => 50.0, Self::WebGpu => 30.0, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum WorkloadType {
Gemm,
Conv2d,
Elementwise,
Reduction,
Attention,
Bandwidth,
}
impl WorkloadType {
pub fn name(&self) -> &'static str {
match self {
Self::Gemm => "GEMM",
Self::Conv2d => "Conv2D",
Self::Elementwise => "Elementwise",
Self::Reduction => "Reduction",
Self::Attention => "Attention",
Self::Bandwidth => "Bandwidth",
}
}
}
#[derive(Debug, Clone)]
pub struct BackendMeasurement {
pub backend: Backend,
pub workload: WorkloadType,
pub size: usize,
pub latency_us: f64,
pub throughput: f64,
pub efficiency_percent: f64,
pub transfer_time_us: Option<f64>,
pub compute_time_us: Option<f64>,
}
impl BackendMeasurement {
pub fn new(
backend: Backend,
workload: WorkloadType,
size: usize,
latency_us: f64,
throughput: f64,
) -> Self {
Self {
backend,
workload,
size,
latency_us,
throughput,
efficiency_percent: 0.0,
transfer_time_us: None,
compute_time_us: None,
}
}
pub fn with_efficiency(mut self, efficiency: f64) -> Self {
self.efficiency_percent = efficiency;
self
}
pub fn with_gpu_timing(mut self, transfer_us: f64, compute_us: f64) -> Self {
self.transfer_time_us = Some(transfer_us);
self.compute_time_us = Some(compute_us);
self
}
pub fn transfer_overhead(&self) -> Option<f64> {
match (self.transfer_time_us, self.compute_time_us) {
(Some(t), Some(c)) if t + c > 0.0 => Some(t / (t + c)),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct BackendComparison {
pub baseline: Backend,
pub comparison: Backend,
pub workload: WorkloadType,
pub size: usize,
pub efficiency_ratio: f64,
pub speedup: f64,
pub is_regression: bool,
pub threshold: f64,
}
impl BackendComparison {
pub fn summary(&self) -> String {
if self.is_regression {
format!(
"REGRESSION: {} -> {} on {} size={}: {:.1}% slower",
self.baseline.name(),
self.comparison.name(),
self.workload.name(),
self.size,
(1.0 - self.speedup) * 100.0
)
} else {
format!(
"OK: {} -> {} on {} size={}: {:.1}x speedup",
self.baseline.name(),
self.comparison.name(),
self.workload.name(),
self.size,
self.speedup
)
}
}
}
#[derive(Debug, Clone)]
pub struct SizeCliff {
pub backend: Backend,
pub workload: WorkloadType,
pub size_before: usize,
pub size_after: usize,
pub efficiency_before: f64,
pub efficiency_after: f64,
pub drop_percent: f64,
}
impl SizeCliff {
pub fn summary(&self) -> String {
format!(
"CLIFF: {} {} at {}\u{2192}{}: {:.1}% efficiency drop",
self.backend.name(),
self.workload.name(),
self.size_before,
self.size_after,
self.drop_percent
)
}
}
#[derive(Debug, Clone)]
pub struct BackendRecommendation {
pub backend: Backend,
pub workload: WorkloadType,
pub size: usize,
pub expected_efficiency: f64,
pub confidence: f64,
pub reason: String,
}