Skip to content

Caching allocator - #2480

Draft
bdice wants to merge 6 commits into
rapidsai:mainfrom
bdice:caching-allocator
Draft

Caching allocator#2480
bdice wants to merge 6 commits into
rapidsai:mainfrom
bdice:caching-allocator

Conversation

@bdice

@bdice bdice commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Description

This is a draft, not ready for review.

I am experimenting with a memory allocator inspired by PyTorch's caching allocator. I plan to compare its performance over a range of workloads, fragmentation behavior, and OOM resilience against the existing RMM pool and arena memory resources.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added a new caching device memory resource with configurable split behavior, OOM fallback strategy, pool (small/large) handling, stream reuse controls, and cache size/release utilities.
    • Benchmarks now include the new caching resource, with CLI policy controls and automated report generation.
  • Bug Fixes

    • Improved stream-aware reuse and strengthened release behavior so only eligible cached memory is returned, including during allocation-failure fallback.
  • Tests

    • Added coverage for sizing, splitting/max-split behavior, small/large reuse and accounting, stream reuse (same vs cross), and cleanup/destructor release.
  • Documentation

    • Added design/plan notes describing the caching-allocator behavior and validation status.

Walkthrough

Changes

Caching memory resource

Layer / File(s) Summary
Resource contracts and stream-aware free-list plumbing
cpp/include/rmm/mr/...
Adds configurable caching policies, the public resource API, predicate-filtered best-fit selection, and stream free-list merge/removal helpers.
Caching allocation and release implementation
cpp/src/mr/..., cpp/CMakeLists.txt
Implements upstream segment sizing, reuse, splitting, OOM fallback, release behavior, cached-byte tracking, and library wiring.
CUDA test coverage and test registration
cpp/tests/...
Tests sizing, reuse, fallback, splitting, release, pool and stream policies, destruction, accounting, and resource properties.
Benchmark integration and design documentation
cpp/benchmarks/..., caching_allocator*.md, .gitignore
Adds caching benchmark modes and report generation, documents behavior and design status, and ignores generated reports.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.80% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too generic to clearly identify the main change in this changeset. Use a more specific title such as "Add experimental caching memory resource and benchmarks".
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is related to the caching allocator changes, even though it notes the PR is still a draft.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
cpp/src/mr/detail/caching_memory_resource_impl.cpp (1)

32-36: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

release() triggers merge_all_free_blocks() twice.

release() calls release_pool(true) then release_pool(false), and each independently calls merge_all_free_blocks() (see release_pool, lines 176-178). For a full release(), the second merge is redundant since the first already merged/synced everything into a single free list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp` around lines 32 - 36, The
caching_memory_resource_impl::release() path is doing redundant work because
release_pool(true) and release_pool(false) each invoke merge_all_free_blocks(),
so the second merge is unnecessary after a full release. Update release()
(and/or release_pool) so the full-release path only merges free blocks once
while still releasing both pools, and keep the behavior localized around
caching_memory_resource_impl::release(), release_pool(), and
merge_all_free_blocks().
cpp/include/rmm/mr/caching_memory_resource.hpp (1)

73-94: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document blocking/synchronization behavior of release* APIs.

release(), release_small_blocks(), and release_large_blocks() are documented only in terms of bytes freed, but the implementation (see caching_memory_resource_impl.cpp) synchronizes CUDA events across streams before releasing segments, which can block the calling thread. Worth calling out in the Doxygen comments given the class docstring already commits to documenting thread-safety/stream semantics.

As per path instructions, "For public C++ API headers, additionally check: Doxygen documentation for all public functions/classes."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/include/rmm/mr/caching_memory_resource.hpp` around lines 73 - 94, Update
the Doxygen comments for caching_memory_resource::release(),
release_small_blocks(), and release_large_blocks() to explicitly mention their
blocking/synchronization behavior; these APIs do more than return bytes to the
upstream resource because they wait on CUDA event/stream synchronization before
freeing cached segments. Add this note in the public header near the existing
declarations so the documented thread/stream semantics match the implementation
in caching_memory_resource_impl.cpp.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@caching_allocator.md`:
- Around line 147-157: The Stream-Ordered Reuse section in caching_allocator.md
conflicts with the existing test coverage for caching_memory_resource. Update
this paragraph to match the actual coverage by referencing the cross-stream
scenarios already exercised in caching_mr_tests.cpp, including
ReleaseMergesCrossStreamFreeBlocks, ReusesOtherStreamAllocation, and
ReusesDeletedStreamAllocation, and remove or soften the claim that no dedicated
cross-stream correctness test exists.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp`:
- Around line 111-134: free_block() currently fabricates a block for pointers
not found in allocated_blocks_, which lets foreign or double-freed pointers
enter the stream free list. Update caching_memory_resource_impl::free_block to
treat any ptr that is not an exact match in allocated_blocks_ and not provably
valid from upstream_blocks_ as an error path, and avoid returning a reusable
block for it. Make stream_ordered_memory_resource::deallocate rely on this
validation so invalid pointers are rejected with a hard failure or log instead
of being inserted into the free list.

