I am new to evolutionary computation and inspyred, and I am currently trying to modify and understand the supplied examples (which are great). Ultimately, my goal is to utilize the NSGA2 algorithm to optimize an external model. As far as I understand, for that I need to write a custom generator and evaluator. Additionally, since the model is computationally expensive, I'd like to use multiprocessing (similar to
this thread).
I started with modifying the
NSGA2 example to have the generator and evaluator in separate functions and pulled the evaluation out of the 'main' function. This all works well and I started looking into multiprocessing.
My first question is related to the
multiprocessing example. Executing this example works. However, I noticed that whatever number I entered for the argument 'mp_num_cpus=8' (e.g. 1,2,4), it was always using 4 processes due to my 4 CPUs (I was printing the 'nprocs' variable from evaluators.parallel_evaluation_mp). In none of inspyred's files I found the argument 'mp_num_cpus'. Isn't it thus necessary to replace 'mp_num_cpus=' with 'mp_nprocs=' to achieve the expected behaviour?
Then, I was trying to merge the multiprocessing example with the modified NSGA2. My code now looks like this:
from random import Random
from time import time
import inspyred
import math
def CustomGenerator(random, args): #from the class Kursawe (benchmark.py)
nr_inputs = args.get('nr_inputs', 10)
return_generator = [random.uniform(-5.0, 5.0) for _ in range(nr_inputs)]
return return_generator
def CustomEvaluator(candidates, args): #from the class Kursawe (benchmark.py)
fitness = []
for c in candidates:
f1 = sum([-10 * math.exp(-0.2 * math.sqrt(c[i]**2 + c[i+1]**2)) for i in range(len(c) - 1)])
f2 = sum([math.pow(abs(x), 0.8) + 5 * math.sin(x)**3 for x in c])
fitness.append(inspyred.ec.emo.Pareto([f1, f2]))
return fitness
prng = Random()
prng.seed(time())
ea = inspyred.ec.emo.NSGA2(prng)
ea.variator = [inspyred.ec.variators.blend_crossover,
inspyred.ec.variators.gaussian_mutation]
ea.terminator = inspyred.ec.terminators.generation_termination
dimensions=3
final_pop = ea.evolve(generator=CustomGenerator,
evaluator=inspyred.ec.evaluators.parallel_evaluation_mp,
mp_evaluator=CustomEvaluator,
mp_nprocs=4,
#evaluator=CustomEvaluator,
pop_size=100,
maximize=False,
nr_inputs = 3,
bounder=inspyred.ec.Bounder([-5.0]*dimensions, [5.0]*dimensions),
max_generations=80)
final_arc = ea.archive
print('Best Solutions: \n')
for f in final_arc:
print(f)
As I mentioned before, when I use the example without multiprocessing it works well. However, when executing the code as posted, python hangs (without error) in 'inspyred.ec.evaluators.parallel_evaluation_mp' when attempting to execute 'pool.join()'. 'pool.close()' is executed. In addition, the number of python processes increase linearly until the computer becomes unresponsive, even after stopping the execution or closing my python IDE. This makes a restart necessary. Also
this and
this should not be an issue since it should be fixed for Python 2.7.3 (which I am using in Windows 8 and Spyder, in case that makes a difference)? Has anybody encountered this or knows what I am doing wrong?
I really appreciate your help! Thanks a lot for looking into this.
Jens