Skip to content

Commit

Permalink
Merge pull request #11 from chenhao-ye/access_mode
Browse files Browse the repository at this point in the history
Support Access Mode
  • Loading branch information
ShawnZhong authored Dec 2, 2023
2 parents 76d21c2 + 9a03ece commit 003a49f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 15 deletions.
44 changes: 34 additions & 10 deletions include/gcache/ghost_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@

namespace gcache {

// AccessMode controls the behavior to update cache stat
enum AccessMode : uint8_t {
DEFAULT, // update normally
AS_MISS, // consider it as a miss for all cache sizes
AS_HIT, // consider it as a hit for all cache sizes
NOOP, // do not update
};

struct CacheStat {
uint64_t hit_cnt;
uint64_t miss_cnt;
Expand Down Expand Up @@ -77,7 +85,7 @@ class GhostCache {
std::vector<Node_t*> size_boundaries;
std::vector<CacheStat> caches_stat;

void access_impl(uint32_t block_id, uint32_t hash);
void access_impl(uint32_t block_id, uint32_t hash, AccessMode mode);

public:
GhostCache(uint32_t tick, uint32_t min_size, uint32_t max_size)
Expand All @@ -94,7 +102,9 @@ class GhostCache {
assert(min_size + (num_ticks - 1) * tick == max_size);
cache.init(max_size);
}
void access(uint32_t block_id) { access_impl(block_id, ghash{}(block_id)); }
void access(uint32_t block_id, AccessMode mode = AccessMode::DEFAULT) {
access_impl(block_id, ghash{}(block_id), mode);
}

[[nodiscard]] uint32_t get_tick() const { return tick; }
[[nodiscard]] uint32_t get_min_size() const { return min_size; }
Expand Down Expand Up @@ -141,9 +151,9 @@ class SampledGhostCache : public GhostCache {
}

// Only update ghost cache if the first few bits of hash is all zero
void access(uint32_t block_id) {
void access(uint32_t block_id, AccessMode mode = AccessMode::DEFAULT) {
uint32_t hash = ghash{}(block_id);
if ((hash >> (32 - SampleShift)) == 0) access_impl(block_id, hash);
if ((hash >> (32 - SampleShift)) == 0) access_impl(block_id, hash, mode);
}

uint32_t get_tick() const { return tick << SampleShift; }
Expand All @@ -168,7 +178,8 @@ class SampledGhostCache : public GhostCache {
/**
* When using ghost cache, we assume in_use list is always empty.
*/
inline void GhostCache::access_impl(uint32_t block_id, uint32_t hash) {
inline void GhostCache::access_impl(uint32_t block_id, uint32_t hash,
AccessMode mode) {
uint32_t size_idx;
Handle_t s; // successor
Handle_t h = cache.refresh(block_id, hash, s);
Expand Down Expand Up @@ -210,11 +221,24 @@ inline void GhostCache::access_impl(uint32_t block_id, uint32_t hash) {
b->value++;
b = b->next;
}
if (s) {
for (uint32_t i = 0; i < size_idx; ++i) caches_stat[i].add_miss();
for (uint32_t i = size_idx; i < num_ticks; ++i) caches_stat[i].add_hit();
} else {
for (uint32_t i = 0; i < num_ticks; ++i) caches_stat[i].add_miss();
switch (mode) {
case AccessMode::DEFAULT:
if (s) {
for (uint32_t i = 0; i < size_idx; ++i) caches_stat[i].add_miss();
for (uint32_t i = size_idx; i < num_ticks; ++i)
caches_stat[i].add_hit();
} else {
for (uint32_t i = 0; i < num_ticks; ++i) caches_stat[i].add_miss();
}
break;
case AccessMode::AS_MISS:
for (uint32_t i = 0; i < num_ticks; ++i) caches_stat[i].add_miss();
break;
case AccessMode::AS_HIT:
for (uint32_t i = 0; i < num_ticks; ++i) caches_stat[i].add_hit();
break;
case AccessMode::NOOP:
break;
}

*h = 0;
Expand Down
42 changes: 37 additions & 5 deletions tests/test_ghost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,38 @@ void test1() {
ghost_cache.access(1);
ghost_cache.access(2);
ghost_cache.access(3);
std::cout
<< "Expect: Boundaries: [1, 0, (null), (null)]; Stat: [0/4, 0/4, 0/4]\n";
std::cout << "Expect: Boundaries: [1, 0, (null), (null)]; "
"Stat: [0/4, 0/4, 0/4, 0/4]\n";
std::cout << ghost_cache;

ghost_cache.access(4);
ghost_cache.access(5);
std::cout << "Expect: Boundaries: [3, 2, 1, 0]; Stat: [0/6, 0/6, 0/6]\n";
std::cout << "Expect: Boundaries: [3, 2, 1, 0]; Stat: [0/6, 0/6, 0/6, 0/6]\n";
std::cout << ghost_cache;

ghost_cache.access(2);
std::cout << "Expect: Boundaries: [4, 3, 1, 0]; Stat: [0/7, 1/7, 1/7]\n";
std::cout << "Expect: Boundaries: [4, 3, 1, 0]; Stat: [0/7, 1/7, 1/7, 1/7]\n";
std::cout << ghost_cache;

ghost_cache.access(4);
std::cout << "Expect: Boundaries: [5, 3, 1, 0]; Stat: [1/8, 2/8, 2/8]\n";
std::cout << "Expect: Boundaries: [5, 3, 1, 0]; Stat: [1/8, 2/8, 2/8, 2/8]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(2, AccessMode::AS_MISS);
std::cout << "Expect: Boundaries: [5, 3, 1, 0]; Stat: [1/9, 2/9, 2/9, 2/9]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(0, AccessMode::AS_HIT);
std::cout
<< "Expect: Boundaries: [4, 5, 3, 1]; Stat: [2/10, 3/10, 3/10, 3/10]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(7, AccessMode::NOOP);
std::cout
<< "Expect: Boundaries: [2, 4, 5, 3]; Stat: [2/10, 3/10, 3/10, 3/10]\n";
std::cout << ghost_cache;
std::cout << std::flush;
}
Expand Down Expand Up @@ -72,6 +89,21 @@ void test2() {
std::cout << "Expect: Boundaries: [1, 6, 3]; Stat: [0/10, 0/10, 1/10]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(8, AccessMode::NOOP);
std::cout << "Expect: Boundaries: [4, 7, 5]; Stat: [0/10, 0/10, 1/10]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(9, AccessMode::AS_HIT);
std::cout << "Expect: Boundaries: [8, 1, 6]; Stat: [1/11, 1/11, 2/11]\n";
std::cout << ghost_cache;
std::cout << std::flush;

ghost_cache.access(1, AccessMode::AS_MISS);
std::cout << "Expect: Boundaries: [9, 4, 6]; Stat: [1/12, 1/12, 2/12]\n";
std::cout << ghost_cache;
std::cout << std::flush;
}

void bench1() {
Expand Down

0 comments on commit 003a49f

Please sign in to comment.