提交 f287501e 编写于 作者: M Megvii Engine Team

fix(src/core): fix pushdown alloc_result inconsistent when run for many time

GitOrigin-RevId: 3b087203a1c1d50a3ceb58ae1a494477d104f902
上级 edea4b80
...@@ -51,7 +51,7 @@ private: ...@@ -51,7 +51,7 @@ private:
std::list<MemBlock> m_mem_block; std::list<MemBlock> m_mem_block;
using MemBlockIter = decltype(m_mem_block.begin()); using MemBlockIter = decltype(m_mem_block.begin());
std::set<FreeBlockBySizeItem> m_free_by_size; std::multiset<FreeBlockBySizeItem> m_free_by_size;
using FreeBySizeIter = decltype(m_free_by_size.begin()); using FreeBySizeIter = decltype(m_free_by_size.begin());
struct MemBlock { struct MemBlock {
...@@ -67,6 +67,8 @@ private: ...@@ -67,6 +67,8 @@ private:
*/ */
size_t size = 0; size_t size = 0;
size_t time_end = -1;
/*! /*!
* FreeBlockBySizeItem iter for unallocated intervals; should be * FreeBlockBySizeItem iter for unallocated intervals; should be
* accessed only when *interval* is nullptr * accessed only when *interval* is nullptr
...@@ -77,6 +79,13 @@ private: ...@@ -77,6 +79,13 @@ private:
bool allocated() const { return interval; } bool allocated() const { return interval; }
bool operator<(const MemBlock& rhs) {
if (time_end != (size_t)(-1) && rhs.time_end != (size_t)(-1))
return time_end > rhs.time_end;
else
return time_end != (size_t)(-1) || this < &rhs;
}
private: private:
IncompleteObjStorageMock<FreeBySizeIter, std::set<int>::iterator> m_fs_iter; IncompleteObjStorageMock<FreeBySizeIter, std::set<int>::iterator> m_fs_iter;
}; };
...@@ -99,7 +108,7 @@ private: ...@@ -99,7 +108,7 @@ private:
return size < rhs.size || return size < rhs.size ||
(size == rhs.size && (size == rhs.size &&
(!blk_iter_valid || (!blk_iter_valid ||
(rhs.blk_iter_valid && &*blk_iter < &*rhs.blk_iter))); (rhs.blk_iter_valid && *blk_iter < *rhs.blk_iter)));
} }
}; };
...@@ -114,14 +123,14 @@ private: ...@@ -114,14 +123,14 @@ private:
* \param size size of free block; if it is zero, no insertion would be * \param size size of free block; if it is zero, no insertion would be
* performed * performed
*/ */
void insert_free_blk_before(MemBlockIter pos, size_t size); void insert_free_blk_before(MemBlockIter pos, size_t size, size_t time_end);
/*! /*!
* \brief insert a free MemBlock after given position * \brief insert a free MemBlock after given position
*/ */
void insert_free_blk_after(MemBlockIter pos, size_t size) { void insert_free_blk_after(MemBlockIter pos, size_t size, size_t time_end) {
mgb_assert(pos != m_mem_block.end()); mgb_assert(pos != m_mem_block.end());
return insert_free_blk_before(++pos, size); return insert_free_blk_before(++pos, size, time_end);
} }
}; };
StaticMemAllocPushdown::BestfitPrealloc::MemBlock::~MemBlock() = default; StaticMemAllocPushdown::BestfitPrealloc::MemBlock::~MemBlock() = default;
...@@ -176,6 +185,7 @@ PREALLOC_MEM_TR(AllocResult)::alloc(Interval* interval) { ...@@ -176,6 +185,7 @@ PREALLOC_MEM_TR(AllocResult)::alloc(Interval* interval) {
--iter; --iter;
mgb_assert(iter->size < interval->size); mgb_assert(iter->size < interval->size);
iter->blk_iter->size = interval->size; iter->blk_iter->size = interval->size;
iter->blk_iter->time_end = interval->time_end;
} }
auto blkpos = iter->blk_iter; auto blkpos = iter->blk_iter;
m_free_by_size.erase(iter); m_free_by_size.erase(iter);
...@@ -185,7 +195,7 @@ PREALLOC_MEM_TR(AllocResult)::alloc(Interval* interval) { ...@@ -185,7 +195,7 @@ PREALLOC_MEM_TR(AllocResult)::alloc(Interval* interval) {
auto free_size = safe_sub(blkpos->size, interval->size); auto free_size = safe_sub(blkpos->size, interval->size);
// mark allocated result before inserting block // mark allocated result before inserting block
blkpos->interval = interval; blkpos->interval = interval;
insert_free_blk_after(blkpos, free_size); insert_free_blk_after(blkpos, free_size, interval->time_end);
return make_alloc_result(blkpos, interval); return make_alloc_result(blkpos, interval);
} }
...@@ -193,9 +203,10 @@ PREALLOC_MEM_TR(AllocResult)::alloc_overwrite( ...@@ -193,9 +203,10 @@ PREALLOC_MEM_TR(AllocResult)::alloc_overwrite(
AllocResult& dest, size_t offset, Interval* interval) { AllocResult& dest, size_t offset, Interval* interval) {
auto iter = dest.m_iter; auto iter = dest.m_iter;
mgb_assert(dest.m_valid && iter->allocated()); mgb_assert(dest.m_valid && iter->allocated());
insert_free_blk_before(iter, offset); insert_free_blk_before(iter, offset, iter->interval->time_end);
insert_free_blk_after( insert_free_blk_after(
iter, safe_sub(iter->interval->size, offset + interval->size)); iter, safe_sub(iter->interval->size, offset + interval->size),
iter->interval->time_end);
dest.m_valid = false; dest.m_valid = false;
return make_alloc_result(iter, interval); return make_alloc_result(iter, interval);
} }
...@@ -204,6 +215,7 @@ PREALLOC_MEM_TR(AllocResult)::make_alloc_result(MemBlockIter pos, Interval* inte ...@@ -204,6 +215,7 @@ PREALLOC_MEM_TR(AllocResult)::make_alloc_result(MemBlockIter pos, Interval* inte
pos->interval = interval; pos->interval = interval;
pos->fsiter() = {}; pos->fsiter() = {};
pos->size = 0; pos->size = 0;
pos->time_end = interval->time_end;
Interval *iprev = nullptr, *inext = nullptr; Interval *iprev = nullptr, *inext = nullptr;
// find prev allocated interval // find prev allocated interval
...@@ -241,13 +253,15 @@ PREALLOC_MEM(void)::free(AllocResult& alloc_rst) { ...@@ -241,13 +253,15 @@ PREALLOC_MEM(void)::free(AllocResult& alloc_rst) {
mgb_assert(iter->allocated()); mgb_assert(iter->allocated());
auto size = iter->interval->size; auto size = iter->interval->size;
auto pos = iter; auto pos = iter;
auto time_end = iter->time_end;
++pos; ++pos;
m_mem_block.erase(iter); m_mem_block.erase(iter);
alloc_rst.m_valid = false; alloc_rst.m_valid = false;
insert_free_blk_before(pos, size); insert_free_blk_before(pos, size, time_end);
} }
PREALLOC_MEM(void)::insert_free_blk_before(MemBlockIter pos, size_t size) { PREALLOC_MEM(void)::insert_free_blk_before(
MemBlockIter pos, size_t size, size_t time_end) {
auto rm = [this](MemBlockIter it) { auto rm = [this](MemBlockIter it) {
mgb_assert(!it->allocated()); mgb_assert(!it->allocated());
m_free_by_size.erase(it->fsiter()); m_free_by_size.erase(it->fsiter());
...@@ -278,10 +292,10 @@ PREALLOC_MEM(void)::insert_free_blk_before(MemBlockIter pos, size_t size) { ...@@ -278,10 +292,10 @@ PREALLOC_MEM(void)::insert_free_blk_before(MemBlockIter pos, size_t size) {
return; return;
auto blk_iter = m_mem_block.insert(pos, MemBlock()); auto blk_iter = m_mem_block.insert(pos, MemBlock());
blk_iter->time_end = time_end;
auto rst_s = m_free_by_size.insert({size, blk_iter}); auto rst_s = m_free_by_size.insert({size, blk_iter});
mgb_assert(rst_s.second);
blk_iter->size = size; blk_iter->size = size;
blk_iter->fsiter() = rst_s.first; blk_iter->fsiter() = rst_s;
} }
#undef PREALLOC_MEM #undef PREALLOC_MEM
......
...@@ -222,6 +222,18 @@ TEST(TestStaticMemAllocAlgo, PushdownChain) { ...@@ -222,6 +222,18 @@ TEST(TestStaticMemAllocAlgo, PushdownChain) {
ASSERT_EQ(NR + NR - 1, allocator->tot_alloc()); ASSERT_EQ(NR + NR - 1, allocator->tot_alloc());
} }
TEST(TestStaticMemAllocAlgo, PushdownConsistence) {
for (size_t run_nr = 0; run_nr < 500; ++run_nr) {
auto allocator = StaticMemAlloc::make(StaticMemAlloc::AllocatorAlgo::PUSHDOWN);
constexpr size_t NR = 100;
for (size_t i = 0; i < NR; ++i)
allocator->add(i, i + 2, i + 1, makeuk(i));
allocator->solve();
ASSERT_EQ(NR + NR - 1, allocator->tot_alloc_lower_bound());
ASSERT_EQ(NR + NR - 1, allocator->tot_alloc());
}
}
#endif // WIN32 #endif // WIN32
// vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}} // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册