From 2a03a2ebce836ccf31637cc890d12e844cba5633 Mon Sep 17 00:00:00 2001 From: Sophia Vorderwuelbecke Date: Tue, 8 Nov 2022 18:07:36 +0000 Subject: [PATCH] Change naming of is_exectubale on Target class to single_subkernel_is_entrypoint, add docs and error when there is more than one subkernel. Update how a subkernel is detected. --- loopy/target/__init__.py | 12 ++++++++---- loopy/target/c/__init__.py | 15 ++++++++++----- loopy/target/cuda.py | 2 +- loopy/target/ispc.py | 13 +++++++------ loopy/target/opencl.py | 2 +- loopy/target/pyopencl.py | 4 ++-- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index 572c0e95f..c078ae9a2 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -161,10 +161,14 @@ def get_kernel_executor(self, kernel, *args, **kwargs): raise NotImplementedError() @abc.abstractproperty - def is_executable(self) -> bool: - """ - Returns *True* only if the target allows executing loopy - translation units through :attr:`loopy.TranslationUnit.__call__`. + def single_subkernel_is_entrypoint(self) -> bool: + r""" + Returns *True* if *self* does NOT support generating code for + linearized kernels with more than one + :class:`~loopy.schedule.CallKernel`\ s. This guarantees the + :class:`~loopy.schedule.CallKernel` for which we generate code is the + entrypoint kernel. This also allows the target to skip the invoker + level code. """ diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index 7a3588373..36e293cfa 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -840,9 +840,14 @@ def get_function_declaration( # subkernel launches occur only as part of entrypoint kernels for now from loopy.schedule.tools import get_subkernel_arg_info + from loopy.kernel.tools import get_subkernels skai = get_subkernel_arg_info(kernel, subkernel_name) + if (self.target.single_subkernel_is_entrypoint + and len(get_subkernels(kernel)) > 1): + raise LoopyError(f"Kernel '{kernel.name}' has more than one" + f" subkernel, not allowed in {self.target}.") passed_names = (skai.passed_names - if self.target.is_executable + if not self.target.single_subkernel_is_entrypoint else [arg.name for arg in kernel.args]) written_names = skai.written_names else: @@ -1336,8 +1341,8 @@ def get_dtype_registry(self): return DTypeRegistryWrapper(result) @property - def is_executable(self) -> bool: - return False + def single_subkernel_is_entrypoint(self) -> bool: + return True class CASTBuilder(CFamilyASTBuilder): @@ -1383,8 +1388,8 @@ def get_host_ast_builder(self): return CFamilyASTBuilder(self) @property - def is_executable(self) -> bool: - return True + def single_subkernel_is_entrypoint(self) -> bool: + return False # }}} diff --git a/loopy/target/cuda.py b/loopy/target/cuda.py index 5254b08dc..21ed93bd6 100644 --- a/loopy/target/cuda.py +++ b/loopy/target/cuda.py @@ -256,7 +256,7 @@ def vector_dtype(self, base, count): # }}} @property - def is_executable(self) -> bool: + def single_subkernel_is_entrypoint(self) -> bool: return False # }}} diff --git a/loopy/target/ispc.py b/loopy/target/ispc.py index 385fcf9f8..ec390085a 100644 --- a/loopy/target/ispc.py +++ b/loopy/target/ispc.py @@ -199,8 +199,8 @@ def get_dtype_registry(self): # }}} @property - def is_executable(self) -> bool: - return False + def single_subkernel_is_entrypoint(self) -> bool: + return True class ISPCASTBuilder(CFamilyASTBuilder): @@ -226,9 +226,9 @@ def get_function_declaration( # subkernel launches occur only as part of entrypoint kernels for now from loopy.schedule.tools import get_subkernel_arg_info skai = get_subkernel_arg_info(codegen_state.kernel, subkernel_name) - passed_names = (skai.passed_names - if self.target.is_executable - else [arg.name for arg in kernel.args]) + passed_names = ([arg.name for arg in kernel.args] + if self.target.single_subkernel_is_entrypoint + else skai.passed_names) written_names = skai.written_names else: passed_names = [arg.name for arg in kernel.args] @@ -269,7 +269,8 @@ def get_kernel_call(self, codegen_state: CodeGenerationState, "assert(programCount == (%s))" % ecm(lsize[0], PREC_NONE))) - if codegen_state.is_entrypoint and self.target.is_executable: + if (codegen_state.is_entrypoint and + self.target.single_subkernel_is_entrypoint): # subkernel launches occur only as part of entrypoint kernels for now from loopy.schedule.tools import get_subkernel_arg_info skai = get_subkernel_arg_info(codegen_state.kernel, subkernel_name) diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 37bee3856..e59f92bb4 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -599,7 +599,7 @@ def vector_dtype(self, base, count): return NumpyType(vec.types[base.numpy_dtype, count]) @property - def is_executable(self) -> bool: + def single_subkernel_is_entrypoint(self) -> bool: return False # }}} diff --git a/loopy/target/pyopencl.py b/loopy/target/pyopencl.py index 641a40bef..f2fb58639 100644 --- a/loopy/target/pyopencl.py +++ b/loopy/target/pyopencl.py @@ -552,8 +552,8 @@ def with_device(self, device): return self @property - def is_executable(self) -> bool: - return True + def single_subkernel_is_entrypoint(self) -> bool: + return False # }}}