Skip to content

Commit de581f6

Browse files
committed
add sycl::info::context queries
1 parent be19858 commit de581f6

6 files changed

Lines changed: 522 additions & 0 deletions

File tree

dpctl/_backend.pxd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,20 @@ cdef extern from "syclinterface/dpctl_sycl_context_interface.h":
512512
cdef size_t DPCTLContext_Hash(const DPCTLSyclContextRef CRef)
513513
cdef _backend_type DPCTLContext_GetBackend(const DPCTLSyclContextRef)
514514
cdef void DPCTLContext_Delete(DPCTLSyclContextRef CtxRef)
515+
cdef DPCTLSyclPlatformRef DPCTLContext_GetPlatform(
516+
const DPCTLSyclContextRef CRef)
517+
cdef int *DPCTLContext_GetAtomicMemoryOrderCapabilities(
518+
const DPCTLSyclContextRef CRef,
519+
size_t *res_len)
520+
cdef int *DPCTLContext_GetAtomicFenceOrderCapabilities(
521+
const DPCTLSyclContextRef CRef,
522+
size_t *res_len)
523+
cdef int *DPCTLContext_GetAtomicMemoryScopeCapabilities(
524+
const DPCTLSyclContextRef CRef,
525+
size_t *res_len)
526+
cdef int *DPCTLContext_GetAtomicFenceScopeCapabilities(
527+
const DPCTLSyclContextRef CRef,
528+
size_t *res_len)
515529

516530

517531
cdef extern from "syclinterface/dpctl_sycl_kernel_bundle_interface.h":

dpctl/_sycl_context.pyx

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,30 @@ from ._backend cimport ( # noqa: E211
3434
DPCTLContext_CreateFromDevices,
3535
DPCTLContext_Delete,
3636
DPCTLContext_DeviceCount,
37+
DPCTLContext_GetAtomicFenceOrderCapabilities,
38+
DPCTLContext_GetAtomicFenceScopeCapabilities,
39+
DPCTLContext_GetAtomicMemoryOrderCapabilities,
40+
DPCTLContext_GetAtomicMemoryScopeCapabilities,
3741
DPCTLContext_GetDevices,
42+
DPCTLContext_GetPlatform,
3843
DPCTLContext_Hash,
3944
DPCTLDeviceMgr_GetCachedContext,
4045
DPCTLDeviceVector_CreateFromArray,
4146
DPCTLDeviceVector_Delete,
4247
DPCTLDeviceVector_GetAt,
4348
DPCTLDeviceVector_Size,
4449
DPCTLDeviceVectorRef,
50+
DPCTLInt_Array_Delete,
4551
DPCTLSyclContextRef,
4652
DPCTLSyclDeviceRef,
53+
DPCTLSyclPlatformRef,
4754
error_handler_callback,
4855
)
4956
from ._sycl_device cimport SyclDevice
5057
from ._sycl_device import SyclDeviceCreationError
58+
from ._sycl_platform cimport SyclPlatform
59+
60+
from .enum_types import memory_order, memory_scope
5161

5262
__all__ = [
5363
"SyclContext",
@@ -84,6 +94,33 @@ cdef void _init_helper(_SyclContext context, DPCTLSyclContextRef CRef):
8494
context._ctxt_ref = CRef
8595

8696

97+
cdef tuple _to_enum_tuple(
98+
int *arr, size_t arr_len, object enum_type, str descr
99+
):
100+
"""
101+
Converts an array of DPCTL enum values into a tuple of ``enum_type``s
102+
103+
The DPCTL enums reserve value 0 for an unrecognized value, so a DPCTL
104+
value of ``n`` corresponds to the ``n``-th member of ``enum_type``, whose
105+
members are numbered from 1 by ``enum.auto()``.
106+
"""
107+
cdef list res = []
108+
cdef size_t i
109+
110+
if arr is NULL:
111+
return ()
112+
try:
113+
for i in range(arr_len):
114+
try:
115+
res.append(enum_type(arr[i]))
116+
except ValueError:
117+
raise RuntimeError(f"Unrecognized {descr} reported")
118+
finally:
119+
DPCTLInt_Array_Delete(arr)
120+
121+
return tuple(res)
122+
123+
87124
cdef class _SyclContext:
88125
""" Data owner for SyclContext
89126
"""
@@ -442,6 +479,110 @@ cdef class SyclContext(_SyclContext):
442479
"associated with this context"
443480
)
444481