In `@cpp/tests/mr/caching_mr_tests.cpp`:
- Around line 1-4: The SPDX header in this C++ test file does not match the
required copyright template. Update the existing header comment to use the
mandated C++/CUDA form with the 2025-2026 year range and the “NVIDIA CORPORATION
& AFFILIATES. All rights reserved.” suffix, matching the project’s standard
SPDX-FileCopyrightText header style.

---

Nitpick comments:
In `@cpp/include/rmm/mr/caching_memory_resource.hpp`:
- Around line 73-94: Update the Doxygen comments for
caching_memory_resource::release(), release_small_blocks(), and
release_large_blocks() to explicitly mention their blocking/synchronization
behavior; these APIs do more than return bytes to the upstream resource because
they wait on CUDA event/stream synchronization before freeing cached segments.
Add this note in the public header near the existing declarations so the
documented thread/stream semantics match the implementation in
caching_memory_resource_impl.cpp.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp`:
- Around line 32-36: The caching_memory_resource_impl::release() path is doing
redundant work because release_pool(true) and release_pool(false) each invoke
merge_all_free_blocks(), so the second merge is unnecessary after a full
release. Update release() (and/or release_pool) so the full-release path only
merges free blocks once while still releasing both pools, and keep the behavior
localized around caching_memory_resource_impl::release(), release_pool(), and
merge_all_free_blocks().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5b302f4c-c802-445e-9e33-1332f62cf739

📥 Commits

Reviewing files that changed from the base of the PR and between 29c61c1 and 4fdab17.

📒 Files selected for processing (12)
  • caching_allocator.md
  • cpp/CMakeLists.txt
  • cpp/benchmarks/multi_stream_allocations/multi_stream_allocations_bench.cu
  • cpp/benchmarks/random_allocations/random_allocations.cpp
  • cpp/include/rmm/mr/caching_memory_resource.hpp
  • cpp/include/rmm/mr/detail/caching_memory_resource_impl.hpp
  • cpp/include/rmm/mr/detail/coalescing_free_list.hpp
  • cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
  • cpp/src/mr/caching_memory_resource.cpp
  • cpp/src/mr/detail/caching_memory_resource_impl.cpp
  • cpp/tests/CMakeLists.txt
  • cpp/tests/mr/caching_mr_tests.cpp

Comment thread caching_allocator.md
Comment on lines +147 to +157
### Stream-Ordered Reuse

The resource inherits the stream ordering model from `stream_ordered_memory_resource`.

This means allocation uses a stream-associated event and free-list. Same-stream blocks can be reused
without waiting. Blocks freed on other streams can be reused after the allocating stream waits on the
other stream's event.

This has not yet received a dedicated cross-stream correctness test for `caching_memory_resource`.
It is inherited from existing RMM infrastructure, but because this resource has new block sizing and
release behavior, it still needs direct tests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Contradicts test coverage claimed later in the same doc.

This section says caching_memory_resource "has not yet received a dedicated cross-stream correctness test," but the "Covered scenarios" list (lines 227-228) and caching_mr_tests.cpp both include cross-stream free-list-merge and cross-stream-reuse tests (ReleaseMergesCrossStreamFreeBlocks, ReusesOtherStreamAllocation, ReusesDeletedStreamAllocation). Recommend reconciling this section with the actual test coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@caching_allocator.md` around lines 147 - 157, The Stream-Ordered Reuse
section in caching_allocator.md conflicts with the existing test coverage for
caching_memory_resource. Update this paragraph to match the actual coverage by
referencing the cross-stream scenarios already exercised in
caching_mr_tests.cpp, including ReleaseMergesCrossStreamFreeBlocks,
ReusesOtherStreamAllocation, and ReusesDeletedStreamAllocation, and remove or
soften the claim that no dedicated cross-stream correctness test exists.

