diff --git a/src/tt.cpp b/src/tt.cpp index f3f58979d1b..8ef06e6355c 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -19,6 +19,7 @@ #include "tt.h" #include +#include #include #include #include @@ -53,6 +54,18 @@ void TTEntry::save( } +uint8_t TTEntry::relative_age(const uint8_t generation8) const { + // Due to our packed storage format for generation and its cyclic + // nature we add GENERATION_CYCLE (256 is the modulus, plus what + // is needed to keep the unrelated lowest n bits from affecting + // the result) to calculate the entry age correctly even after + // generation8 overflows into the next cycle. + + return (TranspositionTable::GENERATION_CYCLE + generation8 - genBound8) + & TranspositionTable::GENERATION_MASK; +} + + // Sets the size of the transposition table, // measured in megabytes. Transposition table consists of a power of 2 number // of clusters and each cluster consists of ClusterSize number of TTEntry. @@ -111,24 +124,18 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const { for (int i = 0; i < ClusterSize; ++i) if (tte[i].key16 == key16 || !tte[i].depth8) { - tte[i].genBound8 = - uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh + constexpr uint8_t lowerBits = GENERATION_DELTA - 1; - return found = bool(tte[i].depth8), &tte[i]; + // Refresh with new generation, keeping the lower bits the same. + tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & lowerBits)); + return found = bool(tte[i].depth8), &tte[i]; } // Find an entry to be replaced according to the replacement strategy TTEntry* replace = tte; for (int i = 1; i < ClusterSize; ++i) - // Due to our packed storage format for generation and its cyclic - // nature we add GENERATION_CYCLE (256 is the modulus, plus what - // is needed to keep the unrelated lowest n bits from affecting - // the result) to calculate the entry age correctly even after - // generation8 overflows into the next cycle. - if (replace->depth8 - - ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK) - > tte[i].depth8 - - ((GENERATION_CYCLE + generation8 - tte[i].genBound8) & GENERATION_MASK)) + if (replace->depth8 - replace->relative_age(generation8) + > tte[i].depth8 - tte[i].relative_age(generation8)) replace = &tte[i]; return found = false, replace; @@ -137,7 +144,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const { // Returns an approximation of the hashtable // occupation during a search. The hash is x permill full, as per UCI protocol. - +// Only counts entries which match the current generation. int TranspositionTable::hashfull() const { int cnt = 0; diff --git a/src/tt.h b/src/tt.h index 4115ee7ae51..554a81a572f 100644 --- a/src/tt.h +++ b/src/tt.h @@ -46,6 +46,8 @@ struct TTEntry { bool is_pv() const { return bool(genBound8 & 0x4); } Bound bound() const { return Bound(genBound8 & 0x3); } void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8); + // The returned age is a multiple of TranspositionTable::GENERATION_DELTA + uint8_t relative_age(const uint8_t generation8) const; private: friend class TranspositionTable; @@ -76,16 +78,25 @@ class TranspositionTable { static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size"); // Constants used to refresh the hash table periodically - static constexpr unsigned GENERATION_BITS = 3; // nb of bits reserved for other things - static constexpr int GENERATION_DELTA = - (1 << GENERATION_BITS); // increment for generation field - static constexpr int GENERATION_CYCLE = 255 + (1 << GENERATION_BITS); // cycle length - static constexpr int GENERATION_MASK = - (0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number + + // We have 8 bits available where the lowest 3 bits are + // reserved for other things. + static constexpr unsigned GENERATION_BITS = 3; + // increment for generation field + static constexpr int GENERATION_DELTA = (1 << GENERATION_BITS); + // cycle length + static constexpr int GENERATION_CYCLE = 255 + GENERATION_DELTA; + // mask to pull out generation number + static constexpr int GENERATION_MASK = (0xFF << GENERATION_BITS) & 0xFF; public: ~TranspositionTable() { aligned_large_pages_free(table); } - void new_search() { generation8 += GENERATION_DELTA; } // Lower bits are used for other things + + void new_search() { + // increment by delta to keep lower bits as is + generation8 += GENERATION_DELTA; + } + TTEntry* probe(const Key key, bool& found) const; int hashfull() const; void resize(size_t mbSize, int threadCount);