Skip to content

Commit c9b2f94

Browse files
Implementing USM memory management (#34)
* Add initial version of _memory.pyx * Import setuptools before Cython. Otherwise, both might disagree about the class to use. * Add dppl._memory Cython module. * Run dppl/tests/dppl_tests too when run all unit tests. * Add tests for memory manager. * Split tests for memory. One test one context (no, CPU, GPU). * [opt] Rename getpyexts() to extensions(). * Adds C and Cython API for portions of Sycl queue, device, context interfaces. - Separates out the queue manager from the sycl queue interface wrapper. - Added API to get context, device froma Sycl queue. - Added C-API wrappers for sycl device, queue, context interfaces exposing some of the API functionalities. More can be added as needed. - The dppl extension now defines extension types for sycl quque, device, context to mimic the C API. - Sycl queues are now returned to callers as a SyclQueue extension type rather than a Py_capsule. * Add C-API stub library for sycl memory. * Add missing DPPL_API. * Move platform specific functions into a separate file. * Create a single utility function to delete C strings. * Update backends/source/dppl_utils.cpp New line at EOF. * Add _sycl_core.pxd file. * Remove using of PyCapsule in _memory.pyx. * Small style fixes in _memory.pyx. * Moved functions from _memory.pyx to C-API interface library. * Move Cython definitions for backend to single pxd file. * Remove SyclQueue from _memory.pyx * Use SyclQueue from * Remove cl::sycl::queue from _memory.pyx * Removed commented code from _memory.pyx * Eliminate temporary context object. * Fix style. * Add MemoryUSM* classes. * Add __getbuffer__ to Shared and Host MemoryUSM classes. * Rename C-API types for USM. * Add DPPLUSM_GetPointerType and remove types from CL/sycl.hpp from _memory.pyx * Clean unused code from _memory_.pyx * Small fixes. * Remove unused code. * Fix style. * Fix style * Use wrap(). * Store context instead of queue in Memory class. * Pass queue as parameter to constructor. If queue is None then get dppl current queue. * Add comment about casting memory_ptr to char*. * Remove pointer property from Memory. * Rename file with usm tests. Co-authored-by: Diptorup Deb <[email protected]>
1 parent 811855d commit c9b2f94

12 files changed

+599
-86
lines changed

backends/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ add_library(
101101
source/dppl_sycl_platform_interface.cpp
102102
source/dppl_sycl_queue_interface.cpp
103103
source/dppl_sycl_queue_manager.cpp
104+
source/dppl_sycl_usm_interface.cpp
104105
source/dppl_utils.cpp
105106
)
106107

backends/include/dppl_sycl_types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,10 @@ typedef struct DPPLOpaqueSyclQueue *DPPLSyclQueueRef;
5555
*
5656
*/
5757
typedef struct DPPLOpaqueSyclProgram *DPPLSyclProgramRef;
58+
59+
/*!
60+
* @brief Used to pass a sycl::usm memory opaquely through DPPL interfaces.
61+
*
62+
* @see sycl::usm
63+
*/
64+
typedef struct DPPLOpaqueSyclUSM *DPPLSyclUSMRef;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//===--- dppl_sycl_usm_interface.h - DPPL-SYCL interface ---*---C++ -*---===//
2+
//
3+
// Python Data Parallel Processing Library (PyDPPL)
4+
//
5+
// Copyright 2020 Intel Corporation
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
///
21+
/// \file
22+
/// This header declares a C interface to sycl::usm interface functions.
23+
///
24+
//===----------------------------------------------------------------------===//
25+
26+
#pragma once
27+
28+
#include "dppl_data_types.h"
29+
#include "dppl_sycl_types.h"
30+
#include "Support/DllExport.h"
31+
#include "Support/ExternC.h"
32+
#include "Support/MemOwnershipAttrs.h"
33+
34+
DPPL_C_EXTERN_C_BEGIN
35+
36+
/*!
37+
* @brief Crete USM shared memory.
38+
*
39+
* @return The pointer to USM shared memory.
40+
*/
41+
DPPL_API
42+
__dppl_give DPPLSyclUSMRef
43+
DPPLmalloc_shared (size_t size, __dppl_keep const DPPLSyclQueueRef QRef);
44+
45+
/*!
46+
* @brief Crete USM host memory.
47+
*
48+
* @return The pointer to USM host memory.
49+
*/
50+
DPPL_API
51+
__dppl_give DPPLSyclUSMRef
52+
DPPLmalloc_host (size_t size, __dppl_keep const DPPLSyclQueueRef QRef);
53+
54+
/*!
55+
* @brief Crete USM device memory.
56+
*
57+
* @return The pointer to USM device memory.
58+
*/
59+
DPPL_API
60+
__dppl_give DPPLSyclUSMRef
61+
DPPLmalloc_device (size_t size, __dppl_keep const DPPLSyclQueueRef QRef);
62+
63+
/*!
64+
* @brief Free USM memory.
65+
*
66+
*/
67+
DPPL_API
68+
void DPPLfree_with_queue (__dppl_take DPPLSyclUSMRef MRef,
69+
__dppl_keep const DPPLSyclQueueRef QRef);
70+
71+
/*!
72+
* @brief Free USM memory.
73+
*
74+
*/
75+
DPPL_API
76+
void DPPLfree_with_context (__dppl_take DPPLSyclUSMRef MRef,
77+
__dppl_keep const DPPLSyclContextRef CRef);
78+
79+
/*!
80+
* @brief Get pointer type.
81+
*
82+
* @return "host", "device", "shared" or "unknown"
83+
*/
84+
DPPL_API
85+
const char *
86+
DPPLUSM_GetPointerType (__dppl_keep const DPPLSyclUSMRef MRef,
87+
__dppl_keep const DPPLSyclContextRef СRef);
88+
89+
DPPL_C_EXTERN_C_END
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//===--- dppl_sycl_usm_interface.cpp - DPPL-SYCL interface --*- C++ -*---===//
2+
//
3+
// Python Data Parallel Processing Library (PyDPPL)
4+
//
5+
// Copyright 2020 Intel Corporation
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
///
21+
/// \file
22+
/// This file implements the data types and functions declared in
23+
/// dppl_sycl_usm_interface.h.
24+
///
25+
//===----------------------------------------------------------------------===//
26+
27+
#include "dppl_sycl_usm_interface.h"
28+
#include "Support/CBindingWrapping.h"
29+
30+
#include <CL/sycl.hpp> /* SYCL headers */
31+
32+
using namespace cl::sycl;
33+
34+
namespace
35+
{
36+
// Create wrappers for C Binding types (see CBindingWrapping.h).
37+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef)
38+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPPLSyclContextRef)
39+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(void, DPPLSyclUSMRef)
40+
41+
} /* end of anonymous namespace */
42+
43+
__dppl_give DPPLSyclUSMRef
44+
DPPLmalloc_shared (size_t size, __dppl_keep const DPPLSyclQueueRef QRef)
45+
{
46+
auto Q = unwrap(QRef);
47+
auto Ptr = malloc_shared(size, *Q);
48+
return wrap(Ptr);
49+
}
50+
51+
__dppl_give DPPLSyclUSMRef
52+
DPPLmalloc_host (size_t size, __dppl_keep const DPPLSyclQueueRef QRef)
53+
{
54+
auto Q = unwrap(QRef);
55+
auto Ptr = malloc_host(size, *Q);
56+
return wrap(Ptr);
57+
}
58+
59+
__dppl_give DPPLSyclUSMRef
60+
DPPLmalloc_device (size_t size, __dppl_keep const DPPLSyclQueueRef QRef)
61+
{
62+
auto Q = unwrap(QRef);
63+
auto Ptr = malloc_device(size, *Q);
64+
return wrap(Ptr);
65+
}
66+
67+
void DPPLfree_with_queue (__dppl_take DPPLSyclUSMRef MRef,
68+
__dppl_keep const DPPLSyclQueueRef QRef)
69+
{
70+
auto Ptr = unwrap(MRef);
71+
auto Q = unwrap(QRef);
72+
free(Ptr, *Q);
73+
}
74+
75+
void DPPLfree_with_context (__dppl_take DPPLSyclUSMRef MRef,
76+
__dppl_keep const DPPLSyclContextRef СRef)
77+
{
78+
auto Ptr = unwrap(MRef);
79+
auto C = unwrap(СRef);
80+
free(Ptr, *C);
81+
}
82+
83+
const char *
84+
DPPLUSM_GetPointerType (__dppl_keep const DPPLSyclUSMRef MRef,
85+
__dppl_keep const DPPLSyclContextRef CRef)
86+
{
87+
auto Ptr = unwrap(MRef);
88+
auto C = unwrap(CRef);
89+
90+
auto kind = get_pointer_type(Ptr, *C);
91+
switch(kind) {
92+
case usm::alloc::host:
93+
return "host";
94+
case usm::alloc::device:
95+
return "device";
96+
case usm::alloc::shared:
97+
return "shared";
98+
default:
99+
return "unknown";
100+
}
101+
}

