Skip to content

Commit 7fc8e51

Browse files
committed
add realloc to MKLMemory
as atomics are a c11+ feature, specific flags are needed to enable on window
1 parent 5f82a77 commit 7fc8e51

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

meson.build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ project(
77
check: true
88
).stdout().strip(),
99
default_options: [
10+
'c_std=c11',
1011
'buildtype=release',
1112
]
1213
)
@@ -18,6 +19,13 @@ c_args = ['-DNDEBUG']
1819
thread_dep = dependency('threads')
1920

2021
cc = meson.get_compiler('c')
22+
if cc.get_id() == 'msvc'
23+
add_project_arguments(
24+
'/experimental:c11atomics',
25+
language: 'c'
26+
)
27+
endif
28+
2129
mkl_dep = dependency('MKL', method: 'cmake',
2230
modules: ['MKL::MKL'],
2331
cmake_args: [

mkl/_mkl_memory.pyx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,25 @@ import numbers
3131
from cpython cimport Py_buffer
3232
from libc.string cimport memcpy
3333

34-
from mkl._mkl_service cimport mkl_malloc, mkl_free
34+
from mkl._mkl_service cimport mkl_malloc, mkl_realloc, mkl_free
35+
36+
cdef extern from "stdatomic.h" nogil:
37+
ctypedef int atomic_int "_Atomic int"
38+
void atomic_init(atomic_int *obj, int value)
39+
int atomic_fetch_add(atomic_int *obj, int value)
40+
int atomic_fetch_sub(atomic_int *obj, int value)
41+
int atomic_load(atomic_int *obj)
3542

3643

3744
cdef class MKLMemory:
3845
cdef void *_memory_ptr
3946
cdef Py_ssize_t nbytes
47+
cdef atomic_int exported_buffers
4048

4149
cdef _cinit_empty(self):
4250
self._memory_ptr = NULL
4351
self.nbytes = 0
52+
atomic_init(&self.exported_buffers, 0)
4453

4554
cdef _cinit_alloc(self, Py_ssize_t nbytes, Py_ssize_t alignment):
4655
self._cinit_empty()
@@ -100,5 +109,23 @@ cdef class MKLMemory:
100109
buffer.strides = &buffer.itemsize
101110
buffer.suboffsets = NULL # for pointer arrays only
102111

112+
atomic_fetch_add(&self.exported_buffers, 1)
113+
103114
def __releasebuffer__(self, Py_buffer *buffer):
104-
pass
115+
atomic_fetch_sub(&self.exported_buffers, 1)
116+
117+
def realloc(self, Py_ssize_t new_nbytes):
118+
if atomic_load(&self.exported_buffers) > 0:
119+
raise BufferError("Cannot realloc memory while there are exported buffers.")
120+
if new_nbytes <= 0:
121+
raise ValueError("New number of bytes must be positive.")
122+
123+
cdef void *p
124+
with nogil:
125+
p = mkl_realloc(self._memory_ptr, new_nbytes)
126+
127+
if not p:
128+
raise MemoryError("MKL memory reallocation failed.")
129+
130+
self._memory_ptr = p
131+
self.nbytes = new_nbytes

mkl/_mkl_service.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ cdef extern from "mkl.h":
152152
MKL_INT64 mkl_peak_mem_usage(int mode)
153153
int mkl_set_memory_limit(int mem_type, size_t limit)
154154
void *mkl_malloc(size_t size, int alignment) nogil
155+
void *mkl_realloc(void *ptr, size_t size) nogil
155156
void mkl_free(void *ptr) nogil
156157

157158
# Conditional Numerical Reproducibility

0 commit comments

Comments
 (0)