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 72... | Line 51... | ||
72 | int16_t value16; |
51 | int16_t value16; |
73 | int16_t eval16; |
52 | int16_t eval16; |
74 | uint8_t genBound8; |
53 | uint8_t genBound8; |
75 | int8_t depth8; |
54 | int8_t depth8; |
76 | }; |
55 | }; |
77 | 56 | ||
78 | 57 | ||
79 | /// A TranspositionTable consists of a power of 2 number of clusters and each |
58 | /// A TranspositionTable consists of a power of 2 number of clusters and each |
80 | /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry |
59 | /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry |
81 | /// contains information of exactly one position. The size of a cluster should |
60 | /// contains information of exactly one position. The size of a cluster should |
82 | /// divide the size of a cache line size, to ensure that clusters never cross |
61 | /// divide the size of a cache line size, to ensure that clusters never cross |
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 | }; |
95 | 74 | ||
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 | }; |