def gen_output_er_1dto1d(output_er_spec,is_call_input,mapir): import iegen.pycloog from iegen.pycloog import codegen from iegen.codegen import Statement,Comment iegen.print_progress("Generating code for output ERSpec '%s'..."%(output_er_spec.name)) iegen.print_detail(str(output_er_spec)) print 'Abstract relation: %s'%(output_er_spec.relation) print 'Input bounds for abstract relation: %s'%(output_er_spec.input_bounds) print 'Output bounds for abstract relation: %s'%(output_er_spec.output_bounds) #Calculate the necessary information before generating code output_bounds_var_name=output_er_spec.output_bounds.tuple_set[0] output_lower_bound=str(list(output_er_spec.output_bounds.lower_bounds(output_bounds_var_name)[0])[0]) output_upper_bound=str(list(output_er_spec.output_bounds.upper_bounds(output_bounds_var_name)[0])[0]) input_bounds_var_name=output_er_spec.input_bounds.tuple_set[0] input_lower_bound=str(list(output_er_spec.input_bounds.lower_bounds(input_bounds_var_name)[0])[0]) input_upper_bound=str(list(output_er_spec.input_bounds.upper_bounds(input_bounds_var_name)[0])[0]) num_entries=calc_size_string(list(output_er_spec.output_bounds)[0],output_bounds_var_name) input_equal_value=calc_equality_value(input_bounds_var_name,list(output_er_spec.relation)[0],mapir) input_var_name=output_er_spec.relation.tuple_in[0] output_var_name=output_er_spec.relation.tuple_out[0] stmts=[] stmts.append(Comment('Creation of ER_1Dto1D for abstract relation:')) stmts.append(Comment(str(output_er_spec.relation))) stmts.append(Comment('Bounds for output domain: '+str(output_er_spec.output_bounds))) #Generate the call to the constructor stmts.append(Statement('%s=%s(%s,%s,%s,%s,%s);'%(output_er_spec.get_var_name(),output_er_spec.get_ctor_str(),input_lower_bound,input_upper_bound,output_lower_bound,output_upper_bound,num_entries))) #Generate the count loop stmts.append(Statement('#define S0(%s) %s(%s,%s)'%(output_var_name,output_er_spec.get_count_name(),output_er_spec.get_var_name(),input_equal_value))) loop_stmts=codegen([iegen.pycloog.Statement(output_er_spec.output_bounds)]).split('\n') for loop_stmt in loop_stmts: stmts.append(Statement(loop_stmt)) stmts.append(Statement('#undef S0')) #Generate the finalize count call stmts.append(Statement('%s(%s)'%(output_er_spec.get_count_finalize_name(),output_er_spec.get_var_name()))) #Generate the insert loop stmts.append(Statement('#define S0(%s) %s(%s,%s,%s)'%(output_var_name,output_er_spec.get_setter_str(),output_er_spec.get_var_name(),input_equal_value,output_var_name))) loop_stmts=codegen([iegen.pycloog.Statement(output_er_spec.output_bounds)]).split('\n') for loop_stmt in loop_stmts: stmts.append(Statement(loop_stmt)) stmts.append(Statement('#undef S0')) stmts.append(Statement('*%s=%s;'%(output_er_spec.get_param_name(),output_er_spec.get_var_name()))) stmts.append(Statement()) return stmts
def calc_input(self,mapir): #This transformation requires the ER for the given sparse tiling self.inputs.append(mapir.er_specs[self.tiling_name]) #and the constant for the specific loop nest statement=mapir.statements[self.statement_name] loop_pos=calc_equality_value(statement.scatter.tuple_vars[-3],list(statement.scatter)[0],mapir) #TODO: The loop constants don't match exactly, they are off by one. loop_pos=str(int(loop_pos)+1) self.inputs.append(Constant(loop_pos))
def calc_input(self,mapir): #The tiling routine takes the dependences into and out of the iteration seed space #These dependences are given by the user currently, so we do not need to calculate them #Create a DataDependence instance for the dependences target=calc_equality_value(self.to_deps.tuple_out[0],list(self.to_deps)[0],mapir) self.to_deps=DataDependence('%s_to_deps'%(self.grouping_name,),self.to_deps,target) self.from_deps=DataDependence('%s_from_deps'%(self.grouping_name,),self.from_deps,target) #Create a new Symbolic for the number of tiles #TODO: The type is constant here, it would be better if this were defined somewhere else mapir.add_symbolic(name=self.num_tile_name,type='int %s',lower_bound=1) self.inputs.append(self.to_deps) self.inputs.append(self.from_deps) self.inputs.append(mapir.symbolics[self.num_tile_name])
def gen_explicit_er_spec(er_spec,mapir): import iegen.pycloog from iegen.pycloog import codegen from iegen.codegen import Statement,Comment if 0==len(er_spec.relation): raise ValueError("ESpec's relation has no terms in the disjunction") if (1,1)!=er_spec.relation.arity(): raise ValueError("ESpec's relation must have arity (1,1)") iegen.print_progress("Generating code for ERSpec '%s'..."%(er_spec.name)) iegen.print_detail(er_spec) var_in_name=er_spec.relation.tuple_in[0] var_out_name=er_spec.relation.tuple_out[0] #Generate the define/undefine statements cloog_stmts=[] define_stmts=[] undefine_stmts=[] for relation_index,relation in enumerate(er_spec.relation): #Get the value to insert value=calc_equality_value(var_out_name,relation,mapir) define_stmts.append(Statement('#define S%d(%s) ER_in_ordered_insert(%s_ER,Tuple_make(%s),Tuple_make(%s));'%(relation_index,var_in_name,er_spec.name,var_in_name,value))) cloog_stmts.append(iegen.pycloog.Statement(er_spec.input_bounds)) undefine_stmts.append(Statement('#undef S%d'%(relation_index,))) #Generate the whole set of statements stmts=[] in_domain_name='in_domain_%s'%(er_spec.name) stmts.extend(gen_domain(in_domain_name,er_spec.input_bounds)) stmts.append(Statement()) stmts.append(Comment('Creation of ExplicitRelation')) stmts.append(Comment(str(er_spec.relation))) stmts.append(Statement('%s_ER = %s(%d,%d,%s,%s,%s);'%(er_spec.name,er_spec.get_ctor_str(),er_spec.relation.arity_in(),er_spec.relation.arity_out(),in_domain_name,str(er_spec.is_function).lower(),str(er_spec.is_permutation).lower()))) stmts.append(Statement()) stmts.append(Comment('Define loop body statements')) stmts.extend(define_stmts) stmts.append(Statement()) loop_stmts=codegen(cloog_stmts).split('\n') for loop_stmt in loop_stmts: stmts.append(Statement(loop_stmt)) stmts.append(Statement()) stmts.append(Comment('Undefine loop body statements')) stmts.extend(undefine_stmts) return stmts
def calc_output(self,mapir): #Create the name of the sparse schedule sparse_sched_name='%s_sched'%(self.statement_name) #Get the ERSpec for the specified tiling function tiling_er_spec=mapir.er_specs[self.tiling_name] statement=mapir.statements[self.statement_name] sparse_loop_iter=statement.iter_space.tuple_vars[-2] #Extract the sparse loop bounds from the statement's iteration space output_bounds=statement.iter_space.bounds(sparse_loop_iter) lower_bounds=' and '.join(list('%s<=%s'%(str(bound),sparse_loop_iter) for bound in list(output_bounds[0])[0])) upper_bounds=' and '.join(list('%s<=%s'%(sparse_loop_iter,str(bound)) for bound in list(output_bounds[0])[1])) output_bounds=Set('{[%s]: %s and %s}'%(sparse_loop_iter,lower_bounds,upper_bounds),symbolics=statement.iter_space.symbolics) #Get the constant for the position of the sparse loop within the tile loop loop_pos=calc_equality_value(statement.scatter.tuple_vars[-3],list(statement.scatter)[0],mapir) #TODO: The loop constants don't match exactly, they are off by one. loop_pos=str(int(loop_pos)+1) relation=Relation('{[tile]->[iter]: tile=theta(%s,iter)}'%(loop_pos)) #Create a new ERSpec that represents the specified statement's sparse schedule self.outputs.append(ERSpec( name=sparse_sched_name, input_bounds=tiling_er_spec.output_bounds.copy(), output_bounds=output_bounds, relation=relation, is_function=False, is_permutation=False, is_gen_output=False)) #Add the ERSpec to the MapIR mapir.add_er_spec(self.outputs[0]) self.print_progress("Calculated output ERSpec '%s' for transformation '%s'..."%(self.outputs[0].name,self.name)) self.print_detail(self.outputs[0])
def gen_executor_loop_stmts(mapir): from iegen.codegen import Statement,Comment from iegen.util import trans_equals stmts=[] stmts.append(Comment('Define the executor main loop body statments')) statement_names=mapir.statements.keys() statement_names.sort() for i,statement_name in enumerate(statement_names): statement=mapir.statements[statement_name] for comment_line in statement.text.split('\n'): stmts.append(Comment(comment_line)) ar_dict={} for access_relation in statement.get_access_relations(): iegen.print_detail('Generating code for access relation %s'%(access_relation.name)) stmts.append(Comment('%s: %s'%(access_relation.name,access_relation.iter_to_data))) ar_string_list=[] for out_var_name in access_relation.iter_to_data.tuple_out: ar_string_list.append(calc_equality_value(out_var_name,access_relation.iter_to_data,mapir)) ar_dict[access_relation.name]=']['.join(ar_string_list) #Gather the loop iterators if statement.sparse_sched is None: iterators=','.join(statement.iter_space.tuple_set) else: iterators=','.join(statement.iter_space.tuple_set[:-1]) #If there are any UFS constraints, wrap the statement text in a guard statement_text=statement.text ufs_constraints=statement.iter_space.ufs_constraints() #Make sure there is only a single conjunction in the iteration space if len(ufs_constraints)!=1: raise ValueError('Iteration space has multiple conjunctions') #Check if we need to generate a sparse loop if statement.sparse_sched is not None: sparse_sched_name=statement.sparse_sched sparse_sched_er=mapir.er_specs[sparse_sched_name] iter_name=statement.iter_space.tuple_set[-1] outer_iter_name=statement.iter_space.tuple_set[-2] sparse_loop='''for(%s=%s(*%s,%s);\ %s!=%s(*%s,%s);\ %s=%s(*%s,%s))'''%(iter_name,sparse_sched_er.get_begin_iter(),sparse_sched_name,outer_iter_name,iter_name,sparse_sched_er.get_end_iter(),sparse_sched_name,outer_iter_name,iter_name,sparse_sched_er.get_next_iter(),sparse_sched_name,outer_iter_name) statement_text='''%s{\ %s\ }'''%(sparse_loop,statement_text) #Check if there are any UFS constraints that we need to generate guards for elif len(ufs_constraints[0])>0: ufs_constraints_strs=[trans_equals(str(constraint.value_string(function_name_map=mapir.ufs_name_map()))) for constraint in ufs_constraints[0]] statement_text='if(%s){%s}'%(' && '.join(ufs_constraints_strs),statement_text) stmt_string='#define S%d(%s) %s'%(i,iterators,statement_text) stmt_string=stmt_string.replace('\n','\\\n') stmts.append(Statement(stmt_string%ar_dict)) stmts.append(Statement()) return stmts
def gen_data_dep(data_dep,mapir): from iegen.pycloog import codegen #Get the dependence relation from the data dependence object dep_rel=data_dep.dep_rel #Ensure the data dep is 2d -> 2d if (2,2)!=dep_rel.arity(): raise ValueError('Code generation for data dependences that are not 2d -> 2d is not supported') stmts=[] #Input constant value (from loop) in_const=calc_equality_value(dep_rel.tuple_in[0],list(dep_rel)[0],mapir) #Determine if the target loop is the input or output of the relation if in_const==data_dep.target: bounds_var=dep_rel.tuple_in[1] else: bounds_var=dep_rel.tuple_out[1] #Get the lower and upper bounds for the bounds variable lbs=calc_single_bounds_from_bounds(dep_rel.lower_bounds(bounds_var)) ubs=calc_single_bounds_from_bounds(dep_rel.upper_bounds(bounds_var)) stmts.append(Comment('Dependences for %s'%(data_dep.name))) stmts.append(Comment(str(dep_rel))) #Declare the explicit dependence variable const_in=calc_equality_value(dep_rel.tuple_in[0],list(dep_rel)[0],mapir) input_size_string=calc_size_string(list(dep_rel)[0],dep_rel.tuple_in[1]) const_out=calc_equality_value(dep_rel.tuple_out[0],list(dep_rel)[0],mapir) output_size_string=calc_size_string(list(dep_rel)[0],dep_rel.tuple_out[1]) stmts.append(Statement('%s %s=%s(%s,%s,%s,%s,%s);'%(data_dep.get_type(),data_dep.get_var_name(),data_dep.get_ctor_str(),const_in,const_out,input_size_string,output_size_string,len(dep_rel)))) #Generate the define/undefine statements cloog_stmts=[] define_stmts=[] undefine_stmts=[] var_in_name=dep_rel.tuple_in[1] var_out_name=dep_rel.tuple_out[1] for conjunction_index,single_relation in enumerate(dep_rel): bounds_set=Set('{[%s]: %s<=%s and %s<=%s}'%(bounds_var,lbs[conjunction_index],bounds_var,bounds_var,ubs[conjunction_index]),mapir.get_symbolics()) #Get the value to insert if in_const==data_dep.target: value=calc_equality_value(var_out_name,single_relation,mapir,only_eqs=True) define_stmts.append(Statement('#define S%d(%s) %s(%s,%s,%s);'%(conjunction_index,bounds_var,data_dep.get_setter_str(),data_dep.get_var_name(),bounds_var,value))) else: value=calc_equality_value(var_in_name,single_relation,mapir,only_eqs=True) define_stmts.append(Statement('#define S%d(%s) %s(%s,%s,%s);'%(conjunction_index,bounds_var,data_dep.get_setter_str(),data_dep.get_var_name(),value,bounds_var))) cloog_stmts.append(iegen.pycloog.Statement(bounds_set)) undefine_stmts.append(Statement('#undef S%d'%(conjunction_index,))) #Generate the whole set of statements stmts.append(Comment('Define loop body statements')) stmts.extend(define_stmts) stmts.append(Statement()) loop_stmts=codegen(cloog_stmts).split('\n') for loop_stmt in loop_stmts: stmts.append(Statement(loop_stmt)) stmts.append(Statement()) stmts.append(Comment('Undefine loop body statements')) stmts.extend(undefine_stmts) stmts.append(Statement()) return stmts
def gen_output_er_u1d(output_er_spec,is_call_input,mapir): import iegen.pycloog from iegen.pycloog import codegen from iegen.codegen import Statement,Comment iegen.print_progress("Generating code for output ERSpec '%s'..."%(output_er_spec.name)) iegen.print_detail(str(output_er_spec)) stmts=[] #TODO: Make this routine more general so it can handle generation for # general relations in addition to functions # Currently it just generates code for explicit functions #TODO: Generalize the bounds expression calculations to handle # more than a single expression (with min/max) input_var_name=output_er_spec.input_bounds.tuple_set[0] input_lower_bound=str(list(output_er_spec.input_bounds.lower_bounds(input_var_name)[0])[0]) input_upper_bound=str(list(output_er_spec.input_bounds.upper_bounds(input_var_name)[0])[0]) output_var_name=output_er_spec.output_bounds.tuple_set[0] output_lower_bound=str(list(output_er_spec.output_bounds.lower_bounds(output_var_name)[0])[0]) output_upper_bound=str(list(output_er_spec.output_bounds.upper_bounds(output_var_name)[0])[0]) stmts.append(Comment('Creation of ExplicitFunction for abstract relation:')) stmts.append(Comment(str(output_er_spec.relation))) stmts.append(Comment('Input bounds for abstract relation: %s'%(output_er_spec.input_bounds))) stmts.append(Comment('Output bounds for abstract relation: %s'%(output_er_spec.output_bounds))) stmts.append(Statement('*%s=%s(%s,%s,%s,%s,%s);'%(output_er_spec.get_param_name(),output_er_spec.get_ctor_str(),input_lower_bound,input_upper_bound,output_lower_bound,output_upper_bound,str(output_er_spec.is_permutation).lower()))) stmts.append(Statement('%s=*%s;'%(output_er_spec.get_var_name(),output_er_spec.get_param_name()))) stmts.append(Statement()) if not is_call_input: #Generate the define/undefine statements cloog_stmts=[] define_stmts=[] undefine_stmts=[] var_in_name=output_er_spec.relation.tuple_in[0] var_out_name=output_er_spec.relation.tuple_out[0] for relation_index,single_relation in enumerate(output_er_spec.relation): #Get the value to insert value=calc_equality_value(var_out_name,single_relation,mapir) define_stmts.append(Statement('#define S%d(%s) %s(%s,%s,%s);'%(relation_index,var_in_name,output_er_spec.get_setter_str(),output_er_spec.get_var_name(),var_in_name,value))) cloog_stmts.append(iegen.pycloog.Statement(output_er_spec.input_bounds)) undefine_stmts.append(Statement('#undef S%d'%(relation_index,))) #Generate the whole set of statements stmts.append(Comment('Define loop body statements')) stmts.extend(define_stmts) stmts.append(Statement()) loop_stmts=codegen(cloog_stmts).split('\n') for loop_stmt in loop_stmts: stmts.append(Statement(loop_stmt)) stmts.append(Statement()) stmts.append(Comment('Undefine loop body statements')) stmts.extend(undefine_stmts) stmts.append(Statement()) #TODO: This is the old code that generates an ER rather than an EF ##Create a domain for the ERSpec #in_domain_name='in_domain_%s'%(output_er_spec.name) #stmts.extend(gen_domain(in_domain_name,output_er_spec.input_bounds)) #stmts.append(Statement('*%s=ER_ctor(%d,%d,%s,%s,%s);'%(output_er_spec.name,output_er_spec.input_bounds.arity(),output_er_spec.output_bounds.arity(),in_domain_name,str(output_er_spec.is_function).lower(),str(output_er_spec.is_permutation).lower()))) #stmts.append(Statement('%s_ER=*%s;'%(output_er_spec.name,output_er_spec.name))) return stmts