[galib] Parallelize the genome evaluation?
headcrash at mac.com
Fri Sep 2 23:10:59 EDT 2011
On Sep 2, 2011, at 9:14 AM, galib-request at mit.edu wrote:
> Is it possible to parallelize the genome evaluation?
Here's an old posting of mine that I've updated with some better changes:
I did this (a pthreaded version) without touching the GALib itself .. it was a tad bit hacky .. but I didn't want to touch the library in case there were updates later on (and I just don't have time to fold .diffs back in).
Anyway, in a nutshell (this is copy, massaged, and pasted code, so YMMV):
1) I get ahold of the GA's GAPopulation:
GAPopulation *pop = const_cast<GAPopulation *>(&ga->population());
2) I make a copy of the current population*:
GAPopulation *newpop = pop->clone();
3) This is optional, but a way to ensure that both populations carry the userData**...
newpop->userData( ga->userData() );
4) I install my (threaded) evaluator:
newpop->evaluator( MyEvaluator );
5) Now I install the new, modified population into my ga:
6) Then in my Evaluator:
extern void MyEvaluator( GAPopulation & p )
7) I launch threads for each individual***:
for ( int i = 0; i < p.size(); i++ )
parameters->individual = &p.individual( i );
int rc = pthread_create( &task_threads[i], &attr, thread_function, parameters );
8) And in my thread / background function:
static void *thread_function( void *parameters )
9) I simply evaluate the individual:
10) Then when all of the threads are complete (joined), I pull out the best genome from the population (just so I can display the progress so far):
GARealGenome *best_genome = (GARealGenome*)&p.individual(0);
double best_score = best_genome->score();
for ( int i = 1; i < p.size(); i++ )
GARealGenome* genome = (GARealGenome*)&p.individual(i);
if ( genome->score() > best_score )
best_genome_index = i;
best_genome = genome;
best_score = genome->score();
11) All of the other magic happens in the outer functionality (e.g. ga->step(), ga->statistics().bestIndividual(), etc.)
* NEW: For optimization purposes (I assume) the population alternates back and forth between the "old" population and the "new" population. This causes galib to clobber the evaluator
(**as well as userData for the members of the population!). The clone forces the generation of the "other" population so that the evaluator (and userData) are swapped correctly.
*** You may want to queue up your threads, and run n-cores at a time, if you have a large population size.
More information about the galib