Skip to content

Commit

Permalink
Add MRU
Browse files Browse the repository at this point in the history
  • Loading branch information
JaeseungYeom committed Feb 27, 2024
1 parent 2a39517 commit b78e765
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 57 deletions.
40 changes: 36 additions & 4 deletions src/dyad/residency/fcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace dyad_residency {
// Associative Cache Set
//=============================================================================

// -------------------------- LRU ------------------------
bool Set_LRU::lookup (const std::string& fname, id_iterator_t &it)
{
id_idx_t& index_id = boost::multi_index::get<id> (m_block_set);
Expand All @@ -22,10 +23,12 @@ void Set_LRU::evict (void)
{ // LRU
if (m_block_set.size () == 0) return;
priority_idx_t& index_priority = boost::multi_index::get<priority> (m_block_set);
priority_iterator_t it = index_priority.begin ();
DYAD_LOG_INFO (NULL, " %s evicts %s from set %u\n", \
m_level.c_str (), it->m_id.c_str (), m_id);
index_priority.erase (it);
if (!index_priority.empty ()) {
priority_iterator_t it = index_priority.begin ();
DYAD_LOG_INFO (NULL, " %s evicts %s from set %u\n", \
m_level.c_str (), it->m_id.c_str (), m_id);
index_priority.erase (it);
}
}

void Set_LRU::load_and_access (const std::string& fname)
Expand Down Expand Up @@ -91,8 +94,32 @@ std::ostream& operator<<(std::ostream& os, const Set_LRU & cc)
return cc.print (os);
}

// -------------------------- MRU ------------------------
void Set_MRU::evict (void)
{ // MRU
if (m_block_set.size () == 0) return;
priority_idx_t& index_priority = boost::multi_index::get<priority> (m_block_set);
if (!index_priority.empty ()) {
auto it = index_priority.end (); --it;
DYAD_LOG_INFO (NULL, " %s evicts %s from set %u\n", \
m_level.c_str (), it->m_id.c_str (), m_id);
index_priority.erase (it);
}
}

bool Set_MRU::access (const std::string& fname)
{
return Set_LRU::access (fname);
}

std::ostream& operator<<(std::ostream& os, const Set_MRU & cc)
{
return cc.print (os);
}



// -------------------------- Prioritied ------------------------
bool Set_Prioritized::lookup (const std::string& fname, id_iterator_t &it)
{
id_idx_t& index_id = boost::multi_index::get<id> (m_block_set);
Expand Down Expand Up @@ -170,4 +197,9 @@ std::ostream& Set_Prioritized::print (std::ostream &os) const
return os;
}

std::ostream& operator<<(std::ostream& os, const Set_Prioritized& cc)
{
return cc.print (os);
}

} // end of namespace dyad_residency
44 changes: 38 additions & 6 deletions src/dyad/residency/fcache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,38 @@ class Set_LRU

std::ostream& operator<<(std::ostream& os, const Set_LRU & sl);

class Set_MRU : public Set_LRU
{
protected:
using Set_LRU::id;
using Set_LRU::priority;
using Set_LRU::LRU_Blocks;
using Set_LRU::id_idx_t;
using Set_LRU::id_iterator_t;
using Set_LRU::id_citerator_t;
using Set_LRU::priority_idx_t;
using Set_LRU::priority_iterator_t;
using Set_LRU::priority_citerator_t;
using Set_LRU::m_block_set;

using Set_LRU::lookup;
using Set_LRU::access;
using Set_LRU::load_and_access;
using Set_LRU::get_priority;

virtual void evict (void) override;

public:
Set_MRU (unsigned int sz, unsigned int n_sets, unsigned int id)
: Set_LRU (sz, n_sets, id) {}
virtual ~Set_MRU () override {}
virtual bool access (const std::string& fname) override;

using Set_LRU::print;
};

std::ostream& operator<<(std::ostream& os, const Set_MRU & sm);


class Set_Prioritized : public Set_LRU
{
Expand Down Expand Up @@ -152,17 +184,17 @@ class Set_Prioritized : public Set_LRU
Prio_Blocks m_block_set;

virtual bool lookup (const std::string& fname, id_iterator_t &it);
virtual void evict (void);
virtual void evict (void) override;
virtual void access (id_iterator_t &it);
virtual void load_and_access (const std::string& fname);
virtual unsigned int get_priority ();
virtual void load_and_access (const std::string& fname) override;
virtual unsigned int get_priority () override;

public:
Set_Prioritized (unsigned int sz, unsigned int n_sets, unsigned int id)
: Set_LRU (sz, n_sets, id) {}
virtual ~Set_Prioritized () {}
virtual bool access (const std::string& fname);
virtual std::ostream& print (std::ostream &os) const;
virtual ~Set_Prioritized () override {}
virtual bool access (const std::string& fname) override;
virtual std::ostream& print (std::ostream &os) const override;
};

