hedgefund

rust_particle_sim_SIMD

Jan 8th, 2025
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.02 KB | Source Code | 0 0
  1. use std::time::Instant;
  2. use rand::prelude::*;
  3.  
  4. const NUM_PARTICLES: usize = 100000;
  5. const SIMD_WIDTH: usize = 8; // AVX equivalent for 256-bit
  6. const GRAVITY: f32 = -9.81;
  7. const DELTA_TIME: f32 = 0.01;
  8. const FIXED_SEED: u64 = 12345;
  9.  
  10. // Structure to hold particle data
  11. struct ParticleData {
  12.     positions_x: Vec<f32>,
  13.     positions_y: Vec<f32>,
  14.     positions_z: Vec<f32>,
  15.     velocities_x: Vec<f32>,
  16.     velocities_y: Vec<f32>,
  17.     velocities_z: Vec<f32>,
  18.     accelerations_x: Vec<f32>,
  19.     accelerations_y: Vec<f32>,
  20.     accelerations_z: Vec<f32>,
  21.     masses: Vec<f32>,
  22. }
  23.  
  24. fn allocate_particle_data() -> ParticleData {
  25.     ParticleData {
  26.         positions_x: vec![0.0; NUM_PARTICLES],
  27.         positions_y: vec![0.0; NUM_PARTICLES],
  28.         positions_z: vec![0.0; NUM_PARTICLES],
  29.         velocities_x: vec![0.0; NUM_PARTICLES],
  30.         velocities_y: vec![0.0; NUM_PARTICLES],
  31.         velocities_z: vec![0.0; NUM_PARTICLES],
  32.         accelerations_x: vec![0.0; NUM_PARTICLES],
  33.         accelerations_y: vec![0.0; NUM_PARTICLES],
  34.         accelerations_z: vec![0.0; NUM_PARTICLES],
  35.         masses: vec![0.0; NUM_PARTICLES],
  36.     }
  37. }
  38.  
  39. fn initialize_particles(data: &mut ParticleData) {
  40.     let mut rng = rand::rngs::StdRng::seed_from_u64(FIXED_SEED);
  41.  
  42.     for i in 0..NUM_PARTICLES {
  43.         data.positions_x[i] = rng.gen::<f32>() * 10.0;
  44.         data.positions_y[i] = rng.gen::<f32>() * 10.0;
  45.         data.positions_z[i] = rng.gen::<f32>() * 10.0;
  46.  
  47.         data.velocities_x[i] = rng.gen::<f32>() * 2.0 - 1.0;
  48.         data.velocities_y[i] = rng.gen::<f32>() * 2.0 - 1.0;
  49.         data.velocities_z[i] = rng.gen::<f32>() * 2.0 - 1.0;
  50.  
  51.         data.accelerations_x[i] = 0.0;
  52.         data.accelerations_y[i] = 0.0;
  53.         data.accelerations_z[i] = 0.0;
  54.  
  55.         data.masses[i] = rng.gen::<f32>() * 2.0 + 1.0;
  56.     }
  57. }
  58.  
  59. //#[cfg(target_arch = "x86_64")]
  60. fn update_particles_simd(data: &mut ParticleData) {
  61.     use core::arch::x86_64::{
  62.         __m256, _mm256_add_ps, _mm256_mul_ps, _mm256_set1_ps, _mm256_loadu_ps, _mm256_storeu_ps
  63.     };
  64.    
  65.     let gravity_vector: __m256 = unsafe { _mm256_set1_ps(GRAVITY) };
  66.     let delta_time_vector: __m256 = unsafe { _mm256_set1_ps(DELTA_TIME) };
  67.  
  68.     for i in (0..NUM_PARTICLES).step_by(SIMD_WIDTH) {
  69.         unsafe {
  70.             // Load data
  71.             let px: __m256 = _mm256_loadu_ps(data.positions_x[i..].as_ptr());
  72.             let py: __m256 = _mm256_loadu_ps(data.positions_y[i..].as_ptr());
  73.             let pz: __m256 = _mm256_loadu_ps(data.positions_z[i..].as_ptr());
  74.  
  75.             let vx: __m256 = _mm256_loadu_ps(data.velocities_x[i..].as_ptr());
  76.             let vy: __m256 = _mm256_loadu_ps(data.velocities_y[i..].as_ptr());
  77.             let vz: __m256 = _mm256_loadu_ps(data.velocities_z[i..].as_ptr());
  78.  
  79.             let ax: __m256 = _mm256_loadu_ps(data.accelerations_x[i..].as_ptr());
  80.             let ay: __m256 = _mm256_loadu_ps(data.accelerations_y[i..].as_ptr());
  81.             let mut az: __m256 = _mm256_loadu_ps(data.accelerations_z[i..].as_ptr());
  82.  
  83.             // Update accelerations (gravity)
  84.             az = _mm256_add_ps(az, gravity_vector);
  85.  
  86.             // Update velocities
  87.             let nvx = _mm256_add_ps(vx, _mm256_mul_ps(ax, delta_time_vector));
  88.             let nvy = _mm256_add_ps(vy, _mm256_mul_ps(ay, delta_time_vector));
  89.             let nvz = _mm256_add_ps(vz, _mm256_mul_ps(az, delta_time_vector));
  90.  
  91.             // Update positions
  92.             let npx = _mm256_add_ps(px, _mm256_mul_ps(nvx, delta_time_vector));
  93.             let npy = _mm256_add_ps(py, _mm256_mul_ps(nvy, delta_time_vector));
  94.             let npz = _mm256_add_ps(pz, _mm256_mul_ps(nvz, delta_time_vector));
  95.  
  96.             // Store results
  97.             _mm256_storeu_ps(data.positions_x[i..].as_mut_ptr(), npx);
  98.             _mm256_storeu_ps(data.positions_y[i..].as_mut_ptr(), npy);
  99.             _mm256_storeu_ps(data.positions_z[i..].as_mut_ptr(), npz);
  100.             _mm256_storeu_ps(data.velocities_x[i..].as_mut_ptr(), nvx);
  101.             _mm256_storeu_ps(data.velocities_y[i..].as_mut_ptr(), nvy);
  102.             _mm256_storeu_ps(data.velocities_z[i..].as_mut_ptr(), nvz);
  103.             _mm256_storeu_ps(data.accelerations_x[i..].as_mut_ptr(), ax);
  104.             _mm256_storeu_ps(data.accelerations_y[i..].as_mut_ptr(), ay);
  105.             _mm256_storeu_ps(data.accelerations_z[i..].as_mut_ptr(), az);
  106.         }
  107.     }
  108. }
  109.  
  110. fn main() {
  111.     let mut particle_data = allocate_particle_data();
  112.     initialize_particles(&mut particle_data);
  113.  
  114.     let num_steps: i32 = 100;
  115.  
  116.      // Time SIMD version
  117.     println!("Starting SIMD test...");
  118.     let start_simd = Instant::now();
  119.     for _ in 0..num_steps {
  120.         update_particles_simd(&mut particle_data);
  121.     }
  122.     let end_simd = Instant::now();
  123.     let time_simd = (end_simd - start_simd).as_secs_f64() * 1000.0;
  124.     println!("SIMD Time: {:.2} ms", time_simd);
  125.  
  126.     println!("First position Rust: x={:.4}, y={:.4}, z={:.4}",
  127.         particle_data.positions_x[0],
  128.         particle_data.positions_y[0],
  129.         particle_data.positions_z[0]
  130.     );
  131. }
  132.  
Advertisement
Add Comment
Please, Sign In to add comment