diff --git a/dpctl/_backend.pxd b/dpctl/_backend.pxd index 23200cd1e5..5f306d70a0 100644 --- a/dpctl/_backend.pxd +++ b/dpctl/_backend.pxd @@ -37,8 +37,8 @@ cdef extern from "syclinterface/dpctl_sycl_enum_types.h": ctypedef enum _usm_type 'DPCTLSyclUSMType': _USM_UNKNOWN 'DPCTL_USM_UNKNOWN' _USM_DEVICE 'DPCTL_USM_DEVICE' - _USM_HOST 'DPCTL_USM_HOST' _USM_SHARED 'DPCTL_USM_SHARED' + _USM_HOST 'DPCTL_USM_HOST' ctypedef enum _backend_type 'DPCTLSyclBackendType': _ALL_BACKENDS 'DPCTL_ALL_BACKENDS' diff --git a/dpctl/memory/_memory.pxd b/dpctl/memory/_memory.pxd index 68fd7f4f13..a9e2719a19 100644 --- a/dpctl/memory/_memory.pxd +++ b/dpctl/memory/_memory.pxd @@ -22,7 +22,7 @@ in dpctl.memory._memory.pyx. """ -from .._backend cimport DPCTLSyclQueueRef, DPCTLSyclUSMRef +from .._backend cimport DPCTLSyclQueueRef, DPCTLSyclUSMRef, _usm_type from .._sycl_context cimport SyclContext from .._sycl_device cimport SyclDevice from .._sycl_queue cimport SyclQueue @@ -57,6 +57,8 @@ cdef public api class _Memory [object Py_MemoryObject, type Py_MemoryType]: @staticmethod cdef bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx) @staticmethod + cdef _usm_type get_pointer_type_enum(DPCTLSyclUSMRef p, SyclContext ctx) + @staticmethod cdef object create_from_usm_pointer_size_qref( DPCTLSyclUSMRef USMRef, Py_ssize_t nbytes, diff --git a/dpctl/memory/_memory.pyx b/dpctl/memory/_memory.pyx index 93d5b507e0..b650dca33c 100644 --- a/dpctl/memory/_memory.pyx +++ b/dpctl/memory/_memory.pyx @@ -376,6 +376,39 @@ cdef class _Memory: "SyclContext or SyclQueue" ) + def get_usm_type_enum(self, syclobj=None): + """ + get_usm_type(syclobj=None) + + Returns the type of USM allocation using Sycl context carried by + `syclobj` keyword argument. Value of None is understood to query + against `self.sycl_context` - the context used to create the + allocation. + """ + cdef const char* kind + cdef SyclContext ctx + cdef SyclQueue q + if syclobj is None: + ctx = self._context + return _Memory.get_pointer_type_enum( + self.memory_ptr, ctx + ) + elif isinstance(syclobj, SyclContext): + ctx = (syclobj) + return _Memory.get_pointer_type_enum( + self.memory_ptr, ctx + ) + elif isinstance(syclobj, SyclQueue): + q = (syclobj) + ctx = q.get_sycl_context() + return _Memory.get_pointer_type_enum( + self.memory_ptr, ctx + ) + raise TypeError( + "syclobj keyword can be either None, or an instance of " + "SyclContext or SyclQueue" + ) + cpdef copy_to_host(self, obj=None): """ Copy content of instance's memory into memory of ``obj``, or allocate @@ -553,13 +586,35 @@ cdef class _Memory: ) if usm_ty == _usm_type._USM_DEVICE: return b'device' - elif usm_ty == _usm_type._USM_HOST: - return b'host' elif usm_ty == _usm_type._USM_SHARED: return b'shared' + elif usm_ty == _usm_type._USM_HOST: + return b'host' else: return b'unknown' + @staticmethod + cdef _usm_type get_pointer_type_enum(DPCTLSyclUSMRef p, SyclContext ctx): + """ + get_pointer_type(p, ctx) + + Gives the SYCL(TM) USM pointer type, using ``sycl::get_pointer_type``, + returning an enum value. + + Args: + p: DPCTLSyclUSMRef + A pointer to test the type of. + ctx: :class:`dpctl.SyclContext` + Python object providing :class:`dpctl.SyclContext` against + which to query for the pointer type. + Returns: + An enum value corresponding to the type of allocation. + """ + cdef _usm_type usm_ty = DPCTLUSM_GetPointerType( + p, ctx.get_context_ref() + ) + return usm_ty + @staticmethod cdef object create_from_usm_pointer_size_qref( DPCTLSyclUSMRef USMRef, Py_ssize_t nbytes, diff --git a/dpctl/tests/test_sycl_usm.py b/dpctl/tests/test_sycl_usm.py index 9c92549c18..0efb6ccf6d 100644 --- a/dpctl/tests/test_sycl_usm.py +++ b/dpctl/tests/test_sycl_usm.py @@ -201,7 +201,7 @@ def test_pickling_reconstructor_invalid_type(memory_ctor): mobj = memory_ctor(1024, alignment=64) good_pickle_bytes = pickle.dumps(mobj) - usm_types = expected_usm_type(memory_ctor).encode("utf-8") + usm_types = expected_usm_type_str(memory_ctor).encode("utf-8") i = good_pickle_bytes.rfind(usm_types) bad_pickle_bytes = good_pickle_bytes[:i] + b"u" + good_pickle_bytes[i + 1 :] with pytest.raises(ValueError): @@ -213,7 +213,7 @@ def memory_ctor(request): return request.param -def expected_usm_type(ctor): +def expected_usm_type_str(ctor): mapping = { MemoryUSMShared: "shared", MemoryUSMDevice: "device", @@ -222,6 +222,15 @@ def expected_usm_type(ctor): return mapping.get(ctor, "unknown") +def expected_usm_type_enum(ctor): + mapping = { + MemoryUSMShared: 2, + MemoryUSMDevice: 1, + MemoryUSMHost: 3, + } + return mapping.get(ctor, 0) + + @pytest.mark.skipif( not has_sycl_platforms(), reason="No SYCL devices except the default host device.", @@ -230,7 +239,8 @@ def test_create_with_size_and_alignment_and_queue(memory_ctor): q = dpctl.SyclQueue() m = memory_ctor(1024, alignment=64, queue=q) assert m.nbytes == 1024 - assert m.get_usm_type() == expected_usm_type(memory_ctor) + assert m.get_usm_type() == expected_usm_type_str(memory_ctor) + assert m.get_usm_type_enum() == expected_usm_type_enum(memory_ctor) @pytest.mark.skipif( @@ -241,7 +251,8 @@ def test_create_with_size_and_queue(memory_ctor): q = dpctl.SyclQueue() m = memory_ctor(1024, queue=q) assert m.nbytes == 1024 - assert m.get_usm_type() == expected_usm_type(memory_ctor) + assert m.get_usm_type() == expected_usm_type_str(memory_ctor) + assert m.get_usm_type_enum() == expected_usm_type_enum(memory_ctor) @pytest.mark.skipif( @@ -251,17 +262,28 @@ def test_create_with_size_and_queue(memory_ctor): def test_create_with_size_and_alignment(memory_ctor): m = memory_ctor(1024, alignment=64) assert m.nbytes == 1024 - assert m.get_usm_type() == expected_usm_type(memory_ctor) + assert m.get_usm_type() == expected_usm_type_str(memory_ctor) + assert m.get_usm_type_enum() == expected_usm_type_enum(memory_ctor) @pytest.mark.skipif( not has_sycl_platforms(), reason="No SYCL devices except the default host device.", ) -def test_create_with_only_size(memory_ctor): - m = memory_ctor(1024) +def test_usm_type_execeptions(): + ctor = MemoryUSMDevice + m = ctor(1024) assert m.nbytes == 1024 - assert m.get_usm_type() == expected_usm_type(memory_ctor) + q = m.sycl_queue + assert m.get_usm_type(syclobj=q) == expected_usm_type_str(ctor) + assert m.get_usm_type_enum(syclobj=q) == expected_usm_type_enum(ctor) + ctx = q.sycl_context + assert m.get_usm_type(syclobj=ctx) == expected_usm_type_str(ctor) + assert m.get_usm_type_enum(syclobj=ctx) == expected_usm_type_enum(ctor) + with pytest.raises(TypeError): + m.get_usm_type(syclobj=Ellipsis) + with pytest.raises(TypeError): + m.get_usm_type_enum(syclobj=list()) @pytest.mark.skipif( diff --git a/libsyclinterface/include/dpctl_sycl_enum_types.h b/libsyclinterface/include/dpctl_sycl_enum_types.h index 87bb279d8a..75a3374ddb 100644 --- a/libsyclinterface/include/dpctl_sycl_enum_types.h +++ b/libsyclinterface/include/dpctl_sycl_enum_types.h @@ -39,8 +39,8 @@ typedef enum { DPCTL_USM_UNKNOWN = 0, DPCTL_USM_DEVICE, - DPCTL_USM_HOST, - DPCTL_USM_SHARED + DPCTL_USM_SHARED, + DPCTL_USM_HOST } DPCTLSyclUSMType; /*!