def test_clinker_literal_cache(): mode = aesara.Mode(linker="c") A = aesara.tensor.matrix() input1 = aesara.tensor.vector() normal_svd = np.array( [ [5.936276e01, -4.664007e-07, -2.56265e-06], [-4.664007e-07, 9.468691e-01, -3.18862e-02], [-2.562651e-06, -3.188625e-02, 1.05226e00], ], dtype=aesara.config.floatX, ) orientationi = np.array([59.36276866, 1.06116353, 0.93797339], dtype=aesara.config.floatX) for out1 in [A - input1[0] * np.identity(3), input1[0] * np.identity(3)]: benchmark = aesara.function(inputs=[A, input1], outputs=[out1], on_unused_input="ignore", mode=mode) out1 = benchmark(normal_svd, orientationi)
def test_borrow_output(self): a = tt.dmatrix() f = function([a], Out(a, borrow=False)) o = np.ones((3, 3)) assert o is not f(o) # function no longer permits aliasing outputs to inputs f = function([a], Out(a * 4, borrow=False)) o = np.ones((3, 3)) four = f(o) assert np.all(four == 4) f(o + 0.1) # should not clobber the memory used to store four assert np.all(four == 4) f = function( [a], Out(a * 4, borrow=True), mode=aesara.Mode("c|py_nogc", "fast_run") ) o = np.ones((3, 3)) four = f(o) assert np.all(four == 4) f(o + 0.1) # should clobber the memory used to store four if aesara.config.cxx: assert not np.all(four == 4) else: # The Elemwise.perform method don't reuse memory # as some numpy version don't support that correctly. assert np.all(four == 4)
def test_reallocation(): x = tensor.scalar("x") y = tensor.scalar("y") z = tensor.tanh(3 * x + y) + tensor.cosh(x + 5 * y) # The functinality is currently implement for non lazy and non c VM only. for linker in [ vm.VM_Linker(allow_gc=False, lazy=False, use_cloop=False), vm.VM_Linker(allow_gc=True, lazy=False, use_cloop=False), ]: m = aesara.compile.get_mode(aesara.Mode(linker=linker)) m = m.excluding("fusion", "inplace") f = aesara.function([x, y], z, name="test_reduce_memory", mode=m) output = f(1, 2) assert output storage_map = f.fn.storage_map def check_storage(storage_map): from aesara.tensor.var import TensorConstant for i in storage_map: if not isinstance(i, TensorConstant): keys_copy = list(storage_map.keys())[:] keys_copy.remove(i) for o in keys_copy: if storage_map[i][ 0] and storage_map[i][0] is storage_map[o][0]: return [True, storage_map[o][0]] return [False, None] assert check_storage(storage_map)[0] assert len({id(v) for v in storage_map.values()}) < len(storage_map)
def test_grad_abs(): a = aesara.tensor.fscalar("a") b = aesara.tensor.nnet.relu(a) c = aesara.grad(b, a) f = aesara.function([a], c, mode=aesara.Mode(optimizer=None)) # Currently Aesara return 0.5, but it isn't sure it won't change # in the futur. ret = f(0.0) assert ret == 0.5, ret
def test_no_recycling(): x = aesara.tensor.vector() for lnk in [ vm.VM_Linker(use_cloop=True), vm.VM_Linker(use_cloop=False, lazy=True), vm.VM_Linker(use_cloop=False, lazy=False, allow_gc=True), vm.VM_Linker(use_cloop=False, lazy=False, allow_gc=False), ]: mode = aesara.Mode(optimizer="fast_compile", linker=lnk) f = aesara.function([x], x + 1, mode=mode) f2 = aesara.function([x], (x + 1) * 2, mode=mode) m1 = f.fn.thunks[0].thunk.module m2 = f2.fn.thunks[0].thunk.module assert m1 is m2
def test_vm_gc(): # This already caused a bug in the trunk of Aesara. # # The bug was introduced in the trunk on July 5th, 2012 and fixed on # July 30th. x = aesara.tensor.vector() p = RunOnce()(x) mode = aesara.Mode(linker=aesara.gof.vm.VM_Linker(lazy=True)) f = aesara.function([aesara.In(x, mutable=True)], [p + 1, p + 2], mode=mode) f([1, 2, 3]) p = RunOnce()(x) pp = p + p f = aesara.function([x], [pp + pp], mode=mode) f([1, 2, 3])
def _get_func(self): """ Return a function that makes a value from an integer. The integer value is assumed to be a valid pointer for the type and no check is done to ensure that. """ from aesara.scalar import get_scalar_type if self._fn is None: with change_flags(compute_test_value="off"): v = get_scalar_type("int64")() self._fn = aesara.function( [v], _make_cdata(self)(v), mode=aesara.Mode(optimizer=None), profile=False, ) return self._fn
def test_sort_schedule_fn(): import aesara from aesara.gof.sched import make_depends, sort_schedule_fn x = aesara.tensor.matrix("x") y = aesara.tensor.dot(x[:5] * 2, x.T + 1).T def str_cmp(a, b): return cmp(str(a), str(b)) # lexicographical sort linker = aesara.OpWiseCLinker(schedule=sort_schedule_fn(str_cmp)) mode = aesara.Mode(linker=linker) f = aesara.function((x, ), (y, ), mode=mode) nodes = f.maker.linker.make_all()[-1] depends = make_depends() for a, b in zip(nodes[:-1], nodes[1:]): if not depends((b, a)): assert str(a) < str(b)
def speed(self): n_calls = 20000 print("n_calls", n_calls) for border_mode in ["valid", "full"]: print() print(border_mode) for openmp in [False, True]: print("OpenMP", openmp) image_shapes = [(1, 5, 6, 6), (10, 5, 6, 6) # (10, 10, 16, 16), # (10, 10, 32, 32)] ] print("image_shape", image_shapes) for image_shape in image_shapes: filter_shapes = [(1, 5, 4, 4), (2, 5, 4, 4), (5, 5, 4, 4)] print("filter_shapes", filter_shapes) for filter_shape in filter_shapes: input = aesara.shared(np.random.random(image_shape)) filters = aesara.shared(np.random.random(filter_shape)) output = self.conv2d( input, filters, image_shape, filter_shape, border_mode, unroll_patch=True, openmp=openmp, ) mode = aesara.Mode(linker=aesara.gof.vm.VM_Linker( allow_gc=False, use_cloop=True)) aesara_conv = aesara.function([], output, mode=mode) t1 = time.time() aesara_conv.fn(n_calls=n_calls) t2 = time.time() print(t2 - t1, end=" ") print()
def test_argtopk_1d_collision(self, size, k, dtype, sorted): # with non-unique kth max value if isinstance(k, str): k = eval(k.replace("n", str(size))) x = aesara.tensor.vector(name="x", dtype=dtype) y = argtopk(x, k, sorted=sorted, idx_dtype="int32") # DebugMode won't like the index change on collision on CPU # So don't use DebugMode here. mode = self.mode if isinstance(self.mode, aesara.compile.DebugMode): mode = aesara.Mode(optimizer=mode.optimizer) fn = aesara.function([x], y, mode=mode) assert any([ isinstance(n.op, self.op_class) for n in fn.maker.fgraph.apply_nodes ]) xval = np.repeat( np.random.uniform(-100.0, 100.0, size=size // 2).astype(dtype), 2) xval = xval[np.random.permutation(size)] yval = fn(xval) idx = slice(-k, None) if k > 0 else slice(-k) goal = np.argsort(xval)[idx].astype("int32") utt.assert_allclose(np.sort(xval[yval]), np.sort(xval[goal]))
import aesara from aesara import change_flags from aesara.gof.sched import sort_schedule_fn from aesara.tensor.io import ( MPISend, MPISendWait, mpi_cmps, mpi_enabled, mpi_send_wait_cmp, recv, send, ) mpi_scheduler = sort_schedule_fn(*mpi_cmps) mpi_linker = aesara.OpWiseCLinker(schedule=mpi_scheduler) mpi_mode = aesara.Mode(linker=mpi_linker) @change_flags(compute_test_value="off") def test_recv(): x = recv((10, 10), "float64", 0, 11) assert x.dtype == "float64" assert x.broadcastable == (False, False) recvnode = x.owner.inputs[0].owner assert recvnode.op.source == 0 assert recvnode.op.tag == 11 def test_send(): x = aesara.tensor.matrix("x")
def test_gc_never_pickles_temporaries(): x = tt.dvector() r = x for i in range(2): # TODO: 30 causes like LONG compilation due to MERGE r = r + r / 10 optimizer = None optimizer = "fast_run" for f_linker, g_linker in [ (aesara.PerformLinker(allow_gc=True), aesara.PerformLinker(allow_gc=False)), (aesara.OpWiseCLinker(allow_gc=True), aesara.OpWiseCLinker(allow_gc=False)), ]: # f_linker has garbage collection # g_linker has no garbage collection f = aesara.function([x], r, mode=aesara.Mode(optimizer=optimizer, linker=f_linker)) g = aesara.function([x], r, mode=aesara.Mode(optimizer=optimizer, linker=g_linker)) pre_f = pickle.dumps(f) # pre_g = pickle.dumps(g) len_pre_f = len(pre_f) # len_pre_g = len(pre_g) # We can't compare the content or the length of the string # between f and g. 2 reason, we store some timming information # in float. They won't be the same each time. Different float # can have different length when printed. def a(fn): return len(pickle.dumps(fn.maker)) assert a(f) == a(f) # some sanity checks on the pickling mechanism assert a(g) == a(g) # some sanity checks on the pickling mechanism def b(fn): return len( pickle.dumps( aesara.compile.function_module._pickle_Function(fn))) assert b(f) == b(f) # some sanity checks on the pickling mechanism def c(fn): return len(pickle.dumps(fn)) assert c(f) == c(f) # some sanity checks on the pickling mechanism assert c(g) == c(g) # some sanity checks on the pickling mechanism # now run the function once to create temporaries within the no-gc # linker f(np.ones(100, dtype="float64")) g(np.ones(100, dtype="float64")) # serialize the functions again post_f = pickle.dumps(f) post_g = pickle.dumps(g) len_post_f = len(post_f) len_post_g = len(post_g) # assert that f() didn't cause the function to grow # allow_gc should leave the function un-changed by calling assert len_pre_f == len_post_f, (len_pre_f, len_post_f) # assert that g() didn't cause g to grow because temporaries # that weren't collected shouldn't be pickled anyway # Allow for a couple of bytes of difference, since timing info, # for instance, can be represented as text of varying size. assert abs(len_post_f - len_post_g) < 256, (f_linker, len_post_f, len_post_g)
def test_including(): mode = aesara.Mode(optimizer="merge") mode.including("fast_compile")
comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() if size != 2: stderr.write("mpiexec failed to create a world with two nodes.\n" "Closing with success message.") stdout.write("True") exit(0) shape = (2, 2) dtype = "float32" scheduler = sort_schedule_fn(*mpi_cmps) mode = aesara.Mode(optimizer=None, linker=aesara.OpWiseCLinker(schedule=scheduler)) with change_flags(compute_test_value="off"): if rank == 0: x = aesara.tensor.matrix("x", dtype=dtype) y = x + 1 send_request = send(y, 1, 11) z = recv(shape, dtype, 1, 12) f = aesara.function([x], [send_request, z], mode=mode) xx = np.random.rand(*shape).astype(dtype) expected = (xx + 1) * 2 _, zz = f(xx)
def test_shared_input_output(): # Test bug reported on the mailing list by Alberto Orlandi # https://groups.google.com/d/topic/aesara-users/6dLaEqc2R6g/discussion # The shared variable is both an input and an output of the function. inc = aesara.tensor.iscalar("inc") state = aesara.shared(0) state.name = "state" linker = aesara.gof.CLinker() mode = aesara.Mode(linker=linker) f = aesara.function([inc], state, updates=[(state, state + inc)], mode=mode) g = aesara.function([inc], state, updates=[(state, state + inc)]) # Initial value f0 = f(0) g0 = g(0) assert f0 == g0 == 0, (f0, g0) # Increment state via f, returns the previous value. f2 = f(2) assert f2 == f0, (f2, f0) f0 = f(0) g0 = g(0) assert f0 == g0 == 2, (f0, g0) # Increment state via g, returns the previous value g3 = g(3) assert g3 == g0, (g3, g0) f0 = f(0) g0 = g(0) assert f0 == g0 == 5, (f0, g0) vstate = aesara.shared(np.zeros(3, dtype="int32")) vstate.name = "vstate" fv = aesara.function([inc], vstate, updates=[(vstate, vstate + inc)], mode=mode) gv = aesara.function([inc], vstate, updates=[(vstate, vstate + inc)]) # Initial value fv0 = fv(0) gv0 = gv(0) assert np.all(fv0 == 0), fv0 assert np.all(gv0 == 0), gv0 # Increment state via f, returns the previous value. fv2 = fv(2) assert np.all(fv2 == fv0), (fv2, fv0) fv0 = fv(0) gv0 = gv(0) assert np.all(fv0 == 2), fv0 assert np.all(gv0 == 2), gv0 # Increment state via g, returns the previous value gv3 = gv(3) assert np.all(gv3 == gv0), (gv3, gv0) fv0 = fv(0) gv0 = gv(0) assert np.all(fv0 == 5), fv0 assert np.all(gv0 == 5), gv0