1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![cfg_attr(coverage_nightly, coverage(off))]
//! Analytics Backend Abstraction (Issue #79, P0-3)
//!
//! Provides unified backend selection for GPU/SIMD/Scalar compute operations.
//! Implements graceful degradation: GPU → SIMD → Scalar.
//!
//! # Backend Selection
//!
//! ```rust
//! use pmat::services::analytics_backend::{Backend, BackendSelector};
//!
//! // Automatic backend selection (graceful degradation)
//! let backend = BackendSelector::auto_select();
//!
//! // Manual backend selection
//! let backend = Backend::Simd;
//! ```
//!
//! # Statistical Equivalence Testing
//!
//! The primary use case is validating GPU floating-point results against SIMD
//! to ensure CI stability despite GPU non-associativity.
//!
//! Reference: Higham (1993) - "The Accuracy of Floating Point Summation" (SIAM)
/// Compute backend selection for analytics operations
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Backend {
/// GPU-accelerated compute using wgpu (requires analytics-gpu feature)
#[cfg(feature = "analytics-gpu")]
Gpu,
/// SIMD-accelerated compute using trueno (requires analytics-simd feature)
#[cfg(feature = "analytics-simd")]
Simd,
/// Scalar fallback (always available)
Scalar,
}
/// Backend selector with graceful degradation
pub struct BackendSelector;
impl BackendSelector {
/// Automatically select best available backend
///
/// Preference order: GPU > SIMD > Scalar
///
/// # Example
///
/// ```rust
/// use pmat::services::analytics_backend::BackendSelector;
///
/// let backend = BackendSelector::auto_select();
/// println!("Selected backend: {:?}", backend);
/// ```
pub fn auto_select() -> Backend {
#[cfg(feature = "analytics-gpu")]
{
// GPU availability check not yet implemented; fall through to SIMD
}
#[cfg(feature = "analytics-simd")]
{
return Backend::Simd;
}
#[allow(unreachable_code)]
Backend::Scalar
}
/// Check if GPU backend is available
#[cfg(feature = "analytics-gpu")]
pub fn is_gpu_available() -> bool {
// TODO: Implement GPU device detection
false
}
/// Check if SIMD backend is available
#[cfg(feature = "analytics-simd")]
pub fn is_simd_available() -> bool {
true // Always available when feature is enabled
}
}
/// Statistical helper functions for equivalence testing
pub mod stats {
use super::Backend;
use anyhow::Result;
include!("analytics_backend_stats.rs");
}
/// GPU compute backend (Issue #79, P0-3 and P0-5)
///
/// Implements GPU-accelerated compute operations using wgpu.
/// Provides PCIe bandwidth calibration for cost-based query optimization.
#[cfg(feature = "analytics-gpu")]
pub mod gpu {
use anyhow::{bail, Context, Result};
use std::sync::Once;
use wgpu::util::DeviceExt;
include!("analytics_backend_gpu.rs");
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::stats::*;
use super::*;
include!("analytics_backend_tests.rs");
}
// Design-by-contract specifications (Verus-style)
// #[requires(project_path.is_dir())]
// #[ensures(result.is_ok() ==> ret.len() > 0)]