Program Listing for File cache_manager.hpp¶
↰ Return to documentation for file (SeQuant/domain/eval/cache_manager.hpp
)
#ifndef SEQUANT_EVAL_CACHE_MANAGER_HPP
#define SEQUANT_EVAL_CACHE_MANAGER_HPP
#include <SeQuant/core/asy_cost.hpp>
#include <SeQuant/core/container.hpp>
#include <SeQuant/core/eval_node.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/domain/eval/eval_result.hpp>
#include <memory>
#include <range/v3/view.hpp>
namespace sequant {
class CacheManager {
public:
using key_type = size_t;
private:
class entry {
private:
size_t max_life;
size_t life_c;
ERPtr data_p;
public:
explicit entry(size_t count) noexcept;
[[nodiscard]] ERPtr access() noexcept;
void store(ERPtr data) noexcept;
void reset() noexcept;
[[nodiscard]] size_t life_count() const noexcept;
[[nodiscard]] size_t max_life_count() const noexcept;
private:
[[nodiscard]] int decay() noexcept;
}; // entry
static ERPtr store(entry& entry, ERPtr data) noexcept;
container::map<key_type, entry> cache_map_;
public:
template <typename Iterable1 = container::map<size_t, size_t>>
explicit CacheManager(Iterable1&& decaying) noexcept {
for (auto&& [k, c] : decaying) cache_map_.try_emplace(k, entry{c});
}
void reset() noexcept;
ERPtr access(key_type key) noexcept;
[[nodiscard]] ERPtr store(key_type key, ERPtr data) noexcept;
[[nodiscard]] bool exists(key_type key) const noexcept;
[[nodiscard]] int life(key_type key) const noexcept;
[[nodiscard]] int max_life(key_type key) const noexcept;
[[nodiscard]] container::set<size_t> keys() const noexcept;
static CacheManager empty() noexcept;
// for unit testing
template <typename T>
struct access_by;
template <typename T>
friend struct access_by;
}; // CacheManager
template <typename NodesI,
typename = std::enable_if_t<IsIterableOfEvalNodes<NodesI>>>
CacheManager cache_manager(NodesI const& nodes,
size_t min_repeats = 2) noexcept {
auto imed_counts = container::map<size_t, size_t>{};
// visits a node and check if its hash value exists in imed_counts map
// if it does increase the count and return false (to signal stop visiting
// children nodes) otherwise returns true.
auto imed_visitor = [&imed_counts](auto&& n) -> bool {
auto&& end = imed_counts.end();
auto&& h = hash::value(*n);
if (auto&& found = imed_counts.find(h); found != end) {
++found->second;
return false;
} else
imed_counts.emplace(h, 1);
return true;
}; // imed_visitor
// visit imeds
ranges::for_each(nodes, [&imed_visitor](auto&& tree) {
tree.visit_internal(imed_visitor);
});
// remove less repeating imeds
auto less_repeating = [min_repeats](auto&& pair) {
return pair.second < min_repeats;
};
ranges::actions::remove_if(imed_counts, less_repeating);
return CacheManager{imed_counts};
}
AsyCost peak_cache(Sum const& expr);
} // namespace sequant
#endif // SEQUANT_EVAL_CACHE_MANAGER_HPP