Skip to content

Commit e128f67

Browse files
authored
Merge branch 'main' into fix/gb300-arena-test-timeout
2 parents 0067d3e + 06b5776 commit e128f67

10 files changed

Lines changed: 281 additions & 16 deletions

File tree

conda/environments/all_cuda-129_arch-aarch64.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies:
3535
- pytest-cov
3636
- python>=3.11
3737
- rapids-build-backend>=0.4.0,<0.5.0
38-
- rapids-logger==0.2.*,>=0.0.0a0
38+
- rapids-logger==0.3.*
3939
- scikit-build-core>=0.11.0
4040
- sphinx
4141
- sphinx-copybutton

conda/environments/all_cuda-129_arch-x86_64.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies:
3535
- pytest-cov
3636
- python>=3.11
3737
- rapids-build-backend>=0.4.0,<0.5.0
38-
- rapids-logger==0.2.*,>=0.0.0a0
38+
- rapids-logger==0.3.*
3939
- scikit-build-core>=0.11.0
4040
- sphinx
4141
- sphinx-copybutton

conda/environments/all_cuda-133_arch-aarch64.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies:
3535
- pytest-cov
3636
- python>=3.11
3737
- rapids-build-backend>=0.4.0,<0.5.0
38-
- rapids-logger==0.2.*,>=0.0.0a0
38+
- rapids-logger==0.3.*
3939
- scikit-build-core>=0.11.0
4040
- sphinx
4141
- sphinx-copybutton

conda/environments/all_cuda-133_arch-x86_64.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies:
3535
- pytest-cov
3636
- python>=3.11
3737
- rapids-build-backend>=0.4.0,<0.5.0
38-
- rapids-logger==0.2.*,>=0.0.0a0
38+
- rapids-logger==0.3.*
3939
- scikit-build-core>=0.11.0
4040
- sphinx
4141
- sphinx-copybutton

conda/recipes/librmm/recipe.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ cache:
7373
- cuda-version =${{ cuda_version }}
7474
- ${{ stdlib("c") }}
7575
host:
76-
- rapids-logger =0.2
76+
- rapids-logger =0.3
7777
- cuda-driver-dev
7878

7979
outputs:
@@ -97,10 +97,10 @@ outputs:
9797
host:
9898
- cuda-version =${{ cuda_version }}
9999
- cuda-cudart-dev
100-
- rapids-logger =0.2
100+
- rapids-logger =0.3
101101
run:
102102
- ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }}
103-
- rapids-logger =0.2
103+
- rapids-logger =0.3
104104
run_exports:
105105
- ${{ pin_subpackage("librmm", upper_bound="x.x") }}
106106
ignore_run_exports:
@@ -138,7 +138,7 @@ outputs:
138138
run:
139139
- ${{ pin_compatible("cuda-version", upper_bound="x", lower_bound="x") }}
140140
- ${{ pin_subpackage("librmm", exact=True) }}
141-
- rapids-logger =0.2
141+
- rapids-logger =0.3
142142
- cuda-cudart
143143
ignore_run_exports:
144144
from_package:

cpp/include/rmm/mr/detail/pool_memory_resource_impl.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class pool_memory_resource_impl final
7070
block_type try_to_expand(std::size_t try_size, std::size_t min_size, cuda_stream_view stream);
7171
void initialize_pool(std::size_t initial_size, std::optional<std::size_t> maximum_size);
7272
block_type expand_pool(std::size_t size, free_list& blocks, cuda_stream_view stream);
73+
void reclaim_free_blocks(std::size_t size, free_list& blocks, cuda_stream_view stream);
7374
[[nodiscard]] std::size_t size_to_grow(std::size_t size) const;
7475
block_type block_from_upstream(std::size_t size, cuda_stream_view stream);
7576
split_block allocate_from_block(block_type const& block, std::size_t size);
@@ -85,9 +86,9 @@ class pool_memory_resource_impl final
8586
cuda::mr::any_resource<cuda::mr::device_accessible> upstream_mr_;
8687
std::size_t current_pool_size_{};
8788
std::optional<std::size_t> maximum_pool_size_{};
88-
std::set<block_type, compare_blocks<block_type>> upstream_blocks_;
89+
std::set<block_type, compare_blocks<block_type>> upstream_blocks_; ///< Upstream allocations.
8990
#ifdef RMM_POOL_TRACK_ALLOCATIONS
90-
std::set<block_type, compare_blocks<block_type>> allocated_blocks_;
91+
std::set<block_type, compare_blocks<block_type>> allocated_blocks_; ///< Live suballocations.
9192
#endif
9293
};
9394

cpp/src/mr/detail/pool_memory_resource_impl.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,66 @@ void pool_memory_resource_impl::initialize_pool(std::size_t initial_size,
106106
}
107107

