Compare commits
7 Commits
a21fc9e08d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 1916781bbb | |||
| 539df093a3 | |||
| 49ef72e1ea | |||
| 49410552c6 | |||
| 1a84f77192 | |||
| 552953591e | |||
| 55345b7c76 |
+3
-1
@@ -1,4 +1,6 @@
|
||||
*.o
|
||||
*.
|
||||
*.txt
|
||||
*.vscode
|
||||
*.vscode
|
||||
*.out
|
||||
*.exe
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
class Ideal_Cache {
|
||||
private:
|
||||
int capacity;
|
||||
std::vector<int> cache;
|
||||
std::unordered_map<int, int> cacheMap; // Для быстрого доступа к индексам
|
||||
|
||||
|
||||
public:
|
||||
Ideal_Cache(size_t capacity) : capacity(capacity) {}
|
||||
|
||||
int tic_number = 0;
|
||||
|
||||
void get_request_vector(const std::vector<int>& requests) {
|
||||
// смотрим есть ли айди в кэше
|
||||
// Есть - тик
|
||||
// Нет - смотрим размер, если размер не полный добавляем в кэш
|
||||
// если размер полный, то уберем тот, который позже всех встретится
|
||||
|
||||
|
||||
for (size_t i = 0; i < requests.size(); ++i) {
|
||||
int item = requests[i];
|
||||
|
||||
if (cacheMap.find(item) != cacheMap.end()) {
|
||||
tic_number++; //tic
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cache.size() < capacity) {
|
||||
cache.push_back(item);
|
||||
cacheMap[item] = cache.size() - 1;
|
||||
} else {
|
||||
int farthest = -1;
|
||||
int indexToRemove = -1;
|
||||
|
||||
for (size_t j = 0; j < cache.size(); ++j) {
|
||||
auto nextIndex = std::find(requests.begin() + i, requests.end(), cache[j]); //находим следующее вхождение (начиная с i ого тк предыдущие обработались)
|
||||
|
||||
if (nextIndex == requests.end()) {
|
||||
indexToRemove = j; //В конце удалим последний
|
||||
break;
|
||||
} else {
|
||||
int nextIdx = std::distance(requests.begin(), nextIndex);
|
||||
if (nextIdx > farthest) {
|
||||
farthest = nextIdx;
|
||||
indexToRemove = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cacheMap.erase(cache[indexToRemove]);
|
||||
cache[indexToRemove] = item;
|
||||
cacheMap[item] = indexToRemove;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void info() const {
|
||||
std::cout << "ideal cache: ";
|
||||
for (int item : cache) {
|
||||
std::cout << item << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
@@ -1,14 +1,22 @@
|
||||
# Алгоритм кэширования 2Q
|
||||
Алгоритм кэширования 2Q (Two Queues) представляет собой метод управления кэш-памятью. Этот алгоритм состоит из двух очередей: q1 и q2. q1 является буфером, в который добавляются данные только в начале и замещаются из конца, а q2 используется для хранения "недавно использованных" данных.
|
||||
|
||||
# Тестирование
|
||||
Генератор тестов - test_gen.py спрашивает количество тестов и создает pytests.txt
|
||||
# Запуск тестов
|
||||
make test - собирает программу затем
|
||||
./cache_test "test_file_name"
|
||||
## Напиример:
|
||||
./cache_test pytests.txt
|
||||
# Принцип работы
|
||||
Когда данные добавляются в кэш, они помещаются в начало q1.
|
||||
Если данные извлекаются из кэша, они перемещаются из q1 в начало q2.
|
||||
Если данные снова запрашиваются и они находятся в q2, они перемещаются в конец q1.
|
||||
Если данные снова запрашиваются и их уже нет в кэше, они добавляются в начало q1, а если q1 заполнена, то данные из конца q1 удаляются и добавляются новые данные в начало q1.
|
||||
# Преимущества
|
||||
## Эффективность: алгоритм 2Q обладает хорошей производительностью и способен эффективно управлять кэш-памятью.
|
||||
## Адаптивность: алгоритм автоматически регулируется в зависимости от обращаемости данных, приспосабливаясь к изменениям в запросах.
|
||||
## Эффективность:
|
||||
алгоритм 2Q обладает хорошей производительностью и способен эффективно управлять кэш-памятью.
|
||||
## Адаптивность:
|
||||
алгоритм автоматически регулируется в зависимости от обращаемости данных, приспосабливаясь к изменениям в запросах.
|
||||
## Недостатки
|
||||
Не подходит для всех типов данных: алгоритм 2Q неэффективен для случаев, когда данные необходимо хранить в определённом порядке.
|
||||
Сложность реализации: реализация алгоритма кэширования 2Q может быть более сложной, чем у других методов управления кэш-памятью.
|
||||
|
||||
BIN
Binary file not shown.
+15
-6
@@ -1,7 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "2Q_cache.h"
|
||||
#include "Ideal_cache.h"
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
const char* default_test_file = "tests.txt";
|
||||
|
||||
@@ -20,21 +23,28 @@ int cache_test(std::string file_name) {
|
||||
std::string test_line, answer_line;
|
||||
int fast_q_sz, slow_q_sz, num_of_calls, page_id, test_number = 0, test_passed = 0, test_failed = 0;
|
||||
|
||||
while(std::getline(file, test_line)) {
|
||||
while (std::getline(file, test_line)) {
|
||||
std::stringstream ss(test_line);
|
||||
ss >> fast_q_sz >> slow_q_sz>>num_of_calls; //read input
|
||||
|
||||
TwoCache cache(fast_q_sz, slow_q_sz); //initialising
|
||||
Ideal_Cache ideal_cache(fast_q_sz + slow_q_sz);
|
||||
|
||||
for(int i = 0; i < num_of_calls; i++) { //executing
|
||||
std::vector <int> requests;
|
||||
|
||||
for (int i = 0; i < num_of_calls; i++) { //executing
|
||||
ss >> page_id;
|
||||
cache.put_page(page_id);
|
||||
requests.push_back(page_id);
|
||||
}
|
||||
|
||||
ideal_cache.get_request_vector(requests);
|
||||
|
||||
std::getline(file, answer_line);
|
||||
|
||||
if(cache.string_info() == answer_line) { //compare answers
|
||||
if (cache.string_info() == answer_line) { //compare answers
|
||||
std::cout << "test - " << test_number << " passed\n";
|
||||
std::cout << "ideal tics/your tics " << ideal_cache.tic_number << "/" << cache.tic_number << std::endl;
|
||||
test_passed++;
|
||||
} else {
|
||||
std::cout << "test - " << test_number << " failed\n";
|
||||
@@ -53,10 +63,9 @@ int cache_test(std::string file_name) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc == 0) {
|
||||
if (argc == 0) {
|
||||
cache_test(default_test_file);
|
||||
} else {
|
||||
cache_test(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
TARGET = Q2
|
||||
|
||||
CXX = g++
|
||||
|
||||
CXXFLAGS = -Wall -Wextra -std=c++11
|
||||
|
||||
SRCS = main.cpp
|
||||
TEST = cache_test.cpp
|
||||
|
||||
@@ -15,15 +12,22 @@ $(TARGET): $(OBJS)
|
||||
$(CXX) -o $@ $^
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
$(CXX) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
test:
|
||||
$(CXX) $(CXXFLAGS) $(TEST) -o cache_test
|
||||
|
||||
$(CXX) $(CPPFLAGS) $(TEST) -o cache_test
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
||||
rm -f $(OBJS) $(TARGET) cache_test
|
||||
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
.PHONY: all clean run
|
||||
ifeq ($(OS), Windows_NT)
|
||||
clean:
|
||||
del /Q $(OBJS) $(TARGET) cache_test
|
||||
run: $(TARGET)
|
||||
$(TARGET).exe
|
||||
endif
|
||||
|
||||
.PHONY: all clean run test
|
||||
+1
-1
@@ -45,7 +45,7 @@ if __name__ == "__main__":
|
||||
vect = []
|
||||
szq1 = random.randint(5, 10)
|
||||
szq2 = random.randint(5, 10)
|
||||
num_of_requests = (random.randint(1, 100))
|
||||
num_of_requests = (random.randint(1, 1000000))
|
||||
|
||||
cache = Cache(szq1, szq2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user