diff --git a/loopy/kernel/array.py b/loopy/kernel/array.py index 84b0a4a74bdc0e4dc32b5823c50a4a9c0a8d9f25..d16908ba3c50bd922aeab69212c219039b1c9e38 100644 --- a/loopy/kernel/array.py +++ b/loopy/kernel/array.py @@ -1193,11 +1193,10 @@ class ArrayBase(ImmutableRecord): else: return idx - from pytools import indices_in_shape return [ (unwrap_1d_indices(i), self.name + "".join("_s%d" % sub_i for sub_i in i)) - for i in indices_in_shape(sep_shape)] + for i in np.ndindex(sep_shape)] # }}} diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index 8869ebecf3e08bf7921d4c9118dd1fda263adb32..909a8f6fb9f45e8175bd4e88c73d81fb18b81896 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -251,8 +251,7 @@ def generate_linearized_array(array, value): assert array.offset == 0 - from pytools import indices_in_shape - for ituple in indices_in_shape(value.shape): + for ituple in np.ndindex(value.shape): i = sum(i_ax * strd_ax for i_ax, strd_ax in zip(ituple, strides)) data[i] = value[ituple] diff --git a/loopy/target/pyopencl.py b/loopy/target/pyopencl.py index 845e0a4326dbb24e509f98c808a9ce3ac3cb52be..1c8bf4caac63a436bcc541907986fbead50a72e4 100644 --- a/loopy/target/pyopencl.py +++ b/loopy/target/pyopencl.py @@ -318,20 +318,21 @@ class PyOpenCLTarget(OpenCLTarget): if self.device is not None: assert other.device is not None - return (self.device.persistent_unique_id - == other.device.persistent_unique_id) + return (self.device.hashable_model_and_version_identifier + == other.device.hashable_model_and_version_identifier) else: assert other.device is None return True def update_persistent_hash(self, key_hash, key_builder): super(PyOpenCLTarget, self).update_persistent_hash(key_hash, key_builder) - key_builder.rec(key_hash, getattr(self.device, "persistent_unique_id", None)) + key_builder.rec(key_hash, getattr( + self.device, "hashable_model_and_version_identifier", None)) def __getstate__(self): dev_id = None if self.device is not None: - dev_id = self.device.persistent_unique_id + dev_id = self.device.hashable_model_and_version_identifier return { "device_id": dev_id, @@ -354,7 +355,7 @@ class PyOpenCLTarget(OpenCLTarget): dev for plat in cl.get_platforms() for dev in plat.get_devices() - if dev.persistent_unique_id == dev_id] + if dev.hashable_model_and_version_identifier == dev_id] if matches: self.device = matches[0] @@ -643,7 +644,7 @@ class PyOpenCLPythonASTBuilder(PythonASTBuilderBase): + ["wait_for=None", "allocator=None"]) from genpy import (For, Function, Suite, Import, ImportAs, Return, - FromImport, If, Assign, Line, Statement as S) + FromImport, Line, Statement as S) return Function( codegen_result.current_program(codegen_state).name, args, @@ -652,11 +653,6 @@ class PyOpenCLPythonASTBuilder(PythonASTBuilderBase): ImportAs("pyopencl", "_lpy_cl"), Import("pyopencl.tools"), Line(), - If("allocator is None", - Assign( - "allocator", - "_lpy_cl_tools.DeferredAllocator(queue.context)")), - Line(), ] + [ Line(), function_body, @@ -731,6 +727,13 @@ class PyOpenCLPythonASTBuilder(PythonASTBuilderBase): from genpy import Suite, Assign, Assert, Line, Comment from pymbolic.mapper.stringifier import PREC_NONE + import pyopencl.version as cl_ver + if cl_ver.VERSION < (2020, 2): + from warnings import warn + warn("Your kernel invocation will likely fail because your " + "version of PyOpenCL does not support allow_empty_ndrange. " + "Please upgrade to version 2020.2 or newer.") + # TODO: Generate finer-grained dependency structure return Suite([ Comment("{{{ enqueue %s" % name), @@ -742,7 +745,8 @@ class PyOpenCLPythonASTBuilder(PythonASTBuilderBase): arry_arg_code, Assign("_lpy_evt", "%(pyopencl_module_name)s.enqueue_nd_range_kernel(" "queue, _lpy_knl, " - "%(gsize)s, %(lsize)s, wait_for=wait_for, g_times_l=True)" + "%(gsize)s, %(lsize)s, wait_for=wait_for, " + "g_times_l=True, allow_empty_ndrange=True)" % dict( pyopencl_module_name=self.target.pyopencl_module_name, gsize=ecm(gsize, prec=PREC_NONE, type_context="i"), diff --git a/loopy/version.py b/loopy/version.py index d69a3b574122622105e4b52c74ec8c595fc816b6..4eab69c14d8fb2cded8356a83d208353cd8f19eb 100644 --- a/loopy/version.py +++ b/loopy/version.py @@ -60,7 +60,7 @@ except ImportError: else: _cgen_version = cgen.version.VERSION_TEXT -DATA_MODEL_VERSION = "%s-islpy%s-cgen%s-%s-v0" % ( +DATA_MODEL_VERSION = "%s-islpy%s-cgen%s-%s-v1" % ( VERSION_TEXT, _islpy_version, _cgen_version, _git_rev) diff --git a/requirements.txt b/requirements.txt index 97c2024764715d0a715520800e2e1dd467183479..cd9b67cf4e0e744668b3ef0ae2f2b494d9c2c6e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,4 @@ git+https://github.com/inducer/codepy.git git+https://github.com/inducer/f2py # Optional, needed for using the C preprocessor on Fortran -ply>=3.6 \ No newline at end of file +ply>=3.6 diff --git a/setup.py b/setup.py index bba29986997e8e762ad52f38feae6311c4892c10..2687d7e099c53bbd01935f7115ad98990921f915 100644 --- a/setup.py +++ b/setup.py @@ -99,7 +99,7 @@ setup(name="loo.py", extras_require={ "pyopencl": [ - "pyopencl>=2015.2", + "pyopencl>=2020.2", ], "fortran": [ # Note that this is *not* regular 'f2py2e', this is diff --git a/test/test_loopy.py b/test/test_loopy.py index 61a3f167be66f1c99adc3a52473d8edc747479e1..85b857a3e01ac430efe97fc144574d319290fd72 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -2859,6 +2859,33 @@ def test_non_integral_array_idx_raises(): print(lp.generate_code_v2(knl).device_code()) +@pytest.mark.parametrize("tag", ["for", "l.0", "g.0", "fixed"]) +def test_empty_domain(ctx_factory, tag): + ctx = ctx_factory() + queue = cl.CommandQueue(ctx) + + prg = lp.make_kernel( + "{[i,j]: 0 <= i < n}", + """ + for i + c = 1 + end + """) + + if tag == "fixed": + prg = lp.fix_parameters(prg, n=0) + kwargs = {} + else: + prg = lp.tag_inames(prg, {"i": tag}) + kwargs = {"n": 0} + + prg = lp.set_options(prg, write_code=True) + c = cl.array.zeros(queue, (), dtype=np.int32) + prg(queue, c=c, **kwargs) + + assert (c.get() == 0).all() + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1])