ruvector_memopt/accel/
cpu.rs1#[cfg(target_arch = "x86_64")]
4use std::arch::x86_64::*;
5
6#[derive(Debug, Clone)]
8pub struct CpuCapabilities {
9 pub vendor: String,
10 pub model: String,
11 pub has_avx: bool,
12 pub has_avx2: bool,
13 pub has_avx512: bool,
14 pub has_avx_vnni: bool,
15 pub has_npu: bool,
16 pub core_count: usize,
17 pub cache_line_size: usize,
18}
19
20impl CpuCapabilities {
21 pub fn detect() -> Self {
22 let mut caps = Self {
23 vendor: String::new(),
24 model: String::new(),
25 has_avx: false,
26 has_avx2: false,
27 has_avx512: false,
28 has_avx_vnni: false,
29 has_npu: false,
30 core_count: num_cpus::get(),
31 cache_line_size: 64,
32 };
33
34 #[cfg(target_arch = "x86_64")]
35 {
36 if is_x86_feature_detected!("avx") { caps.has_avx = true; }
37 if is_x86_feature_detected!("avx2") { caps.has_avx2 = true; }
38 if is_x86_feature_detected!("avx512f") { caps.has_avx512 = true; }
39
40 caps.has_avx_vnni = Self::detect_avx_vnni();
42
43 caps.has_npu = Self::detect_intel_npu();
45 caps.vendor = Self::get_vendor();
46 caps.model = Self::get_model();
47 }
48
49 caps
50 }
51
52 #[cfg(target_arch = "x86_64")]
53 fn detect_avx_vnni() -> bool {
54 unsafe {
56 let result = __cpuid_count(7, 1);
57 (result.eax & (1 << 4)) != 0
58 }
59 }
60
61 #[cfg(not(target_arch = "x86_64"))]
62 fn detect_avx_vnni() -> bool { false }
63
64 #[cfg(target_arch = "x86_64")]
65 fn detect_intel_npu() -> bool {
66 let model = Self::get_model();
68 model.contains("Ultra") || model.contains("Meteor") || model.contains("Arrow")
69 }
70
71 #[cfg(not(target_arch = "x86_64"))]
72 fn detect_intel_npu() -> bool { false }
73
74 #[cfg(target_arch = "x86_64")]
75 fn get_vendor() -> String {
76 unsafe {
77 let result = __cpuid(0);
78 let vendor_bytes: [u8; 12] = std::mem::transmute([result.ebx, result.edx, result.ecx]);
79 String::from_utf8_lossy(&vendor_bytes).trim().to_string()
80 }
81 }
82
83 #[cfg(not(target_arch = "x86_64"))]
84 fn get_vendor() -> String { "Unknown".into() }
85
86 #[cfg(target_arch = "x86_64")]
87 fn get_model() -> String {
88 let mut model = String::new();
89 unsafe {
90 for i in 0x80000002u32..=0x80000004u32 {
91 let result = __cpuid(i);
92 let bytes: [u8; 16] = std::mem::transmute([result.eax, result.ebx, result.ecx, result.edx]);
93 model.push_str(&String::from_utf8_lossy(&bytes));
94 }
95 }
96 model.trim().to_string()
97 }
98
99 #[cfg(not(target_arch = "x86_64"))]
100 fn get_model() -> String { "Unknown".into() }
101
102 pub fn recommended_simd_width(&self) -> usize {
104 if self.has_avx512 { 512 }
105 else if self.has_avx2 { 256 }
106 else if self.has_avx { 128 }
107 else { 64 }
108 }
109
110 pub fn estimated_speedup(&self) -> f32 {
112 if self.has_avx512 { 16.0 }
113 else if self.has_avx2 { 8.0 }
114 else if self.has_avx { 4.0 }
115 else { 1.0 }
116 }
117
118 pub fn print_report(&self) {
119 println!("CPU Capabilities:");
120 println!(" Vendor: {}", self.vendor);
121 println!(" Model: {}", self.model);
122 println!(" Cores: {}", self.core_count);
123 println!(" AVX: {}", if self.has_avx { "Yes" } else { "No" });
124 println!(" AVX2: {}", if self.has_avx2 { "Yes (8x SIMD)" } else { "No" });
125 println!(" AVX-512: {}", if self.has_avx512 { "Yes (16x SIMD)" } else { "No" });
126 println!(" AVX-VNNI: {}", if self.has_avx_vnni { "Yes (AI Accel)" } else { "No" });
127 println!(" Intel NPU: {}", if self.has_npu { "Yes (Neural Proc)" } else { "No" });
128 println!(" Est Speedup: {:.0}x", self.estimated_speedup());
129 }
130}
131
132impl Default for CpuCapabilities {
133 fn default() -> Self { Self::detect() }
134}