Program Listing for File component_cache.cpp¶
↰ Return to documentation for file (src/component_cache.cpp
)
#include <algorithm>
#include <vector>
#include "component_cache.h"
#include "sampler_tools.h"
#ifdef __linux__
#include <sys/sysinfo.h>
#include <cstdint>
uint64_t freeram() {
struct sysinfo info;
sysinfo(&info);
return info.freeram *(uint64_t) info.mem_unit;
}
#elif __APPLE__ && __MACH__
#include <sys/sysctl.h>
uint64_t freeram() {
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
return physical_memory;
}
#else
#endif
ComponentCache::ComponentCache(DataAndStatistics &statistics, SolverConfiguration &config) :
statistics_(statistics), config_(config) {
}
void ComponentCache::init(Component &super_comp, bool quiet) {
if (!quiet) {
std::cout << "Initialize cache\n"
<< "Size of Cacheable Component:\t" << sizeof(CacheableComponent) << "\n"
<< "Size of MPZ Class:\t" << sizeof(mpz_class) << std::endl;
}
CacheableComponent &packed_super_comp = *new CacheableComponent(super_comp);
my_time_ = 1;
entry_base_.clear();
entry_base_.reserve(2000000);
entry_base_.push_back(new CacheableComponent()); // dummy Element
table_.clear();
table_.resize(1024*1024, 0);
table_size_mask_ = table_.size() - 1;
free_entry_base_slots_.clear();
free_entry_base_slots_.reserve(10000);
uint64_t free_ram = freeram();
uint64_t max_cache_bound = 95 * (free_ram / 100);
if (statistics_.maximum_cache_size_bytes_ == 0) {
statistics_.maximum_cache_size_bytes_ = max_cache_bound;
}
if (!quiet) {
if (statistics_.maximum_cache_size_bytes_ > free_ram) {
std::cout << "\n";
//PrintWarning("Maximum cache size larger than free RAM available");
std::cout << " Free RAM " << free_ram / 1000000 << "MB\n";
}
std::cout << "Maximum cache size:\t"
<< statistics_.maximum_cache_size_bytes_ / 1000000 << " MB\n"
<< std::endl;
}
assert(!statistics_.cache_full());
if (entry_base_.capacity() == entry_base_.size())
entry_base_.reserve(2 * entry_base_.size());
entry_base_.push_back(&packed_super_comp);
statistics_.incorporate_cache_store(packed_super_comp);
super_comp.set_id(1);
}
void ComponentCache::test_descendantstree_consistency() {
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr) {
CacheEntryID act_child = entry(id).first_descendant();
while (act_child) {
CacheEntryID next_child = entry(act_child).next_sibling();
assert(entry(act_child).father() == id);
act_child = next_child;
}
CacheEntryID father = entry(id).father();
CacheEntryID act_sib = entry(father).first_descendant();
bool found = false;
while (act_sib && !found) {
CacheEntryID next_sib = entry(act_sib).next_sibling();
if (act_sib == id)
found = true;
act_sib = next_sib;
}
assert(found);
}
}
bool ComponentCache::deleteEntries() {
assert(statistics_.cache_full());
// Build a list of all the scores, sorts the list, then delete all
// entries with a score below the median.
std::vector<double> scores;
for (auto it = entry_base_.begin() + 1; it != entry_base_.end(); it++)
if (*it != nullptr && (*it)->isDeletable()) {
scores.push_back(static_cast<double>((*it)->creation_time()));
}
std::sort(scores.begin(), scores.end());
double cutoff = scores[scores.size() / 2];
//std::cout << "cutoff" << cutoff << " entries: "<< entry_base_.size()<< std::endl;
// first : go through the EntryBase and mark the entries to be deleted as deleted (i.e. EMPTY
// note we start at index 2,
// since index 1 is the whole formula,
// should always stay here!
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr &&
entry_base_[id]->isDeletable() &&
static_cast<double>(entry_base_[id]->creation_time()) <= cutoff) {
removeFromDescendantsTree(id);
eraseEntry(id);
}
// then go through the Hash Table and erase all Links to empty entries
#ifdef DEBUG
test_descendantstree_consistency();
#endif
reHashTable(table_.size());
statistics_.sum_size_cached_components_ = 0;
statistics_.sum_bytes_cached_components_ = 0;
statistics_.sys_overhead_sum_bytes_cached_components_ = 0;
statistics_.sum_bytes_pure_cached_component_data_ = 0;
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr) {
statistics_.sum_size_cached_components_ +=
entry_base_[id]->num_variables();
statistics_.sum_bytes_cached_components_ +=
entry_base_[id]->SizeInBytes();
statistics_.sum_bytes_pure_cached_component_data_ +=
entry_base_[id]->data_only_byte_size();
statistics_.sys_overhead_sum_bytes_cached_components_ +=
entry_base_[id]->sys_overhead_SizeInBytes();
}
statistics_.num_cached_components_ = entry_base_.size();
compute_byte_size_infrastructure();
//std::cout << " \t entries: "<< entry_base_.size() - free_entry_base_slots_.size()<< std::endl;
return true;
}
uint64_t ComponentCache::compute_byte_size_infrastructure() {
statistics_.cache_infrastructure_bytes_memory_usage_ =
sizeof(ComponentCache)
+ sizeof(CacheEntryID)* table_.capacity()
+ sizeof(CacheableComponent *)* entry_base_.capacity()
+ sizeof(CacheEntryID) * free_entry_base_slots_.capacity();
return statistics_.cache_infrastructure_bytes_memory_usage_;
}
void ComponentCache::debug_dump_data() {
std::cout << "sizeof (CacheableComponent *, CacheEntryID) "
<< sizeof(CacheableComponent *) << ", "
<< sizeof(CacheEntryID) << std::endl;
std::cout << "table (size/capacity) " << table_.size()
<< "/" << table_.capacity() << std::endl;
std::cout << "entry_base_ (size/capacity) " << entry_base_.size()
<< "/" << entry_base_.capacity() << std::endl;
std::cout << "free_entry_base_slots_ (size/capacity) " << free_entry_base_slots_.size()
<< "/" << free_entry_base_slots_.capacity() << std::endl;
// uint64_t size_model_counts = 0;
uint64_t alloc_model_counts = 0;
for (auto &pentry : entry_base_)
if (pentry != nullptr) {
// size_model_counts += pentry->size_of_model_count();
alloc_model_counts += pentry->alloc_of_model_count();
}
std::cout << "model counts size " << alloc_model_counts << std::endl;
}