1#![cfg_attr(not(feature = "std"), no_std)]
11#![deny(missing_docs)]
12
13#[cfg(feature = "std")]
14extern crate std;
15
16#[cfg(not(feature = "std"))]
17extern crate alloc;
18
19pub mod atomic;
21pub mod cache;
22pub mod memory;
23pub mod queue;
24
25#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
27pub mod simd;
28
29pub use atomic::AtomicCounter;
31pub use cache::{align_to_cache_line, CacheAligned, CACHE_LINE_SIZE};
32pub use memory::{prefetch_read, prefetch_write};
33pub use queue::LockFreeQueue;
34
35#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
37pub use simd::{has_native_vector_path, SimdReal, SimdScalar};
38
39#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
40use std::sync::OnceLock;
41
42#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
43static GLOBAL_SIMD_COUNTER: OnceLock<SimdCounter> = OnceLock::new();
44
45#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
50pub fn global_simd_counter() -> &'static SimdCounter {
51 GLOBAL_SIMD_COUNTER.get_or_init(SimdCounter::new)
52}
53
54#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
59#[derive(Debug)]
60pub struct SimdCounter {
61 vectorized_ops: AtomicCounter,
62 scalar_ops: AtomicCounter,
63 vectorized_elements: AtomicCounter,
64 scalar_elements: AtomicCounter,
65}
66
67#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
68impl SimdCounter {
69 pub fn new() -> Self {
71 Self {
72 vectorized_ops: AtomicCounter::new(),
73 scalar_ops: AtomicCounter::new(),
74 vectorized_elements: AtomicCounter::new(),
75 scalar_elements: AtomicCounter::new(),
76 }
77 }
78
79 pub fn record_vectorized_op(&self, elements: usize) {
81 self.vectorized_ops.increment();
82 self.vectorized_elements.add(elements);
83 }
84
85 pub fn record_scalar_op(&self, elements: usize) {
87 self.scalar_ops.increment();
88 self.scalar_elements.add(elements);
89 }
90
91 pub fn vectorized_ops(&self) -> usize {
93 self.vectorized_ops.get()
94 }
95
96 pub fn scalar_ops(&self) -> usize {
98 self.scalar_ops.get()
99 }
100
101 pub fn vectorization_rate(&self) -> f64 {
103 let total = self.vectorized_ops() + self.scalar_ops();
104 if total == 0 {
105 0.0
106 } else {
107 self.vectorized_ops() as f64 / total as f64
108 }
109 }
110
111 pub fn get_stats(&self) -> (usize, usize, usize, usize) {
113 (
114 self.vectorized_ops(),
115 self.scalar_ops(),
116 self.vectorized_elements.get(),
117 self.scalar_elements.get(),
118 )
119 }
120
121 pub fn reset(&self) {
123 self.vectorized_ops.reset();
124 self.scalar_ops.reset();
125 self.vectorized_elements.reset();
126 self.scalar_elements.reset();
127 }
128}
129
130#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
131impl Default for SimdCounter {
132 fn default() -> Self {
133 Self::new()
134 }
135}
136
137#[cfg(test)]
138mod integration_tests {
139 use super::*;
140
141 #[test]
142 fn test_modular_integration() {
143 let aligned_data = CacheAligned::new(42);
145 assert_eq!(*aligned_data, 42);
146
147 let counter = AtomicCounter::new();
148 counter.increment();
149 assert_eq!(counter.get(), 1);
150
151 let queue = LockFreeQueue::<i32>::with_capacity(4);
152 queue.enqueue(1);
153 assert_eq!(queue.try_dequeue(), Some(1));
154 }
155
156 #[test]
157 fn test_cache_line_alignment() {
158 assert_eq!(align_to_cache_line(1), CACHE_LINE_SIZE);
159 assert_eq!(align_to_cache_line(CACHE_LINE_SIZE), CACHE_LINE_SIZE);
160 assert_eq!(
161 align_to_cache_line(CACHE_LINE_SIZE + 1),
162 CACHE_LINE_SIZE * 2
163 );
164 }
165}