def run(self): dprint_func_ir(self.func_ir, "starting hiframes") topo_order = find_topo_order(self.func_ir.blocks) for label in topo_order: self._get_reverse_copies(self.func_ir.blocks[label].body) new_body = [] for inst in self.func_ir.blocks[label].body: # df['col'] = arr if isinstance( inst, ir.StaticSetItem) and inst.target.name in self.df_vars: df_name = inst.target.name self.df_vars[df_name][inst.index] = inst.value self._update_df_cols() elif isinstance(inst, ir.Assign): out_nodes = self._run_assign(inst) if isinstance(out_nodes, list): new_body.extend(out_nodes) if isinstance(out_nodes, dict): label = include_new_blocks(self.func_ir.blocks, out_nodes, label, new_body) new_body = [] else: new_body.append(inst) self.func_ir.blocks[label].body = new_body self.func_ir._definitions = get_definitions(self.func_ir.blocks) self.func_ir.df_cols = self.df_cols #remove_dead(self.func_ir.blocks, self.func_ir.arg_names) dprint_func_ir(self.func_ir, "after hiframes") if numba.config.DEBUG_ARRAY_OPT == 1: print("df_vars: ", self.df_vars) return
def get_stencil_accesses(parfor, typemap): # if a parfor has stencil pattern, see which accesses depend on loop index # XXX: assuming loop index is not used for non-stencil arrays # TODO support recursive parfor, multi-D, mutiple body blocks # no access if not stencil is_stencil = False for pattern in parfor.patterns: if pattern[0] == 'stencil': is_stencil = True neighborhood = pattern[1] if not is_stencil: return {}, None par_index_var = parfor.loop_nests[0].index_variable body = parfor.loop_body body_defs = get_definitions(body) stencil_accesses = {} for block in body.values(): for stmt in block.body: if isinstance(stmt, ir.Assign) and isinstance(stmt.value, ir.Expr): lhs = stmt.target.name rhs = stmt.value if (rhs.op == 'getitem' and is_array(rhs.value.name, typemap) and vars_dependent(body_defs, rhs.index, par_index_var)): stencil_accesses[rhs.index.name] = rhs.value.name return stencil_accesses, neighborhood
def run(self): blocks = self.func_ir.blocks call_table, _ = ir_utils.get_call_table(blocks) topo_order = find_topo_order(blocks) for label in topo_order: new_body = [] for inst in blocks[label].body: if isinstance(inst, ir.Assign): out_nodes = self._run_assign(inst, call_table) if isinstance(out_nodes, list): new_body.extend(out_nodes) if isinstance(out_nodes, dict): label = include_new_blocks(blocks, out_nodes, label, new_body) new_body = [] if isinstance(out_nodes, tuple): gen_blocks, post_nodes = out_nodes label = include_new_blocks(blocks, gen_blocks, label, new_body) new_body = post_nodes else: new_body.append(inst) blocks[label].body = new_body self.func_ir._definitions = get_definitions(self.func_ir.blocks) return
def run(self): dprint_func_ir(self.func_ir, "starting IO") topo_order = find_topo_order(self.func_ir.blocks) for label in topo_order: new_body = [] # copies are collected before running the pass since # variables typed in locals are assigned late self._get_reverse_copies(self.func_ir.blocks[label].body) for inst in self.func_ir.blocks[label].body: if isinstance(inst, ir.Assign): inst_list = self._run_assign(inst) new_body.extend(inst_list) elif isinstance(inst, ir.StaticSetItem): inst_list = self._run_static_setitem(inst) new_body.extend(inst_list) else: new_body.append(inst) self.func_ir.blocks[label].body = new_body # iterative remove dead to make sure all extra code (e.g. df vars) is removed while remove_dead(self.func_ir.blocks, self.func_ir.arg_names, self.func_ir): pass self.func_ir._definitions = get_definitions(self.func_ir.blocks) dprint_func_ir(self.func_ir, "after IO") if debug_prints(): print("h5 files: ", self.h5_files) print("h5 dsets: ", self.h5_dsets)
def run(self): dprint_func_ir(self.func_ir, "starting hiframes") topo_order = find_topo_order(self.func_ir.blocks) for label in topo_order: new_body = [] for inst in self.func_ir.blocks[label].body: # df['col'] = arr if isinstance(inst, ir.StaticSetItem) and inst.target.name in self.df_vars: df_name = inst.target.name self.df_vars[df_name][inst.index] = inst.value self._update_df_cols() elif isinstance(inst, ir.Assign): out_nodes = self._run_assign(inst) if isinstance(out_nodes, list): new_body.extend(out_nodes) if isinstance(out_nodes, dict): label = include_new_blocks(self.func_ir.blocks, out_nodes, label, new_body) new_body = [] else: new_body.append(inst) self.func_ir.blocks[label].body = new_body self.func_ir._definitions = get_definitions(self.func_ir.blocks) #remove_dead(self.func_ir.blocks, self.func_ir.arg_names) if config._has_h5py: io_pass = pio.PIO(self.func_ir, self.locals) io_pass.run() remove_dead(self.func_ir.blocks, self.func_ir.arg_names) DummyFlags = namedtuple('DummyFlags', 'auto_parallel') inline_pass = InlineClosureCallPass(self.func_ir, DummyFlags(True)) inline_pass.run() self.typemap, self.return_type, self.calltypes = numba_compiler.type_inference_stage( self.typingctx, self.func_ir, self.args, None) self.fixes_after_typing(self.func_ir.blocks) self.func_ir._definitions = get_definitions(self.func_ir.blocks) dprint_func_ir(self.func_ir, "after hiframes") if numba.config.DEBUG_ARRAY_OPT==1: print("df_vars: ", self.df_vars) return
def inline_calls(func_ir): call_table, _ = ir_utils.get_call_table(func_ir.blocks) for label, block in func_ir.blocks.items(): for i, stmt in enumerate(block.body): if isinstance(stmt, ir.Assign): rhs = stmt.value if isinstance(rhs, ir.Expr) and rhs.op == 'call': func = rhs.func.name if (func in call_table and call_table[func] and isinstance( call_table[func][0], CPUDispatcher)): py_func = call_table[func][0].py_func inline_calls_inner(func_ir, block, stmt, i, py_func) return # inline_calls_inner will call back recursively func_ir._definitions = get_definitions(func_ir.blocks)
def run(self): dprint_func_ir(self.func_ir, "starting IO") topo_order = find_topo_order(self.func_ir.blocks) for label in topo_order: new_body = [] # copies are collected before running the pass since # variables typed in locals are assigned late self._get_reverse_copies(self.func_ir.blocks[label].body) for inst in self.func_ir.blocks[label].body: if isinstance(inst, ir.Assign): inst_list = self._run_assign(inst) new_body.extend(inst_list) elif isinstance(inst, ir.StaticSetItem): inst_list = self._run_static_setitem(inst) new_body.extend(inst_list) else: new_body.append(inst) self.func_ir.blocks[label].body = new_body remove_dead(self.func_ir.blocks, self.func_ir.arg_names) self.func_ir._definitions = get_definitions(self.func_ir.blocks) dprint_func_ir(self.func_ir, "after IO") if config.DEBUG_ARRAY_OPT == 1: print("h5 files: ", self.h5_files) print("h5 dsets: ", self.h5_dsets)
def run(self): blocks = self.func_ir.blocks topo_order = find_topo_order(blocks) for label in topo_order: new_body = [] for inst in blocks[label].body: if isinstance(inst, ir.Assign): out_nodes = self._run_assign(inst) if isinstance(out_nodes, list): new_body.extend(out_nodes) if isinstance(out_nodes, dict): label = include_new_blocks(blocks, out_nodes, label, new_body) new_body = [] if isinstance(out_nodes, tuple): gen_blocks, post_nodes = out_nodes label = include_new_blocks(blocks, gen_blocks, label, new_body) new_body = post_nodes else: new_body.append(inst) blocks[label].body = new_body if debug_prints(): # pragma: no cover print("--- types before Series replacement:", self.typemap) print("calltypes: ", self.calltypes) replace_series = {} for vname, typ in self.typemap.items(): if isinstance(typ, SeriesType): # print("replacing series type", vname) new_typ = series_to_array_type(typ) replace_series[vname] = new_typ # replace array.call() variable types if isinstance(typ, types.BoundFunction) and isinstance( typ.this, SeriesType): this = series_to_array_type(typ.this) # TODO: handle string arrays, etc. assert typ.typing_key.startswith('array.') attr = typ.typing_key[len('array.'):] resolver = getattr(ArrayAttribute, 'resolve_' + attr) # methods are either installed with install_array_method or # using @bound_function in arraydecl.py if hasattr(resolver, '__wrapped__'): resolver = bound_function(typ.typing_key)( resolver.__wrapped__) new_typ = resolver(ArrayAttribute(self.typingctx), this) replace_series[vname] = new_typ for vname, typ in replace_series.items(): self.typemap.pop(vname) self.typemap[vname] = typ replace_calltype = {} # replace sig of getitem/setitem/... series type with array for call, sig in self.calltypes.items(): if sig is None: continue assert isinstance(sig, Signature) sig.return_type = if_series_to_array_type(sig.return_type) sig.args = tuple(map(if_series_to_array_type, sig.args)) # XXX: side effect: force update of call signatures if isinstance(call, ir.Expr) and call.op == 'call': # StencilFunc requires kws for typing so sig.args can't be used # reusing sig.args since some types become Const in sig argtyps = sig.args[:len(call.args)] kwtyps = {name: self.typemap[v.name] for name, v in call.kws} new_sig = self.typemap[call.func.name].get_call_type( self.typingctx, argtyps, kwtyps) # calltypes of things like BoundFunction (array.call) need to # be update for lowering to work # XXX: new_sig could be None for things like np.int32() if call in self.calltypes and new_sig is not None: old_sig = self.calltypes[call] # fix types with undefined dtypes in empty_inferred, etc. return_type = _fix_typ_undefs(new_sig.return_type, old_sig.return_type) args = tuple( _fix_typ_undefs(a, b) for a, b in zip(new_sig.args, old_sig.args)) replace_calltype[call] = Signature(return_type, args, new_sig.recvr, new_sig.pysig) for call, sig in replace_calltype.items(): self.calltypes.pop(call) self.calltypes[call] = sig if debug_prints(): # pragma: no cover print("--- types after Series replacement:", self.typemap) print("calltypes: ", self.calltypes) self.func_ir._definitions = get_definitions(self.func_ir.blocks) return if_series_to_unbox(self.return_type)