Guest User

sf : Store full 64-bit key to reduce collisions

a guest
Sep 15th, 2026
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.24 KB | None | 0 0
  1. commit e8fb927f6cdfed33e8c7d31838fc43684546e8df
  2. Author: Kuba <[email protected]>
  3. Date: Tue Dec 9 08:06:52 2025 +0100
  4.  
  5. TT: Store full 64-bit key to reduce collisions
  6.  
  7. - Change key16 (uint16_t) to key64 (Key/uint64_t)
  8. - Reduce ClusterSize from 3 to 2 for 32-byte alignment
  9. - Entry size: 10 → 16 bytes
  10. - Virtually eliminates false positive key matches within clusters
  11.  
  12. diff --git a/tt.cpp b/tt.cpp
  13. index 9533489..79ae409 100644
  14. --- a/tt.cpp
  15. +++ b/tt.cpp
  16. @@ -32,9 +32,9 @@
  17. namespace Stockfish {
  18.  
  19.  
  20. -// TTEntry struct is the 10 bytes transposition table entry, defined as below:
  21. +// TTEntry struct is the 16 bytes transposition table entry, defined as below:
  22. //
  23. -// key 16 bit
  24. +// key 64 bit
  25. // depth 8 bit
  26. // generation 5 bit
  27. // pv node 1 bit
  28. @@ -63,7 +63,7 @@ struct TTEntry {
  29. private:
  30. friend class TranspositionTable;
  31.  
  32. - uint16_t key16;
  33. + Key key64;
  34. uint8_t depth8;
  35. uint8_t genBound8;
  36. Move move16;
  37. @@ -94,17 +94,17 @@ void TTEntry::save(
  38. Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8) {
  39.  
  40. // Preserve the old ttmove if we don't have a new one
  41. - if (m || uint16_t(k) != key16)
  42. + if (m || k != key64)
  43. move16 = m;
  44.  
  45. // Overwrite less valuable entries (cheapest checks first)
  46. - if (b == BOUND_EXACT || uint16_t(k) != key16 || d - DEPTH_ENTRY_OFFSET + 2 * pv > depth8 - 4
  47. + if (b == BOUND_EXACT || k != key64 || d - DEPTH_ENTRY_OFFSET + 2 * pv > depth8 - 4
  48. || relative_age(generation8))
  49. {
  50. assert(d > DEPTH_ENTRY_OFFSET);
  51. assert(d < 256 + DEPTH_ENTRY_OFFSET);
  52.  
  53. - key16 = uint16_t(k);
  54. + key64 = k;
  55. depth8 = uint8_t(d - DEPTH_ENTRY_OFFSET);
  56. genBound8 = uint8_t(generation8 | uint8_t(pv) << 2 | b);
  57. value16 = int16_t(v);
  58. @@ -139,11 +139,10 @@ void TTWriter::write(
  59. // of TTEntry. Each non-empty TTEntry contains information on exactly one position. The size of a Cluster should
  60. // divide the size of a cache line for best performance, as the cacheline is prefetched when possible.
  61.  
  62. -static constexpr int ClusterSize = 3;
  63. +static constexpr int ClusterSize = 2;
  64.  
  65. struct Cluster {
  66. - TTEntry entry[ClusterSize];
  67. - char padding[2]; // Pad to 32 bytes
  68. + TTEntry entry[ClusterSize]; // 2 × 16 = 32 bytes, no padding needed
  69. };
  70.  
  71. static_assert(sizeof(Cluster) == 32, "Suboptimal Cluster size");
  72. @@ -224,11 +223,10 @@ uint8_t TranspositionTable::generation() const { return generation8; }
  73. // TTEntry t2 if its replace value is greater than that of t2.
  74. std::tuple<bool, TTData, TTWriter> TranspositionTable::probe(const Key key) const {
  75.  
  76. - TTEntry* const tte = first_entry(key);
  77. - const uint16_t key16 = uint16_t(key); // Use the low 16 bits as key inside the cluster
  78. + TTEntry* const tte = first_entry(key);
  79.  
  80. for (int i = 0; i < ClusterSize; ++i)
  81. - if (tte[i].key16 == key16)
  82. + if (tte[i].key64 == key)
  83. // This gap is the main place for read races.
  84. // After `read()` completes that copy is final, but may be self-inconsistent.
  85. return {tte[i].is_occupied(), tte[i].read(), TTWriter(&tte[i])};
  86.  
Advertisement
Add Comment
Please, Sign In to add comment