@@ -116,6 +116,49 @@ def _to_memory(unsigned char[::1] b, str usm_kind):
116116 return res
117117
118118
119+ def get_usm_pointer_type (ptr , syclobj ):
120+ """
121+ get_usm_pointer_type(ptr, syclobj)
122+
123+ Gives the SYCL(TM) USM pointer type, using ``sycl::get_pointer_type``,
124+ returning one of 4 possible strings: 'shared', 'host', 'device',
125+ or 'unknown'.
126+
127+ Args:
128+ ptr: int
129+ A pointer stored as size_t Python integer.
130+ syclobj: :class:`dpctl.SyclContext` or :class:`dpctl.SyclQueue`
131+ Python object providing :class:`dpctl.SyclContext` against which
132+ to query for the pointer type.
133+ Returns:
134+ 'unknown' if the pointer does not represent USM allocation made using
135+ the given context. Otherwise, returns 'shared', 'device', or 'host'
136+ type of the allocation.
137+ """
138+ cdef const char * kind
139+ cdef SyclContext ctx
140+ cdef SyclQueue q
141+ cdef DPCTLSyclUSMRef USMRef = NULL
142+ try :
143+ USMRef = < DPCTLSyclUSMRef> (< size_t> ptr)
144+ except Exception as e:
145+ raise TypeError (
146+ " First argument {} could not be converted to Python integer of "
147+ " size_t" .format(ptr)
148+ ) from e
149+ if isinstance (syclobj, SyclContext):
150+ ctx = < SyclContext> (syclobj)
151+ return _Memory.get_pointer_type(USMRef, ctx).decode(" UTF-8" )
152+ elif isinstance (syclobj, SyclQueue):
153+ q = < SyclQueue> (syclobj)
154+ ctx = q.get_sycl_context()
155+ return _Memory.get_pointer_type(USMRef, ctx).decode(" UTF-8" )
156+ raise TypeError (
157+ " Second argument {} is expected to be an instance of "
158+ " SyclContext or SyclQueue" .format(syclobj)
159+ )
160+
161+
119162cdef class _Memory:
120163 """ Internal class implementing methods common to
121164 MemoryUSMShared, MemoryUSMDevice, MemoryUSMHost
@@ -282,7 +325,7 @@ cdef class _Memory:
282325
283326 def __repr__ (self ):
284327 return (
285- " <SYCL(TM) USM-{} allocated memory block of {} bytes at {}>"
328+ " <SYCL(TM) USM-{} allocation of {} bytes at {}>"
286329 .format(
287330 self .get_usm_type(),
288331 self .nbytes,
@@ -316,31 +359,37 @@ cdef class _Memory:
316359 return iface
317360
318361 def get_usm_type (self , syclobj = None ):
362+ """
363+ get_usm_type(syclobj=None)
364+
365+ Returns the type of USM allocation using Sycl context carried by
366+ `syclobj` keyword argument. Value of None is understood to query
367+ against `self.sycl_context` - the context used to create the
368+ allocation.
369+ """
319370 cdef const char * kind
320371 cdef SyclContext ctx
321372 cdef SyclQueue q
322373 if syclobj is None :
323374 ctx = self ._context
324- kind = DPCTLUSM_GetPointerType (
325- self .memory_ptr, ctx.get_context_ref()
326- )
375+ return _Memory.get_pointer_type (
376+ self .memory_ptr, ctx
377+ ).decode( " UTF-8 " )
327378 elif isinstance (syclobj, SyclContext):
328379 ctx = < SyclContext> (syclobj)
329- kind = DPCTLUSM_GetPointerType (
330- self .memory_ptr, ctx.get_context_ref()
331- )
380+ return _Memory.get_pointer_type (
381+ self .memory_ptr, ctx
382+ ).decode( " UTF-8 " )
332383 elif isinstance (syclobj, SyclQueue):
333384 q = < SyclQueue> (syclobj)
334385 ctx = q.get_sycl_context()
335- kind = DPCTLUSM_GetPointerType(
336- self .memory_ptr, ctx.get_context_ref()
337- )
338- else :
339- raise ValueError (
340- " syclobj keyword can be either None, or an instance of "
341- " SyclContext or SyclQueue"
342- )
343- return kind.decode(' UTF-8' )
386+ return _Memory.get_pointer_type(
387+ self .memory_ptr, ctx
388+ ).decode(" UTF-8" )
389+ raise TypeError (
390+ " syclobj keyword can be either None, or an instance of "
391+ " SyclContext or SyclQueue"
392+ )
344393
345394 cpdef copy_to_host(self , obj = None ):
346395 """
@@ -457,7 +506,24 @@ cdef class _Memory:
457506
458507 @staticmethod
459508 cdef bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx):
460- """ Returns USM-type of given pointer `p` in given sycl context `ctx`"""
509+ """
510+ get_pointer_type(p, ctx)
511+
512+ Gives the SYCL(TM) USM pointer type, using ``sycl::get_pointer_type``,
513+ returning one of 4 possible strings: 'shared', 'host', 'device', or
514+ 'unknown'.
515+
516+ Args:
517+ p: DPCTLSyclUSMRef
518+ A pointer to test the type of.
519+ ctx: :class:`dpctl.SyclContext`
520+ Python object providing :class:`dpctl.SyclContext` against
521+ which to query for the pointer type.
522+ Returns:
523+ b'unknown' if the pointer does not represent USM allocation made
524+ using the given context. Otherwise, returns b'shared', b'device',
525+ or b'host' type of the allocation.
526+ """
461527 cdef const char * usm_type = DPCTLUSM_GetPointerType(
462528 p, ctx.get_context_ref()
463529 )
@@ -530,12 +596,14 @@ cdef class MemoryUSMShared(_Memory):
530596 allocates nbytes of USM shared memory.
531597
532598 Non-positive alignments are not used (malloc_shared is used instead).
533- For the queue=None cast the `dpctl.SyclQueue()` is used to allocate memory.
534-
535- MemoryUSMShared(usm_obj) constructor create instance from `usm_obj`
536- expected to implement `__sycl_usm_array_interface__` protocol and exposing
537- a contiguous block of USM memory of USM shared type. Using copy=True to
538- perform a copy if USM type is other than 'shared'.
599+ For the queue=None case the ``dpctl.SyclQueue()`` is used to allocate
600+ memory.
601+
602+ MemoryUSMShared(usm_obj) constructor creates instance from `usm_obj`
603+ expected to implement `__sycl_usm_array_interface__` protocol and to expose
604+ a contiguous block of USM shared allocation. Use `copy=True` to
605+ perform a copy if USM type of the allocation represented by the argument
606+ is other than 'shared'.
539607 """
540608 def __cinit__ (self , other , *, Py_ssize_t alignment = 0 ,
541609 SyclQueue queue = None , int copy = False ):
@@ -569,12 +637,14 @@ cdef class MemoryUSMHost(_Memory):
569637 allocates nbytes of USM host memory.
570638
571639 Non-positive alignments are not used (malloc_host is used instead).
572- For the queue=None case `dpctl.SyclQueue()` is used to allocate memory.
640+ For the queue=None case the ``dpctl.SyclQueue()`` is used to allocate
641+ memory.
573642
574643 MemoryUSMDevice(usm_obj) constructor create instance from `usm_obj`
575- expected to implement `__sycl_usm_array_interface__` protocol and exposing
576- a contiguous block of USM memory of USM host type. Using copy=True to
577- perform a copy if USM type is other than 'host'.
644+ expected to implement `__sycl_usm_array_interface__` protocol and to expose
645+ a contiguous block of USM host allocation. Use `copy=True` to
646+ perform a copy if USM type of the allocation represented by the argument
647+ is other than 'host'.
578648 """
579649 def __cinit__ (self , other , *, Py_ssize_t alignment = 0 ,
580650 SyclQueue queue = None , int copy = False ):
@@ -609,12 +679,14 @@ cdef class MemoryUSMDevice(_Memory):
609679 allocates nbytes of USM device memory.
610680
611681 Non-positive alignments are not used (malloc_device is used instead).
612- For the queue=None cast the `dpctl.SyclQueue()` is used to allocate memory.
682+ For the queue=None case the ``dpctl.SyclQueue()`` is used to allocate
683+ memory.
613684
614685 MemoryUSMDevice(usm_obj) constructor create instance from `usm_obj`
615686 expected to implement `__sycl_usm_array_interface__` protocol and exposing
616- a contiguous block of USM memory of USM device type. Using copy=True to
617- perform a copy if USM type is other than 'device'.
687+ a contiguous block of USM device allocation. Use `copy=True` to
688+ perform a copy if USM type of the allocation represented by the argument
689+ is other than 'device'.
618690 """
619691 def __cinit__ (self , other , *, Py_ssize_t alignment = 0 ,
620692 SyclQueue queue = None , int copy = False ):
@@ -638,3 +710,41 @@ cdef class MemoryUSMDevice(_Memory):
638710 other, self .get_usm_type()
639711 )
640712 )
713+
714+
715+ def as_usm_memory (obj ):
716+ """
717+ as_usm_memory(obj)
718+
719+ Converts Python object with `__sycl_usm_array_interface__` property
720+ to one of :class:`.MemoryUSMShared`, :class:`.MemoryUSMDevice`, or
721+ :class:`.MemoryUSMHost` instances depending on the type of USM allocation
722+ they represent.
723+
724+ Raises:
725+ ValueError
726+ When object does not expose the `__sycl_usm_array_interface__`,
727+ or it is malformed
728+ TypeError
729+ When unexpected types of entries in the interface are encountered
730+ SyclQueueCreationError
731+ When a :class:`dpctl.SyclQueue` could not be created from the
732+ information given by the interface
733+ """
734+ cdef _Memory res = _Memory.__new__ (_Memory)
735+ cdef str kind
736+ res._cinit_empty()
737+ res._cinit_other(obj)
738+ kind = res.get_usm_type()
739+ if kind == " shared" :
740+ return MemoryUSMShared(res)
741+ elif kind == " device" :
742+ return MemoryUSMDevice(res)
743+ elif kind == " host" :
744+ return MemoryUSMHost(res)
745+ else :
746+ raise ValueError (
747+ " Could not determine the type "
748+ " USM allocation represented by argument {}" .
749+ format(obj)
750+ )
0 commit comments