To practice Rust I'm implementing a raytracer.
First step I only implemented it only using spheres. I would loop over a Vector of Sphere structs.
I could easily increase performance using rayon
by doing into_iter_par
.
Now I'm trying to add cubes. So instead of looping over Vec<Sphere>
I'm looping over Vec<Box<dyn Body>>
. This seems to negate the performance gained by using rayon.
How is this performance loss happening and I can I fix it?
In this code snippet I can reproduce the behavior.
use rayon::prelude::*;
use std::f64::consts::PI;
use std::time::Instant;
pub trait Body: Sync + Send {
fn size(&self) -> f64 {
0.
}
}
#[derive(Clone)]
pub struct Sphere {
radius: f64,
}
impl Sphere {
pub fn new() -> Self {
Sphere { radius: 4.0 }
}
}
impl Body for Sphere {
fn size(&self) -> f64 {
4.0 / 3.0 * PI * self.radius * self.radius * self.radius
}
}
pub struct World {
bodies: Vec<Box<dyn Body>>,
spheres: Vec<Sphere>,
}
impl World {
fn new() -> Self {
let mut world = World {
bodies: vec![],
spheres: vec![],
};
for _ in 0..100000000 {
world.spheres.push(Sphere::new());
world.bodies.push(Box::new(Sphere::new()));
}
world
}
}
pub fn main() {
println!("Creating structs");
let world = World::new();
println!("Normal,Spheres");
let timer = Instant::now();
world.spheres.iter().map(|s| s.size()).sum::<f64>();
println!("elapsed time:{:?}", timer.elapsed());
println!("Normal,Bodies");
let timer = Instant::now();
world.bodies.iter().map(|s| s.size()).sum::<f64>();
println!("elapsed time:{:?}", timer.elapsed());
println!("Parallel,Spheres");
let timer = Instant::now();
world.spheres.into_par_iter().map(|s| s.size()).sum::<f64>();
println!("elapsed time:{:?}", timer.elapsed());
println!("Parallel,Bodies");
let timer = Instant::now();
world.bodies.into_par_iter().map(|s| s.size()).sum::<f64>();
println!("elapsed time:{:?}", timer.elapsed());
}
When running with the release build, this produces the output:
Creating structs
Normal,Spheres
elapsed time:97ns
Normal,Bodies
elapsed time:323.960404ms
Parallel,Spheres
elapsed time:88.960257ms
Parallel,Bodies
elapsed time:6.015788183s