std::ostream& operator<<(std::ostream& os, const Set_Prioritized & sp);
Expand Down
4 changes: 2 additions & 2 deletions src/dyad/residency/fcache_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ template <typename Set>
bool Cache<Set>::access (const std::string& fname)
{
//const unsigned int set_id = 0u;
//const unsigned int set_id = std::stoi (fname) % m_num_sets;
const unsigned int set_id = get_cache_set_id (fname);
const unsigned int set_id = std::stoi (fname) % m_num_sets;
//const unsigned int set_id = get_cache_set_id (fname);

return m_set[set_id].access (fname);
}
Expand Down
147 changes: 102 additions & 45 deletions src/dyad/residency/test_fcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,136 @@
#include <string>
#include <iostream>
#include <cstdlib>
#include <memory>
#include <type_traits>

int main (int argc, char** argv)
namespace dyad_residency
{
using namespace dyad_residency;

int seed = 0;
enum Set_Type {Set_LRU_, Set_MRU_, Set_Prio_, Set_End_};


if (argc > 2) {
template<Set_Type V>
using st = std::integral_constant<Set_Type, V>;

std::unique_ptr<Cache<Set_LRU>> make_cache(st<Set_LRU_>, unsigned size, unsigned ways) {
return std::unique_ptr<Cache<Set_LRU>>(new Cache<Set_LRU>(size, ways));
}
std::unique_ptr<Cache<Set_MRU>> make_cache(st<Set_MRU_>, unsigned size, unsigned ways) {
return std::unique_ptr<Cache<Set_MRU>>(new Cache<Set_MRU>(size, ways));
}
std::unique_ptr<Cache<Set_Prioritized>> make_cache(st<Set_Prio_>, unsigned size, unsigned ways) {
return std::unique_ptr<Cache<Set_Prioritized>>(new Cache<Set_Prioritized>(size, ways));
}

template< template<typename S> typename C, typename S>
int run_cache (int seed,
std::unique_ptr<C<S>>& cacheL1,
std::unique_ptr<C<S>>& cacheL2,
const std::vector<std::string>& acc)
{
bool hitL1 = false;

if (!cacheL1 || !cacheL2) {
std::cerr << "Cannot allocate cache." << std::endl;
return EXIT_FAILURE;
}
if (argc == 2) {
seed = atoi (argv[1]);
}
cacheL1->set_seed (seed + 104677u);
cacheL1->set_level ("L1");
cacheL2->set_seed (seed + 104681u);
cacheL2->set_level (" L2");

typedef std::vector<std::string> access;
access acc; // access pattern in terms of the block index
acc.push_back ("1");
acc.push_back ("4");
acc.push_back ("2");
acc.push_back ("3");
acc.push_back ("5");
acc.push_back ("5");
acc.push_back ("3");
bool hitL1;

#if 1
Cache<Set_LRU> cacheL1 (4, 2); // 2-way set-associative
Cache<Set_LRU> cacheL2 (8, 2); // cache capacity = 8 blocks
#else
Cache<Set_LRU> cacheL1 (4, 0); // cache capacity = 4 blocks
Cache<Set_LRU> cacheL2 (8, 0); // fully-associative
#endif
cacheL1.set_seed (seed + 104677u);
cacheL1.set_level ("L1");
cacheL2.set_seed (seed + 104681u);
cacheL2.set_level (" L2");

std::cout << "L1 Cache size set to " << cacheL1.size () << " blocks" << std::endl;
std::cout << "L2 Cache size set to " << cacheL2.size () << " blocks" << std::endl;
std::cout << "L1 Cache size set to " << cacheL1->size () << " blocks" << std::endl;
std::cout << "L2 Cache size set to " << cacheL2->size () << " blocks" << std::endl;

std::cout << "accessing block 1, 4, 2, and 3 in order" << std::endl;
for (unsigned int i = 0; (i < cacheL1.size ()) && (i < acc.size ()); i++) {
hitL1 = cacheL1.access (acc[i]);
if (!hitL1) cacheL2.access (acc[i]);
for (unsigned int i = 0; (i < cacheL1->size ()) && (i < acc.size ()); i++) {
hitL1 = cacheL1->access (acc[i]);
if (!hitL1) cacheL2->access (acc[i]);
}

std::cout << "-------------------------L1----------------------------" << std::endl;
std::cout << cacheL1 << std::endl;
std::cout << *cacheL1 << std::endl;
std::cout << "-------------------------L2----------------------------" << std::endl;
std::cout << cacheL2 << std::endl;
std::cout << *cacheL2 << std::endl;
std::cout << "-------------------------------------------------------" << std::endl;

std::cout << "accessing block 5" << std::endl;
hitL1 = cacheL1.access (acc[4]);
if (!hitL1) cacheL2.access (acc[4]);
hitL1 = cacheL1->access (acc[4]);
if (!hitL1) cacheL2->access (acc[4]);

std::cout << "-------------------------L1----------------------------" << std::endl;
std::cout << cacheL1 << std::endl;
std::cout << *cacheL1 << std::endl;
std::cout << "-------------------------L2----------------------------" << std::endl;
std::cout << cacheL2 << std::endl;
std::cout << *cacheL2 << std::endl;
std::cout << "-------------------------------------------------------" << std::endl;

std::cout << "accessing block 1, 4, 2, 3, 5, 5, and 3 in order" << std::endl;
for (unsigned int i = 0; i < acc.size (); i++) {
hitL1 = cacheL1.access (acc[i]);
if (!hitL1) cacheL2.access (acc[i]);
hitL1 = cacheL1->access (acc[i]);
if (!hitL1) cacheL2->access (acc[i]);
}

std::cout << "-------------------------L1----------------------------" << std::endl;
std::cout << cacheL1 << std::endl;
std::cout << *cacheL1 << std::endl;
std::cout << "-------------------------L2----------------------------" << std::endl;
std::cout << cacheL2 << std::endl;
std::cout << *cacheL2 << std::endl;
std::cout << "-------------------------------------------------------" << std::endl;

return EXIT_SUCCESS;
}

int cache_demo (const Set_Type st, int seed,
unsigned sizeL1, unsigned waysL1,
unsigned sizeL2, unsigned waysL2,
const std::vector<std::string>& acc)
{
if (st == Set_LRU_) {
auto cacheL1 = std::unique_ptr<Cache<Set_LRU>>(new Cache<Set_LRU> (sizeL1, waysL1));
auto cacheL2 = std::unique_ptr<Cache<Set_LRU>>(new Cache<Set_LRU> (sizeL2, waysL2));
return run_cache (seed, cacheL1, cacheL2, acc);
} else if (st == Set_MRU_) {
auto cacheL1 = std::unique_ptr<Cache<Set_MRU>>(new Cache<Set_MRU> (sizeL1, waysL1));
auto cacheL2 = std::unique_ptr<Cache<Set_MRU>>(new Cache<Set_MRU> (sizeL2, waysL2));
return run_cache (seed, cacheL1, cacheL2, acc);
} else if (st == Set_Prio_) {
auto cacheL1 = std::unique_ptr<Cache<Set_Prioritized>>(new Cache<Set_Prioritized> (sizeL1, waysL1));
auto cacheL2 = std::unique_ptr<Cache<Set_Prioritized>>(new Cache<Set_Prioritized> (sizeL2, waysL2));
return run_cache (seed, cacheL1, cacheL2, acc);
}
return EXIT_FAILURE;
}

} // end of namespace dyad_Residency


int main (int argc, char** argv)
{
using namespace dyad_residency;

int seed = 0;
Set_Type set_type = Set_LRU_;

if (argc > 3) {
return EXIT_FAILURE;
}
if (argc >= 2) {
seed = atoi (argv[1]);
}
if (argc == 3) {
int st = atoi (argv[2]);
set_type = static_cast<Set_Type> (st % Set_End_);
}

typedef std::vector<std::string> access;
access acc; // access pattern in terms of the block index
acc.push_back ("1");
acc.push_back ("4");
acc.push_back ("2");
acc.push_back ("3");
acc.push_back ("5");
acc.push_back ("5");
acc.push_back ("3");

return cache_demo (set_type, seed, 4, 2, 8, 2, acc);
}

0 comments on commit b78e765

Please sign in to comment.