def test_ast_convertion(self, equation, expected): """ Test OPS generated expressions for 1, 2 and 3 space dimensions. Parameters ---------- equation : str A string with a :class:`Eq`to be evaluated. expected : str Expected expression to be generated from devito. """ grid_1d = Grid(shape=(4)) grid_2d = Grid(shape=(4, 4)) grid_3d = Grid(shape=(4, 4, 4)) a = 1.43 # noqa b = 0.000000987 # noqa c = 999999999999999 # noqa u = TimeFunction(name='u', grid=grid_1d, space_order=2) # noqa v = TimeFunction(name='v', grid=grid_2d, space_order=2) # noqa w = TimeFunction(name='w', grid=grid_3d, space_order=2) # noqa nfops = OPSNodeFactory() result = make_ops_ast(indexify(eval(equation).evaluate), nfops) assert str(result) == expected
def opsit(trees, count, name_to_ops_dat, block, dims): """ Given an affine tree, generate a Callable representing an OPS Kernel. Parameters ---------- tree : IterationTree IterationTree containing the loop to extract into an OPS Kernel count : int Generated kernel counters """ node_factory = OPSNodeFactory() expressions = [] expressions.extend( *[FindNodes(Expression).visit(tree.inner) for tree in trees]) ops_expressions = [ Expression(make_ops_ast(expr.expr, node_factory)) for expr in expressions ] parameters = sorted(node_factory.ops_params, key=lambda i: (i.is_Constant, i.name)) stencil_arrays_initializations = [] par_to_ops_stencil = {} for p in parameters: if isinstance(p, OpsAccessible): stencil, initialization = to_ops_stencil( p, node_factory.ops_args_accesses[p]) par_to_ops_stencil[p] = stencil stencil_arrays_initializations.append(initialization) ops_kernel = Callable(namespace['ops_kernel'](count), ops_expressions, "void", parameters) ops_par_loop_init, ops_par_loop_call = create_ops_par_loop( trees, ops_kernel, parameters, block, name_to_ops_dat, node_factory.ops_args, par_to_ops_stencil, dims) pre_time_loop = stencil_arrays_initializations + ops_par_loop_init return pre_time_loop, ops_kernel, ops_par_loop_call
def test_accesses_extraction(self, equation, expected): grid_1d = Grid(shape=(4)) grid_3d = Grid(shape=(4, 4, 4)) a = 1.43 # noqa c = 999999999999999 # noqa u = TimeFunction(name='u', grid=grid_1d, space_order=2) # noqa v = TimeFunction(name='v', grid=grid_1d, space_order=2) # noqa w = TimeFunction(name='w', grid=grid_3d, space_order=2) # noqa node_factory = OPSNodeFactory() make_ops_ast(indexify(eval(equation).evaluate), node_factory) result = eval(expected) for k, v in node_factory.ops_args_accesses.items(): assert len(v) == len(result[k.name]) for idx in result[k.name]: assert idx in v
def opsit(trees, count): """ Given an affine tree, generate a Callable representing an OPS Kernel. Parameters ---------- tree : IterationTree IterationTree containing the loop to extract into an OPS Kernel count : int Generated kernel counters """ node_factory = OPSNodeFactory() expressions = [] ops_expressions = [] for tree in trees: expressions.extend(FindNodes(Expression).visit(tree.inner)) for expr in expressions: ops_expressions.append( Expression(make_ops_ast(expr.expr, node_factory))) parameters = sorted(node_factory.ops_params, key=lambda i: (i.is_Constant, i.name)) ops_kernel = Callable(namespace['ops_kernel'](count), ops_expressions, "void", parameters) stencil_arrays_initializations = itertools.chain(*[ to_ops_stencil(p, node_factory.ops_args_accesses[p]) for p in parameters if isinstance(p, OpsAccessible) ]) pre_time_loop = stencil_arrays_initializations return pre_time_loop, ops_kernel
def opsit(trees, count): node_factory = OPSNodeFactory() expressions = [] for tree in trees: expressions.extend(FindNodes(Expression).visit(tree.inner)) it_range = [] it_dims = 0 for tree in trees: if isinstance(tree, IterationTree): it_range = [it.bounds() for it in tree] it_dims = len(tree) block = OPSBlock(namespace['ops_block'](count)) block_init = Element( cgen.Initializer( block, Call("ops_decl_block", [it_dims, String(block.name)], False))) ops_expressions = [] accesses = defaultdict(set) for i in reversed(expressions): extend_accesses(accesses, get_accesses(i.expr)) ops_expressions.insert(0, Expression(make_ops_ast(i.expr, node_factory))) ops_stencils_initializers, ops_stencils = generate_ops_stencils(accesses) to_remove = [ f.name for f in FindSymbols('defines').visit(List(body=expressions)) ] parameters = FindSymbols('symbolics').visit(List(body=ops_expressions)) parameters = [ p for p in parameters if p.name != 'OPS_ACC_size' and p.name not in to_remove ] parameters = sorted(parameters, key=lambda i: (i.is_Constant, i.name)) arguments = FindSymbols('symbolics').visit(List(body=expressions)) arguments = [a for a in arguments if a.name not in to_remove] arguments = sorted(arguments, key=lambda i: (i.is_Constant, i.name)) ops_expressions = [ Expression(fix_ops_acc(e.expr, [p.name for p in parameters])) for e in ops_expressions ] callable_kernel = Callable(namespace['ops_kernel'](count), ops_expressions, "void", parameters) dat_declarations = [] argname_to_dat = {} for a in arguments: if a.is_Constant: continue dat_dec, dat_sym = to_ops_dat(a, block) dat_declarations.extend(dat_dec) argname_to_dat.update(dat_sym) par_loop_range_arr = SymbolicArray(name=namespace['ops_range'](count), dimensions=(len(it_range) * 2, ), dtype=np.int32) range_vals = [] for mn, mx in it_range: range_vals.append(mn) range_vals.append(mx) par_loop_range_init = Expression( ClusterizedEq(Eq(par_loop_range_arr, ListInitializer(range_vals)))) ops_args = get_ops_args([p for p in parameters], ops_stencils, argname_to_dat) par_loop = Call("ops_par_loop", [ FunctionPointer(callable_kernel.name), String(callable_kernel.name), block, it_dims, par_loop_range_arr, *ops_args ]) return (callable_kernel, [par_loop_range_init, block_init] + ops_stencils_initializers + dat_declarations + [Call("ops_partition", [String("")])], List(body=[par_loop]), it_dims)