Skip to content

Commit 5a29a5a

Browse files
authored
Add BufferResource.memory_available Python API (rapidsai#495)
Changes in this PR: - Adds a Python API for `BufferResource.memory_available`. - ~Adds an additional `BufferResource.device_memory_available` API for convenience.~ - Adds test coverage to `test_buffer_resource.py` **Background**: I've been experimenting with spilling improvements in cudf-polars (e.g. rapidsai#489). While prototyping next steps, I found myself needing to query the amount of available device memory within a cudf-polars task. As far as I can tell, this is not currently possible, because we do not have access to the `LimitAvailableMemory` object used to construct the workers `BufferResource`. Therefore, we need bindings for `BufferResource.memory_available` to get this information from the `BufferResource` itself (Please do let me know if I'm mistaken about this). **Note**: My Cython skills are limited, so feel free to suggest dramatic changes :) Authors: - Richard (Rick) Zamora (https://github.com/rjzamora) Approvers: - Mads R. B. Kristensen (https://github.com/madsbk) URL: rapidsai#495
1 parent d939029 commit 5a29a5a

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

python/rapidsmpf/rapidsmpf/buffer/resource.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ cdef extern from "<rapidsmpf/buffer/resource.hpp>" nogil:
3232
size_t cpp_memory_reserved "memory_reserved"(
3333
MemoryType mem_type
3434
) except +
35+
cpp_MemoryAvailable cpp_memory_available "memory_available"(
36+
MemoryType mem_type
37+
) except +
3538
cpp_SpillManager &cpp_spill_manager "spill_manager"() except +
3639

3740

python/rapidsmpf/rapidsmpf/buffer/resource.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class BufferResource:
1616
memory_available: Mapping[MemoryType, Callable[[], int]] | None = None,
1717
periodic_spill_check: float | None = 1e-3,
1818
) -> None: ...
19+
def memory_available(self, mem_type: MemoryType) -> int: ...
1920
def memory_reserved(self, mem_type: MemoryType) -> int: ...
2021
@property
2122
def spill_manager(self) -> SpillManager: ...

python/rapidsmpf/rapidsmpf/buffer/resource.pyx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,21 @@ cdef extern from *:
1616
) {
1717
return *functor;
1818
}
19+
20+
std::int64_t _call_memory_available(
21+
rapidsmpf::BufferResource* resource,
22+
rapidsmpf::MemoryType mem_type
23+
) {
24+
return resource->memory_available(mem_type)();
25+
}
1926
"""
2027
cpp_MemoryAvailable to_MemoryAvailable(
2128
shared_ptr[cpp_LimitAvailableMemory]
2229
) except +
30+
int64_t _call_memory_available(
31+
cpp_BufferResource* resource,
32+
MemoryType mem_type
33+
) except + nogil
2334

2435

2536
cdef class BufferResource:
@@ -121,6 +132,17 @@ cdef class BufferResource:
121132
ret = deref(self._handle).cpp_memory_reserved(mem_type)
122133
return ret
123134

135+
def memory_available(self, MemoryType mem_type):
136+
"""
137+
Get the current available memory of the specified memory type.
138+
"""
139+
cdef int64_t ret
140+
cdef cpp_BufferResource* resource_ptr = self.ptr()
141+
# Use inline C++ to handle the function object call
142+
with nogil:
143+
ret = _call_memory_available(resource_ptr, mem_type)
144+
return ret
145+
124146

125147
cdef class LimitAvailableMemory:
126148
"""

python/rapidsmpf/rapidsmpf/tests/test_buffer_resource.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ def test_buffer_resource() -> None:
6161
assert br.memory_reserved(MemoryType.DEVICE) == 0
6262
assert br.memory_reserved(MemoryType.HOST) == 0
6363

64+
# Chack BufferResource.memory_available
65+
assert br.memory_available(MemoryType.DEVICE) == mem_available() == KiB(100)
66+
buf1 = rmm.DeviceBuffer(size=KiB(50), mr=mr)
67+
assert br.memory_available(MemoryType.DEVICE) == mem_available() == KiB(50)
68+
del buf1
69+
assert br.memory_available(MemoryType.DEVICE) == mem_available() == KiB(100)
70+
6471
# TODO: add more `BufferResource` checks here as we add python bindings.

0 commit comments

Comments
 (0)