Comment on lines +111 to +134
caching_memory_resource_impl::block_type caching_memory_resource_impl::free_block(
void* ptr, std::size_t size) noexcept
{
auto const iter = allocated_blocks_.find(static_cast<char*>(ptr));
if (iter != allocated_blocks_.end()) {
auto block = *iter;
allocated_blocks_.erase(iter);
return block;
}

auto const aligned_size = rmm::align_up(size, rmm::CUDA_ALLOCATION_ALIGNMENT);
auto const upstream_iter =
upstream_blocks_.upper_bound(segment{static_cast<char*>(ptr), 0, false});
if (upstream_iter != upstream_blocks_.begin()) {
auto const candidate = std::prev(upstream_iter);
auto const segment_end = candidate->pointer + candidate->size;
if (candidate->pointer <= static_cast<char*>(ptr) && static_cast<char*>(ptr) < segment_end) {
return block_type{
static_cast<char*>(ptr), aligned_size, candidate->pointer == static_cast<char*>(ptr)};
}
}

return block_type{static_cast<char*>(ptr), aligned_size, false};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and surrounding symbols.
ast-grep outline cpp/src/mr/detail/caching_memory_resource_impl.cpp --view expanded || true

# Read the relevant region with line numbers.
sed -n '1,240p' cpp/src/mr/detail/caching_memory_resource_impl.cpp | cat -n

# Find the caller and related deallocation path.
rg -n "free_block\\(|deallocate\\(|allocated_blocks_|upstream_blocks_|stream_ordered_memory_resource" cpp/src/mr/detail/caching_memory_resource_impl.cpp cpp/include cpp/src -g '!**/build/**'

Repository: rapidsai/rmm

Length of output: 30452


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the deallocation path that consumes free_block().
sed -n '120,240p' cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp | cat -n

# Inspect the coalescing free-list insertion/merge behavior.
rg -n "class coalescing_free_list|insert\\(|get_block\\(|merge|remove_free_block|add_free_block" cpp/include/rmm/mr/detail cpp/src/mr/detail -g '!**/build/**'

# Read the relevant free-list implementation if present.
fd -a "coalescing_free_list*" cpp/include cpp/src

Repository: rapidsai/rmm

Length of output: 15679


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the coalescing free-list implementation.
sed -n '1,320p' cpp/include/rmm/mr/detail/coalescing_free_list.hpp | cat -n

# Read the block/segment comparison helpers if they are in the same area.
sed -n '1,240p' cpp/include/rmm/mr/detail/free_list.hpp | cat -n

Repository: rapidsai/rmm

Length of output: 18720


Reject untracked pointers in free_block()

free_block() should not synthesize a plausible block when allocated_blocks_ has no match. stream_ordered_memory_resource::deallocate() inserts whatever comes back into the stream free list, so a double-free or foreign pointer can corrupt coalescing and later hand out overlapping live allocations. Add a hard failure/logging path and keep invalid blocks out of the free list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp` around lines 111 - 134,
free_block() currently fabricates a block for pointers not found in
allocated_blocks_, which lets foreign or double-freed pointers enter the stream
free list. Update caching_memory_resource_impl::free_block to treat any ptr that
is not an exact match in allocated_blocks_ and not provably valid from
upstream_blocks_ as an error path, and avoid returning a reusable block for it.
Make stream_ordered_memory_resource::deallocate rely on this validation so
invalid pointers are rejected with a hard failure or log instead of being
inserted into the free list.

Comment on lines +1 to +4
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

SPDX header doesn't match the required template.

Header omits the "2025-" start year and "& AFFILIATES. All rights reserved." suffix mandated for C++/CUDA files.

As per coding guidelines: "SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved."

📝 Proposed fix
 /*
- * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
+ * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  * SPDX-License-Identifier: Apache-2.0
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
/*
* SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/tests/mr/caching_mr_tests.cpp` around lines 1 - 4, The SPDX header in
this C++ test file does not match the required copyright template. Update the
existing header comment to use the mandated C++/CUDA form with the 2025-2026
year range and the “NVIDIA CORPORATION & AFFILIATES. All rights reserved.”
suffix, matching the project’s standard SPDX-FileCopyrightText header style.

Source: Coding guidelines

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
cpp/src/mr/detail/caching_memory_resource_impl.cpp (2)

57-65: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

HIGH: Synchronize cache-accounting reads.

These accessors read non-atomic counters while allocation and release paths mutate them under the resource mutex. Concurrent callers can cause a C++ data race. Lock these reads or use atomic accounting.

As per coding guidelines, “Memory resources must be thread-safe by default with proper synchronization.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp` around lines 57 - 65,
Synchronize the cached_small_bytes() and cached_large_bytes() accessors with the
resource mutex before reading their counters, matching the locking used by
allocation and release paths. Preserve their const noexcept behavior and return
values while ensuring concurrent accounting updates cannot race.

Source: Coding guidelines


138-142: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

CRITICAL: Make allocator metadata updates exception-safe.

If either tracking-container insertion throws after ownership has moved, the block is no longer recoverable: allocated_blocks_ loses a removed free block, and upstream_blocks_ leaks an upstream allocation. Roll back the free-list transition or deallocate upstream via a scope guard before rethrowing.

As per coding guidelines, “Device memory allocated must be properly returned to upstream on all error paths to prevent GPU memory leaks.”

Also applies to: 285-295

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp` around lines 138 - 142,
Make the metadata updates in the allocation path exception-safe around the
visible allocated_blocks_.insert(alloc) and the corresponding upstream_blocks_
insertion near the additionally referenced code. Add rollback or scope-guard
handling so any container insertion failure restores the removed free-list block
or returns the upstream allocation before rethrowing, while preserving the
normal split and return behavior.

Source: Coding guidelines

🧹 Nitpick comments (1)
cpp/include/rmm/mr/caching_memory_resource.hpp (1)

64-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the observable semantics of the new policies.

These public @param descriptions are too generic: explain release_all versus release_oversized_then_all, separate versus unified, and that cross_stream enables event-waited reuse while same_stream does not. Also reflect these guarantees in the class-level stream-semantics documentation.

As per path instructions, public C++ API changes must be documented and public memory resources must document stream semantics and thread-safety guarantees.

Suggested documentation update
- * `@param` oom_fallback_policy Policy used after an upstream allocation failure.
- * `@param` pool_policy Policy controlling cross-pool cached block reuse.
- * `@param` stream_reuse_policy Policy controlling cross-stream cached block reuse.
+ * `@param` oom_fallback_policy Controls which cached segments are released before retrying
+ *   an upstream allocation.
+ * `@param` pool_policy Controls whether small and large cached segments may satisfy each
+ *   other's requests.
+ * `@param` stream_reuse_policy Controls whether cached blocks may be reused across streams;
+ *   cross-stream reuse inserts the required CUDA event waits.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/include/rmm/mr/caching_memory_resource.hpp` around lines 64 - 75, Update
the public documentation for the policy parameters in caching_memory_resource:
describe the observable behavior of release_all versus
release_oversized_then_all, separate versus unified pool reuse, and cross_stream
versus same_stream, including that cross_stream uses event-waited reuse while
same_stream does not. Extend the class-level stream-semantics documentation to
reflect these guarantees and document the resource’s thread-safety guarantees as
required for public memory resources.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/benchmarks/caching_allocator_reports.py`:
- Around line 141-157: Update the default_build path used by the argument parser
to the repository-supported standard build location, cpp/build, so the
--random-bench and --multi-stream-bench defaults resolve to benchmarks produced
by the documented CMake workflow. Keep the existing argument names and benchmark
executable paths unchanged.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp`:
- Around line 80-82: Update
caching_memory_resource_impl::get_maximum_allocation_size() to return the
largest size that can be safely rounded up to CUDA_ALLOCATION_ALIGNMENT, rather
than std::numeric_limits<std::size_t>::max(). Ensure near-limit allocation
requests are capped or rejected before alignment can overflow.

---

Outside diff comments:
In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp`:
- Around line 57-65: Synchronize the cached_small_bytes() and
cached_large_bytes() accessors with the resource mutex before reading their
counters, matching the locking used by allocation and release paths. Preserve
their const noexcept behavior and return values while ensuring concurrent
accounting updates cannot race.
- Around line 138-142: Make the metadata updates in the allocation path
exception-safe around the visible allocated_blocks_.insert(alloc) and the
corresponding upstream_blocks_ insertion near the additionally referenced code.
Add rollback or scope-guard handling so any container insertion failure restores
the removed free-list block or returns the upstream allocation before
rethrowing, while preserving the normal split and return behavior.

---

Nitpick comments:
In `@cpp/include/rmm/mr/caching_memory_resource.hpp`:
- Around line 64-75: Update the public documentation for the policy parameters
in caching_memory_resource: describe the observable behavior of release_all
versus release_oversized_then_all, separate versus unified pool reuse, and
cross_stream versus same_stream, including that cross_stream uses event-waited
reuse while same_stream does not. Extend the class-level stream-semantics
documentation to reflect these guarantees and document the resource’s
thread-safety guarantees as required for public memory resources.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7a301b87-ff4c-4759-84ca-1b5e7694806d

📥 Commits

Reviewing files that changed from the base of the PR and between 4fdab17 and 62fc11b.

📒 Files selected for processing (11)
  • .gitignore
  • caching_allocator_plan.md
  • cpp/benchmarks/caching_allocator_reports.py
  • cpp/benchmarks/multi_stream_allocations/multi_stream_allocations_bench.cu
  • cpp/benchmarks/random_allocations/random_allocations.cpp
  • cpp/include/rmm/mr/caching_memory_resource.hpp
  • cpp/include/rmm/mr/detail/caching_memory_resource_impl.hpp
  • cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
  • cpp/src/mr/caching_memory_resource.cpp
  • cpp/src/mr/detail/caching_memory_resource_impl.cpp
  • cpp/tests/mr/caching_mr_tests.cpp
🚧 Files skipped from review as they are similar to previous changes (4)
  • cpp/benchmarks/random_allocations/random_allocations.cpp
  • cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
  • cpp/benchmarks/multi_stream_allocations/multi_stream_allocations_bench.cu
  • cpp/tests/mr/caching_mr_tests.cpp

Comment on lines +141 to +157
default_build = root / "cpp" / "build-bench-opencode" / "gbenchmarks"
parser = argparse.ArgumentParser(
description="Generate caching allocator benchmark reports."
)
parser.add_argument(
"--random-bench",
type=Path,
default=default_build / "RANDOM_ALLOCATIONS_BENCH",
)
parser.add_argument(
"--multi-stream-bench",
type=Path,
default=default_build / "MULTI_STREAM_ALLOCATIONS_BENCH",
)
parser.add_argument(
"--output-dir", type=Path, default=root / "caching-allocator-reports"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

HIGH: Use a repository-supported default benchmark path.

cpp/build-bench-opencode is not produced by the documented build workflows, so the script fails with default arguments on normal builds. Default to the standard cpp/build benchmark output location or discover it explicitly.

As per coding guidelines, “cmake -S cpp -B cpp/build -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/benchmarks/caching_allocator_reports.py` around lines 141 - 157, Update
the default_build path used by the argument parser to the repository-supported
standard build location, cpp/build, so the --random-bench and
--multi-stream-bench defaults resolve to benchmarks produced by the documented
CMake workflow. Keep the existing argument names and benchmark executable paths
unchanged.

Source: Coding guidelines

Comment on lines +80 to +82
std::size_t caching_memory_resource_impl::get_maximum_allocation_size() const
{
return std::numeric_limits<std::size_t>::max();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant implementation and allocation paths.
git ls-files 'cpp/src/mr/detail/*' 'cpp/include/rmm/mr/*' | sed -n '1,200p'
echo '---'
rg -n "get_maximum_allocation_size|align_up\(|maximum_allocation_size|stream_ordered_memory_resource::allocate|allocate\(" cpp/src cpp/include/rmm/mr -g '!**/build/**' -g '!**/dist/**'

Repository: rapidsai/rmm

Length of output: 27173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the relevant file sections with line numbers.
FILE=cpp/src/mr/detail/caching_memory_resource_impl.cpp
wc -l "$FILE"
echo '---'
cat -n "$FILE" | sed -n '1,220p'

echo '---'
# Inspect the stream-ordered allocation implementation if present.
FILE2=$(rg -l "stream_ordered_memory_resource" cpp/include/rmm/mr cpp/src | head -n 1 || true)
if [[ -n "${FILE2:-}" ]]; then
  echo "FILE2=$FILE2"
  wc -l "$FILE2"
  echo '---'
  cat -n "$FILE2" | sed -n '1,260p'
fi

Repository: rapidsai/rmm

Length of output: 16286


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Probe the exact rounding behavior and compare against size limits.
python3 - <<'PY'
import sys
from math import isfinite

SIZE_MAX = (1 << (8 * (sys.maxsize.bit_length() + 1))) - 1 if False else (2**64 - 1)

def align_up(n, a):
    return (n + a - 1) // a * a

for align in [2, 8, 16, 64, 256, 4096, 1 << 20]:
    safe_max = SIZE_MAX - (align - 1)
    # Check whether any n <= SIZE_MAX can round to > SIZE_MAX.
    bad = []
    for n in [SIZE_MAX, SIZE_MAX-1, safe_max, safe_max+1 if safe_max < SIZE_MAX else safe_max]:
        try:
            rounded = align_up(n, align)
            if rounded > SIZE_MAX:
                bad.append((n, rounded))
        except Exception as e:
            bad.append((n, repr(e)))
    print(f"align={align} safe_max={safe_max} bad={bad[:3]}")
PY

Repository: rapidsai/rmm

Length of output: 1384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact implementation around the reported lines and the allocation path it feeds.
for f in \
  cpp/src/mr/detail/caching_memory_resource_impl.cpp \
  cpp/include/rmm/mr/stream_ordered_memory_resource.hpp \
  cpp/src/mr/stream_ordered_memory_resource.cpp \
  cpp/include/rmm/mr/detail/align.hpp \
  cpp/include/rmm/detail/align.hpp
do
  if [[ -f "$f" ]]; then
    echo "=== $f ==="
    wc -l "$f"
    cat -n "$f" | sed -n '1,260p'
    echo
  fi
done

Repository: rapidsai/rmm

Length of output: 10789


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the alignment helper and the stream-ordered allocation check sequence.
rg -n "std::size_t align_up|align_up\(" cpp/src cpp/include/rmm -g '!**/build/**'
echo '---'
FILE=cpp/src/aligned.cpp
if [[ -f "$FILE" ]]; then
  cat -n "$FILE" | sed -n '1,120p'
fi
echo '---'
FILE=cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
cat -n "$FILE" | sed -n '80,130p'

Repository: rapidsai/rmm

Length of output: 6214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Compare similar maximum-allocation contracts in other memory resources.
rg -n "get_maximum_allocation_size\(\) const" cpp/src cpp/include/rmm/mr/detail -g '!**/build/**' -A4 -B4

Repository: rapidsai/rmm

Length of output: 7467


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the exact align_up implementation used by the MR codepaths.
FILE=cpp/include/rmm/aligned.hpp
if [[ -f "$FILE" ]]; then
  cat -n "$FILE" | sed -n '1,220p'
fi
echo '---'
FILE=cpp/src/aligned.cpp
if [[ -f "$FILE" ]]; then
  cat -n "$FILE" | sed -n '1,120p'
fi

Repository: rapidsai/rmm

Length of output: 5117


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the alignment helper and the stream-ordered allocation path.
FILE=cpp/include/rmm/aligned.hpp
if [[ -f "$FILE" ]]; then
  cat -n "$FILE" | sed -n '1,220p'
fi
echo '---'
FILE=cpp/src/aligned.cpp
if [[ -f "$FILE" ]]; then
  cat -n "$FILE" | sed -n '1,120p'
fi
echo '---'
FILE=cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
cat -n "$FILE" | sed -n '88,116p'

Repository: rapidsai/rmm

Length of output: 6463


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the get_block logic to understand the effect of a wrapped-to-zero size.
FILE=cpp/include/rmm/mr/detail/stream_ordered_memory_resource.hpp
cat -n "$FILE" | sed -n '130,230p'

Repository: rapidsai/rmm

Length of output: 4766


Cap requests before alignment. stream_ordered_memory_resource::allocate() rounds before checking get_maximum_allocation_size(), so std::numeric_limits<std::size_t>::max() can wrap rmm::align_up() for near-limit requests and let an oversized request slip through. Return the largest safely roundable size for CUDA_ALLOCATION_ALIGNMENT, or reject oversized requests before rounding.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/mr/detail/caching_memory_resource_impl.cpp` around lines 80 - 82,
Update caching_memory_resource_impl::get_maximum_allocation_size() to return the
largest size that can be safely rounded up to CUDA_ALLOCATION_ALIGNMENT, rather
than std::numeric_limits<std::size_t>::max(). Ensure near-limit allocation
requests are capped or rejected before alignment can overflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant