Skip to content

Commit 8a55469

Browse files
Feature/submit barrier (#524)
* Implemented DPCTLQueue_SubmitBarrier, DPCTLQueue_SubmitBarrierForEvents * Implemented SyclQueue.submit_barrier
1 parent d1d8d4e commit 8a55469

File tree

7 files changed

+180
-0
lines changed

7 files changed

+180
-0
lines changed

dpctl-capi/include/dpctl_sycl_queue_interface.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,4 +343,32 @@ bool DPCTLQueue_IsInOrder(__dpctl_keep const DPCTLSyclQueueRef QRef);
343343
DPCTL_API
344344
size_t DPCTLQueue_Hash(__dpctl_keep const DPCTLSyclQueueRef QRef);
345345

346+
/*!
347+
* @brief C-API wraper for ``sycl::queue::submit_barrier()``.
348+
*
349+
* @param QRef An opaque pointer to the ``sycl::queue``.
350+
* @return An opaque pointer to the ``sycl::event`` returned by the
351+
* ``sycl::queue::submit_barrier()`` function.
352+
*/
353+
DPCTL_API
354+
DPCTLSyclEventRef
355+
DPCTLQueue_SubmitBarrier(__dpctl_keep const DPCTLSyclQueueRef QRef);
356+
357+
/*!
358+
* @brief C-API wraper for ``sycl::queue::submit_barrier(event_vector)``.
359+
*
360+
* @param QRef An opaque pointer to the ``sycl::queue``.
361+
* @param DepEvents List of dependent DPCTLSyclEventRef objects (events)
362+
* for the barrier. We call ``sycl::handler.depends_on``
363+
* for each of the provided events.
364+
* @param NDepEvents Size of the DepEvents list.
365+
* @return An opaque pointer to the ``sycl::event`` returned by the
366+
* ``sycl::queue::submit_barrier()`` function.
367+
*/
368+
DPCTL_API
369+
DPCTLSyclEventRef DPCTLQueue_SubmitBarrierForEvents(
370+
__dpctl_keep const DPCTLSyclQueueRef QRef,
371+
__dpctl_keep const DPCTLSyclEventRef *DepEvents,
372+
size_t NDepEvents);
373+
346374
DPCTL_C_EXTERN_C_END

dpctl-capi/source/dpctl_sycl_queue_interface.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,3 +533,44 @@ size_t DPCTLQueue_Hash(__dpctl_keep const DPCTLSyclQueueRef QRef)
533533
return 0;
534534
}
535535
}
536+
537+
__dpctl_give DPCTLSyclEventRef DPCTLQueue_SubmitBarrierForEvents(
538+
__dpctl_keep const DPCTLSyclQueueRef QRef,
539+
__dpctl_keep const DPCTLSyclEventRef *DepEvents,
540+
size_t NDepEvents)
541+
{
542+
auto Q = unwrap(QRef);
543+
event e;
544+
if (Q) {
545+
try {
546+
e = Q->submit([&](handler &cgh) {
547+
// Depend on any event that was specified by the caller.
548+
if (NDepEvents)
549+
for (auto i = 0ul; i < NDepEvents; ++i)
550+
cgh.depends_on(*unwrap(DepEvents[i]));
551+
552+
cgh.barrier();
553+
});
554+
} catch (runtime_error &re) {
555+
// \todo fix error handling
556+
std::cerr << re.what() << '\n';
557+
return nullptr;
558+
} catch (std::runtime_error &sre) {
559+
std::cerr << sre.what() << '\n';
560+
return nullptr;
561+
}
562+
563+
return wrap(new event(e));
564+
}
565+
else {
566+
// todo: log error
567+
std::cerr << "Argument QRef is null" << '\n';
568+
return nullptr;
569+
}
570+
}
571+
572+
__dpctl_give DPCTLSyclEventRef
573+
DPCTLQueue_SubmitBarrier(__dpctl_keep const DPCTLSyclQueueRef QRef)
574+
{
575+
return DPCTLQueue_SubmitBarrierForEvents(QRef, nullptr, 0);
576+
}

dpctl-capi/tests/test_sycl_queue_submit.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,56 @@ TEST_F(TestQueueSubmitNDRange, ChkSubmitNDRangeDouble)
356356
EXPECT_TRUE(worked);
357357
}
358358

359+
struct TestQueueSubmitBarrier : public ::testing::Test
360+
{
361+
DPCTLSyclQueueRef QRef = nullptr;
362+
363+
TestQueueSubmitBarrier()
364+
{
365+
DPCTLSyclDeviceSelectorRef DSRef = nullptr;
366+
DPCTLSyclDeviceRef DRef = nullptr;
367+
368+
EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create());
369+
EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef));
370+
EXPECT_NO_FATAL_FAILURE(QRef = DPCTLQueue_CreateForDevice(
371+
DRef, nullptr, DPCTL_DEFAULT_PROPERTY));
372+
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef));
373+
EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef));
374+
}
375+
~TestQueueSubmitBarrier()
376+
{
377+
EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(QRef));
378+
}
379+
};
380+
381+
TEST_F(TestQueueSubmitBarrier, ChkSubmitBarrier)
382+
{
383+
DPCTLSyclEventRef ERef = nullptr;
384+
385+
ASSERT_TRUE(QRef != nullptr);
386+
EXPECT_NO_FATAL_FAILURE(ERef = DPCTLQueue_SubmitBarrier(QRef));
387+
ASSERT_TRUE(ERef != nullptr);
388+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Wait(ERef));
389+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Delete(ERef));
390+
}
391+
392+
TEST_F(TestQueueSubmitBarrier, ChkSubmitBarrierWithEvents)
393+
{
394+
DPCTLSyclEventRef ERef = nullptr;
395+
DPCTLSyclEventRef DepsERefs[2] = {nullptr, nullptr};
396+
397+
EXPECT_NO_FATAL_FAILURE(DepsERefs[0] = DPCTLEvent_Create());
398+
EXPECT_NO_FATAL_FAILURE(DepsERefs[1] = DPCTLEvent_Create());
399+
400+
ASSERT_TRUE(QRef != nullptr);
401+
EXPECT_NO_FATAL_FAILURE(
402+
ERef = DPCTLQueue_SubmitBarrierForEvents(QRef, DepsERefs, 2));
403+
404+
ASSERT_TRUE(ERef != nullptr);
405+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Wait(ERef));
406+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Delete(ERef));
407+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Delete(DepsERefs[0]));
408+
EXPECT_NO_FATAL_FAILURE(DPCTLEvent_Delete(DepsERefs[1]));
409+
}
410+
359411
#endif

