carl  24.04
Computer ARithmetic Library
Cache.h
Go to the documentation of this file.
1 /*
2  * File: Cache.h
3  * Author: Florian Corzilius
4  *
5  * Created on September 4, 2014, 11:24 AM
6  */
7 
8 #pragma once
9 
10 #include "../util/container_types.h"
11 
12 #include <cassert>
13 #include <limits>
14 #include <mutex>
15 #include <stack>
16 #include <unordered_set>
17 #include <vector>
18 
19 namespace carl {
20  template<typename T, class I>
21  using TypeInfoPair = std::pair<T*,I>;
22 
23  template<typename T, class I>
24  bool operator==(const TypeInfoPair<T,I>& _tipA, const TypeInfoPair<T,I>& _tipB) {
25  return *_tipA.first == *_tipB.first;
26  }
27 }
28 
29 namespace std {
30  template<typename T, class I>
31  struct hash<carl::TypeInfoPair<T,I>> {
32  std::size_t operator()(const carl::TypeInfoPair<T,I>& _tip) const {
33  return _tip.first->hash();
34  }
35  };
36 }
37 
38 namespace carl
39 {
40  template<typename T>
41  bool returnFalse( const T& /*unused*/, const T& /*unused*/) { return false; }
42 
43  template<typename T>
44  void doNothing( const T& /*unused*/, const T& /*unused*/) {}
45 
46  template<typename T>
47  class Cache {
48 
49  public:
50  // The type of the reference of an entry in the cache.
51  using Ref = std::size_t;
52 
53  struct Info {
54  /**
55  * Store the number of usages of the entry in the cache for which this information hold by external objects.
56  */
57  std::size_t usageCount;
58 
59  /**
60  * Stores the reference of the entry in the cache for which this information hold.
61  */
62  std::vector<Ref> refStoragePositions;
63 
64  /**
65  * Stores the activity of the entry in the cache for which this information hold. The activity states how often the entry
66  * is involved in computations in the recent past.
67  */
68  double activity;
69 
70  explicit Info( double _activity ):
71  usageCount(0),
73  activity(_activity)
74  {}
75  };
76 
77  using Container = std::unordered_set<TypeInfoPair<T,Info>*, pointerHash<TypeInfoPair<T,Info>>, pointerEqual<TypeInfoPair<T,Info>>>;
78 
79  private:
80  // Members
81 
82  /**
83  * The threshold for the cache's size which should not be exceeded, except more of the cache entries are still in use.
84  */
85  std::size_t mMaxCacheSize;
86 
87  /**
88  * The current number of entries in the cache, which are not used.
89  */
90  std::size_t mNumOfUnusedEntries = 0;
91 
92  /**
93  * The percentage of the cache, which shall be removed at best, if the cache size exceeds the threshold. (NOT YET USED)
94  */
96 
97  /**
98  * The threshold for the maximum activity. In case it is exceeded, all activities are rescaled.
99  */
100  double mMaxActivity = 0.0;
101 
102  /**
103  * The reciprocal of the factor to multiply an activity with in order to increase it.
104  * This member can increased by a user interface.
105  */
106  double mActivityIncrement = 1.0;
107 
108  /**
109  * The decay (between 0.9 and 1.0) of the given increments on activities.
110  * It is applied by increasing the increment by multiplying this members reciprocal to it.
111  */
112  double mDecay;
113 
114  /**
115  * The threshold limiting the maximum activity. If this threshold is exceeded, all activities are rescaled.
116  */
117  double mActivityThreshold = 1e100;
118 
119  /**
120  * The factor multiplied to all activities in order to rescale (decrease) them.
121  */
122  double mActivityDecrementFactor = 1e-100;
123 
124  /**
125  * A mutex for situation where any member is changed. TODO: Refine the locking-situations.
126  */
127  std::recursive_mutex mMutex;
128 
129  /**
130  * The container storing all cached entries. It maps the objects to store to cache information, which cover a usage counter,
131  * the position in mCacheRefs, being the entries reference, and the activity of this entry.
132  */
134 
135  /**
136  * Stores at the reference of an entry in the cache an iterator to this entry.
137  * This reference can be used to access the entry outside this class.
138  */
139  std::vector<TypeInfoPair<T,Info>*> mCacheRefs;
140  /// A stack containing free references, which have been used before but freed now.
142 
143  public:
144 
145  static const Ref NO_REF;
146 
147  // The constructor.
148  explicit Cache( size_t _maxCacheSize = 10000, double _cacheReductionAmount = 0.2, double _decay = 0.98 );
149  Cache( const Cache& ) = delete; // no implementation
150  Cache& operator=( const Cache& ) = delete; // no implementation
151 
153 
154  /**
155  * Caches the given object.
156  * @param _toCache The object to cache.
157  * @param _canBeUpdated A function, which determines whether, in the case an equal object has already been cached, the given object
158  * can update the information in this already cached object.
159  * @param _update A function which updates an object in the cache, which is equal to the given object, by the information in the given object.
160  * After this function has been applied, the corresponding entry in the cache will be reinserted in it after been rehashed.
161  * @return The reference of the entry, which can be used outside this class to access the entry.
162  */
163  std::pair<Ref,bool> cache( T* _toCache, bool (*_canBeUpdated)( const T&, const T& ) = &returnFalse<T>, void (*_update)( const T&, const T& ) = &doNothing<T> );
164 
165  /**
166  * Registers the entry to the given reference. It mainly increases the usage counter of this entry in the cache.
167  * @param _refStoragePos The reference of the entry to register.
168  */
169  void reg( Ref _refStoragePos );
170 
171  /**
172  * Deregisters the entry to the given reference. It mainly decreases the usage counter of this entry in the cache.
173  * @param _refStoragePos The reference of the entry to deregister.
174  */
175  void dereg( Ref _refStoragePos );
176 
177  /**
178  * Removes and reinserts the entry with the given reference, after its hash value is recalculated.
179  * @param _refStoragePos The reference of the entry to apply the given function to.
180  * @return The new reference.
181  */
182  void rehash( Ref _refStoragePos );
183 
184  /**
185  * Decays all activities by increasing the activity increment.
186  */
188 
189  /**
190  * Strenghtens the activity of the entry in the cache with the given reference, by increasing its activity.
191  * @param _refStoragePos The reference of the entry in the cache to strengthen its activity.
192  */
193  void strengthenActivity( Ref _refStoragePos );
194 
195  /**
196  * Prints all information stored in this cache to std::cout.
197  * @param _out The stream to print on.
198  */
199  void print( std::ostream& _out = std::cout ) const;
200 
201  /**
202  * @param _refStoragePos The reference of the entry to obtain the object from.
203  * @return The object in the entry with the given reference.
204  */
205  const T& get( Ref _refStoragePos ) const
206  {
207  assert( _refStoragePos < mCacheRefs.size() );
208  assert( mCacheRefs[_refStoragePos] != nullptr );
209  assert( mCacheRefs[_refStoragePos]->second.usageCount > 0 );
210  return *mCacheRefs[_refStoragePos]->first;
211  }
212 
213  private:
214 
215  /**
216  * Removes a certain amount of unused entries in the cache.
217  */
218  void clean();
219 
220  /**
221  * Removes the entry at the given position in the cache.
222  * @param _toRemove The position to the entry to remove from the cache.
223  * @return
224  */
225  std::size_t erase( TypeInfoPair<T,Info>* _toRemove )
226  {
227  assert( checkNumOfUnusedEntries() );
228  std::lock_guard<std::recursive_mutex> lock( mMutex );
229  assert( _toRemove->second.usageCount == 0 );
230  for( const Ref& ref : _toRemove->second.refStoragePositions )
231  {
232  mCacheRefs[ref] = nullptr;
233  assert (ref > 0);
234  mUnusedPositionsInCacheRefs.push( ref );
235  }
236  assert( mNumOfUnusedEntries > 0 );
238  assert(_toRemove->second.usageCount == 0);
239  auto result = mCache.erase( _toRemove );
240  T* toDel = _toRemove->first;
241  delete _toRemove;
242  delete toDel;
243  assert( checkNumOfUnusedEntries() );
244  return result;
245  }
246 
247  /**
248  * Removes the entry at the given position in the cache.
249  * @param _toRemove The position to the entry to remove from the cache.
250  * @return An iterator to the entry in the cache right after the entry which has to be removed.
251  */
252  typename Container::iterator erase( typename Container::iterator _toRemove )
253  {
254  assert( checkNumOfUnusedEntries() );
255  std::lock_guard<std::recursive_mutex> lock( mMutex );
256  assert( (*_toRemove)->second.usageCount == 0 );
257  for( const Ref& ref : (*_toRemove)->second.refStoragePositions )
258  {
259  mCacheRefs[ref] = nullptr;
260  assert (ref > 0);
261  mUnusedPositionsInCacheRefs.push( ref );
262  }
263  assert( mNumOfUnusedEntries > 0 );
265  assert((*_toRemove)->second.usageCount == 0);
266  T* toDel = (*_toRemove)->first;
267  TypeInfoPair<T,Info>* toDelB = *_toRemove;
268  auto result = mCache.erase( _toRemove );
269  delete toDelB;
270  delete toDel;
271  assert( checkNumOfUnusedEntries() );
272  return result;
273  }
274 
275  bool hasDuplicates(const std::vector<Ref>& _vec) const
276  {
277  std::set<Ref> vecEntries;
278  for (const Ref& r: _vec) {
279  if (!vecEntries.insert(r).second) {
280  return true;
281  }
282  }
283  return false;
284  }
285 
287  {
288  std::size_t actualNumOfUnusedEntries = 0;
289  for( auto iter = mCache.begin(); iter != mCache.end(); ++iter )
290  {
291  if( (*iter)->second.usageCount == 0 )
292  {
293  ++actualNumOfUnusedEntries;
294  }
295  }
296  return mNumOfUnusedEntries == actualNumOfUnusedEntries;
297  }
298 
299  size_t sumOfAllUsageCounts() const
300  {
301  std::size_t result = 0;
302  for( auto iter = mCache.begin(); iter != mCache.end(); ++iter )
303  {
304  result += (*iter)->second.usageCount;
305  }
306  return result;
307  }
308 
309  };
310 
311 } // namespace carl
312 
313 
314 #include "Cache.tpp"
carl is the main namespace for the library.
void doNothing(const T &, const T &)
Definition: Cache.h:44
std::pair< T *, I > TypeInfoPair
Definition: Cache.h:21
bool returnFalse(const T &, const T &)
Definition: Cache.h:41
bool operator==(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
std::size_t operator()(const carl::TypeInfoPair< T, I > &_tip) const
Definition: Cache.h:32
std::size_t Ref
Definition: Cache.h:51
double mActivityDecrementFactor
The factor multiplied to all activities in order to rescale (decrease) them.
Definition: Cache.h:122
std::size_t mMaxCacheSize
The threshold for the cache's size which should not be exceeded, except more of the cache entries are...
Definition: Cache.h:85
double mCacheReductionAmount
The percentage of the cache, which shall be removed at best, if the cache size exceeds the threshold.
Definition: Cache.h:95
void dereg(Ref _refStoragePos)
Deregisters the entry to the given reference.
const T & get(Ref _refStoragePos) const
Definition: Cache.h:205
size_t sumOfAllUsageCounts() const
Definition: Cache.h:299
std::unordered_set< TypeInfoPair< T, Info > *, pointerHash< TypeInfoPair< T, Info > >, pointerEqual< TypeInfoPair< T, Info > >> Container
Definition: Cache.h:77
Cache(const Cache &)=delete
bool hasDuplicates(const std::vector< Ref > &_vec) const
Definition: Cache.h:275
std::vector< TypeInfoPair< T, Info > * > mCacheRefs
Stores at the reference of an entry in the cache an iterator to this entry.
Definition: Cache.h:139
bool checkNumOfUnusedEntries() const
Definition: Cache.h:286
std::size_t erase(TypeInfoPair< T, Info > *_toRemove)
Removes the entry at the given position in the cache.
Definition: Cache.h:225
Cache & operator=(const Cache &)=delete
Container::iterator erase(typename Container::iterator _toRemove)
Removes the entry at the given position in the cache.
Definition: Cache.h:252
void print(std::ostream &_out=std::cout) const
Prints all information stored in this cache to std::cout.
double mDecay
The decay (between 0.9 and 1.0) of the given increments on activities.
Definition: Cache.h:112
void clean()
Removes a certain amount of unused entries in the cache.
double mActivityThreshold
The threshold limiting the maximum activity.
Definition: Cache.h:117
std::pair< Ref, bool > cache(T *_toCache, bool(*_canBeUpdated)(const T &, const T &)=&returnFalse< T >, void(*_update)(const T &, const T &)=&doNothing< T >)
Caches the given object.
void rehash(Ref _refStoragePos)
Removes and reinserts the entry with the given reference, after its hash value is recalculated.
void strengthenActivity(Ref _refStoragePos)
Strenghtens the activity of the entry in the cache with the given reference, by increasing its activi...
Container mCache
The container storing all cached entries.
Definition: Cache.h:133
static const Ref NO_REF
Definition: Cache.h:145
double mMaxActivity
The threshold for the maximum activity.
Definition: Cache.h:100
std::stack< Ref > mUnusedPositionsInCacheRefs
A stack containing free references, which have been used before but freed now.
Definition: Cache.h:141
void reg(Ref _refStoragePos)
Registers the entry to the given reference.
Cache(size_t _maxCacheSize=10000, double _cacheReductionAmount=0.2, double _decay=0.98)
double mActivityIncrement
The reciprocal of the factor to multiply an activity with in order to increase it.
Definition: Cache.h:106
std::size_t mNumOfUnusedEntries
The current number of entries in the cache, which are not used.
Definition: Cache.h:90
std::recursive_mutex mMutex
A mutex for situation where any member is changed.
Definition: Cache.h:127
void decayActivity()
Decays all activities by increasing the activity increment.
double activity
Stores the activity of the entry in the cache for which this information hold.
Definition: Cache.h:68
Info(double _activity)
Definition: Cache.h:70
std::vector< Ref > refStoragePositions
Stores the reference of the entry in the cache for which this information hold.
Definition: Cache.h:62
std::size_t usageCount
Store the number of usages of the entry in the cache for which this information hold by external obje...
Definition: Cache.h:57
Alternative specialization of std::equal_to for pointer types.
Alternative specialization of std::hash for pointer types.