@@ -162,7 +162,8 @@ void dropInvalidConfigurations(GeneticSearch::Population& population) {
162162} // namespace
163163
164164#define VALIDATE () \
165- CHECK_LT (kNumberElites , kMaxPopulationSize ); \
165+ CHECK_LT (kMaxPopulationSize , kMatingPoolSize ); \
166+ CHECK_LT (kMaxPopulationSize , kSelectionPoolSize ); \
166167 CHECK (kMutationRate >= 0 and kMutationRate <= 100 ) \
167168 << " the mutation rate (" << kMutationRate \
168169 << " ) should be in the [0,100] interval" ; \
@@ -189,14 +190,15 @@ GeneticSearch::GeneticSearch(
189190 size_t n,
190191 uint8_t crossOverRate,
191192 uint8_t mutationRate,
192- size_t numberElites)
193+ size_t matingPoolSize,
194+ size_t selectionPoolSize)
193195 : population(),
194196 lastBestConf (confs[0 ]),
195197 kMaxPopulationSize(n),
196- kMatingPoolSize(n * 3 ),
198+ kMatingPoolSize(matingPoolSize),
199+ kSelectionPoolSize(selectionPoolSize),
197200 kCrossOverRate(crossOverRate),
198201 kMutationRate(mutationRate),
199- kNumberElites(numberElites),
200202 rng{std::random_device{}()} {
201203 restoreRngState (rng);
202204 VALIDATE ();
@@ -222,14 +224,15 @@ GeneticSearch::GeneticSearch(
222224 size_t n,
223225 uint8_t crossOverRate,
224226 uint8_t mutationRate,
225- size_t numberElites)
227+ size_t matingPoolSize,
228+ size_t selectionPoolSize)
226229 : population(),
227230 lastBestConf (conf),
228231 kMaxPopulationSize(n),
229- kMatingPoolSize(n * 3 ),
232+ kMatingPoolSize(matingPoolSize),
233+ kSelectionPoolSize(selectionPoolSize),
230234 kCrossOverRate(crossOverRate),
231235 kMutationRate(mutationRate),
232- kNumberElites(numberElites),
233236 rng{std::random_device{}()} {
234237 restoreRngState (rng);
235238 VALIDATE ();
@@ -301,13 +304,6 @@ void GeneticSearch::breed() {
301304 auto matingPool =
302305 stochasticUniversalSampling (computeAccumulatedFitness (population));
303306
304- Population new_population;
305- new_population.reserve (kMatingPoolSize );
306- for (size_t c = 0 ; c < kNumberElites ; ++c) {
307- new_population.push_back (
308- make_unique<CandidateConfiguration>(population.at (c)->configuration ));
309- }
310-
311307 auto select = [&]() -> TuningConfiguration& {
312308 auto idx = std::uniform_int_distribution<size_t >{
313309 size_t (0 ), matingPool.size () - 1 }(rng);
@@ -323,45 +319,20 @@ void GeneticSearch::breed() {
323319 return dist (rng);
324320 };
325321
326- while (new_population .size () < kMaxPopulationSize ) {
322+ while (selectionPool .size () < kSelectionPoolSize ) {
327323 if (shouldCrossOver ()) {
328324 auto parent1 = select ();
329325 auto parent2 = select ();
330326 auto parent3 = select ();
331- new_population .emplace_back (make_unique<CandidateConfiguration>(
327+ selectionPool .emplace_back (make_unique<CandidateConfiguration>(
332328 crossover (parent1, parent2, parent3)));
333329 } else {
334- new_population.emplace_back (
335- make_unique<CandidateConfiguration>(select ()));
330+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(select ()));
336331 }
337332 }
338- population = std::move (new_population);
339333}
340334
341- void GeneticSearch::updateParameters () {
342- dropInvalidConfigurations (population);
343-
344- // Sort population before taking any decision
345- std::sort (
346- population.begin (),
347- population.end (),
348- [](const std::unique_ptr<CandidateConfiguration>& a,
349- const std::unique_ptr<CandidateConfiguration>& b) {
350- checkRuntimeRecorded (a->runtime );
351- checkRuntimeRecorded (b->runtime );
352- return a->runtime < b->runtime ;
353- });
354-
355- // Update failsafe lastBestConf
356- lastBestConf =
357- population.size () > 0 ? population.front ()->configuration : lastBestConf;
358- if (FLAGS_tuner_print_best) {
359- CudaMappingOptions options (
360- CudaMappingOptions::makeSingleThreadCudaMappingOptions ());
361- lastBestConf.applyToCudaMappingOptions (options);
362- LOG (INFO) << " Best so far:\n " << options;
363- }
364-
335+ void GeneticSearch::resetPopulationIfNotEnoughCandidates () {
365336 if (population.size () < kMinCandidatesForBreeding ) {
366337 LOG_IF (ERROR, FLAGS_debug_tuner)
367338 << population.size () << " out of " << kMaxPopulationSize
@@ -380,12 +351,70 @@ void GeneticSearch::updateParameters() {
380351 // Don't lose the first one which was the best from before
381352 CHECK_LT (0 , population.size ());
382353 randomizePopulation (population.begin () + 1 , population.end (), rng);
383- return ;
384354 }
355+ }
385356
357+ namespace {
358+ void sortByRuntime (GeneticSearch::Population& population) {
359+ std::sort (
360+ population.begin (),
361+ population.end (),
362+ [](const std::unique_ptr<CandidateConfiguration>& a,
363+ const std::unique_ptr<CandidateConfiguration>& b) {
364+ checkRuntimeRecorded (a->runtime );
365+ checkRuntimeRecorded (b->runtime );
366+ return a->runtime < b->runtime ;
367+ });
368+ }
369+ } // namespace
370+
371+ void GeneticSearch::updateBestCandidate (const TuningConfiguration& c) {
372+ lastBestConf = c;
373+ if (FLAGS_tuner_print_best) {
374+ CudaMappingOptions options (
375+ CudaMappingOptions::makeSingleThreadCudaMappingOptions ());
376+ lastBestConf.applyToCudaMappingOptions (options);
377+ LOG (INFO) << " Best so far:\n " << options;
378+ }
379+ }
380+
381+ void GeneticSearch::generateSelectionPool () {
382+ dropInvalidConfigurations (population);
383+ sortByRuntime (population);
384+ updateBestCandidate (
385+ population.size () > 0 ? population.front ()->configuration : lastBestConf);
386+ resetPopulationIfNotEnoughCandidates ();
386387 breed ();
387- for (int i = kNumberElites ; i < population.size (); ++i) {
388- mutate (*population[i], kMutationRate , kMutateIterations , rng);
388+ selectionPool.clear ();
389+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(lastBestConf));
390+ breed ();
391+ for (size_t i = 1 ; i < selectionPool.size (); ++i) {
392+ mutate (*selectionPool[i], kMutationRate , kMutateIterations , rng);
393+ }
394+ }
395+
396+ void GeneticSearch::selectSurvivors () {
397+ dropInvalidConfigurations (selectionPool);
398+ sortByRuntime (selectionPool);
399+ population.clear ();
400+ std::transform (
401+ selectionPool.begin (),
402+ selectionPool.begin () +
403+ std::min (selectionPool.size (), kMaxPopulationSize ),
404+ std::back_inserter (population),
405+ [](const std::unique_ptr<CandidateConfiguration>& c) {
406+ return make_unique<CandidateConfiguration>(c->configuration );
407+ });
408+
409+ if (selectionPool.size () < kMaxPopulationSize ) {
410+ auto numberMissing = kMaxPopulationSize - selectionPool.size ();
411+
412+ for (size_t i = 0 ; i < numberMissing; ++i) {
413+ selectionPool.emplace_back (
414+ make_unique<CandidateConfiguration>(lastBestConf));
415+ }
416+ randomizePopulation (
417+ selectionPool.end () - numberMissing, selectionPool.end (), rng);
389418 }
390419}
391420
0 commit comments