Skip to content

Commit

Permalink
Clean associative cache
Browse files Browse the repository at this point in the history
  • Loading branch information
rickb80 committed Aug 21, 2023
1 parent 7966943 commit 0620c02
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 60 deletions.
85 changes: 31 additions & 54 deletions src/hashdb/database_associative_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ DatabaseMTAssociativeCache::DatabaseMTAssociativeCache()
indexes = NULL;
keys = NULL;
values = NULL;
isLeaf = NULL;
currentCacheIndex = 0;
attempts = 0;
hits = 0;
Expand All @@ -40,8 +39,7 @@ DatabaseMTAssociativeCache::~DatabaseMTAssociativeCache()
delete[] keys;
if (values != NULL)
delete[] values;
if (isLeaf != NULL)
delete[] isLeaf;

};

void DatabaseMTAssociativeCache::postConstruct(int nKeyBits_, int log2CacheSize_, string name_)
Expand All @@ -65,6 +63,7 @@ void DatabaseMTAssociativeCache::postConstruct(int nKeyBits_, int log2CacheSize_

if(indexes != NULL) delete[] indexes;
indexes = new uint32_t[indexesSize];
//initialization of indexes array
uint32_t initValue = UINT32_MAX-cacheSize-(uint32_t)1;
#pragma omp parallel for schedule(static) num_threads(4)
for (size_t i = 0; i < indexesSize; i++)
Expand All @@ -76,29 +75,15 @@ void DatabaseMTAssociativeCache::postConstruct(int nKeyBits_, int log2CacheSize_

if(values != NULL) delete[] values;
values = new Goldilocks::Element[12 * cacheSize];
if(isLeaf != NULL) delete[] isLeaf;
isLeaf = new bool[cacheSize];

currentCacheIndex = 0;
attempts = 0;
hits = 0;
name = name_;

cacheMask = 0;
for (int i = 0; i < log2CacheSize; i++)
{
cacheMask = cacheMask << 1;
cacheMask += 1;
}
assert(cacheMask == cacheSize - 1);

indexesMask = 0;
for (int i = 0; i < nKeyBits; i++)
{
indexesMask = indexesMask << 1;
indexesMask += 1;
}
assert(indexesMask == indexesSize - 1);

//masks for fast module, note cache size and indexes size must be power of 2
cacheMask = cacheSize - 1;
indexesMask = indexesSize - 1;
};

void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], const vector<Goldilocks::Element> &value, bool update)
Expand All @@ -107,7 +92,7 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
//
// Statistics
//
if (attempts%1000000 == 0)
if (attempts<<44 == 0)
{
zklog.info("DatabaseMTAssociativeCache::addKeyValue() name=" + name + " indexesSize=" + to_string(indexesSize) + " cacheSize=" + to_string(cacheSize) + " attempts=" + to_string(attempts) + " hits=" + to_string(hits) + " hit ratio=" + to_string(double(hits) * 100.0 / double(zkmax(attempts, 1))) + "%");
}
Expand All @@ -123,13 +108,11 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
uint32_t cacheIndexKey, cacheIndexValue;
bool write = false;

