Skip to content

Commit d9a1e2e

Browse files
committed
update frequency policy and fix rob
1 parent a48900a commit d9a1e2e

File tree

12 files changed

+250
-43
lines changed

12 files changed

+250
-43
lines changed

include/cxlcontroller.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,94 @@ class CachingPolicy : public Policy {
6464
// paging related
6565
};
6666

67+
struct LRUCacheEntry {
68+
uint64_t key; // 缓存键(地址)
69+
uint64_t value; // 缓存值
70+
uint64_t timestamp; // 最后访问时间戳
71+
};
72+
73+
// LRU缓存
74+
class LRUCache {
75+
public:
76+
int capacity; // 缓存容量
77+
std::unordered_map<uint64_t, LRUCacheEntry> cache; // 缓存映射
78+
std::list<uint64_t> lru_list; // LRU列表,最近使用的在前面
79+
std::unordered_map<uint64_t, std::list<uint64_t>::iterator> lru_map; // 用于O(1)查找列表位置
80+
81+
explicit LRUCache(int size) : capacity(size) {}
82+
83+
// 获取缓存值,如果存在则更新访问顺序
84+
std::optional<uint64_t> get(uint64_t key, uint64_t timestamp) {
85+
auto it = cache.find(key);
86+
if (it == cache.end()) {
87+
return std::nullopt; // 缓存未命中
88+
}
89+
90+
// 更新访问顺序
91+
lru_list.erase(lru_map[key]);
92+
lru_list.push_front(key);
93+
lru_map[key] = lru_list.begin();
94+
95+
// 更新时间戳
96+
it->second.timestamp = timestamp;
97+
98+
return it->second.value; // 返回缓存值
99+
}
100+
101+
// 添加或更新缓存
102+
void put(uint64_t key, uint64_t value, uint64_t timestamp) {
103+
// 如果已存在,先移除旧位置
104+
if (cache.find(key) != cache.end()) {
105+
lru_list.erase(lru_map[key]);
106+
}
107+
// 如果缓存已满,移除最久未使用的项
108+
else if (cache.size() >= capacity) {
109+
uint64_t lru_key = lru_list.back();
110+
lru_list.pop_back();
111+
lru_map.erase(lru_key);
112+
cache.erase(lru_key);
113+
}
114+
115+
// 添加新项到最前面(最近使用)
116+
lru_list.push_front(key);
117+
lru_map[key] = lru_list.begin();
118+
cache[key] = {key, value, timestamp};
119+
}
120+
121+
// 获取缓存使用情况统计
122+
std::tuple<int, int> get_stats() { return {cache.size(), capacity}; }
123+
124+
// 清除缓存
125+
void clear() {
126+
cache.clear();
127+
lru_list.clear();
128+
lru_map.clear();
129+
}
130+
// LRU缓存类中添加size()方法
131+
size_t size() const {
132+
return cache.size();
133+
}
134+
135+
// LRU缓存类中添加remove()方法
136+
bool remove(uint64_t key) {
137+
auto it = cache.find(key);
138+
if (it == cache.end()) {
139+
return false; // 键不存在
140+
}
141+
142+
// 从LRU列表中移除
143+
lru_list.erase(lru_map[key]);
144+
145+
// 从映射中移除
146+
lru_map.erase(key);
147+
148+
// 从缓存中移除
149+
cache.erase(key);
150+
151+
return true;
152+
}
153+
};
154+
67155
class CXLController : public CXLSwitch {
68156
public:
69157
std::vector<CXLMemExpander *> cur_expanders{};
@@ -87,6 +175,8 @@ class CXLController : public CXLSwitch {
87175
std::queue<lbr> ring_buffer;
88176
// rob info
89177
std::unordered_map<uint64_t, thread_info> thread_map;
178+
// LRU cache
179+
LRUCache lru_cache;
90180

91181
explicit CXLController(std::array<Policy *, 4> p, int capacity, page_type page_type_, int epoch,
92182
double dramlatency);
@@ -106,6 +196,11 @@ class CXLController : public CXLSwitch {
106196
void set_stats(mem_stats stats);
107197
static void set_process_info(const proc_info &process_info);
108198
static void set_thread_info(const proc_info &thread_info);
199+
// 添加缓存访问方法
200+
std::optional<uint64_t> access_cache(uint64_t addr, uint64_t timestamp) { return lru_cache.get(addr, timestamp); }
201+
202+
// 添加缓存更新方法
203+
void update_cache(uint64_t addr, uint64_t value, uint64_t timestamp) { lru_cache.put(addr, value, timestamp); }
109204
};
110205

111206
template <> struct std::formatter<CXLController> {
@@ -206,6 +301,7 @@ template <> struct std::formatter<CXLController> {
206301
result += "\nStatistics:\n";
207302
result += std::format(" Number of Switches: {}\n", controller.num_switches);
208303
result += std::format(" Number of Endpoints: {}\n", controller.num_end_points);
304+
result += std::format(" Number of Threads created: {}\n", controller.thread_map.size());
209305
result += std::format(" Memory Freed: {} bytes\n", controller.freed);
210306

211307
return format_to(ctx.out(), "{}", result);

include/cxlendpoint.h

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <list>
1818
#include <queue>
1919
#include <map>
20-
#include <string>
2120
#include <tuple>
2221
#include <unordered_set>
2322
#include <vector>
@@ -75,6 +74,21 @@ class CXLMemExpander : public CXLEndPoint {
7574
int epoch = 0;
7675
uint64_t last_timestamp = 0;
7776
int id = -1;
77+
struct AddressRange {
78+
uint64_t start;
79+
uint64_t end;
80+
81+
// 添加比较运算符,用于二分查找
82+
bool operator<(const AddressRange& other) const {
83+
return end < other.start;
84+
}
85+
86+
bool operator<(uint64_t addr) const {
87+
return end < addr;
88+
}
89+
};
90+
std::vector<AddressRange> address_ranges;
91+
7892
CXLMemExpander(int read_bw, int write_bw, int read_lat, int write_lat, int id, int capacity);
7993
std::vector<std::tuple<uint64_t, uint64_t>> get_access(uint64_t timestamp) override;
8094
void set_epoch(int epoch) override;
@@ -86,25 +100,50 @@ class CXLMemExpander : public CXLEndPoint {
86100
void delete_entry(uint64_t addr, uint64_t length) override;
87101
void update_address_cache() {
88102
if (cache_valid) return;
89-
90103
address_cache.clear();
91-
for (const auto& occ : occupation) {
104+
for (const auto& occ : occupation)
92105
address_cache.insert(occ.address);
93-
}
94106
cache_valid = true;
95107
}
96108
// 当 occupation 更新时调用此函数
97109
void invalidate_cache() {
98110
cache_valid = false;
99111
}
100112

101-
// 检查地址是否在 occupation 中
102-
bool is_address_local(uint64_t addr) {
103-
if (!cache_valid) {
104-
update_address_cache();
113+
void update_range_cache() {
114+
if (cache_valid) return;
115+
address_ranges.clear();
116+
// 排序occupation以便合并连续地址
117+
std::sort(occupation.begin(), occupation.end(),
118+
[](const auto& a, const auto& b) { return a.address < b.address; });
119+
if (occupation.empty()) {
120+
cache_valid = true;
121+
return;
122+
}
123+
AddressRange current{occupation[0].address, occupation[0].address};
124+
for (size_t i = 1; i < occupation.size(); i++) {
125+
if (occupation[i].address == current.end + 1) {
126+
// 连续地址,扩展范围
127+
current.end = occupation[i].address;
128+
} else {
129+
// 新范围
130+
address_ranges.push_back(current);
131+
current = {occupation[i].address, occupation[i].address};
132+
}
105133
}
134+
address_ranges.push_back(current);
135+
cache_valid = true;
136+
}
106137

107-
return address_cache.find(addr) != address_cache.end();
138+
bool is_address_local(uint64_t addr) {
139+
if (!cache_valid)
140+
update_range_cache();
141+
// 使用标准库的二分查找,查找第一个"不小于"addr的元素
142+
auto it = std::lower_bound(address_ranges.begin(), address_ranges.end(), addr);
143+
// 如果找到了范围,且addr在这个范围内
144+
if (it != address_ranges.end() && addr >= it->start && addr <= it->end)
145+
return true;
146+
return false;
108147
}
109148
};
110149
class CXLSwitch : public CXLEndPoint {

include/policy.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,56 @@ class FIFOPolicy : public CachingPolicy {
5353
FIFOPolicy() = default;
5454
int compute_once(CXLController *) override;
5555
};
56+
// 基于访问频率的后向失效策略
57+
class FrequencyBasedInvalidationPolicy : public CachingPolicy {
58+
private:
59+
std::unordered_map<uint64_t, uint64_t> access_count; // 地址到访问计数的映射
60+
uint64_t access_threshold; // 访问阈值
61+
uint64_t last_cleanup; // 上次清理时间戳
62+
uint64_t cleanup_interval; // 清理间隔
5663

64+
public:
65+
explicit FrequencyBasedInvalidationPolicy(uint64_t threshold = 100, uint64_t interval = 10000000)
66+
: access_threshold(threshold), last_cleanup(0), cleanup_interval(interval) {}
67+
68+
bool should_cache(uint64_t addr, uint64_t timestamp) {
69+
// 记录访问
70+
access_count[addr]++;
71+
return true; // 总是缓存
72+
}
73+
74+
bool should_invalidate(uint64_t addr, uint64_t timestamp) {
75+
// 根据访问频率决定是否应该失效
76+
auto it = access_count.find(addr);
77+
if (it != access_count.end()) {
78+
return it->second < access_threshold;
79+
}
80+
return false;
81+
}
82+
83+
std::vector<uint64_t> get_invalidation_list(CXLController* controller) {
84+
std::vector<uint64_t> to_invalidate;
85+
86+
// 遍历缓存查找低频访问的地址
87+
for (const auto& [addr, entry] : controller->lru_cache.cache) {
88+
if (should_invalidate(addr, 0)) {
89+
to_invalidate.push_back(addr);
90+
}
91+
}
92+
93+
// 清理访问计数(周期性)
94+
uint64_t current_time = controller->last_timestamp;
95+
if (current_time - last_cleanup > cleanup_interval) {
96+
access_count.clear();
97+
last_cleanup = current_time;
98+
}
99+
100+
return to_invalidate;
101+
}
102+
103+
int compute_once(CXLController* controller) override {
104+
// 如果有需要失效的地址,返回正数
105+
return !get_invalidation_list(controller).empty() ? 1 : 0;
106+
}
107+
};
57108
#endif // CXLMEMSIM_POLICY_H

microbench/st.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"add $" STR(MOVE_SIZE) ", %%r8 \n" \
4747
"cmp $" STR(FENCE_BOUND) ",%%r8\n" \
4848
"jl LOOP_START%= \n" \
49+
"clflush (%%r9) \n" \
4950
"mfence \n"
5051

5152

microbench/st_serial.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"movdqa %%xmm1, (%%r9) \n" \
4646
"add $" STR(MOVE_SIZE) ", %%r8 \n" \
4747
"cmp $" STR(FENCE_BOUND) ",%%r8\n" \
48+
"clflush (%%r9) \n" \
4849
"mfence \n" \
4950
"jl LOOP_START%= \n"
5051

src/cxlcontroller.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CXLController::CXLController(std::array<Policy *, 4> p, int capacity, page_type
4646
double dramlatency)
4747
: CXLSwitch(0), capacity(capacity), allocation_policy(dynamic_cast<AllocationPolicy *>(p[0])),
4848
migration_policy(dynamic_cast<MigrationPolicy *>(p[1])), paging_policy(dynamic_cast<PagingPolicy *>(p[2])),
49-
caching_policy(dynamic_cast<CachingPolicy *>(p[3])), page_type_(page_type_), dramlatency(dramlatency) {
49+
caching_policy(dynamic_cast<CachingPolicy *>(p[3])), page_type_(page_type_), dramlatency(dramlatency), lru_cache(32 * 1024 * 1024 / 64) {
5050
for (auto switch_ : this->switches) {
5151
switch_->set_epoch(epoch);
5252
}
@@ -56,7 +56,6 @@ CXLController::CXLController(std::array<Policy *, 4> p, int capacity, page_type
5656
// TODO get LRU wb
5757
// TODO BW type series
5858
// TODO cache
59-
// TODO back invalidation
6059
// deferentiate R/W for multi reader multi writer
6160
}
6261

@@ -130,9 +129,7 @@ void CXLController::insert_one(thread_info &t_info, lbr &lbr) {
130129
ring_buffer.pop();
131130
}
132131
}
133-
134132
int CXLController::insert(uint64_t timestamp, uint64_t tid, uint64_t phys_addr, uint64_t virt_addr, int index) {
135-
auto res = true;
136133
auto &t_info = thread_map[tid];
137134

138135
// 计算时间步长,使timestamp均匀分布
@@ -142,31 +139,54 @@ int CXLController::insert(uint64_t timestamp, uint64_t tid, uint64_t phys_addr,
142139
}
143140
uint64_t current_timestamp = last_timestamp;
144141

142+
bool res = true;
145143
for (int i = last_index; i < index; i++) {
146144
// 更新当前时间戳
147145
current_timestamp += time_step;
148146

147+
// 首先检查LRU缓存
148+
auto cache_result = access_cache(phys_addr, current_timestamp);
149+
150+
if (cache_result.has_value()) {
151+
// 缓存命中
152+
this->counter.inc_local();
153+
t_info.llcm_type.push(0); // 本地访问类型
154+
continue;
155+
}
156+
157+
// 缓存未命中,决定分配策略
149158
auto numa_policy = allocation_policy->compute_once(this);
159+
150160
if (numa_policy == -1) {
161+
// 本地访问
151162
this->occupation.emplace(current_timestamp, phys_addr);
152163
this->counter.inc_local();
153164
t_info.llcm_type.push(0);
154-
continue;
155-
}
156-
this->counter.inc_remote();
157-
for (auto switch_ : this->switches) {
158-
res &= switch_->insert(current_timestamp, tid, phys_addr, virt_addr, numa_policy);
159-
}
160-
for (auto expander_ : this->expanders) {
161-
res &= expander_->insert(current_timestamp, tid, phys_addr, virt_addr, numa_policy);
165+
166+
// 更新缓存
167+
update_cache(phys_addr, phys_addr, current_timestamp); // 使用物理地址作为值
168+
} else {
169+
// 远程访问
170+
this->counter.inc_remote();
171+
for (auto switch_ : this->switches) {
172+
res &= switch_->insert(current_timestamp, tid, phys_addr, virt_addr, numa_policy);
173+
}
174+
for (auto expander_ : this->expanders) {
175+
res &= expander_->insert(current_timestamp, tid, phys_addr, virt_addr, numa_policy);
176+
}
177+
t_info.llcm_type.push(1); // 远程访问类型
178+
// 可以选择是否缓存远程访问的数据
179+
if (caching_policy->compute_once(this)) {
180+
counter.inc_hitm();
181+
update_cache(phys_addr, phys_addr, current_timestamp);
182+
}
162183
}
163-
t_info.llcm_type.push(1);
164184
}
165185

166186
// 更新最后的索引和时间戳
167187
last_index = index;
168188
last_timestamp = timestamp;
169-
return res; // 返回实际的结果而不是固定的true
189+
return res;
170190
}
171191
int CXLController::insert(uint64_t timestamp, uint64_t tid, lbr lbrs[32], cntr counters[32]) {
172192
// 处理LBR记录

0 commit comments

Comments
 (0)