108108
pool_memory_resource_impl::block_type pool_memory_resource_impl::expand_pool(
109-
std::size_t size, [[maybe_unused]] free_list& blocks, cuda_stream_view stream)
109+
std::size_t size, free_list& blocks, cuda_stream_view stream)
110110
{
111-
return try_to_expand(size_to_grow(size), size, stream);
111+
auto grow_size = size_to_grow(size);
112+
// When the pool is capped and cannot grow enough to satisfy `size` in a single new upstream
113+
// block, try to reclaim entirely-free upstream blocks (whose budget prevents growth) back to
114+
// upstream, freeing headroom under `maximum_pool_size_` to grow a sufficiently large block.
115+
if (grow_size < size && maximum_pool_size_.has_value()) {
116+
reclaim_free_blocks(size, blocks, stream);
117+
grow_size = size_to_grow(size);
118+
}
119+
return try_to_expand(grow_size, size, stream);
120+
}
121+
122+
void pool_memory_resource_impl::reclaim_free_blocks(std::size_t size,
123+
free_list& blocks,
124+
cuda_stream_view stream)
125+
{
126+
// Reclamation only frees headroom when the pool has a capped maximum size.
127+
if (!maximum_pool_size_.has_value()) { return; }
128+
auto const max_pool_size = maximum_pool_size_.value();
129+
130+
// If `size` can never fit under the cap even with every free block reclaimed, there is nothing to
131+
// gain: avoid the synchronize and the destructive reclaim on a request that will fail anyway.
132+
if (size > max_pool_size) { return; }
133+
134+
auto free_iter = blocks.cbegin();
135+
auto upstream_iter = upstream_blocks_.cbegin();
136+
using compare_t = decltype(upstream_blocks_)::key_compare;
137+
auto const compare = compare_t{};
138+
139+
// This merge join requires `blocks` and `upstream_blocks_` to remain sorted by `compare_blocks`.
140+
// coalescing_free_list maintains that order on insertion, and upstream_blocks_ uses the same
141+
// comparator. Erasing matched entries below preserves the ordering of both collections.
142+
while (free_iter != blocks.cend() && upstream_iter != upstream_blocks_.cend()) {
143+
// `current_pool_size_ <= max_pool_size` is an invariant, so the subtraction cannot underflow.
144+
if (max_pool_size - current_pool_size_ >= size) { return; }
145+
146+
if (compare(*free_iter, *upstream_iter)) {
147+
++free_iter;
148+
continue;
149+
}
150+
if (compare(*upstream_iter, *free_iter)) {
151+
++upstream_iter;
152+
continue;
153+
}
154+
155+
auto const candidate = free_iter++;
156+
auto const upstream = upstream_iter++;
157+
if (!candidate->is_head() || upstream->size() != candidate->size()) { continue; }
158+
159+
auto const blk = *candidate;
160+
// The free lists were merged onto `stream`, which waits on their recorded events. Enqueueing
161+
// the upstream deallocation on the same stream preserves those dependencies without blocking
162+
// the host.
163+
get_upstream_resource().deallocate(
164+
stream, blk.pointer(), blk.size(), rmm::CUDA_ALLOCATION_ALIGNMENT);
165+
blocks.erase(candidate);
166+
upstream_blocks_.erase(upstream);
167+
current_pool_size_ -= blk.size();
168+
}
112169
}
113170

114171
std::size_t pool_memory_resource_impl::size_to_grow(std::size_t size) const
@@ -152,6 +209,8 @@ pool_memory_resource_impl::block_type pool_memory_resource_impl::free_block(
152209
void* ptr, std::size_t size) noexcept
153210
{
154211
#ifdef RMM_POOL_TRACK_ALLOCATIONS
212+
// Fetch the metadata recorded for this block's suballocation and validate
213+
// the caller's provided size before returning the block to a free list.
155214
if (ptr == nullptr) return block_type{};
156215
auto const iter = allocated_blocks_.find(static_cast<char*>(ptr));
157216
RMM_LOGGING_ASSERT(iter != allocated_blocks_.end());
@@ -162,6 +221,9 @@ pool_memory_resource_impl::block_type pool_memory_resource_impl::free_block(
162221

163222
return block;
164223
#else
224+
// Reconstruct the block, trusting the validity of the caller's pointer and
225+
// size. A pointer is a block head if and only if it is the start of an
226+
// upstream allocation.
165227
auto const iter = upstream_blocks_.find(static_cast<char*>(ptr));
166228
return block_type{static_cast<char*>(ptr), size, (iter != upstream_blocks_.end())};
167229
#endif

0 commit comments

Comments
 (0)