Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 6 additions & 2 deletions dali/core/mm/basic_resource_test.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,7 +53,11 @@ struct MMBasicResourceTest : public ::testing::Test {

void OOMTest() {
Resource res;
EXPECT_THROW((res.allocate(static_cast<size_t>(-1L) / 4)), std::bad_alloc);
void *ptr = nullptr;
size_t size = static_cast<size_t>(-1L) / 4;
EXPECT_THROW((ptr = res.allocate(size)), std::bad_alloc);
if (ptr)
res.deallocate(ptr, size);
Comment on lines +59 to +60
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've seen this succeed once with plain host mem - in this case, even if the test fails, we should free the memory.

// TODO(michalz): Remove when error handling is fixed in RMM
(void)cudaGetLastError();
}
Expand Down
27 changes: 23 additions & 4 deletions include/dali/core/mm/detail/aux_alloc.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020, 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2020, 2024, 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -37,7 +37,10 @@ namespace detail {
* as size and alignment requirements match and if the purge function links against the same
* C runtime library.
*/
template <size_t size, size_t alignment, class LockObject = dali::spinlock>
template <size_t size,
size_t alignment,
class LockObject = dali::spinlock,
size_t threshold = (1 << 10)>
struct fixed_size_allocator {
~fixed_size_allocator() {
purge();
Expand All @@ -52,7 +55,9 @@ struct fixed_size_allocator {
Block *next = free_list_->next;
free(free_list_);
free_list_ = next;
count_--;
}
assert(count_ == 0);
}

/**
Expand All @@ -77,6 +82,7 @@ struct fixed_size_allocator {
if (Block *blk = free_list_) {
free_list_ = blk->next;
blk->next = nullptr;
count_--;
return reinterpret_cast<T*>(blk->storage);
}
}
Expand All @@ -99,6 +105,16 @@ struct fixed_size_allocator {
Block *bptr = static_cast<Block*>(ptr);
bptr->next = free_list_;
free_list_ = bptr;
count_++;
if (threshold && count_ > threshold) {
while (count_ > threshold / 2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why threshold / 2?

assert(free_list_);
Block *next = free_list_->next;
free(free_list_);
free_list_ = next;
count_--;
}
}
}

/**
Expand All @@ -117,8 +133,10 @@ struct fixed_size_allocator {
*
* It is not safe to pass this reference to threads other than the calling one.
*/
static fixed_size_allocator<size, alignment, dummy_lock> &thread_instance() {
static thread_local fixed_size_allocator<size, alignment, dummy_lock> inst;
static auto &thread_instance() {
// If there's no threshold, the per-thread instance shall have a limit of items
constexpr size_t thresh = threshold ? threshold : (1 << 10);
static thread_local fixed_size_allocator<size, alignment, dummy_lock, thresh> inst;
return inst;
}

Expand All @@ -127,6 +145,7 @@ struct fixed_size_allocator {
Block *next;
};
Block *free_list_ = nullptr;
size_t count_ = 0;
LockObject lock_;
using lock_guard = std::lock_guard<LockObject>;
};
Expand Down