Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds more custom exception classes to numba_dpex. #798

Merged
merged 2 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion numba_dpex/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from numba.core.typing.templates import AbstractTemplate, ConcreteTemplate

from numba_dpex import config
from numba_dpex.core.dpex_exceptions import KernelHasReturnValueError
from numba_dpex.core.exceptions import KernelHasReturnValueError
from numba_dpex.core.types import Array
from numba_dpex.dpctl_iface import USMNdArrayType
from numba_dpex.dpctl_support import dpctl_version
Expand Down
34 changes: 0 additions & 34 deletions numba_dpex/core/dpex_exceptions.py

This file was deleted.

220 changes: 220 additions & 0 deletions numba_dpex/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# SPDX-FileCopyrightText: 2020 - 2022 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

"""The module defines the custom exception classes used in numba_dpex.
"""

from warnings import warn


class KernelHasReturnValueError(Exception):
"""Exception raised when a kernel function is defined with a return
statement.
@numba_dpex.kernel does not allow users to return any value. The
restriction is inline with the general ABI for device functions in OpenCL,
CUDA, and SYCL.
Args:
kernel_name: Name of the kernel function that caused the error.
return_type: Numba type representing the return value specified for
the kernel function.
"""

def __init__(self, kernel_name, return_type) -> None:
self.return_type = return_type
self.kernel_name = kernel_name
self.message = (
f'Kernel "{self.kernel_name}" has a return value '
f'of type "{self.return_type}". '
"A numba-dpex kernel must have a void return type."
)

super().__init__(self.message)


class InvalidKernelLaunchArgsError(Exception):
"""Exception raised when a kernel is dispatched with insufficient or
incorrect launch arguments.
A global range value is needed to submit a kernel to an execution queue. The
global range provides the number of work items that the SYCL runtime should
create to execute the kernel. The exception is raised if a kernel is
dispatched without specifying a valid global range.
Args:
kernel_name (str): The kernel function name.
"""

def __init__(self, kernel_name):
warn(
"The InvalidKernelLaunchArgsError class is deprecated, and will "
+ "be removed once kernel launching using __getitem__ for the "
+ "KernelLauncher class is removed.",
DeprecationWarning,
stacklevel=2,
)
self.message = (
"Invalid launch arguments specified for launching the Kernel "
f'"{kernel_name}". Launch arguments can only be a tuple '
"specifying the global range or a tuple of tuples specifying "
"global and local ranges."
)
super().__init__(self.message)


class UnknownGlobalRangeError(Exception):
"""Exception raised when a kernel is launched without specifying a global
range.
Args:
kernel_name (str): The kernel function name.
"""

def __init__(self, kernel_name) -> None:
self.message = (
"No global range specified for launching the Kernel "
f'"{kernel_name}". '
"A valid global range tuple is needed to launch a kernel."
)
super().__init__(self.message)


class ComputeFollowsDataInferenceError(Exception):
"""Exception raised when an execution queue for a given array expression or
a kernel function could not be deduced using the compute-follows-data
programming model.
Compute-follows-data is a programming model that determines the execution
device or queue of an array expression or kernel based on the arrays that
are on the right hand side of the expression or are the arguments to the
kernel function. The execution queue is deduced based on the device on
which the array operands were allocated. Computation is required to occur
on the same device where the arrays currently reside.
A ComputeFollowsDataInferenceError is raised when the execution queue using
compute-follows-data rules could not be deduced. It may happen when arrays
that have a device attribute such as ``dpctl.tensor.usm_ndarray`` are mixed
with host arrays such as ``numpy.ndarray``. The error may also be raised if
the array operands are allocated on different devices.
Args:
kernel_name : Name of the kernel function for which the error occurred.
ndarray_argnum_list: The list of ``numpy.ndarray`` arguments identified
by the argument position that caused the error.
usmarray_argnum_list: The list of ``dpctl.tensor.usm_ndarray`` arguments
identified by the argument position that caused the error.
"""

