Skip to main content

quantrs2_core/platform/
capabilities.rs

1//! Platform capabilities structures
2
3use serde::{Deserialize, Serialize};
4
5/// Comprehensive platform capabilities
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct PlatformCapabilities {
8    /// CPU capabilities
9    pub cpu: CpuCapabilities,
10    /// GPU capabilities
11    pub gpu: GpuCapabilities,
12    /// Memory capabilities
13    pub memory: MemoryCapabilities,
14    /// Platform type
15    pub platform_type: PlatformType,
16    /// Operating system
17    pub os: OperatingSystem,
18    /// Architecture
19    pub architecture: Architecture,
20}
21
22/// CPU capabilities
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct CpuCapabilities {
25    /// Number of physical cores
26    pub physical_cores: usize,
27    /// Number of logical cores
28    pub logical_cores: usize,
29    /// SIMD capabilities
30    pub simd: SimdCapabilities,
31    /// Cache sizes
32    pub cache: CacheInfo,
33    /// Clock speed in MHz
34    pub base_clock_mhz: Option<f32>,
35    /// CPU vendor
36    pub vendor: String,
37    /// CPU model name
38    pub model_name: String,
39}
40
41/// SIMD capabilities
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct SimdCapabilities {
44    /// SSE support
45    pub sse: bool,
46    /// SSE2 support
47    pub sse2: bool,
48    /// SSE3 support
49    pub sse3: bool,
50    /// SSSE3 support
51    pub ssse3: bool,
52    /// SSE4.1 support
53    pub sse4_1: bool,
54    /// SSE4.2 support
55    pub sse4_2: bool,
56    /// AVX support
57    pub avx: bool,
58    /// AVX2 support
59    pub avx2: bool,
60    /// AVX512 support
61    pub avx512: bool,
62    /// FMA support
63    pub fma: bool,
64    /// ARM NEON support
65    pub neon: bool,
66    /// ARM SVE support
67    pub sve: bool,
68}
69
70/// Cache information
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct CacheInfo {
73    /// L1 data cache size in bytes
74    pub l1_data: Option<usize>,
75    /// L1 instruction cache size in bytes
76    pub l1_instruction: Option<usize>,
77    /// L2 cache size in bytes
78    pub l2: Option<usize>,
79    /// L3 cache size in bytes
80    pub l3: Option<usize>,
81    /// Cache line size in bytes
82    pub line_size: Option<usize>,
83}
84
85/// GPU capabilities
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct GpuCapabilities {
88    /// GPU available
89    pub available: bool,
90    /// GPU devices
91    pub devices: Vec<GpuDevice>,
92    /// Primary GPU index
93    pub primary_device: Option<usize>,
94}
95
96/// Individual GPU device information
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct GpuDevice {
99    /// Device name
100    pub name: String,
101    /// Device vendor
102    pub vendor: String,
103    /// Device type
104    pub device_type: GpuType,
105    /// Memory in bytes
106    pub memory_bytes: usize,
107    /// Compute units
108    pub compute_units: usize,
109    /// Maximum workgroup size
110    pub max_workgroup_size: usize,
111    /// CUDA cores (if applicable)
112    pub cuda_cores: Option<usize>,
113    /// Compute capability (for NVIDIA)
114    pub compute_capability: Option<(u32, u32)>,
115}
116
117/// GPU type
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
119pub enum GpuType {
120    Discrete,
121    Integrated,
122    Virtual,
123    Unknown,
124}
125
126/// Memory capabilities
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct MemoryCapabilities {
129    /// Total physical memory in bytes
130    pub total_memory: usize,
131    /// Available memory in bytes
132    pub available_memory: usize,
133    /// Memory bandwidth estimate in GB/s
134    pub bandwidth_gbps: Option<f32>,
135    /// NUMA nodes
136    pub numa_nodes: usize,
137    /// Hugepage support
138    pub hugepage_support: bool,
139}
140
141/// Platform type
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
143pub enum PlatformType {
144    Desktop,
145    Server,
146    Mobile,
147    Embedded,
148    Cloud,
149    Unknown,
150}
151
152/// Operating system
153#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
154pub enum OperatingSystem {
155    Linux,
156    Windows,
157    MacOS,
158    FreeBSD,
159    Android,
160    Unknown,
161}
162
163/// Architecture
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
165pub enum Architecture {
166    X86_64,
167    Aarch64,
168    Riscv64,
169    Wasm32,
170    Unknown,
171}
172
173impl PlatformCapabilities {
174    /// Detect platform capabilities
175    ///
176    /// This is the main entry point for platform detection as required by SciRS2 policy.
177    /// All modules should use this instead of direct platform detection.
178    ///
179    /// Detection is performed once per process and cached: probing the host walks every
180    /// running process and refreshes every CPU (several `sysinfo::System` scans, ~0.4s a
181    /// call). Callers such as `SimdGateEngine::new` construct an engine per circuit
182    /// evaluation, so an uncached probe here dominated the runtime of anything that
183    /// simulates in a loop — a 30-step parameter-shift training loop spent over an hour
184    /// in process enumeration rather than in simulation.
185    ///
186    /// Use [`crate::platform::get_platform_capabilities`] to borrow the cached value
187    /// instead of cloning it.
188    pub fn detect() -> Self {
189        crate::platform::get_platform_capabilities().clone()
190    }
191
192    /// Check if the platform supports SIMD operations
193    pub const fn has_simd(&self) -> bool {
194        self.cpu.simd.sse2
195            || self.cpu.simd.avx
196            || self.cpu.simd.avx2
197            || self.cpu.simd.neon
198            || self.cpu.simd.sve
199    }
200
201    /// Check if SIMD is available (compatibility method)
202    pub const fn simd_available(&self) -> bool {
203        self.has_simd()
204    }
205
206    /// Check if GPU is available (compatibility method)
207    pub const fn gpu_available(&self) -> bool {
208        self.gpu.available
209    }
210
211    /// Get the optimal SIMD width for f64 operations
212    pub const fn optimal_simd_width_f64(&self) -> usize {
213        if self.cpu.simd.avx512 {
214            8
215        } else if self.cpu.simd.avx || self.cpu.simd.avx2 {
216            4
217        } else if self.cpu.simd.sse2 || self.cpu.simd.neon {
218            2
219        } else {
220            1
221        }
222    }
223
224    /// Check if GPU acceleration is available
225    pub fn has_gpu(&self) -> bool {
226        self.gpu.available && !self.gpu.devices.is_empty()
227    }
228
229    /// Get the primary GPU device
230    pub fn primary_gpu(&self) -> Option<&GpuDevice> {
231        self.gpu
232            .primary_device
233            .and_then(|idx| self.gpu.devices.get(idx))
234    }
235
236    /// Check if the platform is suitable for large-scale quantum simulation
237    pub const fn is_suitable_for_large_quantum_sim(&self) -> bool {
238        self.memory.total_memory >= 16 * 1024 * 1024 * 1024 // At least 16GB RAM
239            && self.cpu.logical_cores >= 8
240            && self.has_simd()
241    }
242}