diff --git a/backends/include/dppl_sycl_queue_interface.h b/backends/include/dppl_sycl_queue_interface.h index 7b9002e8de..0aca3512be 100644 --- a/backends/include/dppl_sycl_queue_interface.h +++ b/backends/include/dppl_sycl_queue_interface.h @@ -63,4 +63,16 @@ DPPLQueue_GetDevice (__dppl_keep const DPPLSyclQueueRef QRef); DPPL_API void DPPLQueue_Delete (__dppl_take DPPLSyclQueueRef QRef); +/*! + * @brief C-API wrapper for sycl::queue::memcpy. It waits an event. + * + * @param QRef An opaque pointer to the sycl queue. + * @param Dest An USM pointer to the destination memory. + * @param Src An USM pointer to the source memory. + * @param Count A number of bytes to copy. + */ +DPPL_API +void DPPLQueue_Memcpy (__dppl_keep const DPPLSyclQueueRef QRef, + void *Dest, const void *Src, size_t Count); + DPPL_C_EXTERN_C_END diff --git a/backends/source/dppl_sycl_queue_interface.cpp b/backends/source/dppl_sycl_queue_interface.cpp index af3fd7a611..c2f462badf 100644 --- a/backends/source/dppl_sycl_queue_interface.cpp +++ b/backends/source/dppl_sycl_queue_interface.cpp @@ -61,3 +61,11 @@ void DPPLQueue_Delete (__dppl_take DPPLSyclQueueRef QRef) { delete unwrap(QRef); } + +void DPPLQueue_Memcpy (__dppl_take const DPPLSyclQueueRef QRef, + void *Dest, const void *Src, size_t Count) +{ + auto Q = unwrap(QRef); + auto event = Q->memcpy(Dest, Src, Count); + event.wait(); +} diff --git a/dpctl/_memory.pxd b/dpctl/_memory.pxd new file mode 100644 index 0000000000..3c868125ca --- /dev/null +++ b/dpctl/_memory.pxd @@ -0,0 +1,46 @@ +##===--------------- _memory.pxd - dpctl module --------*- Cython -*-------===## +## +## Data Parallel Control (dpCtl) +## +## Copyright 2020 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +##===----------------------------------------------------------------------===## + +# distutils: language = c++ +# cython: language_level=3 + +from .backend cimport DPPLSyclUSMRef +from ._sycl_core cimport SyclQueue + + +cdef class Memory: + cdef DPPLSyclUSMRef memory_ptr + cdef Py_ssize_t nbytes + cdef SyclQueue queue + + cdef _cinit(self, Py_ssize_t nbytes, ptr_type, SyclQueue queue) + cdef _getbuffer(self, Py_buffer *buffer, int flags) + + +cdef class MemoryUSMShared(Memory): + pass + + +cdef class MemoryUSMHost(Memory): + pass + + +cdef class MemoryUSMDevice(Memory): + pass diff --git a/dpctl/_memory.pyx b/dpctl/_memory.pyx index 97ff0dcdc5..1671d3bb7c 100644 --- a/dpctl/_memory.pyx +++ b/dpctl/_memory.pyx @@ -36,9 +36,6 @@ from cpython cimport Py_buffer cdef class Memory: - cdef DPPLSyclUSMRef memory_ptr - cdef Py_ssize_t nbytes - cdef SyclQueue queue cdef _cinit(self, Py_ssize_t nbytes, ptr_type, SyclQueue queue): cdef DPPLSyclUSMRef p diff --git a/dpctl/_sycl_core.pxd b/dpctl/_sycl_core.pxd index caa18814d8..b10afa787e 100644 --- a/dpctl/_sycl_core.pxd +++ b/dpctl/_sycl_core.pxd @@ -63,3 +63,4 @@ cdef class SyclQueue: cpdef SyclContext get_sycl_context (self) cpdef SyclDevice get_sycl_device (self) cdef DPPLSyclQueueRef get_queue_ref (self) + cpdef memcpy (self, dest, src, int count) diff --git a/dpctl/backend.pxd b/dpctl/backend.pxd index f15f51b529..cab1b7430d 100644 --- a/dpctl/backend.pxd +++ b/dpctl/backend.pxd @@ -78,6 +78,9 @@ cdef extern from "dppl_sycl_queue_interface.h": except+ cdef DPPLSyclDeviceRef DPPLQueue_GetDevice (const DPPLSyclQueueRef Q) \ except + + cdef void DPPLQueue_Memcpy (const DPPLSyclQueueRef Q, + void *Dest, const void *Src, size_t Count) \ + except + cdef extern from "dppl_sycl_queue_manager.h": diff --git a/dpctl/sycl_core.pyx b/dpctl/sycl_core.pyx index 15f51c4928..b1a5df9b8c 100644 --- a/dpctl/sycl_core.pyx +++ b/dpctl/sycl_core.pyx @@ -29,7 +29,8 @@ from __future__ import print_function from enum import Enum, auto import logging -from dpctl.backend cimport * +from .backend cimport * +from ._memory cimport Memory _logger = logging.getLogger(__name__) @@ -132,6 +133,22 @@ cdef class SyclQueue: cdef DPPLSyclQueueRef get_queue_ref (self): return self.queue_ptr + cpdef memcpy (self, dest, src, int count): + cdef void *c_dest + cdef void *c_src + + if isinstance(dest, Memory): + c_dest = (dest).memory_ptr + else: + raise TypeError("Parameter dest should be Memory.") + + if isinstance(src, Memory): + c_src = (src).memory_ptr + else: + raise TypeError("Parameter src should be Memory.") + + DPPLQueue_Memcpy(self.queue_ptr, c_dest, c_src, count) + cdef class _SyclQueueManager: def _set_as_current_queue (self, device_ty, device_id): diff --git a/dpctl/tests/test_sycl_queue_memcpy.py b/dpctl/tests/test_sycl_queue_memcpy.py new file mode 100644 index 0000000000..6cb95ea63e --- /dev/null +++ b/dpctl/tests/test_sycl_queue_memcpy.py @@ -0,0 +1,70 @@ +##===---------- test_sycl_queue_manager.py - dpctl -------*- Python -*----===## +## +## Data Parallel Control (dpCtl) +## +## Copyright 2020 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +##===----------------------------------------------------------------------===## +### +### \file +### Defines unit test cases for the SyclQueue.memcpy in sycl_core.pyx. +##===----------------------------------------------------------------------===## + +import dpctl +import unittest + + + +class TestQueueMemcpy (unittest.TestCase): + + def _create_memory (self): + nbytes = 1024 + queue = dpctl.get_current_queue() + mobj = dpctl._memory.MemoryUSMShared(nbytes, queue) + return mobj + + def test_memcpy_copy_usm_to_usm (self): + mobj1 = self._create_memory() + mobj2 = self._create_memory() + q = dpctl.get_current_queue() + + mv1 = memoryview(mobj1) + mv2 = memoryview(mobj2) + + mv1[:3] = b'123' + + q.memcpy(mobj2, mobj1, 3) + + self.assertEqual(mv2[:3], b'123') + + def test_memcpy_type_error (self): + mobj = self._create_memory() + q = dpctl.get_current_queue() + + with self.assertRaises(TypeError) as cm: + q.memcpy(None, mobj, 3) + + self.assertEqual(type(cm.exception), TypeError) + self.assertEqual(str(cm.exception), "Parameter dest should be Memory.") + + with self.assertRaises(TypeError) as cm: + q.memcpy(mobj, None, 3) + + self.assertEqual(type(cm.exception), TypeError) + self.assertEqual(str(cm.exception), "Parameter src should be Memory.") + + +if __name__ == '__main__': + unittest.main() diff --git a/dpctl/tests/test_sycl_usm.py b/dpctl/tests/test_sycl_usm.py index 3737a01a4c..895a9f5180 100644 --- a/dpctl/tests/test_sycl_usm.py +++ b/dpctl/tests/test_sycl_usm.py @@ -78,6 +78,13 @@ def test_memory_gpu_context (self): self.assertTrue(usm_type in ['unknown', 'shared']) + def test_buffer_protocol (self): + mobj = self._create_memory() + mv1 = memoryview(mobj) + mv2 = memoryview(mobj) + self.assertEqual(mv1, mv2) + + class TestMemoryUSMBase: """ Base tests for MemoryUSM* """ @@ -116,5 +123,6 @@ class TestMemoryUSMDevice(TestMemoryUSMBase, unittest.TestCase): MemoryUSMClass = MemoryUSMDevice usm_type = 'device' + if __name__ == '__main__': unittest.main()