mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00

Previously, we had two type aliases, LargePagePtr and AlignedPtr, which required manually initializing the aligned memory for the pointer. The new helpers: - make_unique_aligned - make_unique_large_page are now available for allocating aligned memory (with large pages). They behave similarly to std::make_unique, ensuring objects allocated with these functions follow RAII. The old approach had issues with initializing non-trivial types or arrays of objects. The evaluation function of the network is now a unique pointer to an array instead of an array of unique pointers. Memory related functions have been moved into memory.h Passed High Hash Pressure Test Non-Regression STC: https://tests.stockfishchess.org/tests/view/665b2b36586058766677cfd2 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 476992 W: 122426 L: 122677 D: 231889 Ptnml(0-2): 1145, 51027, 134419, 50744, 1161 Failed Normal Non-Regression STC: https://tests.stockfishchess.org/tests/view/665b2997586058766677cfc8 LLR: -2.94 (-2.94,2.94) <-1.75,0.25> Total: 877312 W: 225233 L: 226395 D: 425684 Ptnml(0-2): 2110, 94642, 246239, 93630, 2035 Probably a fluke since there shouldn't be a real slowndown and it has also passed the high hash pressure test. closes https://github.com/official-stockfish/Stockfish/pull/5332 No functional change
125 lines
3.9 KiB
C++
125 lines
3.9 KiB
C++
/*
|
|
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
|
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
|
|
|
|
Stockfish is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Stockfish is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef TT_H_INCLUDED
|
|
#define TT_H_INCLUDED
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#include "memory.h"
|
|
#include "misc.h"
|
|
#include "types.h"
|
|
|
|
namespace Stockfish {
|
|
|
|
// TTEntry struct is the 10 bytes transposition table entry, defined as below:
|
|
//
|
|
// key 16 bit
|
|
// depth 8 bit
|
|
// generation 5 bit
|
|
// pv node 1 bit
|
|
// bound type 2 bit
|
|
// move 16 bit
|
|
// value 16 bit
|
|
// eval value 16 bit
|
|
//
|
|
// These fields are in the same order as accessed by TT::probe(), since memory is fastest sequentially.
|
|
// Equally, the store order in save() matches this order.
|
|
struct TTEntry {
|
|
|
|
Move move() const { return Move(move16); }
|
|
Value value() const { return Value(value16); }
|
|
Value eval() const { return Value(eval16); }
|
|
Depth depth() const { return Depth(depth8 + DEPTH_ENTRY_OFFSET); }
|
|
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;
|
|
|
|
uint16_t key16;
|
|
uint8_t depth8;
|
|
uint8_t genBound8;
|
|
Move move16;
|
|
int16_t value16;
|
|
int16_t eval16;
|
|
};
|
|
|
|
class ThreadPool;
|
|
|
|
// A TranspositionTable is an array of Cluster, of size clusterCount. Each
|
|
// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
|
|
// contains information on exactly one position. The size of a Cluster should
|
|
// divide the size of a cache line for best performance, as the cacheline is
|
|
// prefetched when possible.
|
|
class TranspositionTable {
|
|
|
|
static constexpr int ClusterSize = 3;
|
|
|
|
struct Cluster {
|
|
TTEntry entry[ClusterSize];
|
|
char padding[2]; // Pad to 32 bytes
|
|
};
|
|
|
|
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
|
|
|
|
// Constants used to refresh the hash table periodically
|
|
|
|
// 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:
|
|
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, ThreadPool& threads);
|
|
void clear(ThreadPool& threads);
|
|
|
|
TTEntry* first_entry(const Key key) const {
|
|
return &table[mul_hi64(key, clusterCount)].entry[0];
|
|
}
|
|
|
|
uint8_t generation() const { return generation8; }
|
|
|
|
private:
|
|
friend struct TTEntry;
|
|
|
|
size_t clusterCount;
|
|
LargePagePtr<Cluster[]> table;
|
|
uint8_t generation8 = 0; // Size must be not bigger than TTEntry::genBound8
|
|
};
|
|
|
|
} // namespace Stockfish
|
|
|
|
#endif // #ifndef TT_H_INCLUDED
|