stim: re-express the AbstractStimulus list op as a fold
this gives a big perf boost: 10.5 fps -> 446 fps. still far lower from the 720 fps we got on an ordinary Vec<Box<dyn AbstractRegion>>. i think we had achieved 730 using the old ListVisitor. it's probably not worth list-ifying the stimuli; at least not at this level. at the least, we probably want only 5 stimuli: one per core. if we did that, the stimuli could even have all the same typename, and be put into a plain old array; no boxing.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::real::Real as _;
|
||||
use crate::cross::vec::Vec3;
|
||||
use crate::geom::{HasCrossSection, Meters, Region};
|
||||
use coremem_cross::compound::list::{Map, MapVisitor, Sum};
|
||||
use coremem_cross::compound::list::{Fold, FoldOp};
|
||||
use rand;
|
||||
|
||||
/// field densities
|
||||
@@ -45,21 +45,19 @@ struct StimulusEvaluator {
|
||||
pos: Meters,
|
||||
}
|
||||
|
||||
impl<S: AbstractStimulus> MapVisitor<&S> for StimulusEvaluator {
|
||||
impl<S: AbstractStimulus> FoldOp<Fields, &S> for StimulusEvaluator {
|
||||
type Output = Fields;
|
||||
fn map(&self, s: &S) -> Self::Output {
|
||||
s.at(self.t_sec, self.pos)
|
||||
fn feed(&self, prev: Fields, next: &S) -> Self::Output {
|
||||
prev + next.at(self.t_sec, self.pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Sync> AbstractStimulus for L
|
||||
where
|
||||
for<'a> &'a L: Map<StimulusEvaluator>,
|
||||
for<'a> <&'a L as Map<StimulusEvaluator>>::Output: Sum<Fields, Output=Fields>,
|
||||
for<'a> &'a L: Fold<StimulusEvaluator, Fields, Output=Fields>,
|
||||
{
|
||||
fn at(&self, t_sec: f32, pos: Meters) -> Fields {
|
||||
self.map(StimulusEvaluator { t_sec, pos })
|
||||
.sum(Fields::default())
|
||||
self.fold(StimulusEvaluator { t_sec, pos}, Fields::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user