diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85e0336b046b1fbad50c7e969efb46daae3e9f3b..0b1f8156ce5bd76b28b947c1441f22bac567ed7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,10 +107,15 @@ jobs: - uses: actions/checkout@v4 - name: "Main Script" run: | + # This test makes sure that loopy can run with kernels loaded from disk cache. curl -L -O https://tiker.net/ci-support-v0 . ./ci-support-v0 build_py_project_in_conda_env ( test_py_project ) + + # See https://github.com/inducer/loopy/pull/828 why this is disabled. + # export LOOPY_ABORT_ON_CACHE_MISS=1 + ( test_py_project ) examples: diff --git a/doc/ref_other.rst b/doc/ref_other.rst index 538f0cdb924507cb502a8eecf30a48ece3909f56..81b6eca1e8e637cd80cab72e738e02adbe53a7d2 100644 --- a/doc/ref_other.rst +++ b/doc/ref_other.rst @@ -25,6 +25,13 @@ Controlling caching is suppressed. +.. envvar:: LOOPY_ABORT_ON_CACHE_MISS + + If set to a string that :func:`pytools.strtobool` evaluates as ``True``, + loopy will raise an exception if a cache miss occurs. This can be useful + for debugging cache-related issues. For example, it can be used to automatically test whether caching is successful for a particular code, by setting this variable to ``True`` and re-running the code. + + .. autofunction:: set_caching_enabled .. autoclass:: CacheMode diff --git a/loopy/__init__.py b/loopy/__init__.py index 7a1942f3d9446e71560f457239f182791f66472d..8060ee0bc796b7cb6c0cd37a516e249b44b831bb 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -509,6 +509,9 @@ CACHING_ENABLED = ( not strtobool(os.environ.get("CG_NO_CACHE", "false"))) +ABORT_ON_CACHE_MISS = strtobool(os.environ.get("LOOPY_ABORT_ON_CACHE_MISS", "false")) + + def set_caching_enabled(flag): """Set whether :mod:`loopy` is allowed to use disk caching for its various code generation stages. diff --git a/loopy/codegen/__init__.py b/loopy/codegen/__init__.py index 3de36e242e34b93340c914f742db0d46cb5d3539..e7decb8f25091ab39e16422b7e4ce423b50baff3 100644 --- a/loopy/codegen/__init__.py +++ b/loopy/codegen/__init__.py @@ -549,7 +549,8 @@ class TranslationUnitCodeGenerationResult: def generate_code_v2(t_unit: TranslationUnit) -> CodeGenerationResult: # {{{ cache retrieval - from loopy import CACHING_ENABLED + + from loopy import ABORT_ON_CACHE_MISS, CACHING_ENABLED from loopy.kernel import LoopKernel from loopy.translation_unit import make_program @@ -563,6 +564,8 @@ def generate_code_v2(t_unit: TranslationUnit) -> CodeGenerationResult: except KeyError: logger.debug(f"TranslationUnit with entrypoints {t_unit.entrypoints}:" " code generation cache miss") + if ABORT_ON_CACHE_MISS: + raise # }}} diff --git a/test/test_c_execution.py b/test/test_c_execution.py index 9943d41df8330f765509db6339f57ef3a263a4d4..33e50e3ab1eea4645d6df3bfc8899b6ece5e1b5d 100644 --- a/test/test_c_execution.py +++ b/test/test_c_execution.py @@ -93,10 +93,11 @@ def test_c_target_strides(): def test_c_target_strides_nonsquare(): from loopy.target.c import ExecutableCTarget + rng = np.random.default_rng(seed=42) def __get_kernel(order="C"): indices = ["i", "j", "k"] - sizes = tuple(np.random.randint(1, 11, size=len(indices))) + sizes = tuple(rng.integers(1, 11, size=len(indices))) # create domain strings domain_template = "{{ [{iname}]: 0 <= {iname} < {size} }}" domains = [] @@ -141,9 +142,11 @@ def test_c_target_strides_nonsquare(): def test_c_optimizations(): from loopy.target.c import ExecutableCTarget + rng = np.random.default_rng(seed=42) + def __get_kernel(order="C"): indices = ["i", "j", "k"] - sizes = tuple(np.random.randint(1, 11, size=len(indices))) + sizes = tuple(rng.integers(1, 11, size=len(indices))) # create domain strings domain_template = "{{ [{iname}]: 0 <= {iname} < {size} }}" domains = []