482+
@property
483+
def sycl_platform(self):
484+
""" Returns the platform associated with this context.
485+
486+
Returns:
487+
:class:`dpctl.SyclPlatform`:
488+
The platform associated with this context.
489+
490+
Raises:
491+
RuntimeError:
492+
If ``DPCTLContext_GetPlatform`` fails to return a platform.
493+
"""
494+
cdef DPCTLSyclPlatformRef PRef = (
495+
DPCTLContext_GetPlatform(self.get_context_ref())
496+
)
497+
if (PRef == NULL):
498+
raise RuntimeError("Could not get platform for context.")
499+
else:
500+
return SyclPlatform._create(PRef)
501+
502+
@property
503+
def atomic_memory_order_capabilities(self):
504+
""" Returns a tuple of :class:`dpctl.memory_order` describing atomic
505+
memory order capabilities of the context.
506+
507+
Returns:
508+
Tuple[:class:`dpctl.memory_order`]:
509+
Tuple of supported memory orders.
510+
511+
Raises:
512+
RuntimeError:
513+
If an unrecognized memory order is given by runtime.
514+
"""
515+
cdef int *arr = NULL
516+
cdef size_t arr_len = 0
517+
518+
arr = DPCTLContext_GetAtomicMemoryOrderCapabilities(
519+
self.get_context_ref(), &arr_len
520+
)
521+
return _to_enum_tuple(arr, arr_len, memory_order, "memory order")
522+
523+
@property
524+
def atomic_fence_order_capabilities(self):
525+
""" Returns a tuple of :class:`dpctl.memory_order` describing atomic
526+
fence order capabilities of the context.
527+
528+
Returns:
529+
Tuple[:class:`dpctl.memory_order`]:
530+
Tuple of supported fence orders.
531+
532+
Raises:
533+
RuntimeError:
534+
If an unrecognized memory order is given by runtime.
535+
"""
536+
cdef int *arr = NULL
537+
cdef size_t arr_len = 0
538+
539+
arr = DPCTLContext_GetAtomicFenceOrderCapabilities(
540+
self.get_context_ref(), &arr_len
541+
)
542+
return _to_enum_tuple(arr, arr_len, memory_order, "memory order")
543+
544+
@property
545+
def atomic_memory_scope_capabilities(self):
546+
""" Returns a tuple of :class:`dpctl.memory_scope` describing atomic
547+
memory scope capabilities of the context.
548+
549+
Returns:
550+
Tuple[:class:`dpctl.memory_scope`]:
551+
Tuple of supported memory scopes.
552+
553+
Raises:
554+
RuntimeError:
555+
If an unrecognized memory scope is given by runtime.
556+
"""
557+
cdef int *arr = NULL
558+
cdef size_t arr_len = 0
559+
560+
arr = DPCTLContext_GetAtomicMemoryScopeCapabilities(
561+
self.get_context_ref(), &arr_len
562+
)
563+
return _to_enum_tuple(arr, arr_len, memory_scope, "memory scope")
564+
565+
@property
566+
def atomic_fence_scope_capabilities(self):
567+
""" Returns a tuple of :class:`dpctl.memory_scope` describing atomic
568+
fence scope capabilities of the context.
569+
570+
Returns:
571+
Tuple[:class:`dpctl.memory_scope`]:
572+
Tuple of supported fence scopes.
573+
574+
Raises:
575+
RuntimeError:
576+
If an unrecognized memory scope is given by runtime.
577+
"""
578+
cdef int *arr = NULL
579+
cdef size_t arr_len = 0
580+
581+
arr = DPCTLContext_GetAtomicFenceScopeCapabilities(
582+
self.get_context_ref(), &arr_len
583+
)
584+
return _to_enum_tuple(arr, arr_len, memory_scope, "memory scope")
585+
445586
@property
446587
def __name__(self):
447588
return "SyclContext"

dpctl/tests/test_sycl_context.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,71 @@ def test_multi_device_different_platforms():
273273
dpctl.SyclContext(devs)
274274
else:
275275
pytest.skip("Insufficient amount of available devices for this test")
276+
277+
278+
def test_context_sycl_platform(valid_filter):
279+
"""
280+
Test that :attr:`dpctl.SyclContext.sycl_platform` returns the
281+
platform shared by the context's devices.
282+
"""
283+
try:
284+
ctx = dpctl.SyclContext(valid_filter)
285+
except dpctl.SyclContextCreationError:
286+
pytest.skip()
287+
plat = ctx.sycl_platform
288+
assert isinstance(plat, dpctl.SyclPlatform)
289+
for d in ctx.get_devices():
290+
assert d.sycl_platform == plat
291+
292+
293+
def test_context_atomic_memory_order_capabilities(valid_filter):
294+
try:
295+
ctx = dpctl.SyclContext(valid_filter)
296+
except dpctl.SyclContextCreationError:
297+
pytest.skip()
298+
caps = ctx.atomic_memory_order_capabilities
299+
assert isinstance(caps, tuple)
300+
assert all(isinstance(m, dpctl.memory_order) for m in caps)
301+
# SYCL 2020 requires at least these capabilities
302+
assert dpctl.memory_order.relaxed in caps
303+
# capabilities of the context must be a subset of every device
304+
for d in ctx.get_devices():
305+
assert set(caps).issubset(set(d.atomic_memory_order_capabilities))
306+
307+
308+
def test_context_atomic_fence_order_capabilities(valid_filter):
309+
try:
310+
ctx = dpctl.SyclContext(valid_filter)
311+
except dpctl.SyclContextCreationError:
312+
pytest.skip()
313+
caps = ctx.atomic_fence_order_capabilities
314+
assert isinstance(caps, tuple)
315+
assert all(isinstance(m, dpctl.memory_order) for m in caps)
316+
for d in ctx.get_devices():
317+
assert set(caps).issubset(set(d.atomic_fence_order_capabilities))
318+
319+
320+
def test_context_atomic_memory_scope_capabilities(valid_filter):
321+
try:
322+
ctx = dpctl.SyclContext(valid_filter)
323+
except dpctl.SyclContextCreationError:
324+
pytest.skip()
325+
caps = ctx.atomic_memory_scope_capabilities
326+
assert isinstance(caps, tuple)
327+
assert all(isinstance(m, dpctl.memory_scope) for m in caps)
328+
# SYCL 2020 requires at least these capabilities
329+
assert dpctl.memory_scope.work_group in caps
330+
for d in ctx.get_devices():
331+
assert set(caps).issubset(set(d.atomic_memory_scope_capabilities))
332+
333+
334+
def test_context_atomic_fence_scope_capabilities(valid_filter):
335+
try:
336+
ctx = dpctl.SyclContext(valid_filter)
337+
except dpctl.SyclContextCreationError:
338+
pytest.skip()
339+
caps = ctx.atomic_fence_scope_capabilities
340+
assert isinstance(caps, tuple)
341+
assert all(isinstance(m, dpctl.memory_scope) for m in caps)
342+
for d in ctx.get_devices():
343+
assert set(caps).issubset(set(d.atomic_fence_scope_capabilities))

