mirror of
https://github.com/sockspls/badfish
synced 2025-04-29 16:23:09 +00:00
Document TT code more
Slight refactor of the TT code with the goal to make it easier to understand / tweak. Passed Non-Regression STC: https://tests.stockfishchess.org/tests/view/65d51e401d8e83c78bfdc427 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 56416 W: 14750 L: 14550 D: 27116 Ptnml(0-2): 227, 6386, 14796, 6558, 241 closes https://github.com/official-stockfish/Stockfish/pull/5061 No functional change
This commit is contained in:
parent
f77eddfa2f
commit
0a3eb1d8fa
2 changed files with 38 additions and 20 deletions
33
src/tt.cpp
33
src/tt.cpp
|
@ -19,6 +19,7 @@
|
||||||
#include "tt.h"
|
#include "tt.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -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,
|
// Sets the size of the transposition table,
|
||||||
// measured in megabytes. Transposition table consists of a power of 2 number
|
// measured in megabytes. Transposition table consists of a power of 2 number
|
||||||
// of clusters and each cluster consists of ClusterSize number of TTEntry.
|
// 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)
|
for (int i = 0; i < ClusterSize; ++i)
|
||||||
if (tte[i].key16 == key16 || !tte[i].depth8)
|
if (tte[i].key16 == key16 || !tte[i].depth8)
|
||||||
{
|
{
|
||||||
tte[i].genBound8 =
|
constexpr uint8_t lowerBits = GENERATION_DELTA - 1;
|
||||||
uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
|
|
||||||
|
|
||||||
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
|
// Find an entry to be replaced according to the replacement strategy
|
||||||
TTEntry* replace = tte;
|
TTEntry* replace = tte;
|
||||||
for (int i = 1; i < ClusterSize; ++i)
|
for (int i = 1; i < ClusterSize; ++i)
|
||||||
// Due to our packed storage format for generation and its cyclic
|
if (replace->depth8 - replace->relative_age(generation8)
|
||||||
// nature we add GENERATION_CYCLE (256 is the modulus, plus what
|
> tte[i].depth8 - tte[i].relative_age(generation8))
|
||||||
// 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))
|
|
||||||
replace = &tte[i];
|
replace = &tte[i];
|
||||||
|
|
||||||
return found = false, replace;
|
return found = false, replace;
|
||||||
|
@ -137,7 +144,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
|
||||||
|
|
||||||
// Returns an approximation of the hashtable
|
// Returns an approximation of the hashtable
|
||||||
// occupation during a search. The hash is x permill full, as per UCI protocol.
|
// 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 TranspositionTable::hashfull() const {
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
25
src/tt.h
25
src/tt.h
|
@ -46,6 +46,8 @@ struct TTEntry {
|
||||||
bool is_pv() const { return bool(genBound8 & 0x4); }
|
bool is_pv() const { return bool(genBound8 & 0x4); }
|
||||||
Bound bound() const { return Bound(genBound8 & 0x3); }
|
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);
|
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:
|
private:
|
||||||
friend class TranspositionTable;
|
friend class TranspositionTable;
|
||||||
|
@ -76,16 +78,25 @@ class TranspositionTable {
|
||||||
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
|
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
|
||||||
|
|
||||||
// Constants used to refresh the hash table periodically
|
// 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 =
|
// We have 8 bits available where the lowest 3 bits are
|
||||||
(1 << GENERATION_BITS); // increment for generation field
|
// reserved for other things.
|
||||||
static constexpr int GENERATION_CYCLE = 255 + (1 << GENERATION_BITS); // cycle length
|
static constexpr unsigned GENERATION_BITS = 3;
|
||||||
static constexpr int GENERATION_MASK =
|
// increment for generation field
|
||||||
(0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number
|
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:
|
public:
|
||||||
~TranspositionTable() { aligned_large_pages_free(table); }
|
~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;
|
TTEntry* probe(const Key key, bool& found) const;
|
||||||
int hashfull() const;
|
int hashfull() const;
|
||||||
void resize(size_t mbSize, int threadCount);
|
void resize(size_t mbSize, int threadCount);
|
||||||
|
|
Loading…
Add table
Reference in a new issue