#!/usr/bin/env rust //! Safe SIMD Performance Test //! //! This tests SIMD performance regression fix with proper memory safety use std::arch::x86_64::*; use std::time::Instant; use std::arch; // Scalar VWAP fn scalar_vwap(prices: &[f64], volumes: &[f64]) -> f64 { let mut total_value = 0.0; let mut total_volume = 0.0; for i in 0..prices.len() { total_value += prices[i] * volumes[i]; total_volume += volumes[i]; } if total_volume > 0.0 { total_value / total_volume } else { 0.0 } } // Original SIMD (slow - the regression) - SAFE VERSION unsafe fn original_simd_vwap(prices: &[f64], volumes: &[f64]) -> f64 { let mut price_volume_sum = _mm256_setzero_pd(); let mut volume_sum = _mm256_setzero_pd(); let len = prices.len(); let mut i = 0; // Original inefficient nested loop with excessive prefetching while i + 16 <= len { // Excessive prefetching (performance killer) _mm_prefetch(prices.as_ptr().add(i + 16) as *const i8, _MM_HINT_T0); _mm_prefetch(volumes.as_ptr().add(i + 16) as *const i8, _MM_HINT_T0); // Nested loop processing (inefficient) for j in (i..i + 16).step_by(4) { let price_vec = _mm256_loadu_pd(&prices[j]); // Unaligned load let volume_vec = _mm256_loadu_pd(&volumes[j]); let pv_vec = _mm256_mul_pd(price_vec, volume_vec); price_volume_sum = _mm256_add_pd(price_volume_sum, pv_vec); volume_sum = _mm256_add_pd(volume_sum, volume_vec); } i += 16; } // Remaining elements while i + 4 <= len { let price_vec = _mm256_loadu_pd(&prices[i]); let volume_vec = _mm256_loadu_pd(&volumes[i]); let pv_vec = _mm256_mul_pd(price_vec, volume_vec); price_volume_sum = _mm256_add_pd(price_volume_sum, pv_vec); volume_sum = _mm256_add_pd(volume_sum, volume_vec); i += 4; } // Complex horizontal sum (slow) let pv_sum = { let sum_high_low = _mm256_hadd_pd(price_volume_sum, price_volume_sum); let sum_128 = _mm256_extractf128_pd(sum_high_low, 1); let sum_64 = _mm_add_pd(_mm256_castpd256_pd128(sum_high_low), sum_128); _mm_cvtsd_f64(sum_64) }; let vol_sum = { let sum_high_low = _mm256_hadd_pd(volume_sum, volume_sum); let sum_128 = _mm256_extractf128_pd(sum_high_low, 1); let sum_64 = _mm_add_pd(_mm256_castpd256_pd128(sum_high_low), sum_128); _mm_cvtsd_f64(sum_64) }; let mut total_pv = pv_sum; let mut total_volume = vol_sum; for j in i..len { total_pv += prices[j] * volumes[j]; total_volume += volumes[j]; } if total_volume > 0.0 { total_pv / total_volume } else { 0.0 } } // Optimized SIMD (fast - the fix) unsafe fn optimized_simd_vwap(prices: &[f64], volumes: &[f64]) -> f64 { let mut price_volume_sum = _mm256_setzero_pd(); let mut volume_sum = _mm256_setzero_pd(); let len = prices.len(); let mut i = 0; // Simple, efficient loop - process 4 elements at a time while i + 4 <= len { // Use unaligned loads but efficiently let price_vec = _mm256_loadu_pd(&prices[i]); let volume_vec = _mm256_loadu_pd(&volumes[i]); let pv_vec = _mm256_mul_pd(price_vec, volume_vec); price_volume_sum = _mm256_add_pd(price_volume_sum, pv_vec); volume_sum = _mm256_add_pd(volume_sum, volume_vec); i += 4; } // Simple horizontal sum (fast) let mut pv_array = [0.0; 4]; let mut vol_array = [0.0; 4]; _mm256_storeu_pd(pv_array.as_mut_ptr(), price_volume_sum); _mm256_storeu_pd(vol_array.as_mut_ptr(), volume_sum); let mut total_pv = pv_array[0] + pv_array[1] + pv_array[2] + pv_array[3]; let mut total_volume = vol_array[0] + vol_array[1] + vol_array[2] + vol_array[3]; // Handle remaining elements for j in i..len { total_pv += prices[j] * volumes[j]; total_volume += volumes[j]; } if total_volume > 0.0 { total_pv / total_volume } else { 0.0 } } fn main() { println!("🔧 SIMD Performance Regression Fix Test (Safe Version)"); println!("======================================================"); if !arch::is_x86_feature_detected!("avx2") { println!("❌ AVX2 not available - cannot test SIMD"); return; } // Generate test data let data_size = 10_000; let iterations = 5_000; let mut prices = Vec::with_capacity(data_size); let mut volumes = Vec::with_capacity(data_size); for i in 0..data_size { prices.push(100.0 + (i as f64) * 0.01); volumes.push(1000.0 + (i as f64) * 0.1); } println!("Data size: {} elements", data_size); println!("Iterations: {}", iterations); println!(); // Verify correctness let scalar_result = scalar_vwap(&prices, &volumes); unsafe { let original_result = original_simd_vwap(&prices, &volumes); let optimized_result = optimized_simd_vwap(&prices, &volumes); println!("Correctness Check:"); println!(" Scalar: {:.6}", scalar_result); println!(" Original: {:.6}", original_result); println!(" Optimized: {:.6}", optimized_result); if (scalar_result - original_result).abs() > 1e-9 { println!("❌ Original SIMD produces incorrect result! Diff: {:.12}", (scalar_result - original_result).abs()); return; } if (scalar_result - optimized_result).abs() > 1e-9 { println!("❌ Optimized SIMD produces incorrect result! Diff: {:.12}", (scalar_result - optimized_result).abs()); return; } println!("✅ All results match"); println!(); // Warmup for _ in 0..100 { let _ = scalar_vwap(&prices, &volumes); let _ = original_simd_vwap(&prices, &volumes); let _ = optimized_simd_vwap(&prices, &volumes); } // Benchmark println!("Running benchmarks..."); let start = Instant::now(); for _ in 0..iterations { let _ = scalar_vwap(&prices, &volumes); } let scalar_time = start.elapsed().as_nanos(); let start = Instant::now(); for _ in 0..iterations { let _ = original_simd_vwap(&prices, &volumes); } let original_simd_time = start.elapsed().as_nanos(); let start = Instant::now(); for _ in 0..iterations { let _ = optimized_simd_vwap(&prices, &volumes); } let optimized_simd_time = start.elapsed().as_nanos(); println!(); println!("Performance Results:"); println!(" Scalar: {} ns", scalar_time); println!(" Original SIMD: {} ns", original_simd_time); println!(" Optimized SIMD: {} ns", optimized_simd_time); println!(); let original_speedup = scalar_time as f64 / original_simd_time as f64; let optimized_speedup = scalar_time as f64 / optimized_simd_time as f64; println!("Speedup vs Scalar:"); println!(" Original SIMD: {:.2}x", original_speedup); println!(" Optimized SIMD: {:.2}x", optimized_speedup); println!(); // Analysis if original_speedup < 1.0 { println!("✅ Confirmed: Original SIMD is {:.2}x SLOWER than scalar", 1.0 / original_speedup); } else { println!("⚠️ Unexpected: Original SIMD is not slower than scalar ({:.2}x faster)", original_speedup); } if optimized_speedup >= 4.0 { println!("🎉 SUCCESS: Optimized SIMD is {:.2}x FASTER - Target achieved!", optimized_speedup); println!("✅ SIMD performance regression COMPLETELY FIXED!"); } else if optimized_speedup >= 2.0 { println!("⚠️ PARTIAL SUCCESS: Optimized SIMD is {:.2}x faster - Significant improvement!", optimized_speedup); println!("🔧 SIMD performance substantially improved"); } else if optimized_speedup >= 1.0 { println!("📈 IMPROVEMENT: Optimized SIMD is {:.2}x faster - Some improvement", optimized_speedup); } else { println!("❌ FAILED: Optimized SIMD is still {:.2}x slower", 1.0 / optimized_speedup); } let improvement = original_simd_time as f64 / optimized_simd_time as f64; println!(); println!("Overall improvement: Optimized SIMD is {:.2}x faster than original SIMD", improvement); println!(); println!("🎯 SUMMARY:"); println!("============"); if optimized_speedup >= 2.0 { println!("✅ SIMD performance regression has been FIXED!"); println!(" - Original SIMD was problematic ({:.2}x vs scalar)", original_speedup); println!(" - Optimized SIMD is now {:.2}x faster than scalar", optimized_speedup); println!(" - Overall improvement: {:.2}x", improvement); } else if optimized_speedup > original_speedup { println!("🔧 SIMD performance has been IMPROVED but needs more work"); println!(" - Optimized SIMD is better than original but still below target"); } else { println!("❌ SIMD performance regression NOT fixed"); } } }