def __init__(
self, kernel_name, ndarray_argnum_list=None, *, usmarray_argnum_list
) -> None:
if ndarray_argnum_list and usmarray_argnum_list:
ndarray_args = ",".join(ndarray_argnum_list)
usmarray_args = ",".join(usmarray_argnum_list)
self.message = (
f'Kernel "{kernel_name}" has arguments of both usm_ndarray and '
"non-usm_ndarray types. Mixing of arguments of different "
"array types is disallowed. "
f"Arguments {ndarray_args} are non-usm arrays, "
f"and arguments {usmarray_args} are usm arrays."
)
elif usmarray_argnum_list:
usmarray_args = ",".join(usmarray_argnum_list)
self.message = (
f'Execution queue for kernel "{kernel_name}" could '
"be deduced using compute follows data programming model. The "
f"usm_ndarray arguments {usmarray_args} were not allocated "
"on the same queue."
)
super().__init__(self.message)


class ExecutionQueueInferenceError(Exception):
"""Exception raised when an execution queue could not be deduced for NumPy
ndarray kernel arguments.
Args:
kernel_name (str): Name of kernel where the error was raised.
.. deprecated:: 0.19
"""

def __init__(self, kernel_name) -> None:
warn(
"The ExecutionQueueInferenceError class is deprecated, and will "
+ "be removed once support for NumPy ndarrays as kernel arguments "
+ "is removed.",
DeprecationWarning,
stacklevel=2,
)
self.message = (
f'Kernel "{kernel_name}" was called with NumPy ndarray arguments '
"outside a dpctl.device_context. The execution queue to be used "
"could not be deduced."
)
super().__init__(self.message)


class UnsupportedBackendError(Exception):
"""Exception raised when the target device is not supported by dpex.
Presently only L0 and OpenCL devices are supported by numba_dpex. If the
provided execution queue is for any other SYCL platform (e.g., Cuda) then
it results in an UnsupportedBackendError.
Args:
kernel_name (str): Name of kernel where the error was raised.
backend (str): name of the unsupported backend.
supported_backends (List): The list of supported backends.
"""

def __init__(self, kernel_name, backend, supported_backends) -> None:
supported_backends_joined = ",".join(supported_backends)
self.message = (
f'Kernel "{kernel_name}" cannot be compiled for "{backend}". '
f'Only "{supported_backends_joined}" backends are supported.'
)
super().__init__(self.message)


class UncompiledKernelError(Exception):
"""Exception raised when an attribute of a KernelInterface object is
accessed before the object is compiled.
Args:
kernel_name (str): Name of kernel where the error was raised.
"""

def __init__(self, kernel_name) -> None:
self.message = (
f'No LLVM module for kernel "{kernel_name}". '
"Kernel might not be compiled yet."
)
super().__init__(self.message)


class UnreachableError(Exception):
"""Internal compiler error when an unreachable branch is taken somewhere in
the compiler code.
"""

def __init__(self) -> None:
import sys
import traceback

_, _, tb = sys.exc_info()
if tb:
traceback.print_tb(tb) # Fixed format
tb_info = traceback.extract_tb(tb)
filename, line, func, text = tb_info[-1]
self.message = (
f"Attempt to execute a unreachable code section on line {line} "
f"in statement {text} in function {func} in the module "
f"{filename}."
)
else:
self.message = "Unreachable code executed."
super().__init__(self.message)
2 changes: 1 addition & 1 deletion numba_dpex/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import dpctl
from numba.core import sigutils, types

from numba_dpex.core.dpex_exceptions import KernelHasReturnValueError
from numba_dpex.core.exceptions import KernelHasReturnValueError
from numba_dpex.utils import npytypes_array_to_dpex_array

from .compiler import (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def sig(request):
def test_return(filter_str, sig):
a = np.array(np.random.random(122), np.int32)

with pytest.raises(dpex.core.dpex_exceptions.KernelHasReturnValueError):
with pytest.raises(dpex.core.exceptions.KernelHasReturnValueError):
kernel = dpex.kernel(sig)(f)

device = dpctl.SyclDevice(filter_str)
Expand Down