-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory Pool Improvement For Variadic Sized Inputs #4190
Changes from 31 commits
f5783b5
7a94b1a
b126e0f
1982605
0fa8689
6a683d3
bf95312
af97b05
a9be63a
976692a
d7007c3
508d143
cf015d8
5084955
48fb4ea
8c4ed97
3c2c1c8
487568d
23db5ab
72777b4
b20d298
4fddf9e
2555b3e
1b118f7
649a63b
49a5b7f
2ecda04
cee9d22
3f2731f
577d593
ee7ca30
d4b6698
4a0a1a9
4066294
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ class PoolAllocatorPrivate | |
Mutex budgets_lock; | ||
Mutex payouts_lock; | ||
unsigned int size_compare_ratio; // 0~256 | ||
static const size_t size_threshold = 10; | ||
std::list<std::pair<size_t, void*> > budgets; | ||
std::list<std::pair<size_t, void*> > payouts; | ||
}; | ||
|
@@ -104,11 +105,20 @@ 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.end(), it_min = d->budgets.end(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are these max/min iterators initialized to end() instead of begin() ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it doesn't matter. |
||
for (; it != d->budgets.end(); ++it) | ||
{ | ||
size_t bs = it->first; | ||
|
||
if (it_min == d->budgets.end() || it->first < it_min->first) | ||
{ | ||
it_min = it; | ||
} | ||
if (it_max == d->budgets.end() || it->first > it_max->first) | ||
{ | ||
it_max = it; | ||
} | ||
|
||
// size_compare_ratio ~ 100% | ||
if (bs >= size && ((bs * d->size_compare_ratio) >> 8) <= size) | ||
{ | ||
|
@@ -128,6 +138,26 @@ void* PoolAllocator::fastMalloc(size_t size) | |
} | ||
} | ||
|
||
if (d->budgets.size() >= d->size_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(); | ||
|
||
// new | ||
|
@@ -178,6 +208,7 @@ class UnlockedPoolAllocatorPrivate | |
{ | ||
public: | ||
unsigned int size_compare_ratio; // 0~256 | ||
static const size_t size_threshold = 10; | ||
std::list<std::pair<size_t, void*> > budgets; | ||
std::list<std::pair<size_t, void*> > payouts; | ||
}; | ||
|
@@ -243,11 +274,20 @@ void UnlockedPoolAllocator::set_size_compare_ratio(float scr) | |
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; | ||
|
||
if (it->first > it_max->first) | ||
{ | ||
it_max = it; | ||
} | ||
if (it->first < it_min->first) | ||
{ | ||
it_min = it; | ||
} | ||
|
||
// size_compare_ratio ~ 100% | ||
if (bs >= size && ((bs * d->size_compare_ratio) >> 8) <= size) | ||
{ | ||
|
@@ -261,6 +301,20 @@ void* UnlockedPoolAllocator::fastMalloc(size_t size) | |
} | ||
} | ||
|
||
if (d->budgets.size() >= d->size_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 | ||
void* ptr = ncnn::fastMalloc(size); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_threshold
does not seem expressive enoughbudget_count_threshold
orbudget_drop_threshold
might be better?How about adding a setter api that allows the user to control whether a more aggressive or conservative budget recycling strategy is required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed & Added a setter.