@@ -35,6 +35,8 @@ from ._backend cimport ( # noqa: E211
3535 DPCTLFilterSelector_Create,
3636 DPCTLQueue_AreEq,
3737 DPCTLQueue_Copy,
38+ DPCTLQueue_CopyData,
39+ DPCTLQueue_CopyDataWithEvents,
3840 DPCTLQueue_Create,
3941 DPCTLQueue_Delete,
4042 DPCTLQueue_GetBackend,
@@ -535,6 +537,80 @@ cdef DPCTLSyclEventRef _memcpy_impl(
535537 return ERef
536538
537539
540+ cdef DPCTLSyclEventRef _copy_impl(
541+ SyclQueue q,
542+ object dst,
543+ object src,
544+ size_t byte_count,
545+ DPCTLSyclEventRef * dep_events,
546+ size_t dep_events_count
547+ ) except * :
548+ cdef void * c_dst_ptr = NULL
549+ cdef void * c_src_ptr = NULL
550+ cdef DPCTLSyclEventRef ERef = NULL
551+ cdef Py_buffer src_buf_view
552+ cdef Py_buffer dst_buf_view
553+ cdef bint src_is_buf = False
554+ cdef bint dst_is_buf = False
555+ cdef int ret_code = 0
556+
557+ if isinstance (src, _Memory):
558+ c_src_ptr = < void * > (< _Memory> src).get_data_ptr()
559+ elif _is_buffer(src):
560+ ret_code = PyObject_GetBuffer(
561+ src, & src_buf_view, PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS
562+ )
563+ if ret_code != 0 : # pragma: no cover
564+ raise RuntimeError (" Could not access buffer" )
565+ c_src_ptr = src_buf_view.buf
566+ src_is_buf = True
567+ else :
568+ raise TypeError (
569+ " Parameter `src` should have either type "
570+ " `dpctl.memory._Memory` or a type that "
571+ " supports Python buffer protocol"
572+ )
573+
574+ if isinstance (dst, _Memory):
575+ c_dst_ptr = < void * > (< _Memory> dst).get_data_ptr()
576+ elif _is_buffer(dst):
577+ ret_code = PyObject_GetBuffer(
578+ dst, & dst_buf_view,
579+ PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS | PyBUF_WRITABLE
580+ )
581+ if ret_code != 0 : # pragma: no cover
582+ if src_is_buf:
583+ PyBuffer_Release(& src_buf_view)
584+ raise RuntimeError (" Could not access buffer" )
585+ c_dst_ptr = dst_buf_view.buf
586+ dst_is_buf = True
587+ else :
588+ raise TypeError (
589+ " Parameter `dst` should have either type "
590+ " `dpctl.memory._Memory` or a type that "
591+ " supports Python buffer protocol"
592+ )
593+
594+ if dep_events_count == 0 or dep_events is NULL :
595+ ERef = DPCTLQueue_CopyData(q._queue_ref, c_dst_ptr, c_src_ptr, byte_count)
596+ else :
597+ ERef = DPCTLQueue_CopyDataWithEvents(
598+ q._queue_ref,
599+ c_dst_ptr,
600+ c_src_ptr,
601+ byte_count,
602+ dep_events,
603+ dep_events_count
604+ )
605+
606+ if src_is_buf:
607+ PyBuffer_Release(& src_buf_view)
608+ if dst_is_buf:
609+ PyBuffer_Release(& dst_buf_view)
610+
611+ return ERef
612+
613+
538614cdef class _SyclQueue:
539615 """ Barebone data owner class used by SyclQueue.
540616 """
@@ -1426,6 +1502,82 @@ cdef class SyclQueue(_SyclQueue):
14261502
14271503 return SyclEvent._create(ERef)
14281504
1505+ cpdef copy(self , dest, src, size_t count):
1506+ """ Copy ``count`` bytes from ``src`` to ``dest`` and wait.
1507+
1508+ Internally, this dispatches ``sycl::queue::copy`` instantiated for
1509+ byte-sized elements.
1510+
1511+ This is a synchronizing variant corresponding to
1512+ :meth:`dpctl.SyclQueue.copy_async`.
1513+ """
1514+ cdef DPCTLSyclEventRef ERef = NULL
1515+
1516+ ERef = _copy_impl(< SyclQueue> self , dest, src, count, NULL , 0 )
1517+ if (ERef is NULL ):
1518+ raise RuntimeError (
1519+ " SyclQueue.copy operation encountered an error"
1520+ )
1521+ with nogil:
1522+ DPCTLEvent_Wait(ERef)
1523+ DPCTLEvent_Delete(ERef)
1524+
1525+ cpdef SyclEvent copy_async(
1526+ self , dest, src, size_t count, list dEvents = None
1527+ ):
1528+ """ Copy ``count`` bytes from ``src`` to ``dest`` asynchronously.
1529+
1530+ Internally, this dispatches ``sycl::queue::copy`` instantiated for
1531+ byte-sized elements.
1532+
1533+ Args:
1534+ dest:
1535+ Destination USM object or Python object supporting
1536+ writable buffer protocol.
1537+ src:
1538+ Source USM object or Python object supporting buffer
1539+ protocol.
1540+ count (int):
1541+ Number of bytes to copy.
1542+ dEvents (List[dpctl.SyclEvent], optional):
1543+ Events that this copy depends on.
1544+
1545+ Returns:
1546+ dpctl.SyclEvent:
1547+ Event associated with the copy operation.
1548+ """
1549+ cdef DPCTLSyclEventRef ERef = NULL
1550+ cdef DPCTLSyclEventRef * depEvents = NULL
1551+ cdef size_t nDE = 0
1552+
1553+ if dEvents is None :
1554+ ERef = _copy_impl(< SyclQueue> self , dest, src, count, NULL , 0 )
1555+ else :
1556+ nDE = len (dEvents)
1557+ depEvents = (
1558+ < DPCTLSyclEventRef* > malloc(nDE* sizeof(DPCTLSyclEventRef))
1559+ )
1560+ if depEvents is NULL :
1561+ raise MemoryError ()
1562+ else :
1563+ for idx, de in enumerate (dEvents):
1564+ if isinstance (de, SyclEvent):
1565+ depEvents[idx] = (< SyclEvent> de).get_event_ref()
1566+ else :
1567+ free(depEvents)
1568+ raise TypeError (
1569+ " A sequence of dpctl.SyclEvent is expected"
1570+ )
1571+ ERef = _copy_impl(self , dest, src, count, depEvents, nDE)
1572+ free(depEvents)
1573+
1574+ if (ERef is NULL ):
1575+ raise RuntimeError (
1576+ " SyclQueue.copy operation encountered an error"
1577+ )
1578+
1579+ return SyclEvent._create(ERef)
1580+
14291581 cpdef prefetch(self , mem, size_t count = 0 ):
14301582 cdef void * ptr
14311583 cdef DPCTLSyclEventRef ERef = NULL
0 commit comments