if ((currentCacheIndex >= cacheIndexRaw && currentCacheIndex - cacheIndexRaw > cacheSize) ||
(currentCacheIndex < cacheIndexRaw && UINT32_MAX - cacheIndexRaw + currentCacheIndex > cacheSize))
if (emptyCacheSlot(cacheIndexRaw))
{
write = true;
indexes[tableIndex] = currentCacheIndex;
cacheIndex = currentCacheIndex & cacheMask;

cacheIndexKey = cacheIndex * 4;
cacheIndexValue = cacheIndex * 12;
currentCacheIndex = (currentCacheIndex == UINT32_MAX) ? 0 : (currentCacheIndex + 1);
Expand All @@ -151,9 +134,8 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
continue;
}
}
if (write) // must be atomic operation!!
if (write)
{
isLeaf[cacheIndex] = (value.size() > 8);
keys[cacheIndexKey + 0].fe = key[0].fe;
keys[cacheIndexKey + 1].fe = key[1].fe;
keys[cacheIndexKey + 2].fe = key[2].fe;
Expand All @@ -166,7 +148,7 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
values[cacheIndexValue + 5] = value[5];
values[cacheIndexValue + 6] = value[6];
values[cacheIndexValue + 7] = value[7];
if (isLeaf[cacheIndex])
if (value.size() > 8)
{
values[cacheIndexValue + 8] = value[8];
values[cacheIndexValue + 9] = value[9];
Expand All @@ -187,10 +169,9 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
// forced entry insertion
//
uint32_t cacheIndex = (uint32_t)(currentCacheIndex & cacheMask);
currentCacheIndex = (currentCacheIndex == UINT32_MAX) ? 0 : (currentCacheIndex + 1); // atomic!
currentCacheIndex = (currentCacheIndex == UINT32_MAX) ? 0 : (currentCacheIndex + 1);
uint32_t cacheIndexKey = cacheIndex * 4;
uint32_t cacheIndexValue = cacheIndex * 12;
isLeaf[cacheIndex] = (value.size() > 8);
keys[cacheIndexKey + 0].fe = key[0].fe;
keys[cacheIndexKey + 1].fe = key[1].fe;
keys[cacheIndexKey + 2].fe = key[2].fe;
Expand All @@ -203,7 +184,7 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
values[cacheIndexValue + 5] = value[5];
values[cacheIndexValue + 6] = value[6];
values[cacheIndexValue + 7] = value[7];
if (isLeaf[cacheIndex])
if (value.size() > 8)
{
values[cacheIndexValue + 8] = value[8];
values[cacheIndexValue + 9] = value[9];
Expand All @@ -219,48 +200,47 @@ void DatabaseMTAssociativeCache::addKeyValue(Goldilocks::Element (&key)[4], cons
// Forced index insertion
//
int iters = 0;
uint32_t rawCacheIndexes[10];
rawCacheIndexes[0] = currentCacheIndex-1;
forcedInsertion(rawCacheIndexes, iters);
uint32_t usedRawCacheIndexes[10];
usedRawCacheIndexes[0] = currentCacheIndex-1;
forcedInsertion(usedRawCacheIndexes, iters);

}

void DatabaseMTAssociativeCache::forcedInsertion(uint32_t (&rawCacheIndexes)[10], int &iters)
void DatabaseMTAssociativeCache::forcedInsertion(uint32_t (&usedRawCacheIndexes)[10], int &iters)
{
uint32_t rawCacheIndex = rawCacheIndexes[iters];
uint32_t inputRawCacheIndex = usedRawCacheIndexes[iters];
//
// avoid infinite loop
//
iters++;
if (iters > 9)
{
zklog.error("forcedInsertion() more than 10 iterations required. Index: " + to_string(rawCacheIndex));
zklog.error("forcedInsertion() more than 10 iterations required. Index: " + to_string(inputRawCacheIndex));
exitProcess();
}

//
// find a slot into my indexes
//
uint32_t cacheIndex = (uint32_t)(rawCacheIndex & cacheMask);
Goldilocks::Element *key = &keys[cacheIndex * 4];
uint32_t inputCacheIndex = (uint32_t)(inputRawCacheIndex & cacheMask);
Goldilocks::Element *inputKey = &keys[inputCacheIndex * 4];
uint32_t minRawCacheIndex = UINT32_MAX;
int pos = -1;

for (int i = 0; i < 4; ++i)
{
uint32_t tableIndex_ = (uint32_t)(key[i].fe & indexesMask);
uint32_t tableIndex_ = (uint32_t)(inputKey[i].fe & indexesMask);
uint32_t rawCacheIndex_ = (uint32_t)(indexes[tableIndex_]);
if ((currentCacheIndex >= rawCacheIndex_ && currentCacheIndex - rawCacheIndex_ > cacheSize) ||
(currentCacheIndex < rawCacheIndex_ && UINT32_MAX - rawCacheIndex_ + currentCacheIndex > cacheSize))
if (emptyCacheSlot(rawCacheIndex_))
{
indexes[tableIndex_] = rawCacheIndex;
indexes[tableIndex_] = inputRawCacheIndex;
return;
}
else
{
bool used = false;
for(int k=0; k<iters; k++){
if(rawCacheIndexes[k] == rawCacheIndex_){
if(usedRawCacheIndexes[k] == rawCacheIndex_){
used = true;
break;
}
Expand All @@ -275,12 +255,12 @@ void DatabaseMTAssociativeCache::forcedInsertion(uint32_t (&rawCacheIndexes)[10]

if (pos < 0)
{
zklog.error("forcedInsertion() could not continue the recursion: " + to_string(rawCacheIndex));
zklog.error("forcedInsertion() could not continue the recursion: " + to_string(inputRawCacheIndex));
exitProcess();
}
indexes[(uint32_t)(key[pos].fe & indexesMask)] = rawCacheIndex;
rawCacheIndexes[iters] = minRawCacheIndex;
forcedInsertion(rawCacheIndexes, iters);
indexes[(uint32_t)(inputKey[pos].fe & indexesMask)] = inputRawCacheIndex;
usedRawCacheIndexes[iters] = minRawCacheIndex;
forcedInsertion(usedRawCacheIndexes, iters);

}

Expand All @@ -292,11 +272,9 @@ bool DatabaseMTAssociativeCache::findKey(Goldilocks::Element (&key)[4], vector<G
{
uint32_t tableIndex = (uint32_t)(key[i].fe & indexesMask);
uint32_t cacheIndexRaw = (uint32_t)(indexes[tableIndex]);
if (emptyCacheSlot(cacheIndexRaw)) continue;

uint32_t cacheIndex = cacheIndexRaw & cacheMask;
if ((currentCacheIndex >= cacheIndexRaw && currentCacheIndex - cacheIndexRaw > cacheSize) ||
(currentCacheIndex < cacheIndexRaw && UINT32_MAX - cacheIndexRaw + currentCacheIndex > cacheSize))
continue;

uint32_t cacheIndexKey = cacheIndex * 4;

if (keys[cacheIndexKey + 0].fe == key[0].fe &&
Expand All @@ -305,7 +283,7 @@ bool DatabaseMTAssociativeCache::findKey(Goldilocks::Element (&key)[4], vector<G
keys[cacheIndexKey + 3].fe == key[3].fe)
{
uint32_t cacheIndexValue = cacheIndex * 12;
++hits; // must be atomic operation!! makes is sence?
++hits;
value.resize(12);
value[0] = values[cacheIndexValue];
value[1] = values[cacheIndexValue + 1];
Expand All @@ -315,7 +293,6 @@ bool DatabaseMTAssociativeCache::findKey(Goldilocks::Element (&key)[4], vector<G
value[5] = values[cacheIndexValue + 5];
value[6] = values[cacheIndexValue + 6];
value[7] = values[cacheIndexValue + 7];

value[8] = values[cacheIndexValue + 8];
value[9] = values[cacheIndexValue + 9];
value[10] = values[cacheIndexValue + 10];
Expand Down
12 changes: 6 additions & 6 deletions src/hashdb/database_associative_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class DatabaseMTAssociativeCache
uint32_t *indexes;
Goldilocks::Element *keys;
Goldilocks::Element *values;
bool *isLeaf;
uint32_t currentCacheIndex;

uint64_t attempts;
Expand All @@ -47,9 +46,10 @@ class DatabaseMTAssociativeCache
inline uint32_t getIndexesSize() const { return indexesSize; };

private:
void forcedInsertion(uint32_t (&rawCacheIndexes)[10], int &iters);
inline bool emptyCacheSlot(uint32_t cacheIndexRaw) const {
return (currentCacheIndex >= cacheIndexRaw && currentCacheIndex - cacheIndexRaw > cacheSize) ||
(currentCacheIndex < cacheIndexRaw && UINT32_MAX - cacheIndexRaw + currentCacheIndex > cacheSize);
};
void forcedInsertion(uint32_t (&usedRawCacheIndexes)[10], int &iters);
};
#endif

// TODO:
// 5. Put attempts and hits in a higher level
#endif

0 comments on commit 0620c02

Please sign in to comment.