Better GA initialization

This commit is contained in:
Philippe Tillet
2014-10-31 18:12:55 -04:00
parent bdeb18429b
commit 89f3e1d211
2 changed files with 81 additions and 80 deletions

View File

@@ -32,12 +32,12 @@ TYPES = { 'vector-axpy': {'template':atd.VectorAxpyTemplate,
'perf-measure': 'GFLOP/s'} } 'perf-measure': 'GFLOP/s'} }
def do_tuning(args, devices): def do_tuning(args):
device = devices[args.device] device = args['device']
dname = misc_tools.sanitize_string(device.name) dname = misc_tools.sanitize_string(device.name)
if args.update: if os.path.isfile(args['json-file']):
json_out = json.load(open(args.update, 'r')) json_out = json.load(open(args['json-file'], 'r'))
else: else:
json_out = {} json_out = {}
json_out["version"] = "1.0" json_out["version"] = "1.0"
@@ -45,16 +45,16 @@ def do_tuning(args, devices):
def map_to_list(T, x): def map_to_list(T, x):
return list(map(T, x if isinstance(x, list) else [x])) return list(map(T, x if isinstance(x, list) else [x]))
if(args.method=='simple'): if(args['method']=='simple'):
default_tuning_sizes = {'vector-axpy': [args.blas1_size], 'reduction': [args.blas1_size], default_tuning_sizes = {'vector-axpy': args['blas1-sizes'], 'reduction': args['blas1-sizes'],
'matrix-axpy' : args.blas2_size, 'row-wise-reduction' : args.blas2_size, 'matrix-axpy' : args['blas2-sizes'], 'row-wise-reduction' : args['blas2-sizes'],
'matrix-product': args.blas3_size} 'matrix-product': args['blas3-sizes']}
for operation in ['vector-axpy', 'reduction', 'matrix-axpy', 'row-wise-reduction', 'matrix-product']: for operation in ['vector-axpy', 'reduction', 'matrix-axpy', 'row-wise-reduction', 'matrix-product']:
for datatype in [vcl.float32, vcl.float64]: for datatype in [vcl.float32, vcl.float64]:
if any(x in args.exclude_operations.split(',') for x in [operation, operation + '-' + datatype.__name__]): if any(x in args['exclude-operations'] for x in [operation, operation + '-' + datatype.__name__]):
continue continue
ctx = cl.Context([device]) ctx = cl.Context([device])
@@ -100,25 +100,25 @@ def do_tuning(args, devices):
json_out[full_operation][datatype.__name__] = {} json_out[full_operation][datatype.__name__] = {}
D = json_out[full_operation][datatype.__name__] D = json_out[full_operation][datatype.__name__]
if args.method == 'simple': if args['method'] == 'simple':
print default_tuning_sizes[operation] print default_tuning_sizes[operation]
profiles = [execution_handler(map(int,default_tuning_sizes[operation]))] profiles = [execution_handler(map(int,default_tuning_sizes[operation]))]
else: else:
def compute_perf(x, t): def compute_perf(x, t):
return TYPES[operation]['perf-index']([datatype().itemsize, x, t]) return TYPES[operation]['perf-index']([datatype().itemsize, x, t])
profiles_generator = log_space_gen_product(a, b, args.sample_size, dimsample) profiles_generator = log_space_gen_product(a, b, args['sample-size'], dimsample)
profiles = dataset.sample_profiles(execution_handler, profiles_generator) profiles = dataset.sample_profiles(execution_handler, profiles_generator)
if args.build_model: if args['build-model']:
dataset_generator = log_space_gen_product(a, b, 1000, dimsample) dataset_generator = log_space_gen_product(a, b, 1000, dimsample)
X, Y, profiles = dataset.sample_dataset(os.path.join(full_operation,datatype.__name__), profiles, execution_handler, dataset_generator) X, Y, profiles = dataset.sample_dataset(os.path.join(full_operation,datatype.__name__), profiles, execution_handler, dataset_generator)
clf = train_model(X, Y, profiles, TYPES[operation]['perf-measure']) clf = train_model(X, Y, profiles, TYPES[operation]['perf-measure'])
D['predictor'] = [{'children_left': e.tree_.children_left.tolist(), D['predictor'] = [{'children_left': e.tree_.children_left.tolist(),
'children_right': e.tree_.children_right.tolist(), 'children_right': e.tree_.children_right.tolist(),
'threshold': e.tree_.threshold.astype('float32').tolist(), 'threshold': e.tree_.threshold.astype('float64').tolist(),
'feature': e.tree_.feature.astype('float32').tolist(), 'feature': e.tree_.feature.astype('float64').tolist(),
'value': e.tree_.value[:,:,0].astype('float32').tolist()} for e in clf.estimators_] 'value': e.tree_.value[:,:,0].astype('float64').tolist()} for e in clf.estimators_]
if args.viennacl_src_path: if args['viennacl-src-path']:
misc_tools.update_viennacl_headers(args.viennacl_src_path,device,datatype,operation,additional_parameters,profiles[0]) misc_tools.update_viennacl_headers(args['viennacl-src-path'],device,datatype,operation,additional_parameters,profiles[0])
D['profiles'] = [map(int, x) for x in profiles] D['profiles'] = [map(int, x) for x in profiles]
@@ -146,7 +146,7 @@ def do_tuning(args, devices):
tune(execution_handler, 100, 4000, 2, ()) tune(execution_handler, 100, 4000, 2, ())
#Row-wise reduction #Row-wise reduction
if operation=='row-wise-reduction': if operation=='row-wise-reduction':
for A_trans in args.gemv_layouts.split(','): for A_trans in args['gemv-layouts']:
def execution_handler(sizes, fname=os.devnull, parameters=None): def execution_handler(sizes, fname=os.devnull, parameters=None):
A = vcl.Matrix(sizes if A_trans=='N' else sizes[::-1], context=ctx, dtype=datatype, layout=vcl.COL_MAJOR) A = vcl.Matrix(sizes if A_trans=='N' else sizes[::-1], context=ctx, dtype=datatype, layout=vcl.COL_MAJOR)
x = vcl.Vector(sizes[1], context=ctx, dtype=datatype) x = vcl.Vector(sizes[1], context=ctx, dtype=datatype)
@@ -156,21 +156,21 @@ def do_tuning(args, devices):
tune(execution_handler, 100, 4000, 2, (A_trans,)) tune(execution_handler, 100, 4000, 2, (A_trans,))
#Matrix Product #Matrix Product
if operation=='matrix-product': if operation=='matrix-product':
for layout in args.gemm_layouts.split(','): for L in args['gemm-layouts']:
A_trans = L[0]
B_trans = L[1]
def execution_handler(sizes, fname=os.devnull, parameters=None): def execution_handler(sizes, fname=os.devnull, parameters=None):
A_trans = layout[0] A = vcl.Matrix((sizes[0], sizes[2]) if A_trans=='N' else (sizes[2],sizes[0]), context=ctx, dtype=datatype, layout=vcl.COL_MAJOR)
B_trans = layout[1] B = vcl.Matrix((sizes[2], sizes[1]) if B_trans=='N' else (sizes[1],sizes[2]), context=ctx, dtype=datatype, layout=vcl.COL_MAJOR)
A = vcl.Matrix((sizes[0], sizes[2]) if A_trans=='N' else (sizes[2],sizes[0]), context=ctx, dtype=datatype, layout=vcl.COL_MAJOR);
B = vcl.Matrix((sizes[2], sizes[1]) if B_trans=='N' else (sizes[1],sizes[2]), context=ctx, dtype=datatype, layout=vcl.COL_MAJOR);
LHS = A if A_trans=='N' else A.T LHS = A if A_trans=='N' else A.T
RHS = B if B_trans=='N' else B.T RHS = B if B_trans=='N' else B.T
alpha = vcl.HostScalar(1.0, context=ctx, dtype = datatype) alpha = vcl.HostScalar(1.0, context=ctx, dtype = datatype)
beta = vcl.HostScalar(1.0, context=ctx, dtype = datatype) beta = vcl.HostScalar(1.0, context=ctx, dtype = datatype)
C = vcl.Matrix((sizes[0], sizes[1]), context=ctx, dtype = datatype, layout=vcl.COL_MAJOR) C = vcl.Matrix((sizes[0], sizes[1]), context=ctx, dtype = datatype, layout=vcl.COL_MAJOR)
return execute(device, vcl.Assign(C,LHS*RHS*alpha + C*beta),(A_trans, B_trans), sizes, fname, parameters) return execute(device, vcl.Assign(C,LHS*RHS*alpha + C*beta),(A_trans,B_trans), sizes, fname, parameters)
tune(execution_handler, 100, 4000, 3,(layout[0], layout[1])) tune(execution_handler, 100, 2000, 3,(A_trans,B_trans))
json.dump(json_out, open(dname + '.json','w')) json.dump(json_out, open(args['json-file'],'w'))
@@ -178,40 +178,37 @@ def do_tuning(args, devices):
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='action')
print_devices_parser = subparsers.add_parser('list-devices', help='list the devices available')
tune_parser = subparsers.add_parser('tune', help='tune using a specific configuration file')
tune_parser.add_argument("--device", default=0, type=int)
tune_parser.add_argument("--exclude-operations", default = '', type=str)
tune_parser.add_argument("--gemm-layouts", default='NN,NT,TN,TT', type=str)
tune_parser.add_argument("--gemv-layouts", default='N,T', type=str)
tune_parser.add_argument("--update", default='', type=str)
tune_parser.add_argument("--viennacl-src-path", default='', type=str)
tune_subparsers = tune_parser.add_subparsers(dest='method')
simple_parser = tune_subparsers.add_parser('simple', help = 'Tune each operation for unique sizes')
simple_parser.add_argument("--blas1-size", default = 10e6, type=int)
simple_parser.add_argument("--blas2-size", nargs=2, default=[2560,2560], type=int)
simple_parser.add_argument("--blas3-size", nargs=3, default=[1536,1536,1536],type=int)
full_parser = tune_subparsers.add_parser('full', help = 'Tune each operation for randomly chosen sizes')
full_parser.add_argument("--build-model", default=False, type=bool)
full_parser.add_argument("--sample-size", default=30, type=int)
args = parser.parse_args()
devices = [d for platform in cl.get_platforms() for d in platform.get_devices()] devices = [d for platform in cl.get_platforms() for d in platform.get_devices()]
if(args.action=='list-devices'): print("----------------")
print("----------------") print("Devices available:")
print("Devices available:") print("----------------")
print("----------------") for (i, d) in enumerate(devices):
for (i, d) in enumerate(devices): print 'Device', i, '|', cl.device_type.to_string(d.type), '|', d.name, 'on', d.platform.name
print 'Device', i, '|', cl.device_type.to_string(d.type), '|', d.name, 'on', d.platform.name print("----------------")
print("----------------")
else: args = {}
print("------")
print("Auto-tuning") def add_input(help, default):
print("------") return raw_input(help + "[" + default + "] : ") or default
do_tuning(args, devices)
args['device'] = devices[int(add_input('Device to tune for','0'))]
args['exclude-operations'] = add_input('Operations to exclude','vector-axpy,matrix-axpy,reduction,row-wise-reduction,matrix-product-float64').split(',')
if not 'matrix-product' in args['exclude-operations']:
args['gemm-layouts'] = add_input('GEMM Layouts', 'NN,NT,TN,TT').split(',')
if not 'row-wise-reduction' in args['exclude-operations']:
args['gemv-layouts'] = add_input('GEMV Layouts', 'N,T').split(',')
args['json-file'] = add_input('JSON File', misc_tools.sanitize_string(args['device'].name) + '.json')
args['method'] = add_input('Tuning type', 'simple')
if args['method'] == 'simple':
args['blas1-sizes'] = [int(float(add_input('BLAS1 size', '10e6')))]
args['blas2-sizes'] = map(int, add_input('BLAS2 sizes (M,N)', '2560,2560').split(','))
args['blas3-sizes'] = map(int, add_input('BLAS3 sizes (M,N,K)', '1024,1024,1024').split(','))
args['build-model'] = True
args['sample-size'] = 30
args['viennacl-src-path'] = ''
print("------")
print("Auto-tuning")
print("------")
do_tuning(args)

