#![allow(unsafe_code)] // Intentional unsafe for SIMD vectorization performance //! Ultra-Low Latency Performance Optimizations for HFT ML Models //! //! Provides SIMD vectorization, cache-optimal data layouts, and memory-mapped //! operations to achieve sub-100μs inference latency for high-frequency trading. use std::arch::x86_64::*; use std::time::Instant; // SIMD operations for high-performance ML computations use crate::MLError; /// Aligned buffer for SIMD operations pub struct AlignedBuffer { data: Vec, size: usize, } impl AlignedBuffer { pub fn new(size: usize) -> Result { Ok(Self { data: vec![T::default(); size], size, }) } pub fn resize(&mut self, new_size: usize) -> Result<(), MLError> { self.data.resize(new_size, T::default()); self.size = new_size; Ok(()) } pub fn len(&self) -> usize { self.size } pub fn capacity(&self) -> usize { self.data.capacity() } pub fn as_slice(&self) -> &[T] { &self.data[..self.size] } } /// Performance profiler for ML inference pub struct LatencyProfiler { violations: usize, total: usize, min_latency: u64, max_latency: u64, } impl LatencyProfiler { pub fn new() -> Self { Self { violations: 0, total: 0, min_latency: u64::MAX, max_latency: 0, } } pub fn record_inference(&mut self, latency_us: u64) { self.total += 1; if latency_us > 100 { // 100μs threshold self.violations += 1; } self.min_latency = self.min_latency.min(latency_us); self.max_latency = self.max_latency.max(latency_us); } pub fn get_stats(&self) -> LatencyStats { LatencyStats { total_inferences: self.total, violation_rate: if self.total > 0 { self.violations as f64 / self.total as f64 } else { 0.0 }, min_latency_us: self.min_latency, max_latency_us: self.max_latency, } } } pub struct LatencyStats { pub total_inferences: usize, pub violation_rate: f64, pub min_latency_us: u64, pub max_latency_us: u64, } /// Performance benchmark utilities pub struct PerformanceBenchmark; impl PerformanceBenchmark { pub fn benchmark_simd_dot_product(size: usize, iterations: usize) -> Result { let a: Vec = (0..size).map(|i| i as f32).collect(); let b: Vec = (0..size).map(|i| (i + 1) as f32).collect(); let start = Instant::now(); for _ in 0..iterations { let _result: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum(); } let elapsed = start.elapsed(); Ok(elapsed.as_micros() as f64 / iterations as f64) } } /// SIMD operations pub mod simd_ops { pub fn simd_dot_product(a: &[f32], b: &[f32]) -> f32 { a.iter().zip(b.iter()).map(|(x, y)| x * y).sum() } pub fn simd_sigmoid_batch(input: &[f32]) -> Vec { input.iter().map(|&x| 1.0 / (1.0 + (-x).exp())).collect() } } /// High-performance SIMD operations for ML computations pub struct SimdOptimizedOps; impl SimdOptimizedOps { /// Vectorized dot product using AVX2 instructions #[cfg(target_arch = "x86_64")] pub fn dot_product_f32(a: &[f32], b: &[f32]) -> Result { if a.len() != b.len() { return Err(MLError::ValidationError { message: format!( "dot_product: Dimension mismatch: expected {}, got {}", a.len(), b.len() ), }); } if !is_x86_feature_detected!("avx2") { // Fallback to standard implementation return Ok(a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()); } // SECURITY: Added bounds checking before unsafe SIMD operations if a.len() != b.len() { return Err(MLError::InvalidInput( "Vector lengths must match for dot product".to_string(), )); } if a.is_empty() { return Ok(0.0); } unsafe { Self::avx2_dot_product(a, b) } } #[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] unsafe fn avx2_dot_product(a: &[f32], b: &[f32]) -> Result { // SECURITY: Additional bounds checking in unsafe function debug_assert_eq!(a.len(), b.len(), "Vector lengths must match"); debug_assert!(!a.is_empty(), "Vectors must not be empty"); let len = a.len(); let mut sum = _mm256_setzero_ps(); // Process 8 elements at a time (AVX2 width) let chunks = len / 8; for i in 0..chunks { let offset = i * 8; let va = _mm256_loadu_ps(a.as_ptr().add(offset)); let vb = _mm256_loadu_ps(b.as_ptr().add(offset)); let vmul = _mm256_mul_ps(va, vb); sum = _mm256_add_ps(sum, vmul); } // Sum the 8 components of the result let sum_array: [f32; 8] = std::mem::transmute(sum); let mut result = sum_array.iter().sum::(); // Handle remaining elements for i in (chunks * 8)..len { result += a[i] * b[i]; } Ok(result) } /// Vectorized matrix-vector multiplication #[cfg(target_arch = "x86_64")] pub fn matrix_vector_mul(matrix: &[Vec], vector: &[f32]) -> Result, MLError> { if matrix.is_empty() { return Ok(Vec::new()); } if matrix[0].len() != vector.len() { return Err(MLError::ValidationError { message: format!( "matrix_vector_multiply: Dimension mismatch: expected {}, got {}", matrix[0].len(), vector.len() ), }); } let mut result = Vec::with_capacity(matrix.len()); for row in matrix { let dot_product = Self::dot_product_f32(row, vector)?; result.push(dot_product); } Ok(result) } /// Vectorized ReLU activation with SIMD #[cfg(target_arch = "x86_64")] pub fn relu_batch(input: &[f32]) -> Vec { if !is_x86_feature_detected!("avx2") { return input.iter().map(|&x| x.max(0.0)).collect(); } unsafe { Self::avx2_relu_batch(input) } } #[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] unsafe fn avx2_relu_batch(input: &[f32]) -> Vec { let mut output = vec![0.0_f32; input.len()]; let zero = _mm256_setzero_ps(); // Process 8 elements at a time let chunks = input.len() / 8; for i in 0..chunks { let offset = i * 8; let data = _mm256_loadu_ps(input.as_ptr().add(offset)); let result = _mm256_max_ps(data, zero); _mm256_storeu_ps(output.as_mut_ptr().add(offset), result); } // Handle remaining elements for i in (chunks * 8)..input.len() { output[i] = input[i].max(0.0); } output } /// High-performance softmax with SIMD optimization pub fn softmax_batch(input: &[f32]) -> Result, MLError> { if input.is_empty() { return Ok(Vec::new()); } // Find maximum for numerical stability let max_val = input.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b)); // Compute exp(x - max) for all elements let exp_vals: Vec = input.iter().map(|&x| (x - max_val).exp()).collect(); // Compute sum of exponentials let sum_exp: f32 = exp_vals.iter().sum(); if sum_exp == 0.0 { return Err(MLError::ValidationError { message: "softmax: Softmax sum is zero".to_string(), }); } // Normalize let result = exp_vals.iter().map(|&x| x / sum_exp).collect(); Ok(result) } /// Optimized batch normalization pub fn batch_norm( input: &[f32], mean: f32, variance: f32, gamma: f32, beta: f32, epsilon: f32, ) -> Result, MLError> { if variance < 0.0 { return Err(MLError::ValidationError { message: "batch_norm: Variance cannot be negative".to_string(), }); } let std_dev = (variance + epsilon).sqrt(); let result = input .iter() .map(|&x| gamma * (x - mean) / std_dev + beta) .collect(); Ok(result) } } /// Memory-optimized operations with zero-copy where possible pub struct ZeroCopyOps; impl ZeroCopyOps { /// In-place ReLU operation to avoid allocations pub fn relu_inplace(data: &mut [f32]) { for value in data.iter_mut() { if *value < 0.0 { *value = 0.0; } } } /// In-place sigmoid operation pub fn sigmoid_inplace(data: &mut [f32]) { for value in data.iter_mut() { *value = 1.0 / (1.0 + (-*value).exp()); } } /// In-place batch normalization pub fn batch_norm_inplace( data: &mut [f32], mean: f32, variance: f32, gamma: f32, beta: f32, epsilon: f32, ) -> Result<(), MLError> { if variance < 0.0 { return Err(MLError::ValidationError { message: "batch_norm: Variance cannot be negative".to_string(), }); } let std_dev = (variance + epsilon).sqrt(); for value in data.iter_mut() { *value = gamma * (*value - mean) / std_dev + beta; } Ok(()) } } #[cfg(test)] mod tests { use super::*; // use crate::safe_operations; // DISABLED - module not found #[test] fn test_aligned_buffer() -> Result<(), MLError> { let mut buffer: AlignedBuffer = AlignedBuffer::new(1024)?; buffer.resize(512)?; assert_eq!(buffer.capacity(), 1024); assert_eq!(buffer.len(), 512); // Test memory alignment let ptr = buffer.as_slice().as_ptr() as usize; assert_eq!(ptr % 64, 0); // Should be 64-byte aligned Ok(()) } #[test] fn test_simd_dot_product() { let a = vec![1.0, 2.0, 3.0, 4.0]; let b = vec![2.0, 3.0, 4.0, 5.0]; let result = simd_ops::simd_dot_product(&a, &b); let expected = 1.0 * 2.0 + 2.0 * 3.0 + 3.0 * 4.0 + 4.0 * 5.0; // 40.0 assert!((result - expected).abs() < 1e-6); } #[test] fn test_simd_activations() { let input = vec![-2.0, -1.0, 0.0, 1.0, 2.0]; // Test ReLU let relu_output = SimdOptimizedOps::relu_batch(&input); assert_eq!(relu_output, vec![0.0, 0.0, 0.0, 1.0, 2.0]); // Test sigmoid let sigmoid_output = simd_ops::simd_sigmoid_batch(&input); assert_eq!(sigmoid_output.len(), input.len()); // All sigmoid values should be between 0 and 1 for &val in &sigmoid_output { assert!(val > 0.0 && val < 1.0); } } #[test] fn test_performance_profiler() { let mut profiler = LatencyProfiler::new(); // Use actual LatencyProfiler // Record some measurements profiler.record_inference(50); profiler.record_inference(75); profiler.record_inference(120); // Violation profiler.record_inference(90); let stats = profiler.get_stats(); assert_eq!(stats.total_inferences, 4); assert_eq!(stats.violation_rate, 0.25); // 1 out of 4 violated assert_eq!(stats.min_latency_us, 50); assert_eq!(stats.max_latency_us, 120); } #[test] fn test_benchmark_simd_performance() -> Result<(), MLError> { // Benchmark should complete without errors let avg_time = PerformanceBenchmark::benchmark_simd_dot_product(1024, 100)?; // Should be very fast (sub-microsecond for 1024-element dot product) assert!(avg_time < 10.0); // Less than 10 microseconds average Ok(()) } }