commit 644090d7e796c3e13c7595700830ddcad8836754
parent 0218a1559240963bdc53c7157b1cb16cfa4878f0
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Wed, 20 Mar 2024 18:51:51 +0000
Improve transposition table, add stats info
Diffstat:
4 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
- VERSION 1.3.8
+ VERSION 1.3.9
DESCRIPTION "Chess engine written in C++"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES CXX
diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
@@ -4,6 +4,10 @@ add_executable(engine
uci.cpp
)
+option(STELLAR_STATS "Provide stats for analysis" OFF)
+if(STELLAR_STATS)
+ add_definitions(-DUSE_STATS)
+endif()
target_link_libraries(engine
PRIVATE Stellar_version
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -45,10 +45,44 @@ template <U64 size> class TTable_internal {
public:
static inline constexpr const int16_t unknown = 32500;
- static void clear() { memset(table.data(), 0x00, size * sizeof(Hashe)); };
+ static void clear() {
+ memset(table.data(), 0x00, size * sizeof(Hashe));
+#ifdef USE_STATS
+ accessed = 0, rewrite = 0, miss = 0;
+#endif
+ };
+
+#ifdef USE_STATS
+ static void print() {
+ std::cout << "Transposition table: " << std::endl;
+ std::cout << "\tSize: " << size << " entries (" << sizeof(Hashe) << "B per entry)" << std::endl;
+ std::cout << "\tSize: " << std::fixed << std::setprecision(2)
+ << (double)size * sizeof(Hashe) / (1 << 20) << "MB" << std::endl;
+ std::cout << "\tReads: " << accessed << std::endl;
+ std::cout << "\tMisses: " << miss << "(" << (double)miss / accessed << "%)" << std::endl;
+ std::cout << "\tRewrite: " << rewrite << std::endl;
+ std::cout << "\tUsed " << (double)used() / size << "%" << std::endl;
+ }
+
+ static U64 used() {
+ U64 res = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (table[i].key) res++;
+ }
+
+ return res;
+ }
+#endif
+
static int16_t read(const Board &board, int ply, Move *best, int16_t alpha, int16_t beta, uint8_t depth) {
U64 hash = board.get_hash();
- const Hashe &phashe = table[hash % table.size()];
+ const Hashe &phashe = table[hash % size];
+
+#ifdef USE_STATS
+ accessed++;
+#endif
+
if (phashe.key == hash) {
if (phashe.depth >= depth) {
int16_t score = phashe.score;
@@ -62,26 +96,54 @@ template <U64 size> class TTable_internal {
}
*best = phashe.best;
}
+#ifdef USE_STATS
+ else {
+ miss++;
+ }
+#endif
return unknown;
}
static void write(const Board &board, int ply, Move best, int16_t score, uint8_t depth,
Hashe::Flag flag) {
U64 hash = board.get_hash();
- Hashe &phashe = table[hash % table.size()];
+ Hashe &phashe = table[hash % size];
if (score < -MATE_SCORE) score += ply;
if (score > MATE_SCORE) score -= ply;
+ if (phashe.key == hash) {
+ if (phashe.depth > depth) return;
+ }
+#ifdef USE_STATS
+ else {
+ rewrite++;
+ }
+#endif
+
phashe = {hash, best, depth, score, flag};
}
private:
static std::array<Hashe, size> table;
+
+#ifdef USE_STATS
+ static U64 accessed, rewrite, miss;
+#endif
};
template <U64 size> std::array<Hashe, size> TTable_internal<size>::table;
+#ifdef USE_STATS
+template <U64 size> U64 TTable_internal<size>::accessed = 0;
+template <U64 size> U64 TTable_internal<size>::rewrite = 0;
+template <U64 size> U64 TTable_internal<size>::miss = 0;
+#endif
+
+using TTable = TTable_internal<C64(0x2000023)>;
+
+TTable ttable;
+
class PVTable {
public:
Move best(uint8_t ply = 0) { return table[0][ply]; }
@@ -107,9 +169,6 @@ std::ostream &operator<<(std::ostream &os, const PVTable &pvtable) {
return os;
}
-using TTable = TTable_internal<C64(0x2FB4377)>;
-TTable ttable;
-
static const uci::Settings *settings = nullptr;
static Board board;
static repetition::Table rtable;
@@ -476,5 +535,8 @@ int main() {
attack::init();
zobrist::init();
uci::loop();
+#ifdef USE_STATS
+ engine::ttable.print();
+#endif
return 0;
}
diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp
@@ -82,6 +82,7 @@ class Perft {
void score(const Board &board, Move move) {
local.node++;
+ std::cout << std::setw(16) << std::hex << board.get_hash() << std::endl;
#ifdef USE_FULL_COUNT
if (board.is_check()) local.check++;
if (move.is_capture()) local.capture++;