More efficient parameters

This commit is contained in:
Philippe Tillet
2014-09-15 18:30:30 -04:00
parent 64344f3a0a
commit 878cefa29b
2 changed files with 89 additions and 74 deletions

View File

@@ -5,7 +5,11 @@ import tools
import pyviennacl as vcl import pyviennacl as vcl
import numpy as np import numpy as np
import copy import copy
from deap import algorithms from deap import algorithms
from deap import base
from deap import creator
from deap import tools as deap_tools
from collections import OrderedDict as odict from collections import OrderedDict as odict
@@ -39,7 +43,17 @@ class GeneticOperators(object):
self.build_template = build_template self.build_template = build_template
self.cache = {} self.cache = {}
self.indpb = 0.1 self.indpb = 0.1
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
self.toolbox = base.Toolbox()
self.toolbox.register("population", self.init)
self.toolbox.register("evaluate", self.evaluate)
self.toolbox.register("mate", deap_tools.cxTwoPoint)
self.toolbox.register("mutate", self.mutate)
self.toolbox.register("select", deap_tools.selBest)
@staticmethod @staticmethod
def decode(s): def decode(s):
FetchingPolicy = vcl.atidlas.FetchingPolicy FetchingPolicy = vcl.atidlas.FetchingPolicy
@@ -62,30 +76,41 @@ class GeneticOperators(object):
lf0, lf1 = 0, 0 lf0, lf1 = 0, 0
return [simd, ls0, kL, ls1, mS, kS, nS, fetchA, fetchB, lf0, lf1] return [simd, ls0, kL, ls1, mS, kS, nS, fetchA, fetchB, lf0, lf1]
def init(self): def init(self, N):
while True: result = []
result = [random.randint(0,2), random.randint(0,2)] + [str(random.randint(0,1)) for i in range(23)]
template = self.build_template(self.TemplateType.Parameters(*self.decode(result)))
registers_usage = template.registers_usage(vcl.atidlas.StatementsTuple(self.statement))/4 def generate(Afetch, Bfetch, K):
lmem_usage = template.lmem_usage(vcl.atidlas.StatementsTuple(self.statement)) result = []
local_size = template.parameters.local_size_0*template.parameters.local_size_1 while len(result) < K:
occupancy_record = tools.OccupancyRecord(self.device, local_size, lmem_usage, registers_usage) bincode = [Afetch, Bfetch] + [str(random.randint(0,1)) for i in range(23)]
if not tools.skip(template, self.statement, self.device): parameters = self.decode(bincode)
return result template = self.build_template(self.TemplateType.Parameters(*parameters))
registers_usage = template.registers_usage(vcl.atidlas.StatementsTuple(self.statement))/4
lmem_usage = template.lmem_usage(vcl.atidlas.StatementsTuple(self.statement))
local_size = template.parameters.local_size_0*template.parameters.local_size_1
occupancy_record = tools.OccupancyRecord(self.device, local_size, lmem_usage, registers_usage)
if not tools.skip(template, self.statement, self.device):
result.append(creator.Individual(bincode))
return result
result += generate(0,0,N/3)
result += generate(1,1,N/3)
result += generate(2,2,N/3)
return result
def mutate(self, individual): def mutate(self, individual):
while True: while True:
new_individual = copy.deepcopy(individual) new_individual = copy.deepcopy(individual)
for i in range(len(new_individual)): for i in range(len(new_individual)):
if random.random() < self.indpb: if i < 2 and random.random() < self.indpb:
if i < 2: while new_individual[i] == individual[i]:
while new_individual[i] == individual[i]: new_individual[i] = random.randint(0, 2)
new_individual[i] = random.randint(0, 2) elif i >= 2 and random.random() < self.indpb:
else: new_individual[i] = '1' if new_individual[i]=='0' else '0'
new_individual[i] = '1' if new_individual[i]=='0' else '0'
parameters = self.decode(new_individual) parameters = self.decode(new_individual)
template = self.build_template(self.TemplateType.Parameters(*parameters)) template = self.build_template(self.TemplateType.Parameters(*parameters))
#print tools.skip(template, self.statement, self.device), parameters
if not tools.skip(template, self.statement, self.device): if not tools.skip(template, self.statement, self.device):
break break
return new_individual, return new_individual,
@@ -100,44 +125,58 @@ class GeneticOperators(object):
self.cache[tuple(individual)] = 10 self.cache[tuple(individual)] = 10
return self.cache[tuple(individual)], return self.cache[tuple(individual)],
def eaMuPlusLambda(population, toolbox, mu, lambda_, cxpb, mutpb, maxtime, maxgen, halloffame, compute_perf, perf_metric): def optimize(self, maxtime, maxgen, compute_perf, perf_metric):
# Evaluate the individuals with an invalid fitness hof = deap_tools.HallOfFame(1)
invalid_ind = [ind for ind in population if not ind.fitness.valid] # Begin the generational process
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) gen = 0
for ind, fit in zip(invalid_ind, fitnesses): maxtime = time.strptime(maxtime, '%Mm%Ss')
maxtime = maxtime.tm_min*60 + maxtime.tm_sec
start_time = time.time()
mu = 30
_lambda = 50
cxpb = 0.4
mutpb = 0.5
population = self.init(mu)
invalid_ind = [ind for ind in population if not ind.fitness.valid]
fitnesses = self.toolbox.map(self.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit ind.fitness.values = fit
hof.update(population)
if halloffame is not None:
halloffame.update(population) while time.time() - start_time < maxtime:
# Vary the population
# Begin the generational process offspring = []
gen = 0 for _ in xrange(_lambda):
maxtime = time.strptime(maxtime, '%Mm%Ss') op_choice = random.random()
maxtime = maxtime.tm_min*60 + maxtime.tm_sec if op_choice < cxpb: # Apply crossover
start_time = time.time() ind1, ind2 = map(self.toolbox.clone, random.sample(population, 2))
while time.time() - start_time < maxtime and gen < maxgen: ind1, ind2 = self.toolbox.mate(ind1, ind2)
# Vary the population del ind1.fitness.values
offspring = algorithms.varOr(population, toolbox, lambda_, cxpb, mutpb) offspring.append(ind1)
elif op_choice < cxpb + mutpb: # Apply mutation
ind = self.toolbox.clone(random.choice(population))
ind, = self.toolbox.mutate(ind)
del ind.fitness.values
offspring.append(ind)
else: # Apply reproduction
offspring.append(random.choice(population))
# Evaluate the individuals with an invalid fitness # Evaluate the individuals with an invalid fitness
invalid_ind = [ind for ind in offspring if not ind.fitness.valid] invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) fitnesses = self.toolbox.map(self.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses): for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit ind.fitness.values = fit
# Update the hall of fame with the generated individuals # Update the hall of fame with the generated individuals
if halloffame is not None: hof.update(offspring)
halloffame.update(offspring)
# Select the next generation population # Select the next generation population
population[:] = toolbox.select(population + offspring, mu) population[:] = self.toolbox.select(population + offspring, mu)
# Update the statistics with the new population
gen = gen + 1 gen = gen + 1
best_profile = '(%s)'%','.join(map(str,GeneticOperators.decode(hof[0])));
best_profile = '(%s)'%','.join(map(str,GeneticOperators.decode(halloffame[0]))); best_performance = compute_perf(hof[0].fitness.values[0])
best_performance = compute_perf(halloffame[0].fitness.values[0])
sys.stdout.write('Generation %d | Time %d | Best %d %s [ for %s ]\n'%(gen, time.time() - start_time, best_performance, perf_metric, best_profile)) sys.stdout.write('Generation %d | Time %d | Best %d %s [ for %s ]\n'%(gen, time.time() - start_time, best_performance, perf_metric, best_profile))
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write('\n') sys.stdout.write('\n')
return population return population

