def test_call_function_with_none(self): @Function def g(x: None): return None Runtime.singleton().compile(g) self.assertEqual(g(None), None)
def test_adding_with_nones_throws(self): @TypedFunction def g(): return None + None Runtime.singleton().compile(g) with self.assertRaisesRegex(Exception, "Can't apply op Add.. to expressions of type NoneType"): g()
def test_exception_before_return_propagated(self): @TypedFunction def g(): None+None return None Runtime.singleton().compile(g) with self.assertRaisesRegex(Exception, "Can't apply op Add.. to expressions of type NoneType"): g()
def test_call_untyped_function(self): @Function def f(x): return x Runtime.singleton().compile(f) x = [] self.assertIs(f(x), x)
def test_call_other_function_with_none(self): def f(x): return x @Function def g(x: int): return f(None) Runtime.singleton().compile(g) self.assertEqual(g(1), None)
def test_call_typed_function(self): @Function def f(x): return x @Function def g(x: int): return f(x + 1) Runtime.singleton().compile(g) Runtime.singleton().compile(f) self.assertEqual(g(10), 11)
def test_call_other_untyped_function(self): def g(x): return x @TypedFunction def f(x): return g(x) Runtime.singleton().compile(f) x = [] self.assertIs(f(x), x)
def test_assign_with_none(self): def f(x): return x @Function def g(x: int): y = f(None) z = y return z Runtime.singleton().compile(g) self.assertEqual(g(1), None)
def test_specialized_entrypoint_doesnt_recompile(self): compiledAdd = SpecializedEntrypoint(add) compileCount = Runtime.singleton().timesCompiled someInts = IntList(range(1000)) someFloats = FloatList(range(1000)) for _ in range(10): compiledAdd(someInts, 1) for _ in range(10): compiledAdd(someFloats, 1) self.assertEqual(Runtime.singleton().timesCompiled - compileCount, 2)
def checkFunctionOfIntegers(self, f): r = Runtime.singleton() f_fast = r.compile(f) for i in range(100): self.assertEqual(f_fast(i), f(i))
def test_in_to_out(self): def identity(x: In) -> Out: return x compiled_identity = Runtime.singleton().compile(identity) self.assertIsInstance(compiled_identity(0.5), float) self.assertIsInstance(compiled_identity(0.0), float) self.assertIsInstance(compiled_identity(1), int)
def test_compile_class_method(self): c = AClass(x=20) t0 = time.time() uncompiled_res = c.loop(100000) uncompiled_time = time.time() - t0 Runtime.singleton().compile(AClass.loop) t0 = time.time() compiled_res = c.loop(100000) compiled_time = time.time() - t0 speedup = uncompiled_time / compiled_time self.assertGreater(speedup, 20) self.assertEqual(compiled_res, uncompiled_res) print("speedup is ", speedup) #I get about 75
def test_compile_simple(self): @TypedFunction def f(x: int) -> int: return x + x + x r = Runtime.singleton() r.compile(f.overloads[0]) self.assertEqual(f(20), 60) self.assertEqual(f(10), 30)
def test_interleaving_nones(self): def f(x,y,z): x+z return y @TypedFunction def works(x: int): return f(x,None,x) @TypedFunction def throws(x: int): return f(None,None,x) Runtime.singleton().compile(works) Runtime.singleton().compile(throws) self.assertEqual(works(1), None) with self.assertRaisesRegex(Exception, "Can't apply op Add.. to expressions of type NoneType"): throws(1)
def test_list_refcounting(self): @TypedFunction def f(x: ListOf(int), y: ListOf(int)) -> ListOf(int): return x for compileIt in [False, True]: if compileIt: Runtime.singleton().compile(f) intTup = ListOf(int)(list(range(1000))) self.assertEqual(_types.refcount(intTup), 1) res = f(intTup, intTup) self.assertEqual(_types.refcount(intTup), 2) res = None self.assertEqual(_types.refcount(intTup), 1)
def test_tuple_refcounting(self): @Function def f(x: TupleOf(int), y: TupleOf(int)) -> TupleOf(int): return x for compileIt in [False, True]: if compileIt: Runtime.singleton().compile(f) intTup = TupleOf(int)(list(range(1000))) self.assertEqual(_types.refcount(intTup), 1) res = f(intTup, intTup) self.assertEqual(_types.refcount(intTup), 2) res = None # noqa: F841 self.assertEqual(_types.refcount(intTup), 1)
def test_mutually_recursive_untyped_functions(self): def q(x): return x - 1 def z(x): return q(x) + 1 def f(x): return z(g(x - 1)) + z(g(x - 2)) + z(x) def g(x): if x > 0: return z(f(x - 1)) * z(2) + f(x - 2) return 1 g_typed = Function(g) Runtime.singleton().compile(g_typed, {'x': int}) Runtime.singleton().compile(g_typed, {'x': float}) self.assertEqual(g(10), g_typed(10)) for input in [18, 18.0]: t0 = time.time() g(input) untyped_duration = time.time() - t0 t0 = time.time() g_typed(input) typed_duration = time.time() - t0 # I get around 50x for ints and 12 for floats speedup = untyped_duration / typed_duration self.assertGreater(speedup, 20 if isinstance(input, int) else 4) print("for ", input, " speedup is ", speedup)
def test_binary_operators(self): r = Runtime.singleton() failures = 0 successes = 0 for f in [ add, sub, mul, div, mod, lshift, rshift, pow, bitxor, bitand, bitor, less, greater, lessEq, greaterEq, eq, neq ]: if f in [pow]: lvals = range(-5, 5) rvals = range(5) lvals = list(lvals) + [x * 1 for x in lvals] rvals = list(rvals) + [x * 1 for x in rvals] else: lvals = list(range(-20, 20)) rvals = lvals lvals = list(lvals) + [x / 3 for x in lvals] rvals = list(rvals) + [x / 3 for x in rvals] f_fast = r.compile(f) for val1 in lvals: for val2 in rvals: try: pyVal = f(val1, val2) except Exception: pyVal = "Exception" try: llvmVal = f_fast(val1, val2) except Exception: llvmVal = "Exception" if type(pyVal) is not type(llvmVal) or pyVal != llvmVal: print("FAILURE", f, val1, val2, pyVal, llvmVal) failures += 1 else: successes += 1 self.assertEqual(failures, 0, successes)
def checkFunction(self, f, argsToCheck): r = Runtime.singleton() f_fast = r.compile(f) t_py = 0.0 t_fast = 0.0 for a in argsToCheck: t0 = time.time() fastval = f_fast(*a) t1 = time.time() slowval = f(*a) t2 = time.time() t_py += t2 - t1 t_fast += t1 - t0 self.assertEqual(fastval, slowval) return t_py, t_fast
def Compiled(f): f = Function(f) return Runtime.singleton().compile(f)
def check(x): self.assertEqual( testfun(x), Runtime.singleton().compile(testfun, {'x': type(x)})(x) )
def test_runtime_singleton(self): self.assertTrue(Runtime.singleton() is Runtime.singleton())