libsyclinterface/include/syclinterface/dpctl_sycl_context_interface.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,73 @@ void DPCTLContext_Delete(__dpctl_take DPCTLSyclContextRef CtxRef);
161161
DPCTL_API
162162
size_t DPCTLContext_Hash(__dpctl_keep DPCTLSyclContextRef CtxRef);
163163

164+
/*!
165+
* @brief Wrapper over
166+
* context.get_info<info::context::platform>().
167+
*
168+
* @param CtxRef Opaque pointer to a ``sycl::context``.
169+
* @return Returns an opaque pointer to the ``sycl::platform`` associated with
170+
* the context.
171+
* @ingroup ContextInterface
172+
*/
173+
DPCTL_API
174+
__dpctl_give DPCTLSyclPlatformRef
175+
DPCTLContext_GetPlatform(__dpctl_keep const DPCTLSyclContextRef CtxRef);
176+
177+
/*!
178+
* @brief Wrapper over
179+
* context.get_info<info::context::atomic_memory_order_capabilities>().
180+
*
181+
* @param CtxRef Opaque pointer to a ``sycl::context``.
182+
* @param res_len Populated with size of the returned array.
183+
* @return Returns an array of DPCTLMemoryOrderType values.
184+
* @ingroup ContextInterface
185+
*/
186+
DPCTL_API
187+
__dpctl_give int *DPCTLContext_GetAtomicMemoryOrderCapabilities(
188+
__dpctl_keep const DPCTLSyclContextRef CtxRef,
189+
size_t *res_len);
190+
191+
/*!
192+
* @brief Wrapper over
193+
* context.get_info<info::context::atomic_fence_order_capabilities>().
194+
*
195+
* @param CtxRef Opaque pointer to a ``sycl::context``.
196+
* @param res_len Populated with size of the returned array.
197+
* @return Returns an array of DPCTLMemoryOrderType values.
198+
* @ingroup ContextInterface
199+
*/
200+
DPCTL_API
201+
__dpctl_give int *DPCTLContext_GetAtomicFenceOrderCapabilities(
202+
__dpctl_keep const DPCTLSyclContextRef CtxRef,
203+
size_t *res_len);
204+
205+
/*!
206+
* @brief Wrapper over
207+
* context.get_info<info::context::atomic_memory_scope_capabilities>().
208+
*
209+
* @param CtxRef Opaque pointer to a ``sycl::context``.
210+
* @param res_len Populated with size of the returned array.
211+
* @return Returns an array of DPCTLMemoryScopeType values.
212+
* @ingroup ContextInterface
213+
*/
214+
DPCTL_API
215+
__dpctl_give int *DPCTLContext_GetAtomicMemoryScopeCapabilities(
216+
__dpctl_keep const DPCTLSyclContextRef CtxRef,
217+
size_t *res_len);
218+
219+
/*!
220+
* @brief Wrapper over
221+
* context.get_info<info::context::atomic_fence_scope_capabilities>().
222+
*
223+
* @param CtxRef Opaque pointer to a ``sycl::context``.
224+
* @param res_len Populated with size of the returned array.
225+
* @return Returns an array of DPCTLMemoryScopeType values.
226+
* @ingroup ContextInterface
227+
*/
228+
DPCTL_API
229+
__dpctl_give int *DPCTLContext_GetAtomicFenceScopeCapabilities(
230+
__dpctl_keep const DPCTLSyclContextRef CtxRef,
231+
size_t *res_len);
232+
164233
DPCTL_C_EXTERN_C_END

0 commit comments

Comments
 (0)