@@ -4,6 +4,7 @@ use clap::{Args, Parser};
44use derivative:: Derivative ;
55use itertools:: Itertools ;
66use rand:: { seq:: IteratorRandom , Rng } ;
7+ use rayon:: prelude:: * ;
78
89use crate :: {
910 core:: {
5354 #[ builder( default = "None" ) ]
5455 #[ arg( long) ]
5556 pub seed : Option < u64 > ,
57+ #[ builder( default = "None" ) ]
58+ #[ arg( long) ]
59+ pub n_threads : Option < usize > ,
5660 #[ command( flatten) ]
5761 pub program_parameters : C :: ProgramParameters ,
5862}
7882 gap = hp. gap,
7983 mutation_percent = hp. mutation_percent,
8084 crossover_percent = hp. crossover_percent,
81- seed = ?hp. seed
85+ seed = ?hp. seed,
86+ n_threads = ?hp. n_threads
8287 ) ) ]
8388 pub fn new ( hp : HyperParameters < C > ) -> Self {
8489 debug ! ( "Initializing evolution engine" ) ;
@@ -116,11 +121,7 @@ where
116121
117122 let mut population = self . next_population . clone ( ) ;
118123
119- C :: eval_fitness (
120- & mut population,
121- & mut self . trials ,
122- self . params . default_fitness ,
123- ) ;
124+ C :: eval_fitness ( & mut population, & self . trials , self . params . default_fitness ) ;
124125 C :: rank ( & mut population) ;
125126
126127 assert ! ( population. iter( ) . all( C :: Status :: evaluated) ) ;
@@ -182,14 +183,22 @@ where
182183{
183184 pub fn build_engine ( & self ) -> CoreIter < T > {
184185 update_seed ( self . seed ) ;
186+
187+ if let Some ( n_threads) = self . n_threads {
188+ rayon:: ThreadPoolBuilder :: new ( )
189+ . num_threads ( n_threads)
190+ . build_global ( )
191+ . ok ( ) ;
192+ }
193+
185194 CoreIter :: new ( self . clone ( ) )
186195 }
187196}
188197
189198pub trait Core {
190199 type Individual : Ord + Clone + Send + Sync + Serialize + DeserializeOwned ;
191200 type ProgramParameters : Copy + Send + Sync + Clone + Serialize + DeserializeOwned + Args ;
192- type State : State ;
201+ type State : State + Clone + Send + Sync ;
193202 type FitnessMarker ;
194203 type Generate : Generate < Self :: ProgramParameters , Self :: Individual > + Generate < ( ) , Self :: State > ;
195204 type Fitness : Fitness < Self :: Individual , Self :: State , Self :: FitnessMarker > ;
@@ -210,27 +219,27 @@ pub trait Core {
210219
211220 fn eval_fitness (
212221 population : & mut Vec < Self :: Individual > ,
213- trials : & mut Vec < Self :: State > ,
222+ trials : & [ Self :: State ] ,
214223 default_fitness : f64 ,
215224 ) {
216- for individual in population. iter_mut ( ) {
217- let mut scores = trials
218- . iter_mut ( )
219- . map ( |trial| {
225+ let n_trials = trials. len ( ) ;
226+ population. par_iter_mut ( ) . for_each ( |individual| {
227+ let total: f64 = trials
228+ . iter ( )
229+ . cloned ( )
230+ . map ( |mut trial| {
220231 Self :: Reset :: reset ( individual) ;
221- Self :: Reset :: reset ( trial) ;
222- Self :: Fitness :: eval_fitness ( individual, trial)
232+ Self :: Reset :: reset ( & mut trial) ;
233+ let score = Self :: Fitness :: eval_fitness ( individual, & mut trial) ;
234+ if score. is_finite ( ) {
235+ score
236+ } else {
237+ default_fitness
238+ }
223239 } )
224- . collect_vec ( ) ;
225-
226- let n_trials = scores. len ( ) ;
227- scores = scores
228- . into_iter ( )
229- . map ( |s| if !s. is_finite ( ) { default_fitness } else { s } )
230- . collect_vec ( ) ;
231- let average = scores. into_iter ( ) . sum :: < f64 > ( ) / n_trials as f64 ;
232- Self :: Status :: set_fitness ( individual, average) ;
233- }
240+ . sum ( ) ;
241+ Self :: Status :: set_fitness ( individual, total / n_trials as f64 ) ;
242+ } ) ;
234243 }
235244
236245 fn rank ( population : & mut Vec < Self :: Individual > ) {
0 commit comments