app: multi_core_inverter: perf: move the stimulus Gating to outside the CurlStimulus
the region.contains() logic is much more expensive than the time bounds check. this gets an easy 50% perf boost to the ENTIRE simulation
This commit is contained in:
@@ -137,30 +137,30 @@ struct Params {
|
|||||||
clock_decay: f32, // exp decay half-life
|
clock_decay: f32, // exp decay half-life
|
||||||
}
|
}
|
||||||
|
|
||||||
type HoldStim = CurlStimulus<Torus, Gated<f32>>;
|
type HoldStim = Gated<CurlStimulus<Torus, f32>>;
|
||||||
type ReleaseStim = CurlStimulus<Torus, Shifted<Gated<Exp<f32>>>>;
|
type ReleaseStim = Shifted<Gated<Exp<CurlStimulus<Torus, f32>>>>;
|
||||||
fn control_signal_hold(params: Params, region: Torus, cycle: u32, ty: DriveType) -> HoldStim {
|
fn control_signal_hold(params: Params, region: Torus, cycle: u32, ty: DriveType) -> HoldStim {
|
||||||
let area = region.cross_section();
|
let area = region.cross_section();
|
||||||
let amp = ty.direction() as f32 * params.input_magnitude / area;
|
let amp = ty.direction() as f32 * params.input_magnitude / area;
|
||||||
let start = params.clock_phase_duration * cycle as f32;
|
let base_stim = CurlStimulus::new(
|
||||||
// simple square wave:
|
|
||||||
let wave = Gated::new(amp, start, start + params.clock_phase_duration);
|
|
||||||
CurlStimulus::new(
|
|
||||||
region.clone(),
|
region.clone(),
|
||||||
wave.clone(),
|
amp,
|
||||||
)
|
);
|
||||||
|
// simple square wave:
|
||||||
|
let start = params.clock_phase_duration * cycle as f32;
|
||||||
|
Gated::new(base_stim, start, start + params.clock_phase_duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn control_signal_release(params: Params, region: Torus, cycle: u32, ty: DriveType) -> ReleaseStim {
|
fn control_signal_release(params: Params, region: Torus, cycle: u32, ty: DriveType) -> ReleaseStim {
|
||||||
let area = region.cross_section();
|
let area = region.cross_section();
|
||||||
let amp = ty.direction() as f32 * params.input_magnitude / area;
|
let amp = ty.direction() as f32 * params.input_magnitude / area;
|
||||||
let start = params.clock_phase_duration * cycle as f32;
|
let base_stim = CurlStimulus::new(
|
||||||
// decaying exponential wave:
|
|
||||||
let wave = Exp::new_at(amp, start, params.clock_decay);
|
|
||||||
CurlStimulus::new(
|
|
||||||
region.clone(),
|
region.clone(),
|
||||||
wave.clone(),
|
amp,
|
||||||
)
|
);
|
||||||
|
// decaying exponential wave:
|
||||||
|
let start = params.clock_phase_duration * cycle as f32;
|
||||||
|
Exp::new_at(base_stim, start, params.clock_decay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ fn main() {
|
|||||||
assert_eq!(num_cores, 5);
|
assert_eq!(num_cores, 5);
|
||||||
let mut driver = driver.with_stimulus(stim);
|
let mut driver = driver.with_stimulus(stim);
|
||||||
|
|
||||||
let prefix = "out/applications/multi_core_inverter/13/";
|
let prefix = "out/applications/multi_core_inverter/14/";
|
||||||
let _ = std::fs::create_dir_all(&prefix);
|
let _ = std::fs::create_dir_all(&prefix);
|
||||||
driver.add_state_file(&*format!("{}state.bc", prefix), 6400);
|
driver.add_state_file(&*format!("{}state.bc", prefix), 6400);
|
||||||
driver.add_serializer_renderer(&*format!("{}frame-", prefix), 3200, None);
|
driver.add_serializer_renderer(&*format!("{}frame-", prefix), 3200, None);
|
||||||
|
@@ -346,6 +346,17 @@ impl TimeVarying3 for Exp3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: AbstractStimulus> AbstractStimulus for Exp<A> {
|
||||||
|
fn at(&self, t_sec: f32, pos: Meters) -> Fields {
|
||||||
|
let scale = (t_sec * -self.tau).exp();
|
||||||
|
let inner = self.amp.at(t_sec, pos);
|
||||||
|
Fields {
|
||||||
|
e: inner.e * scale,
|
||||||
|
h: inner.h * scale,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Gated<T> {
|
pub struct Gated<T> {
|
||||||
inner: T,
|
inner: T,
|
||||||
@@ -380,6 +391,16 @@ impl<T: TimeVarying3> TimeVarying3 for Gated<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: AbstractStimulus> AbstractStimulus for Gated<T> {
|
||||||
|
fn at(&self, t_sec: f32, pos: Meters) -> Fields {
|
||||||
|
if (self.start..self.end).contains(&t_sec) {
|
||||||
|
self.inner.at(t_sec, pos)
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Shifted<T> {
|
pub struct Shifted<T> {
|
||||||
inner: T,
|
inner: T,
|
||||||
@@ -405,6 +426,12 @@ impl<T: TimeVarying3> TimeVarying3 for Shifted<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: AbstractStimulus> AbstractStimulus for Shifted<T> {
|
||||||
|
fn at(&self, t_sec: f32, pos: Meters) -> Fields {
|
||||||
|
self.inner.at(t_sec - self.start_at, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Reference in New Issue
Block a user