Skip to content

Commit 729cbed

Browse files
Add a new SyclEventRaw class (#520)
1 parent 4e1c92b commit 729cbed

File tree

5 files changed

+232
-2
lines changed

5 files changed

+232
-2
lines changed

dpctl/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
select_gpu_device,
4747
select_host_device,
4848
)
49-
from dpctl._sycl_event import SyclEvent
49+
from dpctl._sycl_event import SyclEvent, SyclEventRaw
5050
from dpctl._sycl_platform import SyclPlatform, get_platforms, lsplatform
5151
from dpctl._sycl_queue import (
5252
SyclKernelInvalidRangeError,
@@ -88,6 +88,7 @@
8888
]
8989
__all__ += [
9090
"SyclEvent",
91+
"SyclEventRaw",
9192
]
9293
__all__ += [
9394
"get_platforms",

dpctl/_backend.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ cdef extern from "dpctl_sycl_device_selector_interface.h":
217217

218218

219219
cdef extern from "dpctl_sycl_event_interface.h":
220+
cdef DPCTLSyclEventRef DPCTLEvent_Create()
221+
cdef DPCTLSyclEventRef DPCTLEvent_Copy(const DPCTLSyclEventRef ERef)
220222
cdef void DPCTLEvent_Wait(DPCTLSyclEventRef ERef)
221223
cdef void DPCTLEvent_Delete(DPCTLSyclEventRef ERef)
222224

dpctl/_sycl_event.pxd

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,20 @@ cdef public api class SyclEvent [object PySyclEventObject, type PySyclEventType]
3333
cdef SyclEvent _create (DPCTLSyclEventRef e, list args)
3434
cdef DPCTLSyclEventRef get_event_ref (self)
3535
cpdef void wait (self)
36+
37+
38+
cdef class _SyclEventRaw:
39+
cdef DPCTLSyclEventRef _event_ref
40+
41+
42+
cdef public class SyclEventRaw(_SyclEventRaw) [object PySyclEventRawObject, type PySyclEventRawType]:
43+
@staticmethod
44+
cdef SyclEventRaw _create (DPCTLSyclEventRef event)
45+
@staticmethod
46+
cdef void _init_helper(_SyclEventRaw event, DPCTLSyclEventRef ERef)
47+
cdef int _init_event_default(self)
48+
cdef int _init_event_from__SyclEventRaw(self, _SyclEventRaw other)
49+
cdef int _init_event_from_SyclEvent(self, SyclEvent event)
50+
cdef int _init_event_from_capsule(self, object caps)
51+
cdef DPCTLSyclEventRef get_event_ref (self)
52+
cpdef void wait (self)

dpctl/_sycl_event.pyx

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,19 @@
2323

2424
import logging
2525

26-
from ._backend cimport DPCTLEvent_Delete, DPCTLEvent_Wait, DPCTLSyclEventRef
26+
from cpython cimport pycapsule
27+
28+
from ._backend cimport ( # noqa: E211
29+
DPCTLEvent_Copy,
30+
DPCTLEvent_Create,
31+
DPCTLEvent_Delete,
32+
DPCTLEvent_Wait,
33+
DPCTLSyclEventRef,
34+
)
2735

2836
__all__ = [
2937
"SyclEvent",
38+
"SyclEventRaw",
3039
]
3140

3241
_logger = logging.getLogger(__name__)
@@ -71,3 +80,132 @@ cdef class SyclEvent:
7180
SyclEvent cast to a size_t.
7281
"""
7382
return int(<size_t>self._event_ref)
83+
84+
cdef void _event_capsule_deleter(object o):
85+
cdef DPCTLSyclEventRef ERef = NULL
86+
if pycapsule.PyCapsule_IsValid(o, "SyclEventRef"):
87+
ERef = <DPCTLSyclEventRef> pycapsule.PyCapsule_GetPointer(
88+
o, "SyclEventRef"
89+
)
90+
DPCTLEvent_Delete(ERef)
91+
92+
93+
cdef class _SyclEventRaw:
94+
""" Python wrapper class for a ``cl::sycl::event``.
95+
"""
96+
97+
def __dealloc__(self):
98+
DPCTLEvent_Delete(self._event_ref)
99+
100+
101+
cdef class SyclEventRaw(_SyclEventRaw):
102+
""" Python wrapper class for a ``cl::sycl::event``.
103+
"""
104+
105+
@staticmethod
106+
cdef void _init_helper(_SyclEventRaw event, DPCTLSyclEventRef ERef):
107+
event._event_ref = ERef
108+
109+
@staticmethod
110+
cdef SyclEventRaw _create(DPCTLSyclEventRef eref):
111+
cdef _SyclEventRaw ret = _SyclEventRaw.__new__(_SyclEventRaw)
112+
SyclEventRaw._init_helper(ret, eref)
113+
return SyclEventRaw(ret)
114+
115+
cdef int _init_event_default(self):
116+
self._event_ref = DPCTLEvent_Create()
117+
if (self._event_ref is NULL):
118+
return -1
119+
return 0
120+
121+
cdef int _init_event_from__SyclEventRaw(self, _SyclEventRaw other):
122+
self._event_ref = DPCTLEvent_Copy(other._event_ref)
123+
if (self._event_ref is NULL):
124+
return -1
125+
return 0
126+
127+
cdef int _init_event_from_SyclEvent(self, SyclEvent event):
128+
self._event_ref = DPCTLEvent_Copy(event._event_ref)
129+
if (self._event_ref is NULL):
130+
return -1
131+
return 0
132+
133+
cdef int _init_event_from_capsule(self, object cap):
134+
cdef DPCTLSyclEventRef ERef = NULL
135+
cdef DPCTLSyclEventRef ERef_copy = NULL
136+
cdef int ret = 0
137+
if pycapsule.PyCapsule_IsValid(cap, "SyclEventRef"):
138+
ERef = <DPCTLSyclEventRef> pycapsule.PyCapsule_GetPointer(
139+
cap, "SyclEventRef"
140+
)
141+
if (ERef is NULL):
142+
return -2
143+
ret = pycapsule.PyCapsule_SetName(cap, "used_SyclEventRef")
144+
if (ret):
145+
return -2
146+
ERef_copy = DPCTLEvent_Copy(ERef)
147+
if (ERef_copy is NULL):
148+
return -3
149+
self._event_ref = ERef_copy
150+
return 0
151+
else:
152+
return -128
153+
154+
def __cinit__(self, arg=None):
155+
cdef int ret = 0
156+
if arg is None:
157+
ret = self._init_event_default()
158+
elif type(arg) is _SyclEventRaw:
159+
ret = self._init_event_from__SyclEventRaw(<_SyclEventRaw> arg)
160+
elif isinstance(arg, SyclEvent):
161+
ret = self._init_event_from_SyclEvent(<SyclEvent> arg)
162+
elif pycapsule.PyCapsule_IsValid(arg, "SyclEventRef"):
163+
ret = self._init_event_from_capsule(arg)
164+
else:
165+
raise TypeError(
166+
"Invalid argument."
167+
)
168+
if (ret < 0):
169+
if (ret == -1):
170+
raise ValueError("Event failed to be created.")
171+
elif (ret == -2):
172+
raise TypeError(
173+
"Input capsule {} contains a null pointer or could not be"
174+
" renamed".format(arg)
175+
)
176+
elif (ret == -3):
177+
raise ValueError(
178+
"Internal Error: Could not create a copy of a sycl event."
179+
)
180+
raise ValueError(
181+
"Unrecognized error code ({}) encountered.".format(ret)
182+
)
183+
184+
cdef DPCTLSyclEventRef get_event_ref(self):
185+
""" Returns the `DPCTLSyclEventRef` pointer for this class.
186+
"""
187+
return self._event_ref
188+
189+
cpdef void wait(self):
190+
DPCTLEvent_Wait(self._event_ref)
191+
192+
def addressof_ref(self):
193+
""" Returns the address of the C API `DPCTLSyclEventRef` pointer as
194+
a size_t.
195+
196+
Returns:
197+
The address of the `DPCTLSyclEventRef` object used to create this
198+
`SyclEvent` cast to a size_t.
199+
"""
200+
return <size_t>self._event_ref
201+
202+
def _get_capsule(self):
203+
cdef DPCTLSyclEventRef ERef = NULL
204+
ERef = DPCTLEvent_Copy(self._event_ref)
205+
if (ERef is NULL):
206+
raise ValueError("SyclEvent copy failed.")
207+
return pycapsule.PyCapsule_New(
208+
<void *>ERef,
209+
"SyclEventRef",
210+
&_event_capsule_deleter
211+
)

dpctl/tests/test_sycl_event.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2021 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
""" Defines unit test cases for the SyclEventRaw class.
18+
"""
19+
20+
import numpy as np
21+
import pytest
22+
23+
import dpctl
24+
import dpctl.memory as dpctl_mem
25+
import dpctl.program as dpctl_prog
26+
27+
from ._helper import has_cpu
28+
29+
30+
def test_create_default_event_raw():
31+
try:
32+
dpctl.SyclEventRaw()
33+
except ValueError:
34+
pytest.fail("Failed to create a default event")
35+
36+
37+
def test_create_event_raw_from_SyclEvent():
38+
if has_cpu():
39+
oclSrc = " \
40+
kernel void add(global int* a) { \
41+
size_t index = get_global_id(0); \
42+
a[index] = a[index] + 1; \
43+
}"
44+
q = dpctl.SyclQueue("opencl:cpu")
45+
prog = dpctl_prog.create_program_from_source(q, oclSrc)
46+
addKernel = prog.get_sycl_kernel("add")
47+
48+
bufBytes = 1024 * np.dtype("i").itemsize
49+
abuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
50+
a = np.ndarray((1024), buffer=abuf, dtype="i")
51+
a[:] = np.arange(1024)
52+
args = []
53+
54+
args.append(a.base)
55+
r = [1024]
56+
ev = q.submit(addKernel, args, r)
57+
58+
try:
59+
dpctl.SyclEventRaw(ev)
60+
except ValueError:
61+
pytest.fail("Failed to create an event from SyclEvent")
62+
else:
63+
pytest.skip("No OpenCL CPU queues available")
64+
65+
66+
def test_create_event_raw_from_capsule():
67+
try:
68+
event = dpctl.SyclEventRaw()
69+
event_capsule = event._get_capsule()
70+
dpctl.SyclEventRaw(event_capsule)
71+
except ValueError:
72+
pytest.fail("Failed to create an event from capsule")

0 commit comments

Comments
 (0)