Skip to content

Instantly share code, notes, and snippets.

@havchr
Created August 5, 2023 22:08
Show Gist options
  • Save havchr/bced5b0c0bd916197287492277d90819 to your computer and use it in GitHub Desktop.
Save havchr/bced5b0c0bd916197287492277d90819 to your computer and use it in GitHub Desktop.
simd test with rust, trying to see if I get any performance from std::simd (no luck so far on Macbook pro M2)
#![feature(portable_simd)]
use std::simd::Simd;
use std::array;
use std::time::Duration;
use instant;
use rand::prelude::*;
const lanes : usize = 16;
fn main() {
const precalc_size : usize = lanes * 10_000;
let mut rng = thread_rng();
let (a_precalc_vec,b_precalc_vec) = create_random_float_arrays(precalc_size,&mut rng);
let a: [f32; precalc_size] = a_precalc_vec.try_into().unwrap();
let b: [f32; precalc_size] = b_precalc_vec.try_into().unwrap();
println!("Hello, world!");
let rep_count : usize = 99_000_000;
let (duration,simd_add,simd_prod) = do_simd_calculation(rep_count,&a,&b);
println!("We spent {} seconds doing {} simds and simd_add = {}, and simd_prod = {}",
duration.as_secs_f32(),
rep_count,
simd_add,
simd_prod);
let (duration,simd_add,simd_prod) = do_non_simd_calculation(rep_count,&a,&b);
println!("We spent {} seconds doing {} non simds, simd_add = {}, and simd_prod = {}",
duration.as_secs_f32(),
rep_count,
simd_add,
simd_prod);
}
fn do_non_simd_calculation(rep_count:usize,a:&[f32],b:&[f32])->(Duration,f32,f32){
let start = instant::Instant::now();
let mut total_sum = 0.0;
let mut total_prod = 0.0;
let mut a_local: [f32; lanes] = [0.0;lanes];
let mut b_local: [f32; lanes] = [0.0;lanes];
for i in 0..rep_count{
let mut lower_bound = i%a.len();
let mut upper_bound = std::cmp::min(lower_bound + lanes,a.len());
if upper_bound-lower_bound != lanes {
lower_bound = 0;
upper_bound = lanes;
}
a_local.copy_from_slice(&a[lower_bound..upper_bound]);
b_local.copy_from_slice(&b[lower_bound..upper_bound]);
let sum:[f32;lanes] = array::from_fn(|j| a_local[j] + b_local[j]);
let prod:[f32;lanes] = array::from_fn(|j| a_local[j] * b_local[j]);
for val in sum{
total_sum+=val;
}
for val in prod{
total_prod+=val;
}
}
let now = instant::Instant::now();
(now-start,total_sum,total_prod)
}
fn do_simd_calculation(rep_count:usize,a:&[f32],b:&[f32])->(Duration,f32,f32){
let start = instant::Instant::now();
let mut total_sum = 0.0;
let mut total_prod = 0.0;
let mut a_local: [f32; lanes] = [0.0;lanes];
let mut b_local: [f32; lanes] = [0.0;lanes];
for i in 0..rep_count{
let mut lower_bound = i%a.len();
let mut upper_bound = std::cmp::min(lower_bound + lanes,a.len());
if upper_bound-lower_bound != lanes {
lower_bound = 0;
upper_bound = lanes;
}
a_local.copy_from_slice(&a[lower_bound..upper_bound]);
b_local.copy_from_slice(&b[lower_bound..upper_bound]);
let (v, w) = (Simd::from(a_local), Simd::from(b_local));
let sum = v + w;
let product = v * w;
for val in sum.as_array(){
total_sum+=val;
}
for val in product.as_array(){
total_prod+=val;
}
}
let now = instant::Instant::now();
(now-start,total_sum,total_prod)
}
fn create_random_float_arrays(num_floats: usize,randomizer: &mut ThreadRng)-> (Vec<f32>,Vec<f32>)
{
let mut a_vec: Vec<f32> = Vec::new();
let mut b_vec: Vec<f32> = Vec::new();
for i in 0.. num_floats {
a_vec.push(randomizer.gen());
b_vec.push(randomizer.gen());
}
(a_vec,b_vec)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment