def test_test1(self): typingctx = typing.Context() targetctx = cpu.CPUContext(typingctx) test_ir = compiler.run_frontend(test1) with cpu_target.nested_context(typingctx, targetctx): one_arg = numba.types.npytypes.Array( numba.types.scalars.Float(name="float64"), 1, 'C') args = (one_arg, one_arg, one_arg, one_arg, one_arg) tp = TestPipeline(typingctx, targetctx, args, test_ir) numba.rewrites.rewrite_registry.apply('before-inference', tp, tp.func_ir) tp.typemap, tp.return_type, tp.calltypes = compiler.type_inference_stage( tp.typingctx, tp.func_ir, tp.args, None) type_annotation = type_annotations.TypeAnnotation( func_ir=tp.func_ir, typemap=tp.typemap, calltypes=tp.calltypes, lifted=(), lifted_from=None, args=tp.args, return_type=tp.return_type, html_output=config.HTML) numba.rewrites.rewrite_registry.apply('after-inference', tp, tp.func_ir) parfor_pass = numba.parfor.ParforPass(tp.func_ir, tp.typemap, tp.calltypes, tp.return_type, tp.typingctx) parfor_pass.run() self.assertTrue(countParfors(test_ir) == 1)
def test_use_car_move(self): tyctx = typing.Context() tyctx.insert_class(Car, self.carattrs) cgctx = CPUContext(tyctx) cgctx.insert_class(Car, self.carattrs) car_object = types.Object(Car) argtys = (car_object, types.int32) flags = compiler.Flags() cr = compiler.compile_extra(tyctx, cgctx, use_car_move, args=argtys, return_type=None, flags=flags, locals={}) func = cr.entry_point if cr.typing_error: raise cr.typing_error car1 = Car(value=123) car2 = Car(value=123) self.assertEqual(use_car_move(car1, 321), func(car2, 321)) def bm_python(): use_car_move(car1, 321) def bm_numba(): func(car2, 321) python = utils.benchmark(bm_python, maxsec=.1) numba = utils.benchmark(bm_numba, maxsec=.1) print(python) print(numba)
def mk_range_block(typemap, start, stop, step, calltypes, scope, loc): """make a block that initializes loop range and iteration variables. target label in jump needs to be set. """ # g_range_var = Global(range) g_range_var = ir.Var(scope, mk_unique_var("$range_g_var"), loc) typemap[g_range_var.name] = get_global_func_typ(range) g_range = ir.Global('range', range, loc) g_range_assign = ir.Assign(g_range, g_range_var, loc) arg_nodes, args = _mk_range_args(typemap, start, stop, step, scope, loc) # range_call_var = call g_range_var(start, stop, step) range_call = ir.Expr.call(g_range_var, args, (), loc) calltypes[range_call] = typemap[g_range_var.name].get_call_type( typing.Context(), [types.intp] * len(args), {}) #signature(types.range_state64_type, types.intp) range_call_var = ir.Var(scope, mk_unique_var("$range_c_var"), loc) typemap[range_call_var.name] = types.iterators.RangeType(types.intp) range_call_assign = ir.Assign(range_call, range_call_var, loc) # iter_var = getiter(range_call_var) iter_call = ir.Expr.getiter(range_call_var, loc) calltypes[iter_call] = signature(types.range_iter64_type, types.range_state64_type) iter_var = ir.Var(scope, mk_unique_var("$iter_var"), loc) typemap[iter_var.name] = types.iterators.RangeIteratorType(types.intp) iter_call_assign = ir.Assign(iter_call, iter_var, loc) # $phi = iter_var phi_var = ir.Var(scope, mk_unique_var("$phi"), loc) typemap[phi_var.name] = types.iterators.RangeIteratorType(types.intp) phi_assign = ir.Assign(iter_var, phi_var, loc) # jump to header jump_header = ir.Jump(-1, loc) range_block = ir.Block(scope, loc) range_block.body = arg_nodes + [g_range_assign, range_call_assign, iter_call_assign, phi_assign, jump_header] return range_block
def test1(self): typingctx = typing.Context() targetctx = cpu.CPUContext(typingctx) test_ir = compiler.run_frontend(test_will_propagate) #print("Num blocks = ", len(test_ir.blocks)) #print(test_ir.dump()) with cpu_target.nested_context(typingctx, targetctx): typingctx.refresh() targetctx.refresh() args = (types.int64, types.int64, types.int64) typemap, return_type, calltypes = compiler.type_inference_stage(typingctx, test_ir, args, None) #print("typemap = ", typemap) #print("return_type = ", return_type) type_annotation = type_annotations.TypeAnnotation( func_ir=test_ir, typemap=typemap, calltypes=calltypes, lifted=(), lifted_from=None, args=args, return_type=return_type, html_output=config.HTML) remove_dels(test_ir.blocks) in_cps, out_cps = copy_propagate(test_ir.blocks, typemap) apply_copy_propagate(test_ir.blocks, in_cps, get_name_var_table(test_ir.blocks), typemap, calltypes) remove_dead(test_ir.blocks, test_ir.arg_names, test_ir) self.assertFalse(findLhsAssign(test_ir, "x"))
def mk_alloc(typemap, calltypes, lhs, size_var, dtype, scope, loc): """generate an array allocation with np.empty() and return list of nodes. size_var can be an int variable or tuple of int variables. """ out = [] ndims = 1 size_typ = types.intp if isinstance(size_var, tuple): if len(size_var) == 1: size_var = size_var[0] size_var = convert_size_to_var(size_var, typemap, scope, loc, out) else: # tuple_var = build_tuple([size_var...]) ndims = len(size_var) tuple_var = ir.Var(scope, mk_unique_var("$tuple_var"), loc) if typemap: typemap[tuple_var.name] = types.containers.UniTuple( types.intp, ndims) # constant sizes need to be assigned to vars new_sizes = [ convert_size_to_var(s, typemap, scope, loc, out) for s in size_var ] tuple_call = ir.Expr.build_tuple(new_sizes, loc) tuple_assign = ir.Assign(tuple_call, tuple_var, loc) out.append(tuple_assign) size_var = tuple_var size_typ = types.containers.UniTuple(types.intp, ndims) # g_np_var = Global(numpy) g_np_var = ir.Var(scope, mk_unique_var("$np_g_var"), loc) if typemap: typemap[g_np_var.name] = types.misc.Module(numpy) g_np = ir.Global('np', numpy, loc) g_np_assign = ir.Assign(g_np, g_np_var, loc) # attr call: empty_attr = getattr(g_np_var, empty) empty_attr_call = ir.Expr.getattr(g_np_var, "empty", loc) attr_var = ir.Var(scope, mk_unique_var("$empty_attr_attr"), loc) if typemap: typemap[attr_var.name] = get_np_ufunc_typ(numpy.empty) attr_assign = ir.Assign(empty_attr_call, attr_var, loc) # alloc call: lhs = empty_attr(size_var, typ_var) typ_var = ir.Var(scope, mk_unique_var("$np_typ_var"), loc) if typemap: typemap[typ_var.name] = types.functions.NumberClass(dtype) # assuming str(dtype) returns valid np dtype string np_typ_getattr = ir.Expr.getattr(g_np_var, str(dtype), loc) typ_var_assign = ir.Assign(np_typ_getattr, typ_var, loc) alloc_call = ir.Expr.call(attr_var, [size_var, typ_var], (), loc) if calltypes: calltypes[alloc_call] = typemap[attr_var.name].get_call_type( typing.Context(), [size_typ, types.functions.NumberClass(dtype)], {}) # signature( # types.npytypes.Array(dtype, ndims, 'C'), size_typ, # types.functions.NumberClass(dtype)) alloc_assign = ir.Assign(alloc_call, lhs, loc) out.extend([g_np_assign, attr_assign, typ_var_assign, alloc_assign]) return out
def literal_type(self): if self._literal_type_cache is None: from numba import typing ctx = typing.Context() res = ctx.resolve_value_type(self.literal_value) self._literal_type_cache = res return self._literal_type_cache
def find_op_typ(op, arg_typs): for ft in typing.templates.builtin_registry.functions: if ft.key == op: func_typ = types.Function(ft).get_call_type(typing.Context(), arg_typs, {}) if func_typ is not None: return func_typ raise RuntimeError("unknown array operation")
def compile_isolated(func, args, return_type=None, flags=DEFAULT_FLAGS, locals={}): """ Compile the function is an isolated environment. Good for testing. """ typingctx = typing.Context() targetctx = cpu.CPUContext(typingctx) return compile_extra(typingctx, targetctx, func, args, return_type, flags, locals)
def test_integer(self): ctx = typing.Context() for aty, bty in itertools.product(types.integer_domain, types.integer_domain): key = (str(aty), str(bty)) try: expected = self.int_unify[key] except KeyError: expected = self.int_unify[key[::-1]] self.assert_unify(aty, bty, getattr(types, expected))
def mk_pipeline(cls, args, return_type=None, flags=None, locals={}, library=None, typing_context=None, target_context=None): if not flags: flags = Flags() flags.nrt = True if typing_context is None: typing_context = typing.Context() if target_context is None: target_context = cpu.CPUContext(typing_context) return cls(typing_context, target_context, library, args, return_type, flags, locals)
def assert_unify(self, aty, bty, expected): ctx = typing.Context() template = "{0}, {1} -> {2} != {3}" unified = ctx.unify_types(aty, bty) self.assertEqual(unified, expected, msg=template.format(aty, bty, unified, expected)) unified = ctx.unify_types(bty, aty) self.assertEqual(unified, expected, msg=template.format(bty, aty, unified, expected))
def assert_unify(self, aty, bty, expected): ctx = typing.Context() template = "{0}, {1} -> {2} != {3}" for unify_func in ctx.unify_types, ctx.unify_pairs: unified = unify_func(aty, bty) self.assertEqual(unified, expected, msg=template.format(aty, bty, unified, expected)) unified = unify_func(bty, aty) self.assertEqual(unified, expected, msg=template.format(bty, aty, unified, expected))
def compile_isolated(func, args, return_type=None, flags=DEFAULT_FLAGS, locals={}): """ Compile the function in an isolated environment (typing and target context). Good for testing. """ from .targets.registry import cpu_target typingctx = typing.Context() targetctx = cpu.CPUContext(typingctx) # Register the contexts in case for nested @jit or @overload calls with cpu_target.nested_context(typingctx, targetctx): return compile_extra(typingctx, targetctx, func, args, return_type, flags, locals)
def unify_pair_test(self, n): """ Test all permutations of N-combinations of numeric types and ensure that the unification matches """ ctx = typing.Context() for tys in itertools.combinations(types.number_domain, n): res = [ctx.unify_types(*comb) for comb in itertools.permutations(tys)] # All result must be equal first_result = res[0] for other in res[1:]: self.assertEqual(first_result, other)
def test_unify_to_optional(self): """Test unification to optional type """ ctx = typing.Context() for tys in itertools.combinations(types.number_domain, 2): tys = list(tys) + [types.none] res = [ctx.unify_types(*comb) for comb in itertools.permutations(tys)] # All result must be equal first_result = res[0] self.assertIsInstance(first_result, types.Optional) for other in res[1:]: self.assertEqual(first_result, other)
def test_ambiguous_error(self): ctx = typing.Context() cases = [i16(i16, i16), i32(i32, i32)] with self.assertRaises(TypeError) as raises: ctx.resolve_overload("foo", cases, (i8, i8), {}, allow_ambiguous=False) self.assertEqual( str(raises.exception).splitlines(), [ "Ambiguous overloading for foo (int8, int8):", "(int16, int16) -> int16", "(int32, int32) -> int32", ])
def countParfors(test_func, args, **kws): typingctx = typing.Context() targetctx = cpu.CPUContext(typingctx) test_ir = compiler.run_frontend(test_func) if kws: options = cpu.ParallelOptions(kws) else: options = cpu.ParallelOptions(True) with cpu_target.nested_context(typingctx, targetctx): tp = TestPipeline(typingctx, targetctx, args, test_ir) inline_pass = inline_closurecall.InlineClosureCallPass( tp.func_ir, options) inline_pass.run() numba.rewrites.rewrite_registry.apply('before-inference', tp, tp.func_ir) tp.typemap, tp.return_type, tp.calltypes = compiler.type_inference_stage( tp.typingctx, tp.func_ir, tp.args, None) type_annotations.TypeAnnotation(func_ir=tp.func_ir, typemap=tp.typemap, calltypes=tp.calltypes, lifted=(), lifted_from=None, args=tp.args, return_type=tp.return_type, html_output=config.HTML) preparfor_pass = numba.parfor.PreParforPass(tp.func_ir, tp.typemap, tp.calltypes, tp.typingctx, options) preparfor_pass.run() numba.rewrites.rewrite_registry.apply('after-inference', tp, tp.func_ir) parfor_pass = numba.parfor.ParforPass(tp.func_ir, tp.typemap, tp.calltypes, tp.return_type, tp.typingctx, options) parfor_pass.run() ret_count = 0 for label, block in test_ir.blocks.items(): for i, inst in enumerate(block.body): if isinstance(inst, numba.parfor.Parfor): ret_count += 1 return ret_count
def _context_builder_sig_args(self): typing_context = typing.Context() context = cpu.CPUContext(typing_context) module = lc.Module("test_module") sig = typing.signature(types.int32, types.int32) llvm_fnty = context.call_conv.get_function_type( sig.return_type, sig.args) function = module.get_or_insert_function(llvm_fnty, name='test_fn') args = context.call_conv.get_arguments(function) assert function.is_declaration entry_block = function.append_basic_block('entry') builder = lc.Builder(entry_block) return context, builder, sig, args
def test_cache(self): def times2(i): return 2 * i def times3(i): return i * 3 i32 = lc.Type.int(32) llvm_fnty = lc.Type.function(i32, [i32]) module = lc.Module.new("test_module") function = module.get_or_insert_function(llvm_fnty, name='test_fn') assert function.is_declaration entry_block = function.append_basic_block('entry') builder = lc.Builder.new(entry_block) sig = typing.signature(types.int32, types.int32) typing_context = typing.Context() context = cpu.CPUContext(typing_context) # Ensure the cache is empty to begin with self.assertEqual(0, len(context.cached_internal_func)) # After one compile, it should contain one entry context.compile_internal(builder, times2, sig, function.args) self.assertEqual(1, len(context.cached_internal_func)) # After a second compilation of the same thing, it should still contain # one entry context.compile_internal(builder, times2, sig, function.args) self.assertEqual(1, len(context.cached_internal_func)) # After compilation of another function, the cache should have grown by # one more. context.compile_internal(builder, times3, sig, function.args) self.assertEqual(2, len(context.cached_internal_func)) sig2 = typing.signature(types.float64, types.float64) f64 = lc.Type.double() llvm_fnty2 = lc.Type.function(f64, [f64]) function2 = module.get_or_insert_function(llvm_fnty2, name='test_fn_2') assert function2.is_declaration entry_block2 = function2.append_basic_block('entry') builder2 = lc.Builder.new(entry_block2) # Ensure that the same function with a different signature does not # reuse an entry from the cache in error context.compile_internal(builder2, times3, sig2, function2.args) self.assertEqual(3, len(context.cached_internal_func))
def test_none_to_optional(self): """ Test unification of `none` and multiple number types to optional type """ ctx = typing.Context() for tys in itertools.combinations(types.number_domain, 2): # First unify without none, to provide the control value tys = list(tys) expected = types.Optional(ctx.unify_types(*tys)) results = [ ctx.unify_types(*comb) for comb in itertools.permutations(tys + [types.none]) ] # All results must be equal for res in results: self.assertEqual(res, expected)
def unify_number_pair_test(self, n): """ Test all permutations of N-combinations of numeric types and ensure that the order of types in the sequence is irrelevant. """ ctx = typing.Context() for tys in itertools.combinations(types.number_domain, n): res = [ ctx.unify_types(*comb) for comb in itertools.permutations(tys) ] first_result = res[0] # Sanity check self.assertIsInstance(first_result, types.Number) # All results must be equal for other in res[1:]: self.assertEqual(first_result, other)
def impala_typing_context(): base = typing.Context() _register_impala_numeric_type_conversions(base) _register_impala_other_type_conversions(base) for (gv, gty) in _globals: base.insert_global(gv, gty) for func in _functions: base.insert_function(func(base)) for attr in _attributes: base.insert_attributes(attr(base)) return base
def impala_typing_context(): base = typing.Context() base.insert_global(BooleanVal, BooleanValType) base.insert_function(BooleanValCtor(base)) base.insert_attributes(BooleanValValueAttr(base)) base.insert_attributes(BooleanValTypeAttr(base)) base.insert_global(TinyIntVal, TinyIntValType) base.insert_function(TinyIntValCtor(base)) base.insert_attributes(TinyIntValValueAttr(base)) base.insert_attributes(TinyIntValTypeAttr(base)) base.insert_global(SmallIntVal, SmallIntValType) base.insert_function(SmallIntValCtor(base)) base.insert_attributes(SmallIntValValueAttr(base)) base.insert_attributes(SmallIntValTypeAttr(base)) base.insert_global(IntVal, IntValType) base.insert_function(IntValCtor(base)) base.insert_attributes(IntValValueAttr(base)) base.insert_attributes(IntValTypeAttr(base)) base.insert_global(BigIntVal, BigIntValType) base.insert_function(BigIntValCtor(base)) base.insert_attributes(BigIntValValueAttr(base)) base.insert_attributes(BigIntValTypeAttr(base)) base.insert_global(FloatVal, FloatValType) base.insert_function(FloatValCtor(base)) base.insert_attributes(FloatValValueAttr(base)) base.insert_attributes(FloatValTypeAttr(base)) base.insert_global(DoubleVal, DoubleValType) base.insert_function(DoubleValCtor(base)) base.insert_attributes(DoubleValValueAttr(base)) base.insert_attributes(DoubleValTypeAttr(base)) return base
def __init__(self): self.typingctx = typing.Context() self.targetctx = cpu.CPUContext(self.typingctx) self.cr_cache = {}
def test_convert_number_types(self): # Check that Context.can_convert() is compatible with the default # number conversion rules registered in the typeconv module # (which is used internally by the C _Dispatcher object). ctx = typing.Context() self.check_number_compatibility(ctx.can_convert)
def assert_resolve_overload(self, cases, args, expected): ctx = typing.Context() got = ctx.resolve_overload("foo", cases, args, {}) self.assertEqual(got, expected)
def setUp(self): typing_context = typing.Context() self.context = cpu.CPUContext(typing_context)
def test_integer(self): ctx = typing.Context() for ut, st in itertools.product(types.integer_domain, types.integer_domain): unified = ctx.unify_types(ut, st) self._check_unify(ut, st, unified)
def setUp(self): super(BaseTestWithLifting, self).setUp() self.typingctx = typing.Context() self.targetctx = cpu.CPUContext(self.typingctx) self.flags = DEFAULT_FLAGS
class CPUTarget(TargetDescriptor): options = cpu.CPUTargetOptions typing_context = typing.Context() target_context = cpu.CPUContext(typing_context)