forked from LearningInfiniTensor/TinyInfiniTensor
-
Notifications
You must be signed in to change notification settings - Fork 98
Expand file tree
/
Copy pathallocator.cc
More file actions
146 lines (120 loc) · 4.6 KB
/
allocator.cc
File metadata and controls
146 lines (120 loc) · 4.6 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "core/allocator.h"
#include <utility>
namespace infini
{
Allocator::Allocator(Runtime runtime) : runtime(runtime)
{
used = 0;
peak = 0;
ptr = nullptr;
// 'alignment' defaults to sizeof(uint64_t), because it is the length of
// the longest data type currently supported by the DataType field of
// the tensor
alignment = sizeof(uint64_t);
}
Allocator::~Allocator()
{
if (this->ptr != nullptr)
{
runtime->dealloc(this->ptr);
}
}
size_t Allocator::alloc(size_t size)
{
IT_ASSERT(this->ptr == nullptr);
// pad the size to the multiple of alignment
size = this->getAlignedSize(size);
// =================================== 作业 ===================================
// TODO: 设计一个算法来分配内存,返回起始地址偏移量
// =================================== 作业 ===================================
// 使用First Fit算法查找合适的空闲块
for (auto it = free_blocks.begin(); it != free_blocks.end(); ++it) {
size_t block_addr = it->first;
size_t block_size = it->second;
if (block_size >= size) {
// 找到合适的块,进行分配
size_t remaining_size = block_size - size;
if (remaining_size > 0) {
// 如果剩余空间足够大,创建新的空闲块
free_blocks[block_addr + size] = remaining_size;
}
// 移除或更新当前块
free_blocks.erase(it);
// 更新使用统计
used += size;
if (used > peak) {
peak = used;
}
return block_addr;
}
}
// 如果没有找到合适的空闲块,需要扩展内存
// 这里简化处理,直接返回当前已使用的大小作为新地址
size_t new_addr = used;
used += size;
if (used > peak) {
peak = used;
}
return new_addr;
}
void Allocator::free(size_t addr, size_t size)
{
IT_ASSERT(this->ptr == nullptr);
size = getAlignedSize(size);
// =================================== 作业 ===================================
// TODO: 设计一个算法来回收内存
// =================================== 作业 ===================================
// 将释放的内存块添加到空闲块映射中
free_blocks[addr] = size;
// 尝试与相邻的空闲块合并
mergeAdjacentBlocks(addr, size);
// 更新使用统计
used -= size;
}
void *Allocator::getPtr()
{
if (this->ptr == nullptr)
{
this->ptr = runtime->alloc(this->peak);
printf("Allocator really alloc: %p %lu bytes\n", this->ptr, peak);
}
return this->ptr;
}
size_t Allocator::getAlignedSize(size_t size)
{
return ((size - 1) / this->alignment + 1) * this->alignment;
}
void Allocator::mergeAdjacentBlocks(size_t addr, size_t size)
{
// 查找前一个相邻的空闲块
auto prev_it = free_blocks.find(addr - 1);
if (prev_it != free_blocks.end()) {
// 找到前一个块,检查是否真的相邻
size_t prev_addr = prev_it->first;
size_t prev_size = prev_it->second;
if (prev_addr + prev_size == addr) {
// 可以与前一个块合并
size_t new_size = prev_size + size;
free_blocks[prev_addr] = new_size;
free_blocks.erase(addr); // 移除当前块
// 更新参数,继续检查是否可以与后一个块合并
addr = prev_addr;
size = new_size;
}
}
// 查找后一个相邻的空闲块
auto next_it = free_blocks.find(addr + size);
if (next_it != free_blocks.end()) {
// 找到后一个块,可以合并
size_t next_size = next_it->second;
size_t new_size = size + next_size;
free_blocks[addr] = new_size;
free_blocks.erase(addr + size); // 移除后一个块
}
}
void Allocator::info()
{
std::cout << "Used memory: " << this->used
<< ", peak memory: " << this->peak << std::endl;
}
}