def test_opwiseclinker_constant(): x, y, z = inputs() x = Constant(tdouble, 7.2, name="x") e = add(mul(x, y), mul(y, z)) lnk = OpWiseCLinker().accept(FunctionGraph([y, z], [e])) fn = lnk.make_function() res = fn(1.5, 3.0) assert res == 15.3
def test_c_fail_error(): x, y, z = inputs() x = Constant(tdouble, 7.2, name="x") e = add_fail(mul(x, y), mul(y, z)) lnk = OpWiseCLinker().accept(FunctionGraph([y, z], [e])) fn = lnk.make_function() with pytest.raises(RuntimeError): fn(1.5, 3.0)
def test_opwiseclinker_straightforward(): x, y, z = inputs() e = add(mul(add(x, y), div(x, y)), bad_sub(bad_sub(x, y), z)) lnk = OpWiseCLinker().accept(FunctionGraph([x, y, z], [e])) fn = lnk.make_function() if aesara.config.cxx: assert fn(2.0, 2.0, 2.0) == 2.0 else: # The python version of bad_sub always return -10. assert fn(2.0, 2.0, 2.0) == -6
def __init__(self, pre_func=None, post_func=None, optimizer="default", linker=None): self.pre_func = pre_func self.post_func = post_func wrap_linker = WrapLinkerMany([OpWiseCLinker()], [self.eval]) if optimizer == "default": optimizer = config.optimizer if linker is not None and not isinstance(linker.mode, MonitorMode): raise Exception( "MonitorMode can only use its own linker! You " "should not provide one.", linker, ) super().__init__(wrap_linker, optimizer=optimizer)
def test_sort_schedule_fn(): import aesara from aesara.graph.sched import make_depends, sort_schedule_fn x = 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 = OpWiseCLinker(schedule=sort_schedule_fn(str_cmp)) mode = 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 test_duallinker_mismatch(): x, y, z = inputs() # bad_sub is correct in C but erroneous in Python e = bad_sub(mul(x, y), mul(y, z)) g = FunctionGraph([x, y, z], [e]) lnk = DualLinker(checker=_my_checker).accept(g) fn = make_function(lnk) # good assert make_function(CLinker().accept(g))(1.0, 2.0, 3.0) == -4.0 # good assert make_function(OpWiseCLinker().accept(g))(1.0, 2.0, 3.0) == -4.0 # (purposely) wrong assert make_function(PerformLinker().accept(g))(1.0, 2.0, 3.0) == -10.0 with pytest.raises(MyExc): # this runs OpWiseCLinker and PerformLinker in parallel and feeds # variables of matching operations to _my_checker to verify that they # are the same. fn(1.0, 2.0, 3.0)
) from aesara.graph.optdb import EquilibriumDB, LocalGroupDB, Query, SequenceDB, TopoDB from aesara.link.basic import PerformLinker from aesara.link.c.basic import CLinker, OpWiseCLinker from aesara.link.jax import JAXLinker from aesara.link.vm import VMLinker _logger = logging.getLogger("aesara.compile.mode") # If a string is passed as the linker argument in the constructor for # Mode, it will be used as the key to retrieve the real linker in this # dictionary predefined_linkers = { "py": PerformLinker(), # Use allow_gc Aesara flag "c": CLinker(), # Don't support gc. so don't check allow_gc "c|py": OpWiseCLinker(), # Use allow_gc Aesara flag "c|py_nogc": OpWiseCLinker(allow_gc=False), "vm": VMLinker(use_cloop=False), # Use allow_gc Aesara flag "cvm": VMLinker(use_cloop=True), # Use allow_gc Aesara flag "vm_nogc": VMLinker(allow_gc=False, use_cloop=False), "cvm_nogc": VMLinker(allow_gc=False, use_cloop=True), "jax": JAXLinker(), } def register_linker(name, linker): """Add a `Linker` which can be referred to by `name` in `Mode`.""" if name in predefined_linkers: raise ValueError(f"Linker name already taken: {name}") predefined_linkers[name] = linker
def test_c_or_py(self): # Shape op don't have C code. # But This will test DimShuffle c code self.with_linker(OpWiseCLinker())
def test_gc_never_pickles_temporaries(): x = 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 [ (PerformLinker(allow_gc=True), PerformLinker(allow_gc=False)), (OpWiseCLinker(allow_gc=True), OpWiseCLinker(allow_gc=False)), ]: # f_linker has garbage collection # g_linker has no garbage collection f = aesara.function([x], r, mode=Mode(optimizer=optimizer, linker=f_linker)) g = aesara.function([x], r, mode=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 timing 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.types._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)
from aesara.graph.sched import sort_schedule_fn from aesara.link.c.basic import OpWiseCLinker from aesara.tensor.io import ( MPISend, MPISendWait, mpi_cmps, mpi_enabled, mpi_send_wait_cmp, recv, send, ) from aesara.tensor.type import matrix mpi_scheduler = sort_schedule_fn(*mpi_cmps) mpi_linker = OpWiseCLinker(schedule=mpi_scheduler) mpi_mode = Mode(linker=mpi_linker) @config.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():