提交 ada1c20b 编写于 作者: L liaogang

FIX: Buddy Allocator Free with Merge feature

上级 d0ad0314
...@@ -89,9 +89,8 @@ void BuddyAllocator::Free(void* p) { ...@@ -89,9 +89,8 @@ void BuddyAllocator::Free(void* p) {
block->index(cache_)); block->index(cache_));
// Invalidate GPU allocation from cache // Invalidate GPU allocation from cache
if (system_allocator_->UseGpu()) {
cache_.invalidate(block); cache_.invalidate(block);
}
return; return;
} }
...@@ -104,12 +103,35 @@ void BuddyAllocator::Free(void* p) { ...@@ -104,12 +103,35 @@ void BuddyAllocator::Free(void* p) {
if (block->has_right_buddy(cache_)) { if (block->has_right_buddy(cache_)) {
DLOG(INFO) << "Merging this block " << block << " with its right buddy " DLOG(INFO) << "Merging this block " << block << " with its right buddy "
<< block->right_buddy(cache_); << block->right_buddy(cache_);
auto right_buddy = block->right_buddy(cache_);
if (right_buddy->type(cache_) == MemoryBlock::FREE_CHUNK) {
// Take away right buddy from pool
pool_.erase({right_buddy->index(cache_), right_buddy->total_size(cache_),
right_buddy});
// merge its right buddy to the block
block->merge(cache_, right_buddy);
}
} }
// Trying to merge the left buddy // Trying to merge the left buddy
if (block->has_left_buddy(cache_)) { if (block->has_left_buddy(cache_)) {
DLOG(INFO) << "Merging this block " << block << " with its left buddy " DLOG(INFO) << "Merging this block " << block << " with its left buddy "
<< block->left_buddy(cache_); << block->left_buddy(cache_);
auto left_buddy = block->left_buddy(cache_);
if (left_buddy->type(cache_) == MemoryBlock::FREE_CHUNK) {
// Take away right buddy from pool
pool_.erase({left_buddy->index(cache_), left_buddy->total_size(cache_),
left_buddy});
// merge the block to its left buddy
left_buddy->merge(cache_, block);
block = left_buddy;
}
} }
// Dumping this block into pool // Dumping this block into pool
...@@ -167,13 +189,16 @@ BuddyAllocator::PoolSet::iterator BuddyAllocator::FindExistChunk(size_t size) { ...@@ -167,13 +189,16 @@ BuddyAllocator::PoolSet::iterator BuddyAllocator::FindExistChunk(size_t size) {
while (1) { while (1) {
auto it = pool_.lower_bound({index, size, nullptr}); auto it = pool_.lower_bound({index, size, nullptr});
// no match chunk memory
if (it == pool_.end()) return it; if (it == pool_.end()) return it;
if (std::get<0>(*it) > index) { if (std::get<0>(*it) > index) {
// find suitable one
if (std::get<1>(*it) >= size) { if (std::get<1>(*it) >= size) {
return it; return it;
} }
// update and continue
index = std::get<0>(*it); index = std::get<0>(*it);
continue; continue;
} }
......
...@@ -42,14 +42,14 @@ class BuddyAllocator { ...@@ -42,14 +42,14 @@ class BuddyAllocator {
void Free(void*); void Free(void*);
size_t Used(); size_t Used();
public: private:
// Disable copy and assignment. // Disable copy and assignment.
BuddyAllocator(const BuddyAllocator&) = delete; BuddyAllocator(const BuddyAllocator&) = delete;
BuddyAllocator& operator=(const BuddyAllocator&) = delete; BuddyAllocator& operator=(const BuddyAllocator&) = delete;
private: // Tuple (allocator index, memory size, memory address)
// Tuple type: allocator index, memory size, memory address
using IndexSizeAddress = std::tuple<size_t, size_t, void*>; using IndexSizeAddress = std::tuple<size_t, size_t, void*>;
// Each element in PoolSet is a free allocation
using PoolSet = std::set<IndexSizeAddress>; using PoolSet = std::set<IndexSizeAddress>;
/*! \brief Allocate fixed-size memory from system */ /*! \brief Allocate fixed-size memory from system */
...@@ -57,7 +57,6 @@ class BuddyAllocator { ...@@ -57,7 +57,6 @@ class BuddyAllocator {
/*! \brief If existing chunks are not suitable, refill pool */ /*! \brief If existing chunks are not suitable, refill pool */
PoolSet::iterator RefillPool(); PoolSet::iterator RefillPool();
/** /**
* \brief Find the suitable chunk from existing pool * \brief Find the suitable chunk from existing pool
* *
...@@ -77,13 +76,19 @@ class BuddyAllocator { ...@@ -77,13 +76,19 @@ class BuddyAllocator {
size_t max_chunk_size_; // the maximum size of each chunk size_t max_chunk_size_; // the maximum size of each chunk
private: private:
/**
* \brief A list of free allocation
*
* \note Only store free chunk memory in pool
*/
PoolSet pool_; PoolSet pool_;
private: private:
// Unify the metadata format between GPU and CPU allocations /*! Unify the metadata format between GPU and CPU allocations */
MetadataCache cache_; MetadataCache cache_;
private: private:
/*! Allocate CPU/GPU memory from system */
SystemAllocator* system_allocator_; SystemAllocator* system_allocator_;
std::mutex mutex_; std::mutex mutex_;
}; };
......
...@@ -91,8 +91,8 @@ void MemoryBlock::split(MetadataCache& cache, size_t size) { ...@@ -91,8 +91,8 @@ void MemoryBlock::split(MetadataCache& cache, size_t size) {
void MemoryBlock::merge(MetadataCache& cache, MemoryBlock* right_buddy) { void MemoryBlock::merge(MetadataCache& cache, MemoryBlock* right_buddy) {
// only free blocks can be merged // only free blocks can be merged
PADDLE_ASSERT(type(cache) == FREE_MEMORY); PADDLE_ASSERT(type(cache) == FREE_CHUNK);
PADDLE_ASSERT(right_buddy->type(cache) == FREE_MEMORY); PADDLE_ASSERT(right_buddy->type(cache) == FREE_CHUNK);
auto metadata = cache.load(this); auto metadata = cache.load(this);
......
...@@ -6,4 +6,4 @@ nv_library(gpu_info SRCS gpu_info.cc DEPS gflags) ...@@ -6,4 +6,4 @@ nv_library(gpu_info SRCS gpu_info.cc DEPS gflags)
cc_library(place SRCS place.cc) cc_library(place SRCS place.cc)
cc_test(place_test SRCS place_test.cc DEPS place glog gflags) cc_test(place_test SRCS place_test.cc DEPS place glog gflags)
cc_library(dynamic_loader SRCS dynload/dynamic_loader.cc) cc_library(dynamic_loader SRCS dynload/dynamic_loader.cc DEPS gflags)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册