Skip to content

Commit 39efdaf

Browse files
committed
Implement an SVM memory pool
1 parent b4792ac commit 39efdaf

File tree

7 files changed

+371
-144
lines changed

7 files changed

+371
-144
lines changed

examples/demo_array_svm.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pyopencl as cl
22
import pyopencl.array as cl_array
3-
from pyopencl.tools import SVMAllocator
3+
from pyopencl.tools import SVMAllocator, SVMPool
44
import numpy as np
55
import numpy.linalg as la
66

@@ -12,7 +12,8 @@
1212
ctx = cl.create_some_context()
1313
queue = cl.CommandQueue(ctx)
1414

15-
alloc = SVMAllocator(ctx, cl.svm_mem_flags.READ_WRITE, queue=queue)
15+
alloc = SVMAllocator(ctx, alignment=0, queue=queue)
16+
alloc = SVMPool(alloc)
1617

1718
a_dev = cl_array.to_device(queue, a, allocator=alloc)
1819
print("A_DEV", a_dev.data)

pyopencl/__init__.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,21 +1142,6 @@ def memory_map_exit(self, exc_type, exc_val, exc_tb):
11421142
.. automethod:: enqueue_release
11431143
"""
11441144

1145-
if get_cl_header_version() >= (2, 0):
1146-
class _ArrayInterfaceSVMAllocation(SVMAllocation):
1147-
def __init__(self, ctx, size, alignment, flags, _interface=None,
1148-
queue=None):
1149-
"""
1150-
:arg ctx: a :class:`Context`
1151-
:arg flags: some of :class:`svm_mem_flags`.
1152-
"""
1153-
super().__init__(ctx, size, alignment, flags, queue)
1154-
1155-
# mem_flags.READ_ONLY applies to kernels, not the host
1156-
read_write = True
1157-
_interface["data"] = (
1158-
int(self._ptr_as_int()), not read_write)
1159-
11601145
# }}}
11611146

11621147
# {{{ SVM
@@ -1399,6 +1384,25 @@ def gl_object_get_gl_object(self):
13991384

14001385
# }}}
14011386

1387+
# {{{ _ArrayInterfaceSVMAllocation
1388+
1389+
if get_cl_header_version() >= (2, 0):
1390+
class _ArrayInterfaceSVMAllocation(SVMAllocation):
1391+
def __init__(self, ctx, size, alignment, flags, _interface=None,
1392+
queue=None):
1393+
"""
1394+
:arg ctx: a :class:`Context`
1395+
:arg flags: some of :class:`svm_mem_flags`.
1396+
"""
1397+
super().__init__(ctx, size, alignment, flags, queue)
1398+
1399+
# mem_flags.READ_ONLY applies to kernels, not the host
1400+
read_write = True
1401+
_interface["data"] = (
1402+
int(self.int_ptr), not read_write)
1403+
1404+
# }}}
1405+
14021406

14031407
# {{{ create_some_context
14041408

@@ -1965,7 +1969,7 @@ def enqueue_svm_memfill(queue, dest, pattern, byte_count=None, wait_for=None):
19651969
"""
19661970

19671971
if not isinstance(dest, SVMPointer):
1968-
dest = SVMPointer(dest)
1972+
dest = SVM(dest)
19691973

19701974
return _cl._enqueue_svm_memfill(
19711975
queue, dest, pattern, byte_count=None, wait_for=None)

pyopencl/tools.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
import numpy as np
3535
from pytools import memoize, memoize_method
36-
from pyopencl._cl import bitlog2 # noqa: F401
36+
from pyopencl._cl import bitlog2, get_cl_header_version # noqa: F401
3737
from pytools.persistent_dict import KeyBuilder as KeyBuilderBase
3838

3939
import re
@@ -59,29 +59,19 @@ def _register_types():
5959
# {{{ imported names
6060

6161
from pyopencl._cl import ( # noqa
62-
PooledBuffer as PooledBuffer,
62+
_tools_PooledBuffer as PooledBuffer,
6363
_tools_DeferredAllocator as DeferredAllocator,
6464
_tools_ImmediateAllocator as ImmediateAllocator,
65-
MemoryPool as MemoryPool)
65+
_tools_MemoryPool as MemoryPool,
66+
)
6667

67-
# }}}
68-
69-
70-
# {{{ svm allocator
7168

72-
# FIXME: Replace me with C++
73-
class SVMAllocator:
74-
def __init__(self, ctx, flags, *, alignment=0, queue=None):
75-
self._context = ctx
76-
self._flags = flags
77-
self._alignment = alignment
78-
self._queue = queue
79-
80-
def __call__(self, nbytes):
81-
import pyopencl as cl
82-
return cl.SVMAllocation(
83-
self._context, nbytes, self._alignment, self._flags,
84-
queue=self._queue)
69+
if get_cl_header_version() >= (2, 0):
70+
from pyopencl._cl import ( # noqa
71+
_tools_SVMPool as SVMPool,
72+
_tools_PooledSVM as PooledSVM,
73+
_tools_SVMAllocator as SVMAllocator,
74+
)
8575

