def gen_loops(self, node): dim = len(self.output_grid.shape) ret_node = None cur_node = None for d in xrange(dim): dim_var = self.gen_fresh_var() self.dim_vars.append(dim_var) initial = cpp_ast.CNumber(self.output_grid.ghost_depth) end = cpp_ast.CNumber(self.output_grid.shape[d] - self.output_grid.ghost_depth - 1) increment = cpp_ast.CNumber(1) if d == 0: ret_node = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node = ret_node elif d == dim - 2: cur_node.body = StencilConvertASTCilk.CilkFor( dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node = cur_node.body else: cur_node.body = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node = cur_node.body return (cur_node, ret_node)
def test_StencilConvertAST_array_macro_use(self): import asp.codegen.cpp_ast as cpp_ast result = StencilConvertAST( self.model, self.in_grids, self.out_grid).gen_array_macro( 'in_grid', [cpp_ast.CNumber(3), cpp_ast.CNumber(4)]) self.assertEqual(str(result), "_in_grid_array_macro(3, 4)")
def visit_InputElement(self, node): index = self.gen_array_macro( node.grid.name, map( lambda x, y: cpp_ast.BinOp(cpp_ast.CName(x), "+", cpp_ast.CNumber(y)), self.dim_vars, node.offset_list)) return cpp_ast.Subscript("_my_" + node.grid.name, index)
def gen_loops(self, node): dim = len(self.output_grid.shape) ret_node = None cur_node = None def add_one(n): if self.inject_failure == 'loop_off_by_one': return cpp_ast.CNumber(n.num + 1) else: return n for d in xrange(dim): dim_var = self.gen_fresh_var() self.dim_vars.append(dim_var) initial = cpp_ast.CNumber(self.output_grid.ghost_depth) end = cpp_ast.CNumber(self.output_grid.shape[d] - self.output_grid.ghost_depth - 1) increment = cpp_ast.CNumber(1) if d == 0: ret_node = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node = ret_node elif d == dim - 2: # add OpenMP parallel pragma to 2nd innermost loop pragma = cpp_ast.Pragma("omp parallel for") for_node = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node.body = cpp_ast.Block(contents=[pragma, for_node]) cur_node = for_node elif d == dim - 1: # add ivdep pragma to innermost node pragma = cpp_ast.Pragma("ivdep") for_node = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node.body = cpp_ast.Block(contents=[pragma, for_node]) cur_node = for_node else: cur_node.body = cpp_ast.For(dim_var, add_one(initial), add_one(end), increment, cpp_ast.Block()) cur_node = cur_node.body return (cur_node, ret_node)
def declare(self, converter): """ Returns a c++ statement declaring this object. """ if self.is_scalar(): return cpp_ast.Assign( cpp_ast.Value(self.scalar_t.ctype(), self.ref_name()), cpp_ast.CNumber(0)) else: self._declare = True return cpp_ast.Expression()
def add_one(n): if self.inject_failure == 'loop_off_by_one': return cpp_ast.CNumber(n.num + 1) else: return n
def visit_For(self, node): _iters = self.visit(node.iter) targets = self.visit(node.target) #are we iterating over a data object? if type(_iters) is cpp_ast.CName and _iters.name in self.data_model: _iters = [_iters] targets = [targets] #co-iterating over a set of datasets! if type(_iters) is list: #set up the loop variable and weight self.loopvar.append(self.loopvar[-1] + 'i') loopvar = cpp_ast.CName(self.loopvar[-1]) body = [] weight_loop = self.weighted and reduce(lambda a, b: a or b, [ (_iter.name in self.data_model and self.data_model[_iter.name].should_subsample) for _iter in _iters ]) if weight_loop: self.aggregate_on(loopvar) # add the temporary children to the data model for target, _iter in zip(targets, _iters): if not (type(_iter) is cpp_ast.CName and _iter.name in self.data_model): raise ValueError( "Cannot iterate over unknown data object: '%s'" % _iter.name) parent_model = self.data_model[_iter.name] if type(target) is not cpp_ast.CName: raise ValueError("Not a valid iteration target: '%s'" % str(target)) if target.name in self.data_model: raise ValueError("Cannot reuse iteration target: '%s'" % target.name) target_model = self.data_model[ target.name] = parent_model.branch(name=target.name) ctype = target_model.scalar_t.ctype() decl = cpp_ast.Value( ctype, target.name) if target_model.is_scalar( ) else cpp_ast.Pointer(cpp_ast.Value(ctype, target.name)) init = parent_model.declare_child(target_model, loopvar) #init = cpp_ast.Subscript( _iter, loopvar) if target_model.is_scalar() \ # else cpp_ast.BinOp( _iter, '+', cpp_ast.BinOp( loopvar , '*', parent_model.element_size() ) ) body.append(cpp_ast.Assign(decl, init)) # visit the body of the for body += [self.visit(x) for x in node.body] # generate the C for intializer ret = cpp_ast.RawFor( cpp_ast.Assign( cpp_ast.Value( 'int', loopvar ), cpp_ast.CNumber(0) ), \ cpp_ast.Compare( loopvar, '<', cpp_ast.CNumber( self.data_model[ _iter.name ].dimensions[0] ) ), \ cpp_ast.UnaryOp( '++', loopvar ), cpp_ast.Block( body ) ) # remove temporary children from data model and otherwise clean up self.loopvar = self.loopvar[:-1] for target in targets: del self.data_model[target.name] if weight_loop: self.aggregate_off(loopvar) # return return ret #or perhaps, a known range. elif isinstance(_iters, cpp_ast.CNumber): return cpp_ast.RawFor( cpp_ast.Assign( cpp_ast.Value( 'int', targets ), cpp_ast.CNumber(0) ), \ cpp_ast.Compare( targets, '<', _iter ), cpp_ast.UnaryOp( '++', target ), \ cpp_ast.Block([ self.visit( x ) for x in node.body ] ) ) else: raise ValueError( 'Loop iterand "%s" is not a numeric expression or known data object' % str(_iters))