diff --git a/doc/misc.rst b/doc/misc.rst index c77c7c2252b5d92978c1f8ab33d28a7cabea4913..113427ede53e0c739dcd764b617b2c7bad0d1717 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -19,8 +19,25 @@ and say:: In addition, you need to have :mod:`numpy` installed. +Usage +===== + +Environment variables +--------------------- + ++-----------------------------------+-----------------------------------------------------+ +| Name | Purpose | ++===================================+=====================================================+ +| `SUMPY_FORCE_SYMBOLIC_BACKEND` | Symbolic backend control, see `Symbolic backends`_ | ++-----------------------------------+-----------------------------------------------------+ +| `SUMPY_NO_CACHE` | If set, disables the on-disk cache | ++-----------------------------------+-----------------------------------------------------+ +| `SUMPY_NO_OPT` | If set, disables performance-oriented :mod:`loopy` | +| | transformations | ++-----------------------------------+-----------------------------------------------------+ + Symbolic backends -================= +----------------- :mod:`sumpy` supports two symbolic backends: sympy and SymEngine. To use the SymEngine backend, ensure that the `SymEngine library diff --git a/sumpy/__init__.py b/sumpy/__init__.py index a325e3d1a90a370f7f35883f3de62f6d90486f7c..8bece3a2dccde8dc6bf6a2b0d41eef20dfb3d1f2 100644 --- a/sumpy/__init__.py +++ b/sumpy/__init__.py @@ -40,6 +40,21 @@ __all__ = [ code_cache = WriteOncePersistentDict("sumpy-code-cache-v6-"+VERSION_TEXT) +# {{{ optimization control + +OPT_ENABLED = True + +OPT_ENABLED = "SUMPY_NO_OPT" not in os.environ + + +def set_optimization_enabled(flag): + """Set whether the :mod:`loopy` kernels should be optimized.""" + global OPT_ENABLED + OPT_ENABLED = flag + +# }}} + + # {{{ cache control CACHING_ENABLED = True diff --git a/sumpy/tools.py b/sumpy/tools.py index 428fa2a1ba54afc1151b7874aa89bc81c2bdec35..46fa9ee96c10b49a859871a91354e37c5cda28d9 100644 --- a/sumpy/tools.py +++ b/sumpy/tools.py @@ -365,7 +365,7 @@ class OrderedSet(collections.MutableSet): class KernelCacheWrapper(object): @memoize_method def get_cached_optimized_kernel(self, **kwargs): - from sumpy import code_cache, CACHING_ENABLED + from sumpy import code_cache, CACHING_ENABLED, OPT_ENABLED if CACHING_ENABLED: import loopy.version @@ -374,7 +374,8 @@ class KernelCacheWrapper(object): self.get_cache_key() + tuple(sorted(six.iteritems(kwargs))) + (loopy.version.DATA_MODEL_VERSION,) - + (KERNEL_VERSION,)) + + (KERNEL_VERSION,) + + (OPT_ENABLED,)) try: result = code_cache[cache_key] @@ -391,7 +392,10 @@ class KernelCacheWrapper(object): from pytools import MinRecursionLimit with MinRecursionLimit(3000): - knl = self.get_optimized_kernel(**kwargs) + if OPT_ENABLED: + knl = self.get_optimized_kernel(**kwargs) + else: + knl = self.get_kernel() if CACHING_ENABLED: code_cache.store_if_not_present(cache_key, knl) diff --git a/test/test_cse.py b/test/test_cse.py index ba8e49b463483fee696d3bc5ae910f14955da83e..5f10115cea88a041063b4ef48b4a13a4072ce34f 100644 --- a/test/test_cse.py +++ b/test/test_cse.py @@ -173,25 +173,25 @@ def test_multiple_expressions(): substs, reduced = cse([e1, e2]) assert substs == [(x0, x + y)] assert reduced == [x0*z, x0*w] - l = [w*x*y + z, w*y] - substs, reduced = cse(l) - rsubsts, _ = cse(reversed(l)) + l_ = [w*x*y + z, w*y] + substs, reduced = cse(l_) + rsubsts, _ = cse(reversed(l_)) assert substs == rsubsts assert reduced == [z + x*x0, x0] - l = [w*x*y, w*x*y + z, w*y] - substs, reduced = cse(l) - rsubsts, _ = cse(reversed(l)) + l_ = [w*x*y, w*x*y + z, w*y] + substs, reduced = cse(l_) + rsubsts, _ = cse(reversed(l_)) assert substs == rsubsts assert reduced == [x1, x1 + z, x0] f = Function("f") - l = [f(x - z, y - z), x - z, y - z] - substs, reduced = cse(l) - rsubsts, _ = cse(reversed(l)) + l_ = [f(x - z, y - z), x - z, y - z] + substs, reduced = cse(l_) + rsubsts, _ = cse(reversed(l_)) assert substs == [(x0, -z), (x1, x + x0), (x2, x0 + y)] assert rsubsts == [(x0, -z), (x1, x0 + y), (x2, x + x0)] assert reduced == [f(x1, x2), x1, x2] - l = [w*y + w + x + y + z, w*x*y] - assert cse(l) == ([(x0, w*y)], [w + x + x0 + y + z, x*x0]) + l_ = [w*y + w + x + y + z, w*x*y] + assert cse(l_) == ([(x0, w*y)], [w + x + x0 + y + z, x*x0]) assert cse([x + y, x + y + z]) == ([(x0, x + y)], [x0, z + x0]) assert cse([x + y, x + z]) == ([], [x + y, x + z]) assert cse([x*y, z + x*y, x*y*z + 3]) == \ @@ -302,24 +302,24 @@ def test_Piecewise(): # noqa def test_name_conflict(): z1 = x0 + y z2 = x2 + x3 - l = [cos(z1) + z1, cos(z2) + z2, x0 + x2] - substs, reduced = cse(l) - assert [e.subs(dict(substs)) for e in reduced] == l + l_ = [cos(z1) + z1, cos(z2) + z2, x0 + x2] + substs, reduced = cse(l_) + assert [e.subs(dict(substs)) for e in reduced] == l_ def test_name_conflict_cust_symbols(): z1 = x0 + y z2 = x2 + x3 - l = [cos(z1) + z1, cos(z2) + z2, x0 + x2] - substs, reduced = cse(l, symbols("x:10")) - assert [e.subs(dict(substs)) for e in reduced] == l + l_ = [cos(z1) + z1, cos(z2) + z2, x0 + x2] + substs, reduced = cse(l_, symbols("x:10")) + assert [e.subs(dict(substs)) for e in reduced] == l_ def test_symbols_exhausted_error(): - l = cos(x+y)+x+y+cos(w+y)+sin(w+y) + l_ = cos(x+y)+x+y+cos(w+y)+sin(w+y) sym = [x, y, z] with pytest.raises(ValueError): - print(cse(l, symbols=sym)) + print(cse(l_, symbols=sym)) @sympyonly