1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | #include <atb/types.h>
#include <acl/acl.h>
#include "memorypool.h"
#include "utils/log.h"
#include "utils/utils.h"
constexpr size_t POOL_SIZE = 104857600; // 预分配内存大小 100 MiB,大小可按实际需求决定
MemoryPool::MemoryPool(size_t poolSize = POOL_SIZE)
{
// 调用acl接口预分配内存
CHECK_RET(aclrtMalloc(&baseMemPtr_, poolSize, ACL_MEM_MALLOC_HUGE_FIRST),
"malloc huge size memrory " + std::to_string(poolSize) + " bytes fail");
curMemPtr_ = baseMemPtr_;
remainSize_ = poolSize;
}
MemoryPool::~MemoryPool()
{
// 销毁时通过acl接口释放内存
if (baseMemPtr_ != nullptr) {
CHECK_RET(aclrtFree(baseMemPtr_), "free huge memory fail");
}
LOG_INFO("release MemoryPool success");
}
uint64_t MemoryPool::GenerateBlocksId()
{
return static_cast<uint64_t>(id_.fetch_add(1, std::memory_order_relaxed));
}
void MemoryPool::AllocateBlock(uint32_t size, int &blockId)
{
std::unique_lock<std::mutex> lock(blockMutex_);
size_t alignSize = ((size + 31) & ~31) + 32; // 分配的空间需要32字节对齐后再加32字节
// 寻找是否有足够大小的空闲内存块
for (auto it = freeBlocks_.begin(); it != freeBlocks_.end(); it++) {
if (it->second.blockSize >= alignSize) {
blockId = it->second.blockId;
usedBlocks_.insert(*it);
freeBlocks_.erase(it);
LOG_INFO("find free block id " + std::to_string(blockId) + " to allocate");
return;
}
}
// 没有找到符合的内存块,需要从剩余的内存空间中创建新内存块
if (remainSize_ > alignSize) {
blockId = GenerateBlocksId();
uint64_t curMemPtrAlign = (reinterpret_cast<uint64_t>(curMemPtr_) + 63) & ~63; // 内存地址需要64字节对齐
remainSize_ -= (curMemPtrAlign - reinterpret_cast<uint64_t>(curMemPtr_));
curMemPtr_ = reinterpret_cast<void *>(curMemPtrAlign);
MemoryBlock block = {blockId, alignSize, curMemPtr_};
usedBlocks_.insert({blockId, block});
remainSize_ -= alignSize;
curMemPtr_ = reinterpret_cast<uint8_t *>(curMemPtr_) + alignSize;
LOG_INFO("allocate block id " + std::to_string(blockId) + " for size " + std::to_string(alignSize));
return;
}
// 剩余的内存空间不足,无法分配内存块
LOG_ERROR("allocate block fail");
}
void MemoryPool::FreeBlock(int blockId)
{
std::unique_lock<std::mutex> lock(blockMutex_);
// 内存块索引合法性校验
if (blockId < 0) {
LOG_INFO("skip over the invalid block id " + std::to_string(blockId));
return;
}
// 将需要释放的内存块标记为空闲
auto it = usedBlocks_.find(blockId);
if (it != usedBlocks_.end()) {
freeBlocks_.insert(*it);
usedBlocks_.erase(it);
} else {
LOG_ERROR("Double free block id " + std::to_string(blockId));
}
}
void MemoryPool::GetBlockPtr(int blockId, void *&addr)
{
std::unique_lock<std::mutex> lock(blockMutex_);
if (blockId < 0) {
LOG_INFO("Invalid block id " + std::to_string(blockId) + "to get ptr");
return;
}
// 寻找内存块,返回物理内存地址
auto it = usedBlocks_.find(blockId);
if (it != usedBlocks_.end()) {
addr = it->second.address;
} else {
LOG_ERROR("Get block address error, block id " + std::to_string(blockId));
}
}
|