dpctl/_backend.pxd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,12 @@ cdef extern from "dpctl_sycl_queue_interface.h":
347347
size_t Count,
348348
int Advice)
349349
cdef bool DPCTLQueue_IsInOrder(const DPCTLSyclQueueRef QRef)
350+
cdef DPCTLSyclEventRef DPCTLQueue_SubmitBarrier(
351+
const DPCTLSyclQueueRef QRef)
352+
cdef DPCTLSyclEventRef DPCTLQueue_SubmitBarrierForEvents(
353+
const DPCTLSyclQueueRef QRef,
354+
const DPCTLSyclEventRef *DepEvents,
355+
size_t NDepEvents)
350356

351357

352358
cdef extern from "dpctl_sycl_queue_manager.h":

dpctl/_sycl_queue.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,4 @@ cdef public class SyclQueue (_SyclQueue) [object PySyclQueueObject, type PySyclQ
8181
cpdef memcpy(self, dest, src, size_t count)
8282
cpdef prefetch(self, ptr, size_t count=*)
8383
cpdef mem_advise(self, ptr, size_t count, int mem)
84+
cpdef SyclEvent submit_barrier(self, dependent_events=*)

dpctl/_sycl_queue.pyx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ from ._backend cimport ( # noqa: E211
4343
DPCTLQueue_MemAdvise,
4444
DPCTLQueue_Memcpy,
4545
DPCTLQueue_Prefetch,
46+
DPCTLQueue_SubmitBarrierForEvents,
4647
DPCTLQueue_SubmitNDRange,
4748
DPCTLQueue_SubmitRange,
4849
DPCTLQueue_Wait,
@@ -63,6 +64,7 @@ from .enum_types import backend_type
6364
from cpython cimport pycapsule
6465
from libc.stdlib cimport free, malloc
6566

67+
import collections.abc
6668
import logging
6769

6870
__all__ = [
@@ -879,3 +881,40 @@ cdef class SyclQueue(_SyclQueue):
879881
return pycapsule.PyCapsule_New(
880882
<void *>QRef, "SyclQueueRef", &_queue_capsule_deleter
881883
)
884+
885+
cpdef SyclEvent submit_barrier(self, dependent_events=None):
886+
"""
887+
Submits a barrier to the queue.
888+
"""
889+
cdef DPCTLSyclEventRef *depEvents = NULL
890+
cdef DPCTLSyclEventRef ERef = NULL
891+
cdef size_t nDE = 0
892+
# Create the array of dependent events if any
893+
if (dependent_events is None or
894+
(isinstance(dependent_events, collections.abc.Sequence) and
895+
all([type(de) is SyclEvent for de in dependent_events]))):
896+
nDE = 0 if dependent_events is None else len(dependent_events)
897+
else:
898+
raise TypeError(
899+
"dependent_events must either None, or a sequence of "
900+
":class:`dpctl.SyclEvent` objects")
901+
if nDE > 0:
902+
depEvents = (
903+
<DPCTLSyclEventRef*>malloc(nDE*sizeof(DPCTLSyclEventRef))
904+
)
905+
if not depEvents:
906+
raise MemoryError()
907+
else:
908+
for idx, de in enumerate(dependent_events):
909+
depEvents[idx] = (<SyclEvent>de).get_event_ref()
910+
911+
ERef = DPCTLQueue_SubmitBarrierForEvents(
912+
self.get_queue_ref(), depEvents, nDE)
913+
if (depEvents is not NULL):
914+
free(depEvents)
915+
if ERef is NULL:
916+
raise SyclKernelSubmitError(
917+
"Barrier submission to Sycl queue failed."
918+
)
919+
920+
return SyclEvent._create(ERef, [])

dpctl/tests/test_sycl_queue.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,16 @@ def test_hashing_of_queue():
381381
"""
382382
queue_dict = {dpctl.SyclQueue(): "default_queue"}
383383
assert queue_dict
384+
385+
386+
def test_queue_submit_barrier(valid_filter):
387+
try:
388+
q = dpctl.SyclQueue(valid_filter)
389+
except dpctl.SyclQueueCreationError:
390+
pytest.skip("Failed to create device with supported filter")
391+
ev1 = q.submit_barrier()
392+
ev2 = q.submit_barrier()
393+
ev3 = q.submit_barrier([ev1, ev2])
394+
ev3.wait()
395+
ev1.wait()
396+
ev2.wait()

0 commit comments

Comments
 (0)