View File

@@ -7,10 +7,7 @@ import itertools
import tools import tools
import deap.tools import deap.tools
from deap import base
from deap import creator
from genetic import GeneticOperators from genetic import GeneticOperators
from genetic import eaMuPlusLambda
def exhaustive(statement, context, TemplateType, build_template, parameter_names, all_parameters, compute_perf, perf_metric, out): def exhaustive(statement, context, TemplateType, build_template, parameter_names, all_parameters, compute_perf, perf_metric, out):
device = context.devices[0] device = context.devices[0]
@@ -39,25 +36,4 @@ def exhaustive(statement, context, TemplateType, build_template, parameter_names
def genetic(statement, context, TemplateType, build_template, parameter_names, all_parameters, compute_perf, perf_metric, out): def genetic(statement, context, TemplateType, build_template, parameter_names, all_parameters, compute_perf, perf_metric, out):
GA = GeneticOperators(context.devices[0], statement, all_parameters, parameter_names, TemplateType, build_template) GA = GeneticOperators(context.devices[0], statement, all_parameters, parameter_names, TemplateType, build_template)
creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) GA.optimize(maxtime='5m0s', maxgen=1000, compute_perf=compute_perf, perf_metric=perf_metric)
creator.create("Individual", list, fitness=creator.FitnessMin)
toolbox = base.Toolbox()
toolbox.register("individual", deap.tools.initIterate, creator.Individual, GA.init)
toolbox.register("population", deap.tools.initRepeat, list, toolbox.individual)
toolbox.register("evaluate", GA.evaluate)
toolbox.register("mate", deap.tools.cxTwoPoint)
toolbox.register("mutate", GA.mutate)
toolbox.register("select", deap.tools.selBest)
pop = toolbox.population(n=50)
hof = deap.tools.HallOfFame(1)
best_performer = lambda x: max([compute_perf(hof[0].fitness.values[0]) for t in x])
best_profile = lambda x: '(%s)'%','.join(map(str,hof[0]))
stats = deap.tools.Statistics(lambda ind: ind.fitness.values)
stats.register("max (" + perf_metric + ")", lambda x: max([compute_perf(hof[0].fitness.values[0]) for t in x]))
stats.register("profile ", lambda x: '(%s)'%','.join(map(str,hof[0])))
pop = eaMuPlusLambda(pop, toolbox, 50, 70, cxpb=0.2, mutpb=0.3, maxtime='5m0s', maxgen=1000, halloffame=hof, compute_perf=compute_perf, perf_metric=perf_metric)