LCOV - code coverage report
Current view: top level - Source - transposition.cpp (source / functions) Coverage Total Hit
Test: coverage Lines: 98.6 % 74 73
Test Date: 2026-03-02 16:42:41 Functions: 90.9 % 11 10

            Line data    Source code
       1              : #include "transposition.hpp"
       2              : 
       3              : #include "distributed.h"
       4              : #include "dynamicConfig.hpp"
       5              : #include "logging.hpp"
       6              : #include "moveApply.hpp"
       7              : #include "movePseudoLegal.hpp"
       8              : #include "position.hpp"
       9              : #include "searcher.hpp"
      10              : #include "tools.hpp"
      11              : 
      12              : namespace {
      13              : 
      14              : template<class T> struct DeleteAligned {
      15              :    void operator()(T *ptr) const {
      16              :       if (ptr) std_aligned_free(ptr);
      17           24 :    }
      18              : };
      19              : 
      20              : uint64_t ttSize = 0;
      21              : std::unique_ptr<TT::Entry[], DeleteAligned<TT::Entry>> table(nullptr);
      22              : 
      23              : } // namespace
      24              : namespace TT {
      25              : 
      26              : GenerationType curGen = 0;
      27              : 
      28              : #ifdef __linux__
      29              : #include <sys/mman.h>
      30              : #endif
      31              : 
      32           24 : void initTable() {
      33           24 :    Logging::LogIt(Logging::logInfo) << "Init TT";
      34           24 :    Logging::LogIt(Logging::logInfo) << "Entry size " << sizeof(Entry);
      35           48 :    ttSize = powerFloor((SIZE_MULTIPLIER * DynamicConfig::ttSizeMb) / sizeof(Entry));
      36           24 :    assert(BB::countBit(ttSize) == 1); // a power of 2
      37           24 :    table.reset((Entry *)std_aligned_alloc(1024, ttSize * sizeof(Entry)));
      38           48 :    Logging::LogIt(Logging::logInfo) << "Size of TT " << ttSize * sizeof(Entry) / 1024 / 1024 << "Mb (" << ttSize << " entries)";
      39           24 :    clearTT();
      40           24 : }
      41              : 
      42           50 : void clearTT() {
      43           50 :    TT::curGen = 0;
      44           50 :    Logging::LogIt(Logging::logInfo) << "Now zeroing TT memory using " << DynamicConfig::threads << " threads";
      45           53 :    auto worker = [&](size_t begin, size_t end) { std::fill(&table[0] + begin, &table[0] + end, Entry()); };
      46           50 :    threadedWork(worker, DynamicConfig::threads, ttSize);
      47           50 :    Logging::LogIt(Logging::logInfo) << "... done ";
      48           50 : }
      49              : 
      50           33 : int hashFull() {
      51              :    unsigned int count = 0;
      52              :    const unsigned int samples = 1023 * 64;
      53      2160609 :    for (unsigned int k = 0; k < samples; ++k)
      54      2160576 :       if (table[(k * 67) % ttSize].h != nullHash) ++count;
      55           33 :    return static_cast<int>((count * 1000) / samples);
      56              : }
      57              : 
      58          208 : void age() {
      59          208 :    TT::curGen = static_cast<GenerationType>((TT::curGen + 1) % 8); // see Bound::B_gen
      60          208 : }
      61              : 
      62     12830637 : void prefetch(Hash h) {
      63     12830637 :    void *addr = (&table[h & (ttSize - 1)]);
      64              : #if defined(__INTEL_COMPILER)
      65              :    __asm__("");
      66              : #elif defined(_MSC_VER)
      67              :    _mm_prefetch((char *)addr, _MM_HINT_T0);
      68              : #else
      69     12830637 :    __builtin_prefetch(addr);
      70              : #endif
      71     12830637 : }
      72              : 
      73              : // will return true only if depth is enough
      74              : // e.h is nullHash if the TT entry is not usable
      75      6728628 : bool getEntry(Searcher &context, const Position &p, Hash h, DepthType d, Entry &e) {
      76      6728628 :    assert(h != nullHash);
      77      6728628 :    assert((h & (ttSize - 1)) == (h % ttSize));
      78      6728628 :    if (DynamicConfig::disableTT) return false;
      79              :    // update entry immediatly to avoid further race condition and invalidate it later if needed
      80      6728628 :    e = table[h & (ttSize - 1)];
      81              : #ifdef DEBUG_HASH_ENTRY
      82              :    e._data1 = randomInt<uint32_t, 666>(0, UINT32_MAX);
      83              :    e._data2 = randomInt<uint32_t, 666>(0, UINT32_MAX);
      84              : #endif
      85      6728628 :    if (e.h == nullHash) return false; //early exit
      86              :    if (
      87              : #ifndef DEBUG_HASH_ENTRY
      88      3921616 :        ((e.h ^ e._data1 ^ e._data2) != Hash64to32(h)) ||
      89              : #endif
      90      1692728 :        (isValidMove(e.m) && !isPseudoLegal(p, e.m))) {
      91              :       // move is filled, but wrong in this position, invalidate returned entry.
      92       664064 :       e.h = nullHash;
      93       664064 :       return false;
      94              :    }
      95              : 
      96      3257552 :    if (e.d >= d /*+ (e.b != B_exact)*/) {
      97              :       // valid entry only if depth is ok
      98              :       context.stats.incr(Stats::sid_tthits);
      99      1823139 :       return true;
     100              :    }
     101              :    else{
     102              :       return false;
     103              :    }
     104              : }
     105              : 
     106              : // always replace
     107      5706276 : void setEntry(Searcher &context, Hash h, Move m, ScoreType s, ScoreType eval, Bound b, DepthType d, bool distribute) {
     108      5706276 :    assert(h != nullHash); // can really happen in fact ... but rarely
     109      5706276 :    if (DynamicConfig::disableTT) return;
     110              :    Entry e(h, m, s, eval, b, d);
     111      5706276 :    e.h ^= e._data1;
     112      5706276 :    e.h ^= e._data2;
     113              :    context.stats.incr(Stats::sid_ttInsert);
     114      5706276 :    table[h & (ttSize - 1)] = e; // always replace (favour leaf)
     115              :    // only update buffer for other process on main thread
     116              :    if (distribute) Distributed::setEntry(h, e);
     117              : }
     118              : 
     119            0 : void _setEntry(Hash h, const Entry &e) { table[h & (ttSize - 1)] = e; }
     120              : 
     121          277 : void getPV(const Position &p, Searcher &context, PVList &pv) {
     122              :    TT::Entry e;
     123          277 :    array1d<Hash,MAX_PLY> hashStack = {nullHash};
     124          277 :    Position  p2 = p;
     125              : #ifdef WITH_NNUE
     126          277 :    NNUEEvaluator evaluator;
     127              :    p2.associateEvaluator(evaluator);
     128          277 :    p2.resetNNUEEvaluator(p2.evaluator());
     129              : #endif
     130              :    bool stop = false;
     131         2914 :    for (int k = 0; k < MAX_PLY && !stop; ++k) {
     132         2897 :       if (!TT::getEntry(context, p2, computeHash(p2), 0, e)) break;
     133         2737 :       if (e.h != nullHash) {
     134         2737 :          hashStack[k] = computeHash(p2);
     135              :          if (!isValidMove(e.m)) break;
     136         2637 :          if (const MoveInfo moveInfo(p2,e.m); !applyMove(p2, moveInfo)) break;
     137         2637 :          pv.emplace_back(e.m);
     138         2637 :          const Hash h = computeHash(p2);
     139              :          // stop at first repetition
     140        21084 :          for (int i = k - 1; i >= 0; --i)
     141        18464 :             if (hashStack[i] == h) {
     142              :                stop = true;
     143              :                break;
     144              :             }
     145              :       }
     146              :    }
     147          277 : }
     148              : 
     149     11412552 : ScoreType createHashScore(ScoreType score, DepthType height) {
     150     11412552 :    if (isMatingScore(score))
     151         9133 :       score += height;
     152     11403419 :    else if (isMatedScore(score))
     153      1094909 :       score -= height;
     154              :    //else
     155              :    //   score *= 0.999f;
     156     11412552 :    return score;
     157              : }
     158              : 
     159      1052279 : ScoreType adjustHashScore(ScoreType score, DepthType height) {
     160      1052279 :    if (isMatingScore(score))
     161         4640 :       score -= height;
     162      1047639 :    else if (isMatedScore(score))
     163          509 :       score += height;
     164              :    //else
     165              :    //   score *= 0.999f;
     166      1052279 :    return score;
     167              : }
     168              : 
     169              : } // namespace TT
        

Generated by: LCOV version 2.0-1