dppl/_memory.pyx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import dppl
2+
from dppl.backend cimport *
3+
from ._sycl_core cimport SyclContext, SyclQueue
4+
5+
from cpython cimport Py_buffer
6+
7+
8+
cdef class Memory:
9+
cdef DPPLSyclUSMRef memory_ptr
10+
cdef Py_ssize_t nbytes
11+
cdef SyclContext context
12+
13+
cdef _cinit(self, Py_ssize_t nbytes, ptr_type, SyclQueue queue):
14+
cdef DPPLSyclUSMRef p
15+
16+
self.memory_ptr = NULL
17+
self.nbytes = 0
18+
self.context = None
19+
20+
if (nbytes > 0):
21+
if queue is None:
22+
queue = dppl.get_current_queue()
23+
24+
if (ptr_type == "shared"):
25+
p = DPPLmalloc_shared(nbytes, queue.get_queue_ref())
26+
elif (ptr_type == "host"):
27+
p = DPPLmalloc_host(nbytes, queue.get_queue_ref())
28+
elif (ptr_type == "device"):
29+
p = DPPLmalloc_device(nbytes, queue.get_queue_ref())
30+
else:
31+
raise RuntimeError("Pointer type is unknown: {}" \
32+
.format(ptr_type))
33+
34+
if (p):
35+
self.memory_ptr = p
36+
self.nbytes = nbytes
37+
self.context = queue.get_sycl_context()
38+
else:
39+
raise RuntimeError("Null memory pointer returned")
40+
else:
41+
raise ValueError("Non-positive number of bytes found.")
42+
43+
def __dealloc__(self):
44+
if (self.memory_ptr):
45+
DPPLfree_with_context(self.memory_ptr,
46+
self.context.get_context_ref())
47+
self.memory_ptr = NULL
48+
self.nbytes = 0
49+
self.context = None
50+
51+
cdef _getbuffer(self, Py_buffer *buffer, int flags):
52+
# memory_ptr is Ref which is pointer to SYCL type. For USM it is void*.
53+
buffer.buf = <char *>self.memory_ptr
54+
buffer.format = 'B' # byte
55+
buffer.internal = NULL # see References
56+
buffer.itemsize = 1
57+
buffer.len = self.nbytes
58+
buffer.ndim = 1
59+
buffer.obj = self
60+
buffer.readonly = 0
61+
buffer.shape = &self.nbytes
62+
buffer.strides = &buffer.itemsize
63+
buffer.suboffsets = NULL # for pointer arrays only
64+
65+
property nbytes:
66+
def __get__(self):
67+
return self.nbytes
68+
69+
property _context:
70+
def __get__(self):
71+
return self.context
72+
73+
def __repr__(self):
74+
return "<Intel(R) USM allocated memory block of {} bytes at {}>" \
75+
.format(self.nbytes, hex(<object>(<Py_ssize_t>self.memory_ptr)))
76+
77+
def _usm_type(self):
78+
cdef const char* kind
79+
kind = DPPLUSM_GetPointerType(self.memory_ptr,
80+
self.context.get_context_ref())
81+
return kind.decode('UTF-8')
82+
83+
84+
cdef class MemoryUSMShared(Memory):
85+
86+
def __cinit__(self, Py_ssize_t nbytes, SyclQueue queue=None):
87+
self._cinit(nbytes, "shared", queue)
88+
89+
def __getbuffer__(self, Py_buffer *buffer, int flags):
90+
self._getbuffer(buffer, flags)
91+
92+
93+
cdef class MemoryUSMHost(Memory):
94+
95+
def __cinit__(self, Py_ssize_t nbytes, SyclQueue queue=None):
96+
self._cinit(nbytes, "host", queue)
97+
98+
def __getbuffer__(self, Py_buffer *buffer, int flags):
99+
self._getbuffer(buffer, flags)
100+
101+
102+
cdef class MemoryUSMDevice(Memory):
103+
104+
def __cinit__(self, Py_ssize_t nbytes, SyclQueue queue=None):
105+
self._cinit(nbytes, "device", queue)

