From 8bda52d973ddf18c8b0ab93b8baa39a85ffc44e6 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 11 Jan 2022 16:21:05 -0800 Subject: [PATCH] memoize the region lookups for better perf 102s => 57s --- Cargo.toml | 1 + examples/buffer_proto5.rs | 14 +++++++------- src/geom/mod.rs | 4 ++-- src/geom/region/mod.rs | 28 +++++++++++++++++++++++++--- src/geom/units.rs | 28 +++++++++++++++++++++++++++- src/geom/vec.rs | 2 +- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9a0d45c..a11e6da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ bincode = "1.3" common_macros = "0.1" crossterm = "0.20" csv = "1.1" +dashmap = "5.0" decorum = "0.3" dyn-clone = "1.0" enum_dispatch = "0.3" diff --git a/examples/buffer_proto5.rs b/examples/buffer_proto5.rs index a721b59..c9ab08c 100644 --- a/examples/buffer_proto5.rs +++ b/examples/buffer_proto5.rs @@ -3,7 +3,7 @@ //! clock -> mem2 coupling use coremem::{Driver, mat, meas, SpirvDriver}; -use coremem::geom::{region, Cube, Dilate, Meters, Region, Spiral, SwapYZ, Torus, Translate, Wrap}; +use coremem::geom::{region, Cube, Dilate, Memoize, Meters, Region, Spiral, SwapYZ, Torus, Translate, Wrap}; use coremem::stim::{CurlStimulus, Gated, Sinusoid1, TimeVarying1 as _}; use log::info; @@ -71,7 +71,7 @@ fn run_sim(id: u32, p: Params) { let set1_region = Torus::new_xz(set1_center, p.wire_set_major, p.wire_minor); let set2_region = Torus::new_xz(set2_center, p.wire_set_major, p.wire_minor); - let coupling_region1 = Dilate::new( + let coupling_region1 = Memoize::new(Dilate::new( Wrap::new_about( Translate::new( SwapYZ::new(region::and( @@ -85,9 +85,9 @@ fn run_sim(id: u32, p: Params) { ), p.wire_wrap_dilation, p.wire_wrap_dilation / (p.wire_wrap_iters as f32), - ); + )); - let coupling_region2 = Dilate::new( + let coupling_region2 = Memoize::new(Dilate::new( Wrap::new_about( Translate::new( SwapYZ::new(region::and_not( @@ -101,7 +101,7 @@ fn run_sim(id: u32, p: Params) { ), p.wire_wrap_dilation, p.wire_wrap_dilation / (p.wire_wrap_iters as f32), - ); + )); let coupling_wire_top = Cube::new_centered( ferro_center - Meters::new_y(p.ferro_major + 4.0*p.wire_wrap_minor + 12.0*p.feat_size), @@ -192,8 +192,6 @@ fn run_sim(id: u32, p: Params) { p.feat_size, ).unwrap()); - return; - // mu_r=881.33, starting at H=25 to H=75. let ferro_mat = mat::MHPgram::new(25.0, 881.33, 44000.0); // let ferro_mat = mat::db::conductor(wire_conductivity); @@ -279,6 +277,8 @@ fn run_sim(id: u32, p: Params) { driver.add_measurement(meas::Current::new("couplingtop", coupling_wire_top.clone())); driver.add_measurement(meas::Current::new("couplingbot", coupling_wire_bot.clone())); + return; + let prefix = format!("out/{}/{}-{}-{}setmA-{}setps-{}clkmA-{}clkps-{}um-{}:{}wraps", base, base, diff --git a/src/geom/mod.rs b/src/geom/mod.rs index 93e5e21..6c0beac 100644 --- a/src/geom/mod.rs +++ b/src/geom/mod.rs @@ -8,9 +8,9 @@ mod vecu; pub use line::Line2d; pub use polygon::Polygon2d; pub use region::{ - Cube, CylinderZ, Dilate, InvertedRegion, Region, Sphere, Spiral, SwapXZ, SwapYZ, Torus, Translate, Union, WorldRegion, Wrap + Cube, CylinderZ, Dilate, InvertedRegion, Memoize, Region, Sphere, Spiral, SwapXZ, SwapYZ, Torus, Translate, Union, WorldRegion, Wrap }; -pub use units::{Coord, Meters, Index}; +pub use units::{Coord, Meters, OrdMeters, Index}; pub use vec::{Vec2, Vec3}; pub use vecu::Vec3u; diff --git a/src/geom/region/mod.rs b/src/geom/region/mod.rs index e7dd6ce..b5f7a9f 100644 --- a/src/geom/region/mod.rs +++ b/src/geom/region/mod.rs @@ -1,10 +1,11 @@ -use crate::geom::{Coord, Index, Meters}; +use crate::geom::{Coord, Index, Meters, OrdMeters}; use dyn_clone::{self, DynClone}; use log::info; use rayon::prelude::*; use serde::{Serialize, Deserialize}; use std::collections::{BTreeMap, BTreeSet}; +use std::sync::{Arc, RwLock}; mod primitives; pub use primitives::*; @@ -257,8 +258,6 @@ impl Dilate { #[typetag::serde] impl Region for Dilate { fn contains(&self, p: Meters) -> bool { - let small = p - Meters::new(self.rad, self.rad, self.rad); - let large = p + Meters::new(self.rad, self.rad, self.rad); let rad_iters = (self.rad / self.res).ceil() as i32; let rad_range = -rad_iters..=rad_iters; let rad_sq = self.rad * self.rad; @@ -280,6 +279,29 @@ impl Region for Dilate { } } +#[derive(Clone, Serialize, Deserialize)] +pub struct Memoize { + #[serde(skip)] + lut: Arc>, + inner: Box, +} + +impl Memoize { + pub fn new(inner: R) -> Self { + Self { + lut: Arc::new(dashmap::DashMap::new()), + inner: Box::new(inner), + } + } +} + +#[typetag::serde] +impl Region for Memoize { + fn contains(&self, p: Meters) -> bool { + *self.lut.entry(OrdMeters(p)).or_insert_with(|| self.inner.contains(p)) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/src/geom/units.rs b/src/geom/units.rs index d559028..f01d821 100644 --- a/src/geom/units.rs +++ b/src/geom/units.rs @@ -2,7 +2,9 @@ use crate::real::ToFloat; use serde::{Serialize, Deserialize}; use super::{Vec3, Vec3u}; use std::fmt::{self, Display}; +use std::cmp::Ordering; use std::ops::{Add, Deref, Div, Mul, Neg, Sub}; +use std::hash::{Hash, Hasher}; pub trait Coord: Copy + Clone { fn to_meters(&self, feature_size: f32) -> Meters; @@ -15,7 +17,7 @@ pub trait Coord: Copy + Clone { fn from_either(i: Index, m: Meters) -> Self; } -#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] pub struct Meters(pub Vec3); impl Meters { @@ -105,6 +107,30 @@ impl Display for Meters { } } +#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] +pub struct OrdMeters(pub Meters); + +impl Deref for OrdMeters { + type Target = Meters; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Ord for OrdMeters { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } +} +impl Eq for OrdMeters { } + +impl Hash for OrdMeters { + fn hash(&self, state: &mut H) { + let bits: (u32, u32, u32) = unsafe { std::mem::transmute(*self) }; + bits.hash(state) + } +} + #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Index(pub Vec3u); diff --git a/src/geom/vec.rs b/src/geom/vec.rs index b18cfef..82905d3 100644 --- a/src/geom/vec.rs +++ b/src/geom/vec.rs @@ -134,7 +134,7 @@ impl Vec2 { } } -#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] pub struct Vec3 { pub(crate) x: R, pub(crate) y: R,