*/
#include "MemoryAllocator.h"
+#include "logging.h"
#include <cassert>
namespace neurun
delete[] _base;
}
-uint32_t BumpAllocator::allocate(size_t size)
+Block BumpAllocator::allocate(const graph::operand::Index &index, size_t size)
{
assert(size != 0);
- MemoryBlock blk{_curr_pos, size};
- _mem_blk_map[_mem_idx] = blk;
- _curr_pos += size;
- return _mem_idx++;
+ Block blk{_pos, size};
+ _pos += size;
+
+ VERBOSE(BP_ALLOC) << "alloc(#" << index.value() << "): " << blk.offset << ", " << blk.size
+ << std::endl;
+
+ return blk;
}
void BumpAllocator::finalize()
{
- assert(!_base && !_reserved_size && _curr_pos != 0);
- _reserved_size = _curr_pos;
- _base = new uint8_t[_reserved_size];
-}
+ assert(!_base && _pos != 0);
-void BumpAllocator::free(uint32_t)
-{
- assert(_base && _reserved_size > 0);
+ VERBOSE(BP_ALLOC) << "final position: " << _pos << std::endl;
- // DO NOTHING
- // In the case of this BumpAllocator, ignore the case like where reallocations are needed
+ _base = new uint8_t[_pos];
}
-MemoryBlock BumpAllocator::getMemoryBlock(uint32_t mem_id)
+void BumpAllocator::free(const graph::operand::Index &index)
{
- assert(_mem_blk_map.size() > 0);
-
- return _mem_blk_map[mem_id];
+ VERBOSE(BP_ALLOC) << "free(#" << index.value() << "): "
+ << "NOTHING does" << std::endl;
}
} // namespace cpu
#ifndef __NEURUN_BACKEND_CPU_MEMORY_ALLOCATOR_H__
#define __NEURUN_BACKEND_CPU_MEMORY_ALLOCATOR_H__
-#include <unordered_map>
+#include "graph/operand/Index.h"
namespace neurun
{
namespace cpu
{
-struct MemoryBlock
+struct Block
{
- uint32_t base_offset;
+ uint32_t offset;
uint32_t size;
};
struct IMemoryAllocator
{
virtual ~IMemoryAllocator() = default;
- virtual uint32_t allocate(size_t) = 0;
- virtual void free(uint32_t) = 0;
+ virtual Block allocate(const graph::operand::Index &, size_t) = 0;
+ virtual void free(const graph::operand::Index &) = 0;
virtual void finalize() = 0;
virtual uint8_t *base() const = 0;
- virtual MemoryBlock getMemoryBlock(uint32_t) = 0;
};
class BumpAllocator : public IMemoryAllocator
{
public:
virtual ~BumpAllocator() override;
- virtual uint32_t allocate(size_t size) override;
- virtual void free(uint32_t mem_id) override;
+ virtual Block allocate(const graph::operand::Index &index, size_t size) override;
+ virtual void free(const graph::operand::Index &index) override;
virtual void finalize() override;
virtual uint8_t *base() const override { return _base; }
- virtual MemoryBlock getMemoryBlock(uint32_t mem_id) override;
private:
uint8_t *_base = nullptr;
- uint32_t _reserved_size = 0;
- uint32_t _curr_pos = 0;
- uint32_t _mem_idx = 0;
- std::unordered_map<uint32_t, MemoryBlock> _mem_blk_map;
+ uint32_t _pos = 0;
};
} // namespace cpu
// If we do not make tensor here currently, stages would cause segment fault
const auto size = info.total_size(); // NOTE This size may not be accurate
- auto mem_id = _mem_alloc->allocate(size);
- _tensor_mem_map[ind] = mem_id;
+ auto mem_blk = _mem_alloc->allocate(ind, size);
+ _tensor_mem_map[ind] = mem_blk;
}
assert(_tensor_info_map.size() == _tensor_mem_map.size());
for (auto &entry : _tensor_mem_map)
{
auto ind = entry.first;
- auto mem_id = entry.second;
- auto mem_blk = _mem_alloc->getMemoryBlock(mem_id);
+ auto mem_blk = entry.second;
auto &tensor = _tensors[ind];
- tensor->setBuffer(_mem_alloc->base() + mem_blk.base_offset);
+ tensor->setBuffer(_mem_alloc->base() + mem_blk.offset);
}
}
#include "backend/interface/ITensorBuilder.h"
#include "backend/cpu/operand/Tensor.h"
#include "graph/operand/Index.h"
+#include "MemoryAllocator.h"
namespace neurun
{
namespace cpu
{
-struct IMemoryAllocator;
-
class TensorBuilder : public ITensorBuilder
{
public:
private:
std::unordered_map<graph::operand::Index, ::arm_compute::TensorInfo> _tensor_info_map;
std::unordered_map<graph::operand::Index, std::shared_ptr<operand::Tensor>> _tensors;
- std::unordered_map<graph::operand::Index, uint32_t> _tensor_mem_map;
+ std::unordered_map<graph::operand::Index, Block> _tensor_mem_map;
std::shared_ptr<IMemoryAllocator> _mem_alloc;
};
#include <gtest/gtest.h>
#include "backend/cpu/MemoryAllocator.h"
+#include "graph/operand/Index.h"
TEST(BumpAllocator, allocate_test)
{
::neurun::backend::cpu::BumpAllocator allocator;
- size_t mem_sz0 = 10;
- auto mem_id0 = allocator.allocate(mem_sz0);
- auto mem_blk0 = allocator.getMemoryBlock(mem_id0);
- ASSERT_EQ(mem_blk0.base_offset, 0);
- ASSERT_EQ(mem_blk0.size, mem_sz0);
+ auto allocate = [&allocator](uint32_t index, size_t size, uint32_t expected_offset) {
+ ::neurun::graph::operand::Index mem_idx(index);
+ auto mem_blk = allocator.allocate(mem_idx, size);
+ ASSERT_EQ(mem_blk.offset, expected_offset);
+ ASSERT_EQ(mem_blk.size, size);
+ };
- size_t mem_sz1 = 20;
- auto mem_id1 = allocator.allocate(mem_sz1);
- auto mem_blk1 = allocator.getMemoryBlock(mem_id1);
- ASSERT_EQ(mem_blk1.base_offset, mem_sz0);
- ASSERT_EQ(mem_blk1.size, mem_sz1);
-
- size_t mem_sz2 = 30;
- auto mem_id2 = allocator.allocate(mem_sz2);
- auto mem_blk2 = allocator.getMemoryBlock(mem_id2);
- ASSERT_EQ(mem_blk2.base_offset, mem_sz0 + mem_sz1);
- ASSERT_EQ(mem_blk2.size, mem_sz2);
+ allocate(0, 10, 0);
+ allocate(1, 20, 10);
+ allocate(2, 30, 30);
ASSERT_EQ(allocator.base(), nullptr);
}
{
::neurun::backend::cpu::BumpAllocator allocator;
- size_t mem_sz0 = 10;
- allocator.allocate(mem_sz0);
-
- size_t mem_sz1 = 20;
- allocator.allocate(mem_sz1);
+ auto allocate = [&allocator](uint32_t index, size_t size) {
+ ::neurun::graph::operand::Index mem_idx(index);
+ auto mem_blk = allocator.allocate(mem_idx, size);
+ };
- size_t mem_sz2 = 30;
- allocator.allocate(mem_sz2);
+ allocate(0, 10);
+ allocate(1, 20);
+ allocate(2, 30);
allocator.finalize();