Rev 169 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 169 | Rev 185 | ||
|---|---|---|---|
| Line 4... | Line 4... | ||
| 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
| 5 | Copyright (C) 2015- |
5 | Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
| 6 | 6 | ||
| 7 | Stockfish is free software: you can redistribute it and/or modify |
7 | Stockfish is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
10 | (at your option) any later version. |
| Line 39... | Line 39... | ||
| 39 | Move move() const { return (Move )move16; } |
39 | Move move() const { return (Move )move16; } |
| 40 | Value value() const { return (Value)value16; } |
40 | Value value() const { return (Value)value16; } |
| 41 | Value eval() const { return (Value)eval16; } |
41 | Value eval() const { return (Value)eval16; } |
| 42 | Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); } |
42 | Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); } |
| 43 | Bound bound() const { return (Bound)(genBound8 & 0x3); } |
43 | Bound bound() const { return (Bound)(genBound8 & 0x3); } |
| 44 | - | ||
| 45 | void save(Key k, Value v, Bound b, Depth d, Move m, Value |
44 | void save(Key k, Value v, Bound b, Depth d, Move m, Value ev); |
| 46 | - | ||
| 47 | assert(d / ONE_PLY * ONE_PLY == d); |
- | |
| 48 | - | ||
| 49 | // Preserve any existing move for the same position |
- | |
| 50 | if (m || (k >> 48) != key16) |
- | |
| 51 | move16 = (uint16_t)m; |
- | |
| 52 | - | ||
| 53 | // Don't overwrite more valuable entries |
- | |
| 54 | if ( (k >> 48) != key16 |
- | |
| 55 | || d / ONE_PLY > depth8 - 4 |
- | |
| 56 | /* || g != (genBound8 & 0xFC) // Matching non-zero keys are already refreshed by probe() */ |
- | |
| 57 | || b == BOUND_EXACT) |
- | |
| 58 | { |
- | |
| 59 | key16 = (uint16_t)(k >> 48); |
- | |
| 60 | value16 = (int16_t)v; |
- | |
| 61 | eval16 = (int16_t)ev; |
- | |
| 62 | genBound8 = (uint8_t)(g | b); |
- | |
| 63 | depth8 = (int8_t)(d / ONE_PLY); |
- | |
| 64 | } |
- | |
| 65 | } |
- | |
| 66 | 45 | ||
| 67 | private: |
46 | private: |
| 68 | friend class TranspositionTable; |
47 | friend class TranspositionTable; |
| 69 | 48 | ||
| 70 | uint16_t key16; |
49 | uint16_t key16; |
| Line 83... | Line 62... | ||
| 83 | /// cache lines. This ensures best cache performance, as the cacheline is |
62 | /// cache lines. This ensures best cache performance, as the cacheline is |
| 84 | /// prefetched, as soon as possible. |
63 | /// prefetched, as soon as possible. |
| 85 | 64 | ||
| 86 | class TranspositionTable { |
65 | class TranspositionTable { |
| 87 | 66 | ||
| 88 | static |
67 | static constexpr int CacheLineSize = 64; |
| 89 | static |
68 | static constexpr int ClusterSize = 3; |
| 90 | 69 | ||
| 91 | struct Cluster { |
70 | struct Cluster { |
| 92 | TTEntry entry[ClusterSize]; |
71 | TTEntry entry[ClusterSize]; |
| 93 | char padding[2]; // Align to a divisor of the cache line size |
72 | char padding[2]; // Align to a divisor of the cache line size |
| 94 | }; |
73 | }; |
| Line 96... | Line 75... | ||
| 96 | static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect"); |
75 | static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect"); |
| 97 | 76 | ||
| 98 | public: |
77 | public: |
| 99 | ~TranspositionTable() { free(mem); } |
78 | ~TranspositionTable() { free(mem); } |
| 100 | void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound |
79 | void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound |
| 101 | uint8_t generation() const { return generation8; } |
- | |
| 102 | TTEntry* probe(const Key key, bool& found) const; |
80 | TTEntry* probe(const Key key, bool& found) const; |
| 103 | int hashfull() const; |
81 | int hashfull() const; |
| 104 | void resize(size_t mbSize); |
82 | void resize(size_t mbSize); |
| 105 | void clear(); |
83 | void clear(); |
| 106 | 84 | ||
| Line 108... | Line 86... | ||
| 108 | TTEntry* first_entry(const Key key) const { |
86 | TTEntry* first_entry(const Key key) const { |
| 109 | return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0]; |
87 | return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0]; |
| 110 | } |
88 | } |
| 111 | 89 | ||
| 112 | private: |
90 | private: |
| - | 91 | friend struct TTEntry; |
|
| - | 92 | ||
| 113 | size_t clusterCount; |
93 | size_t clusterCount; |
| 114 | Cluster* table; |
94 | Cluster* table; |
| 115 | void* mem; |
95 | void* mem; |
| 116 | uint8_t generation8; // Size must be not bigger than TTEntry::genBound8 |
96 | uint8_t generation8; // Size must be not bigger than TTEntry::genBound8 |
| 117 | }; |
97 | }; |