| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <cstring> |
| #include <iostream> |
| #include <thread> |
|
|
| #include "bitboard.h" |
| #include "misc.h" |
| #include "thread.h" |
| #include "tt.h" |
| #include "uci.h" |
|
|
| namespace Stockfish { |
|
|
| TranspositionTable TT; |
|
|
| |
| |
|
|
| void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) { |
|
|
| |
| if (m || (uint16_t)k != key16) |
| move16 = (uint16_t)m; |
|
|
| |
| if ( b == BOUND_EXACT |
| || (uint16_t)k != key16 |
| || d - DEPTH_OFFSET + 2 * pv > depth8 - 4) |
| { |
| assert(d > DEPTH_OFFSET); |
| assert(d < 256 + DEPTH_OFFSET); |
|
|
| key16 = (uint16_t)k; |
| depth8 = (uint8_t)(d - DEPTH_OFFSET); |
| genBound8 = (uint8_t)(TT.generation8 | uint8_t(pv) << 2 | b); |
| value16 = (int16_t)v; |
| eval16 = (int16_t)ev; |
| } |
| } |
|
|
|
|
| |
| |
| |
|
|
| void TranspositionTable::resize(size_t mbSize) { |
|
|
| Threads.main()->wait_for_search_finished(); |
|
|
| aligned_large_pages_free(table); |
|
|
| clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster); |
|
|
| table = static_cast<Cluster*>(aligned_large_pages_alloc(clusterCount * sizeof(Cluster))); |
| if (!table) |
| { |
| std::cerr << "Failed to allocate " << mbSize |
| << "MB for transposition table." << std::endl; |
| exit(EXIT_FAILURE); |
| } |
|
|
| clear(); |
| } |
|
|
|
|
| |
| |
|
|
| void TranspositionTable::clear() { |
|
|
| std::vector<std::thread> threads; |
|
|
| for (size_t idx = 0; idx < Options["Threads"]; ++idx) |
| { |
| threads.emplace_back([this, idx]() { |
|
|
| |
| if (Options["Threads"] > 8) |
| WinProcGroup::bindThisThread(idx); |
|
|
| |
| const size_t stride = size_t(clusterCount / Options["Threads"]), |
| start = size_t(stride * idx), |
| len = idx != Options["Threads"] - 1 ? |
| stride : clusterCount - start; |
|
|
| std::memset(&table[start], 0, len * sizeof(Cluster)); |
| }); |
| } |
|
|
| for (std::thread& th : threads) |
| th.join(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
|
|
| TTEntry* TranspositionTable::probe(const Key key, bool& found) const { |
|
|
| TTEntry* const tte = first_entry(key); |
| const uint16_t key16 = (uint16_t)key; |
|
|
| 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))); |
|
|
| return found = (bool)tte[i].depth8, &tte[i]; |
| } |
|
|
| |
| TTEntry* replace = tte; |
| for (int i = 1; i < ClusterSize; ++i) |
| |
| |
| |
| |
| |
| if ( replace->depth8 - ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK) |
| > tte[i].depth8 - ((GENERATION_CYCLE + generation8 - tte[i].genBound8) & GENERATION_MASK)) |
| replace = &tte[i]; |
|
|
| return found = false, replace; |
| } |
|
|
|
|
| |
| |
|
|
| int TranspositionTable::hashfull() const { |
|
|
| int cnt = 0; |
| for (int i = 0; i < 1000; ++i) |
| for (int j = 0; j < ClusterSize; ++j) |
| cnt += table[i].entry[j].depth8 && (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8; |
|
|
| return cnt / ClusterSize; |
| } |
|
|
| } |
|
|