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
177 lines (149 loc) · 5.69 KB
/
allocator.cc
File metadata and controls
177 lines (149 loc) · 5.69 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#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: 设计一个算法来分配内存,返回起始地址偏移量
// Use First Fit algorithm: find the first free block that is large enough
for (auto it = freeBlocksByAddr.begin(); it != freeBlocksByAddr.end(); ++it)
{
size_t addr = it->first;
size_t blockSize = it->second;
if (blockSize >= size)
{
// Found a suitable block
// Remove this block from both maps
freeBlocksByAddr.erase(it);
freeBlocksByEnd.erase(addr + blockSize);
// If the block is larger than needed, add the remaining part back
if (blockSize > size)
{
size_t newAddr = addr + size;
size_t newSize = blockSize - size;
freeBlocksByAddr[newAddr] = newSize;
freeBlocksByEnd[newAddr + newSize] = newSize;
}
// Update memory usage statistics
used += size;
if (used > peak)
{
peak = used;
}
return addr;
}
}
// No suitable free block found, allocate at the end
size_t addr = peak;
used += size;
peak += size;
return addr;
// =================================== 作业 ===================================
return 0;
}
void Allocator::free(size_t addr, size_t size)
{
IT_ASSERT(this->ptr == nullptr);
size = getAlignedSize(size);
// =================================== 作业 ===================================
// TODO: 设计一个算法来回收内存
// Update memory usage
used -= size;
size_t blockStart = addr;
size_t blockEnd = addr + size;
size_t blockSize = size;
// Special case: if freeing the block at the end, just reduce peak
if (blockEnd == peak)
{
// Check if we can merge with a previous free block at the end
auto prevIt = freeBlocksByEnd.find(blockStart);
if (prevIt != freeBlocksByEnd.end())
{
// Merge with the previous block and reduce peak further
size_t prevSize = prevIt->second;
size_t prevStart = blockStart - prevSize;
// Remove the previous block from both maps
freeBlocksByAddr.erase(prevStart);
freeBlocksByEnd.erase(blockStart);
// Reduce peak to the start of the merged block
peak = prevStart;
}
else
{
// Just reduce peak
peak = blockStart;
}
return;
}
// Try to merge with the previous adjacent free block
auto prevIt = freeBlocksByEnd.find(blockStart);
if (prevIt != freeBlocksByEnd.end())
{
// Found a previous adjacent block
size_t prevSize = prevIt->second;
size_t prevStart = blockStart - prevSize;
// Remove the previous block from both maps
freeBlocksByAddr.erase(prevStart);
freeBlocksByEnd.erase(blockStart);
// Merge: extend the current block backwards
blockStart = prevStart;
blockSize += prevSize;
}
// Try to merge with the next adjacent free block
auto nextIt = freeBlocksByAddr.find(blockEnd);
if (nextIt != freeBlocksByAddr.end())
{
// Found a next adjacent block
size_t nextSize = nextIt->second;
// Remove the next block from both maps
freeBlocksByAddr.erase(blockEnd);
freeBlocksByEnd.erase(blockEnd + nextSize);
// Merge: extend the current block forwards
blockSize += nextSize;
blockEnd += nextSize;
}
// Add the merged (or original) free block to both maps
freeBlocksByAddr[blockStart] = blockSize;
freeBlocksByEnd[blockEnd] = blockSize;
// =================================== 作业 ===================================
}
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::info()
{
std::cout << "Used memory: " << this->used
<< ", peak memory: " << this->peak << std::endl;
}
}