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