Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python bindings for limiting_resource_adaptor #1327

Merged
merged 5 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions python/rmm/_lib/memory_resource.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ cdef class CallbackMemoryResource(DeviceMemoryResource):
cdef object _allocate_func
cdef object _deallocate_func

cdef class LimitingResourceAdaptor(UpstreamResourceAdaptor):
pass

cdef class LoggingResourceAdaptor(UpstreamResourceAdaptor):
cdef object _log_file_name
cpdef get_file_name(self)
Expand Down
65 changes: 65 additions & 0 deletions python/rmm/_lib/memory_resource.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ cdef extern from "rmm/mr/device/binning_memory_resource.hpp" \
size_t allocation_size,
device_memory_resource* bin_resource) except +

cdef extern from "rmm/mr/device/limiting_resource_adaptor.hpp" \
namespace "rmm::mr" nogil:
cdef cppclass limiting_resource_adaptor[Upstream](device_memory_resource):
limiting_resource_adaptor(
Upstream* upstream_mr,
size_t allocation_limit) except +

size_t get_allocated_bytes() except +
size_t get_allocation_limit() except +

cdef extern from "rmm/mr/device/logging_resource_adaptor.hpp" \
namespace "rmm::mr" nogil:
cdef cppclass logging_resource_adaptor[Upstream](device_memory_resource):
Expand Down Expand Up @@ -649,6 +659,61 @@ def _append_id(filename, id):
return f"{name}.dev{id}{ext}"


cdef class LimitingResourceAdaptor(UpstreamResourceAdaptor):

def __cinit__(
self,
DeviceMemoryResource upstream_mr,
size_t allocation_limit
):
self.c_obj.reset(
new limiting_resource_adaptor[device_memory_resource](
upstream_mr.get_mr(),
allocation_limit
)
)

def __init__(
self,
DeviceMemoryResource upstream_mr,
size_t allocation_limit
):
"""
Memory resource that limits the total allocation amount possible
performed by an upstream memory resource.

Parameters
----------
upstream_mr : DeviceMemoryResource
The upstream memory resource.
allocation_limit : size_t
Maximum memory allowed for this allocator.
"""
pass

def get_allocated_bytes(self) -> size_t:
"""
Query the number of bytes that have been allocated. Note that this can
not be used to know how large of an allocation is possible due to both
possible fragmentation and also internal page sizes and alignment that
is not tracked by this allocator.
"""
return (<limiting_resource_adaptor[device_memory_resource]*>(
self.c_obj.get())
)[0].get_allocated_bytes()

def get_allocation_limit(self) -> size_t:
"""
Query the maximum number of bytes that this allocator is allowed to
allocate. This is the limit on the allocator and not a representation
of the underlying device. The device may not be able to support this
limit.
"""
return (<limiting_resource_adaptor[device_memory_resource]*>(
self.c_obj.get())
)[0].get_allocation_limit()


cdef class LoggingResourceAdaptor(UpstreamResourceAdaptor):
def __cinit__(
self,
Expand Down
2 changes: 2 additions & 0 deletions python/rmm/mr.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
DeviceMemoryResource,
FailureCallbackResourceAdaptor,
FixedSizeMemoryResource,
LimitingResourceAdaptor,
LoggingResourceAdaptor,
ManagedMemoryResource,
PoolMemoryResource,
Expand Down Expand Up @@ -46,6 +47,7 @@
"CudaMemoryResource",
"DeviceMemoryResource",
"FixedSizeMemoryResource",
"LimitingResourceAdaptor",
"LoggingResourceAdaptor",
"ManagedMemoryResource",
"PoolMemoryResource",
Expand Down
35 changes: 35 additions & 0 deletions python/rmm/tests/test_rmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,41 @@ def test_cuda_async_memory_resource_threshold(nelem, alloc):
array_tester("u1", 2 * nelem, alloc) # should trigger release


@pytest.mark.parametrize(
"mr",
[
rmm.mr.CudaMemoryResource,
pytest.param(
rmm.mr.CudaAsyncMemoryResource,
marks=pytest.mark.skipif(
not _CUDAMALLOC_ASYNC_SUPPORTED,
reason="cudaMallocAsync not supported",
),
),
],
)
def test_limiting_resource_adaptor(mr):
cuda_mr = mr()

allocation_limit = 1 << 20
wence- marked this conversation as resolved.
Show resolved Hide resolved
num_buffers = 2
buffer_size = allocation_limit / num_buffers
vyasr marked this conversation as resolved.
Show resolved Hide resolved

mr = rmm.mr.LimitingResourceAdaptor(
cuda_mr, allocation_limit=allocation_limit
)
assert mr.get_allocation_limit() == allocation_limit

rmm.mr.set_current_device_resource(mr)

buffers = [rmm.DeviceBuffer(size=buffer_size) for _ in range(num_buffers)]

assert mr.get_allocated_bytes() == buffer_size * num_buffers

with pytest.raises(MemoryError):
rmm.DeviceBuffer(size=1)


def test_statistics_resource_adaptor(stats_mr):

buffers = [rmm.DeviceBuffer(size=1000) for _ in range(10)]
Expand Down
Loading