8676
# }}}
8777

src/mempool.hpp

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ namespace PYGPU_PACKAGE
102102
container_t m_container;
103103
typedef typename container_t::value_type bin_pair_t;
104104

105-
std::unique_ptr<Allocator> m_allocator;
105+
std::shared_ptr<Allocator> m_allocator;
106106

107107
// A held block is one that's been released by the application, but that
108108
// we are keeping around to dish out again.
@@ -125,8 +125,8 @@ namespace PYGPU_PACKAGE
125125
unsigned m_leading_bits_in_bin_id;
126126

127127
public:
128-
memory_pool(Allocator const &alloc=Allocator(), unsigned leading_bits_in_bin_id=4)
129-
: m_allocator(alloc.copy()),
128+
memory_pool(std::shared_ptr<Allocator> alloc, unsigned leading_bits_in_bin_id=4)
129+
: m_allocator(alloc),
130130
m_held_blocks(0), m_active_blocks(0),
131131
m_managed_bytes(0), m_active_bytes(0),
132132
m_stop_holding(false),
@@ -233,7 +233,8 @@ namespace PYGPU_PACKAGE
233233
std::cout
234234
<< "[pool] allocation of size " << size << " served from bin " << bin_nr
235235
<< " which contained " << bin.size() << " entries" << std::endl;
236-
return pop_block_from_bin(bin, size);
236+
return m_allocator->hand_out_existing_block(
237+
pop_block_from_bin(bin, size));
237238
}
238239

239240
size_type alloc_sz = alloc_size(bin_nr);
@@ -256,7 +257,8 @@ namespace PYGPU_PACKAGE
256257

257258
m_allocator->try_release_blocks();
258259
if (bin.size())
259-
return pop_block_from_bin(bin, size);
260+
return m_allocator->hand_out_existing_block(
261+
pop_block_from_bin(bin, size));
260262

261263
if (m_trace)
262264
std::cout << "[pool] allocation still OOM after GC" << std::endl;
@@ -282,7 +284,7 @@ namespace PYGPU_PACKAGE
282284
"failed to free memory for allocation");
283285
}
284286

285-
void free(pointer_type p, size_type size)
287+
void free(pointer_type &&p, size_type size)
286288
{
287289
--m_active_blocks;
288290
m_active_bytes -= size;
@@ -291,7 +293,7 @@ namespace PYGPU_PACKAGE
291293
if (!m_stop_holding)
292294
{
293295
inc_held_blocks();
294-
get_bin(bin_nr).push_back(p);
296+
get_bin(bin_nr).push_back(std::move(p));
295297

296298
if (m_trace)
297299
std::cout << "[pool] block of size " << size << " returned to bin "
@@ -300,7 +302,7 @@ namespace PYGPU_PACKAGE
300302
}
301303
else
302304
{
303-
m_allocator->free(p);
305+
m_allocator->free(std::move(p));
304306
m_managed_bytes -= alloc_size(bin_nr);
305307
}
306308
}
@@ -313,7 +315,7 @@ namespace PYGPU_PACKAGE
313315

314316
while (bin.size())
315317
{
316-
m_allocator->free(bin.back());
318+
m_allocator->free(std::move(bin.back()));
317319
m_managed_bytes -= alloc_size(bin_pair.first);
318320
bin.pop_back();
319321

@@ -353,7 +355,7 @@ namespace PYGPU_PACKAGE
353355

354356
if (bin.size())
355357
{
356-
m_allocator->free(bin.back());
358+
m_allocator->free(std::move(bin.back()));
357359
m_managed_bytes -= alloc_size(bin_pair.first);
358360
bin.pop_back();
359361

@@ -379,7 +381,7 @@ namespace PYGPU_PACKAGE
379381

380382
pointer_type pop_block_from_bin(bin_t &bin, size_type size)
381383
{
382-
pointer_type result = bin.back();
384+
pointer_type result(std::move(bin.back()));
383385
bin.pop_back();
384386

385387
dec_held_blocks();
@@ -399,7 +401,7 @@ namespace PYGPU_PACKAGE
399401
typedef typename Pool::pointer_type pointer_type;
400402
typedef typename Pool::size_type size_type;
401403

402-
private:
404+
protected:
403405
PYGPU_SHARED_PTR<pool_type> m_pool;
404406

405407
pointer_type m_ptr;
@@ -421,7 +423,7 @@ namespace PYGPU_PACKAGE
421423
{
422424
if (m_valid)
423425
{
424-
m_pool->free(m_ptr, m_size);
426+
m_pool->free(std::move(m_ptr), m_size);
425427
m_valid = false;
426428
}
427429
else
@@ -435,16 +437,8 @@ namespace PYGPU_PACKAGE
435437
#endif
436438
);
437439
}
438-
439-
pointer_type ptr() const
440-
{ return m_ptr; }
441-
442-
size_type size() const
443-
{ return m_size; }
444440
};
445441
}
446442

447443

448-
449-
450444
#endif

0 commit comments

Comments
 (0)