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 | }; |