Repository navigation
Check the number of kernel arguments only for interoperability kernels #2425
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,6 +82,7 @@ from ._backend cimport ( # noqa: E211 | |
| _md_local_accessor, | ||
| _queue_property_type, | ||
| ) | ||
| from .compiler._compiler cimport _INTEROP_ORIGIN | ||
| from .memory._memory cimport _Memory | ||
|
|
||
| import ctypes | ||
|
|
@@ -174,6 +175,16 @@ cdef class LocalAccessor: | |
| Python class for specifying the dimensionality and type of a | ||
| ``sycl::local_accessor``, to be used as a kernel argument type. | ||
|
|
||
| A ``LocalAccessor`` is passed as a single kernel argument, the pointer to | ||
| the local memory. A kernel compiled from SYCL to SPIR-V may expect a | ||
| ``sycl::local_accessor`` parameter as several arguments instead: the | ||
| pointer, followed by the accessor's access range, memory range and | ||
| offset. Pass the ``LocalAccessor`` as the first of them and the others | ||
| explicitly, e.g. for a one-dimensional accessor of ``n`` elements:: | ||
|
|
||
| [dpctl.LocalAccessor("i4", (n,)), ctypes.c_size_t(n), | ||
| ctypes.c_size_t(n), ctypes.c_size_t(0), ...] | ||
|
|
||
| Args: | ||
| dtype (str): | ||
| the data type of the local memory. | ||
|
|
@@ -1540,8 +1551,13 @@ cdef class SyclQueue(_SyclQueue): | |
|
|
||
| Raises: | ||
| ValueError: | ||
| If the number of arguments in ``args`` differs from the number | ||
| of arguments the kernel takes. | ||
| If ``kernel`` is from a kernel bundle created from OpenCL C | ||
| source or SPIR-V, and the number of arguments in ``args`` | ||
| differs from the number of arguments the kernel takes. The | ||
| arguments of other kernels are not checked: the backend may | ||
| reject a wrong number of arguments, raising | ||
| :class:`SyclKernelSubmitError`, or run the kernel with the | ||
| arguments that were not given left unset. | ||
| SyclKernelSubmitError: | ||
| If ``kernel`` does not reference a ``sycl::kernel``, or if | ||
| submission to the queue fails. | ||
|
|
@@ -1564,13 +1580,24 @@ cdef class SyclQueue(_SyclQueue): | |
| "``sycl::kernel``." | ||
| ) | ||
| # the backend can not detect that the correct number of arguments were | ||
| # provided, so check it here | ||
| nKA = kernel.num_args | ||
| if <size_t>len(args) != nKA: | ||
| raise ValueError( | ||
| f"Kernel '{kernel.get_function_name()}' takes {nKA} " | ||
| f"argument(s), got {len(args)}." | ||
| ) | ||
| # provided, so check it here for the kernels it defines that number for | ||
| if kernel._origin == _INTEROP_ORIGIN: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SYCL source kernels are no longer checked at all. On Level Zero a missing argument now runs the kernel silently, while master raises import numpy as np, dpctl, dpctl.compiler as dpc, dpctl.memory as dpm
src = """
#include <sycl/sycl.hpp>
namespace syclexp = sycl::ext::oneapi::experimental;
extern "C" SYCL_EXTERNAL
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((syclexp::nd_range_kernel<1>))
void fill(int *x, int v) {
auto it = sycl::ext::oneapi::this_work_item::get_nd_item<1>();
x[it.get_global_linear_id()] = v;
}
"""
q = dpctl.SyclQueue()
krn = dpc.create_kernel_bundle_from_sycl_source(q, src).get_sycl_kernel("fill")
x = dpm.MemoryUSMDevice(64 * 4, queue=q)
q.submit(krn, [x], [64], [16]).wait() # `v` is missing
res = np.empty(64, dtype="i4")
q.memcpy(res, x, res.nbytes)
print(res[:4]) # Level Zero GPU: [0 0 0 0]; OpenCL CPU: SyclKernelSubmitError; master: ValueErrorCould the check stay for SYCL source kernels when no |
||
| nKA = kernel.num_args | ||
| if <size_t>len(args) != nKA: | ||
| msg = ( | ||
| f"Kernel '{kernel.get_function_name()}' takes {nKA} " | ||
| f"argument(s), got {len(args)}." | ||
| ) | ||
| if <size_t>len(args) < nKA and any( | ||
| [isinstance(arg, LocalAccessor) for arg in args] | ||
| ): | ||
| msg += ( | ||
| " A kernel compiled from SYCL to SPIR-V may expect a " | ||
| "sycl::local_accessor parameter as several arguments, " | ||
| "of which a dpctl.LocalAccessor is only the first; " | ||
| "see the dpctl.LocalAccessor documentation." | ||
| ) | ||
| raise ValueError(msg) | ||
|
|
||
| # Allocate the arrays to be sent to DPCTLQueue_Submit | ||
| kargs = <void**>malloc(len(args) * sizeof(void*)) | ||
|
|
@@ -1718,8 +1745,13 @@ cdef class SyclQueue(_SyclQueue): | |
|
|
||
| Raises: | ||
| ValueError: | ||
| If the number of arguments in ``args`` differs from the number | ||
| of arguments the kernel takes. | ||
| If ``kernel`` is from a kernel bundle created from OpenCL C | ||
| source or SPIR-V, and the number of arguments in ``args`` | ||
| differs from the number of arguments the kernel takes. The | ||
| arguments of other kernels are not checked: the backend may | ||
| reject a wrong number of arguments, raising | ||
| :class:`SyclKernelSubmitError`, or run the kernel with the | ||
| arguments that were not given left unset. | ||
| SyclKernelSubmitError: | ||
| If ``kernel`` does not reference a ``sycl::kernel``, or if | ||
| submission to the queue fails. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,16 +28,26 @@ from .._sycl_device cimport SyclDevice | |
| from .._sycl_queue cimport SyclQueue | ||
|
|
||
|
|
||
| cdef enum _kernel_origin: | ||
| # kernel from a bundle created outside of dpctl.compiler | ||
| _UNKNOWN_ORIGIN = 0 | ||
| # kernel from an OpenCL C source or SPIR-V bundle | ||
| _INTEROP_ORIGIN = 1 | ||
| # kernel from a SYCL source bundle | ||
| _SYCL_SOURCE_ORIGIN = 2 | ||
|
|
||
|
|
||
| cdef api class SyclKernel [object PySyclKernelObject, type PySyclKernelType]: | ||
| ''' Wraps a sycl::kernel object created from an OpenCL interoperability | ||
| kernel. | ||
| ''' | ||
| cdef DPCTLSyclKernelRef _kernel_ref | ||
| cdef str _function_name | ||
| cdef int _origin | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new # dpnp built against dpctl master, run with this branch
import warnings
warnings.simplefilter("error", RuntimeWarning)
import dpnp # RuntimeWarning: dpctl.compiler._compiler.SyclKernel size changed ... Expected 40 from C header, got 48Could interop kernels be a subclass of |
||
| cdef DPCTLSyclKernelRef get_kernel_ref (self) | ||
|
|
||
| @staticmethod | ||
| cdef SyclKernel _create (DPCTLSyclKernelRef kref, str name) | ||
| cdef SyclKernel _create (DPCTLSyclKernelRef kref, str name, int origin=*) | ||
|
|
||
|
|
||
| cdef api class SyclKernelBundle [ | ||
|
|
@@ -52,11 +62,10 @@ cdef api class SyclKernelBundle [ | |
| binary file. | ||
| """ | ||
| cdef DPCTLSyclKernelBundleRef _kernel_bundle_ref | ||
| cdef bint _is_sycl_source | ||
| cdef int _origin | ||
|
|
||
| @staticmethod | ||
| cdef SyclKernelBundle _create (DPCTLSyclKernelBundleRef kbref, | ||
| bint _is_sycl_source) | ||
| cdef SyclKernelBundle _create (DPCTLSyclKernelBundleRef kbref, int origin) | ||
| cdef DPCTLSyclKernelBundleRef get_kernel_bundle_ref (self) | ||
| cpdef SyclKernel get_sycl_kernel(self, str kernel_name) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For an N-D accessor, each range and the offset is one argument of N
size_t, not N arguments. A SPIR-V kernel withsycl::local_accessor<int, 2>andint *has 5 arguments, and it gives the right result on GPU and CPU with:Could the docstring say this?