Skip to content

Commit

Permalink
Memory Pool Improvement For Variadic Sized Inputs (#4190)
Browse files Browse the repository at this point in the history
* Simple miss count for better space efficiency

* Simple double ended greedy;

* Add size drop threshold setter;

* set workspace allocator cr to zero as we had some sort of recylcing capability :P

Co-authored-by: LinHeLurking <LinHeLurking@users.noreply.github.com>
Co-authored-by: nihuini <nihuini@tencent.com>
  • Loading branch information
3 people authored Oct 9, 2022
1 parent 3fce00b commit 9426e21
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 9 deletions.
4 changes: 2 additions & 2 deletions benchmark/benchncnn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ int main(int argc, char** argv)

g_loop_count = loop_count;

g_blob_pool_allocator.set_size_compare_ratio(0.0f);
g_workspace_pool_allocator.set_size_compare_ratio(0.5f);
g_blob_pool_allocator.set_size_compare_ratio(0.f);
g_workspace_pool_allocator.set_size_compare_ratio(0.f);

#if NCNN_VULKAN
if (use_vulkan_compute)
Expand Down
74 changes: 70 additions & 4 deletions src/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ class PoolAllocatorPrivate
Mutex budgets_lock;
Mutex payouts_lock;
unsigned int size_compare_ratio; // 0~256
size_t size_drop_threshold;
std::list<std::pair<size_t, void*> > budgets;
std::list<std::pair<size_t, void*> > payouts;
};

PoolAllocator::PoolAllocator()
: Allocator(), d(new PoolAllocatorPrivate)
{
d->size_compare_ratio = 192; // 0.75f * 256
d->size_compare_ratio = 0;
d->size_drop_threshold = 10;
}

PoolAllocator::~PoolAllocator()
Expand Down Expand Up @@ -99,12 +101,17 @@ void PoolAllocator::set_size_compare_ratio(float scr)
d->size_compare_ratio = (unsigned int)(scr * 256);
}

void PoolAllocator::set_size_drop_threshold(size_t threshold)
{
d->size_drop_threshold = threshold;
}

void* PoolAllocator::fastMalloc(size_t size)
{
d->budgets_lock.lock();

// find free budget
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin();
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin(), it_max = d->budgets.begin(), it_min = d->budgets.begin();
for (; it != d->budgets.end(); ++it)
{
size_t bs = it->first;
Expand All @@ -126,6 +133,35 @@ void* PoolAllocator::fastMalloc(size_t size)

return ptr;
}

if (bs < it_min->first)
{
it_min = it;
}
if (bs > it_max->first)
{
it_max = it;
}
}

if (d->budgets.size() >= d->size_drop_threshold)
{
// All chunks in pool are not chosen. Then try to drop some outdated
// chunks and return them to OS.
if (it_max->first < size)
{
// Current query is asking for a chunk larger than any cached chunks.
// Then remove the smallest one.
ncnn::fastFree(it_min->second);
d->budgets.erase(it_min);
}
else if (it_min->first > size)
{
// Current query is asking for a chunk smaller than any cached chunks.
// Then remove the largest one.
ncnn::fastFree(it_max->second);
d->budgets.erase(it_max);
}
}

d->budgets_lock.unlock();
Expand Down Expand Up @@ -178,14 +214,16 @@ class UnlockedPoolAllocatorPrivate
{
public:
unsigned int size_compare_ratio; // 0~256
size_t size_drop_threshold;
std::list<std::pair<size_t, void*> > budgets;
std::list<std::pair<size_t, void*> > payouts;
};

UnlockedPoolAllocator::UnlockedPoolAllocator()
: Allocator(), d(new UnlockedPoolAllocatorPrivate)
{
d->size_compare_ratio = 192; // 0.75f * 256
d->size_compare_ratio = 0;
d->size_drop_threshold = 10;
}

UnlockedPoolAllocator::~UnlockedPoolAllocator()
Expand Down Expand Up @@ -240,10 +278,15 @@ void UnlockedPoolAllocator::set_size_compare_ratio(float scr)
d->size_compare_ratio = (unsigned int)(scr * 256);
}

void UnlockedPoolAllocator::set_size_drop_threshold(size_t threshold)
{
d->size_drop_threshold = threshold;
}

void* UnlockedPoolAllocator::fastMalloc(size_t size)
{
// find free budget
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin();
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin(), it_max = d->budgets.begin(), it_min = d->budgets.begin();
for (; it != d->budgets.end(); ++it)
{
size_t bs = it->first;
Expand All @@ -259,6 +302,29 @@ void* UnlockedPoolAllocator::fastMalloc(size_t size)

return ptr;
}

if (bs > it_max->first)
{
it_max = it;
}
if (bs < it_min->first)
{
it_min = it;
}
}

if (d->budgets.size() >= d->size_drop_threshold)
{
if (it_max->first < size)
{
ncnn::fastFree(it_min->second);
d->budgets.erase(it_min);
}
else if (it_min->first > size)
{
ncnn::fastFree(it_max->second);
d->budgets.erase(it_max);
}
}

// new
Expand Down
12 changes: 10 additions & 2 deletions src/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,13 @@ class NCNN_EXPORT PoolAllocator : public Allocator
~PoolAllocator();

// ratio range 0 ~ 1
// default cr = 0.75
// default cr = 0
void set_size_compare_ratio(float scr);

// budget drop threshold
// default threshold = 10
void set_size_drop_threshold(size_t);

// release all budgets immediately
void clear();

Expand All @@ -195,9 +199,13 @@ class NCNN_EXPORT UnlockedPoolAllocator : public Allocator
~UnlockedPoolAllocator();

// ratio range 0 ~ 1
// default cr = 0.75
// default cr = 0
void set_size_compare_ratio(float scr);

// budget drop threshold
// default threshold = 10
void set_size_drop_threshold(size_t);

// release all budgets immediately
void clear();

Expand Down
2 changes: 1 addition & 1 deletion src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,7 @@ int Net::load_model(const DataReader& dr)
if (!d->local_workspace_allocator)
{
d->local_workspace_allocator = new PoolAllocator;
d->local_workspace_allocator->set_size_compare_ratio(0.5f);
d->local_workspace_allocator->set_size_compare_ratio(0.f);
}
}
}
Expand Down

0 comments on commit 9426e21

Please sign in to comment.