View File

@@ -85,23 +85,27 @@ class GeneticOperators(object):
def init(self, N): def init(self, N):
result = [] result = []
while len(result) < N: allowed_idx = [0,1,2] if self.TemplateType==atd.MatrixProductTemplate else [1,2]
while True: for idx in allowed_idx:
bincode = [] current = []
for x in self.genome_info: while len(current) < N/len(allowed_idx):
if x==atd.FetchingPolicy: while True:
bincode = bincode + [random.randint(0,2)] bincode = []
else: for i, x in enumerate(self.genome_info):
bincode = bincode + [str(random.randint(0,1)) for i in range(x)] if x==atd.FetchingPolicy:
parameters = self.decode(bincode) bincode = bincode + [idx]
template = self.build_template(self.TemplateType.Parameters(*parameters)) else:
registers_usage = template.registers_usage(vcl.pycore.StatementsTuple(self.statement))/4 bincode = bincode + [str(random.randint(0,1)) for i in range(x)]
lmem_usage = template.lmem_usage(vcl.pycore.StatementsTuple(self.statement)) parameters = self.decode(bincode)
local_size = template.parameters.local_size_0*template.parameters.local_size_1 template = self.build_template(self.TemplateType.Parameters(*parameters))
occupancy_record = misc_tools.OccupancyRecord(self.device, local_size, lmem_usage, registers_usage) registers_usage = template.registers_usage(vcl.pycore.StatementsTuple(self.statement))/4
if not misc_tools.skip(template, self.statement, self.device): lmem_usage = template.lmem_usage(vcl.pycore.StatementsTuple(self.statement))
result.append(creator.Individual(bincode)) local_size = template.parameters.local_size_0*template.parameters.local_size_1
break occupancy_record = misc_tools.OccupancyRecord(self.device, local_size, lmem_usage, registers_usage)
if not misc_tools.skip(template, self.statement, self.device):
current.append(creator.Individual(bincode))
break
result = result + current
return result return result
def mutate(self, individual): def mutate(self, individual):
@@ -183,7 +187,7 @@ class GeneticOperators(object):
gen = gen + 1 gen = gen + 1
best_profile = '(%s)'%','.join(map(str,self.decode(hof[0]))) best_profile = '(%s)'%','.join(map(str,self.decode(hof[0])))
best_performance = compute_perf(hof[0].fitness.values[0]) best_performance = compute_perf(hof[0].fitness.values[0])
sys.stdout.write('Generation %d | Time %d | Best %d %s [ for %s ]\r'%(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 self.decode(hof[0]) return self.decode(hof[0])