dppl/_sycl_core.pxd

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
##===------------- sycl_core.pxd - DPPL interface ------*- Cython -*-------===##
2+
##
3+
## Python Data Parallel Processing Library (PyDPPL)
4+
##
5+
## Copyright 2020 Intel Corporation
6+
##
7+
## Licensed under the Apache License, Version 2.0 (the "License");
8+
## you may not use this file except in compliance with the License.
9+
## You may obtain a copy of the License at
10+
##
11+
## http://www.apache.org/licenses/LICENSE-2.0
12+
##
13+
## Unless required by applicable law or agreed to in writing, software
14+
## distributed under the License is distributed on an "AS IS" BASIS,
15+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
## See the License for the specific language governing permissions and
17+
## limitations under the License.
18+
##
19+
##===----------------------------------------------------------------------===##
20+
##
21+
## \file
22+
## This file defines the Cython interface for the Sycl API of PyDPPL.
23+
##
24+
##===----------------------------------------------------------------------===##
25+
26+
from .backend cimport *
27+
28+
29+
cdef class SyclContext:
30+
''' Wrapper class for a Sycl Context
31+
'''
32+
cdef DPPLSyclContextRef ctxt_ptr
33+
34+
@staticmethod
35+
cdef SyclContext _create (DPPLSyclContextRef ctxt)
36+
cdef DPPLSyclContextRef get_context_ref (self)
37+
38+
39+
cdef class SyclDevice:
40+
''' Wrapper class for a Sycl Device
41+
'''
42+
cdef DPPLSyclDeviceRef device_ptr
43+
cdef const char *vendor_name
44+
cdef const char *device_name
45+
cdef const char *driver_version
46+
47+
@staticmethod
48+
cdef SyclDevice _create (DPPLSyclDeviceRef dref)
49+
cdef DPPLSyclDeviceRef get_device_ptr (self)
50+
51+
52+
cdef class SyclQueue:
53+
''' Wrapper class for a Sycl queue.
54+
'''
55+
cdef DPPLSyclQueueRef queue_ptr
56+
57+
@staticmethod
58+
cdef SyclQueue _create (DPPLSyclQueueRef qref)
59+
cpdef SyclContext get_sycl_context (self)
60+
cpdef SyclDevice get_sycl_device (self)
61+
cdef DPPLSyclQueueRef get_queue_ref (self)

0 commit comments

Comments
 (0)