2019-04-17 10:49:11 +08:00
|
|
|
//
|
|
|
|
// BufferAllocator.hpp
|
|
|
|
// MNN
|
|
|
|
//
|
|
|
|
// Created by MNN on 2018/08/20.
|
|
|
|
// Copyright © 2018, Alibaba Group Holding Limited
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef BufferAllocator_hpp
|
|
|
|
#define BufferAllocator_hpp
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
|
|
|
#include <vector>
|
|
|
|
#include "MNNMemoryUtils.h"
|
|
|
|
#include "NonCopyable.hpp"
|
2021-04-08 15:34:23 +08:00
|
|
|
#include "AutoStorage.h"
|
2019-04-17 10:49:11 +08:00
|
|
|
|
|
|
|
namespace MNN {
|
|
|
|
|
|
|
|
/** memory utils wrapper. provides memory reusing with alignment ability. */
|
2019-12-27 22:16:57 +08:00
|
|
|
class MNN_PUBLIC BufferAllocator : public NonCopyable {
|
2019-04-17 10:49:11 +08:00
|
|
|
public:
|
2020-12-15 14:12:35 +08:00
|
|
|
class Allocator {
|
|
|
|
public:
|
|
|
|
Allocator() = default;
|
|
|
|
virtual ~ Allocator() = default;
|
2022-02-18 11:30:27 +08:00
|
|
|
virtual std::pair<void*, size_t> onAlloc(size_t size, size_t align) = 0;
|
|
|
|
virtual void onRelease(std::pair<void*, size_t> ptr) = 0;
|
2020-12-15 14:12:35 +08:00
|
|
|
static std::shared_ptr<Allocator> createDefault();
|
|
|
|
static std::shared_ptr<Allocator> createRecurse(BufferAllocator* parent);
|
|
|
|
};
|
2019-04-17 10:49:11 +08:00
|
|
|
/**
|
|
|
|
* @brief init buffer allocator with pointer alignment.
|
|
|
|
* @param align given pointer alignment.
|
|
|
|
*/
|
2022-02-18 11:30:27 +08:00
|
|
|
BufferAllocator(std::shared_ptr<Allocator> parent, size_t align = MNN_MEMORY_ALIGN_DEFAULT) : mAllocator(parent), mAlign(align) {
|
2019-04-17 10:49:11 +08:00
|
|
|
// nothing to do
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @brief deinit buffer allocator. frees all allocated memories.
|
|
|
|
*/
|
|
|
|
~BufferAllocator() {
|
|
|
|
release();
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* @brief alloc CHUNK pointer with given size. if any reusable pointer matches size, reuse it.
|
|
|
|
* @param size given size.
|
|
|
|
* @param seperate if true, the memory can't be alloc from free pool
|
|
|
|
* @return allocated or used CHUNK pointer.
|
|
|
|
* @sa free
|
|
|
|
* @sa release
|
|
|
|
*/
|
2022-02-18 11:30:27 +08:00
|
|
|
std::pair<void*, size_t> alloc(size_t size, bool seperate = false, size_t align = 0);
|
2019-04-17 10:49:11 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief mark CHUNK pointer as reusable.
|
|
|
|
* @param pointer given CHUNK pointer.
|
|
|
|
* @return true if pointer is a CHUNK pointer, false otherwise.
|
|
|
|
* @sa release
|
|
|
|
*/
|
2022-02-18 11:30:27 +08:00
|
|
|
bool free(std::pair<void*, size_t> pointer);
|
2019-04-17 10:49:11 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief free all allocated memories.
|
|
|
|
* @sa allocSeparate
|
|
|
|
* @sa alloc
|
2020-01-15 13:33:47 +08:00
|
|
|
* if allRelease, clear all memory , otherwise delete freelist
|
2019-04-17 10:49:11 +08:00
|
|
|
*/
|
2020-01-15 13:33:47 +08:00
|
|
|
void release(bool allRelease = true);
|
2019-04-17 10:49:11 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief query total size allocated indeed.
|
|
|
|
* @return total size allocated indeed.
|
|
|
|
*/
|
|
|
|
size_t totalSize() const {
|
|
|
|
return mTotalSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
For multi thread case,
|
|
|
|
we must assume that the memory use by different thread don't conflict
|
|
|
|
begin barrier / end barrier means enter the alloc for multi-thread
|
|
|
|
begin group / end group means the memory allocated belong to one thread
|
|
|
|
different group must use different memory,
|
|
|
|
but the origin freelist can be used by every group
|
|
|
|
*/
|
|
|
|
void barrierBegin();
|
|
|
|
void barrierEnd();
|
|
|
|
void beginGroup();
|
|
|
|
void endGroup();
|
|
|
|
|
|
|
|
private:
|
2021-04-08 15:34:23 +08:00
|
|
|
class Node : public RefCount {
|
2019-04-17 10:49:11 +08:00
|
|
|
public:
|
|
|
|
~Node();
|
2022-02-18 11:30:27 +08:00
|
|
|
std::pair<void*, size_t> pointer;
|
2021-04-08 15:34:23 +08:00
|
|
|
SharedPtr<Node> parent = nullptr;
|
2022-02-18 11:30:27 +08:00
|
|
|
size_t size;
|
|
|
|
size_t useCount = 0;
|
2020-12-15 14:12:35 +08:00
|
|
|
Allocator* outside = nullptr;
|
2019-04-17 10:49:11 +08:00
|
|
|
};
|
|
|
|
|
2021-04-08 15:34:23 +08:00
|
|
|
typedef std::multimap<size_t, SharedPtr<Node>> FREELIST;
|
2019-04-17 10:49:11 +08:00
|
|
|
|
2021-04-08 15:34:23 +08:00
|
|
|
static void returnMemory(FREELIST* list, SharedPtr<Node> node, bool permitMerge = true);
|
2022-02-18 11:30:27 +08:00
|
|
|
std::pair<void*, size_t> getFromFreeList(FREELIST* list, size_t size, bool permiteSplit, size_t align);
|
2019-04-17 10:49:11 +08:00
|
|
|
|
2022-02-18 11:30:27 +08:00
|
|
|
std::map<std::pair<void*, size_t>, SharedPtr<Node>> mUsedList;
|
2019-04-17 10:49:11 +08:00
|
|
|
FREELIST mFreeList;
|
|
|
|
size_t mTotalSize = 0;
|
|
|
|
|
2020-10-25 11:01:04 +08:00
|
|
|
FREELIST* mCurrentFreeList = nullptr;
|
2019-04-17 10:49:11 +08:00
|
|
|
std::vector<std::shared_ptr<FREELIST>> mGroups;
|
2020-12-15 14:12:35 +08:00
|
|
|
std::shared_ptr<Allocator> mAllocator;
|
2022-02-18 11:30:27 +08:00
|
|
|
size_t mAlign;
|
2019-04-17 10:49:11 +08:00
|
|
|
};
|
|
|
|
} // namespace MNN
|
|
|
|
#endif
|