@@ -162,7 +162,8 @@ void dropInvalidConfigurations(GeneticSearch::Population& population) {
162
162
} // namespace
163
163
164
164
#define VALIDATE () \
165
- CHECK_LT (kNumberElites , kMaxPopulationSize ); \
165
+ CHECK_LT (kMaxPopulationSize , kMatingPoolSize ); \
166
+ CHECK_LT (kMaxPopulationSize , kSelectionPoolSize ); \
166
167
CHECK (kMutationRate >= 0 and kMutationRate <= 100 ) \
167
168
<< " the mutation rate (" << kMutationRate \
168
169
<< " ) should be in the [0,100] interval" ; \
@@ -189,14 +190,15 @@ GeneticSearch::GeneticSearch(
189
190
size_t n,
190
191
uint8_t crossOverRate,
191
192
uint8_t mutationRate,
192
- size_t numberElites)
193
+ size_t matingPoolSize,
194
+ size_t selectionPoolSize)
193
195
: population(),
194
196
lastBestConf (confs[0 ]),
195
197
kMaxPopulationSize(n),
196
- kMatingPoolSize(n * 3 ),
198
+ kMatingPoolSize(matingPoolSize),
199
+ kSelectionPoolSize(selectionPoolSize),
197
200
kCrossOverRate(crossOverRate),
198
201
kMutationRate(mutationRate),
199
- kNumberElites(numberElites),
200
202
rng{std::random_device{}()} {
201
203
restoreRngState (rng);
202
204
VALIDATE ();
@@ -222,14 +224,15 @@ GeneticSearch::GeneticSearch(
222
224
size_t n,
223
225
uint8_t crossOverRate,
224
226
uint8_t mutationRate,
225
- size_t numberElites)
227
+ size_t matingPoolSize,
228
+ size_t selectionPoolSize)
226
229
: population(),
227
230
lastBestConf (conf),
228
231
kMaxPopulationSize(n),
229
- kMatingPoolSize(n * 3 ),
232
+ kMatingPoolSize(matingPoolSize),
233
+ kSelectionPoolSize(selectionPoolSize),
230
234
kCrossOverRate(crossOverRate),
231
235
kMutationRate(mutationRate),
232
- kNumberElites(numberElites),
233
236
rng{std::random_device{}()} {
234
237
restoreRngState (rng);
235
238
VALIDATE ();
@@ -301,13 +304,6 @@ void GeneticSearch::breed() {
301
304
auto matingPool =
302
305
stochasticUniversalSampling (computeAccumulatedFitness (population));
303
306
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
-
311
307
auto select = [&]() -> TuningConfiguration& {
312
308
auto idx = std::uniform_int_distribution<size_t >{
313
309
size_t (0 ), matingPool.size () - 1 }(rng);
@@ -323,45 +319,20 @@ void GeneticSearch::breed() {
323
319
return dist (rng);
324
320
};
325
321
326
- while (new_population .size () < kMaxPopulationSize ) {
322
+ while (selectionPool .size () < kSelectionPoolSize ) {
327
323
if (shouldCrossOver ()) {
328
324
auto parent1 = select ();
329
325
auto parent2 = select ();
330
326
auto parent3 = select ();
331
- new_population .emplace_back (make_unique<CandidateConfiguration>(
327
+ selectionPool .emplace_back (make_unique<CandidateConfiguration>(
332
328
crossover (parent1, parent2, parent3)));
333
329
} else {
334
- new_population.emplace_back (
335
- make_unique<CandidateConfiguration>(select ()));
330
+ selectionPool.emplace_back (make_unique<CandidateConfiguration>(select ()));
336
331
}
337
332
}
338
- population = std::move (new_population);
339
333
}
340
334
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 () {
365
336
if (population.size () < kMinCandidatesForBreeding ) {
366
337
LOG_IF (ERROR, FLAGS_debug_tuner)
367
338
<< population.size () << " out of " << kMaxPopulationSize
@@ -380,12 +351,70 @@ void GeneticSearch::updateParameters() {
380
351
// Don't lose the first one which was the best from before
381
352
CHECK_LT (0 , population.size ());
382
353
randomizePopulation (population.begin () + 1 , population.end (), rng);
383
- return ;
384
354
}
355
+ }
385
356
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 ();
386
387
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);
389
418
}
390
419
}
391
420
0 commit comments