Fix fragile code to use proper random 64 bit keys.
authormstembera <MissingEmail@email>
Sat, 27 Jun 2020 00:26:46 +0000 (17:26 -0700)
committerJoost VandeVondele <Joost.VandeVondele@gmail.com>
Sun, 28 Jun 2020 19:57:37 +0000 (21:57 +0200)
This fixes an old issue where we want to make a position unique but only
change a small number of bits in the key instead of all 64 of them randomly.
This is fragile and can lead to non uniqueness issues in the TT.

Key make_key(uint64_t seed) takes any integer and produces a unique random 64 bit key.
It is computationally efficient and is based on a congruential pseudo random number
generator using well tested constants by Donald Knuth
(see https://en.wikipedia.org/wiki/Linear_congruential_generator)

STC https://tests.stockfishchess.org/tests/view/5ef6c78f761b685b4c724bb6
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 154320 W: 29343 L: 29376 D: 95601
Ptnml(0-2): 2543, 18170, 35891, 17889, 2667

LTC https://tests.stockfishchess.org/tests/view/5ef7d1a9020eec13834a940e
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 53488 W: 6629 L: 6584 D: 40275
Ptnml(0-2): 372, 4878, 16183, 4955, 356

closes https://github.com/official-stockfish/Stockfish/pull/2773

bench: 4626776

src/search.cpp
src/types.h

index 1e2980cb0cda1138dd35118e3b1ab603bfe909f5..0fa399882c287ead30231442edbc416af1b5aa94 100644 (file)
@@ -662,7 +662,7 @@ namespace {
     // search to overwrite a previous full search TT value, so we use a different
     // position key in case of an excluded move.
     excludedMove = ss->excludedMove;
-    posKey = pos.key() ^ (Key(excludedMove) << 48); // Isn't a very good hash
+    posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove);
     tte = TT.probe(posKey, ttHit);
     ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
     ttMove =  rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
index 0c512f5bf3f7544afcae25a0cb451fb31d952ece..c1598561812d949d775bd801d26cc803b61538c8 100644 (file)
@@ -455,6 +455,11 @@ constexpr bool is_ok(Move m) {
   return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
 }
 
+/// Based on a congruential pseudo random number generator
+constexpr Key make_key(uint64_t seed) {
+  return seed * 6364136223846793005ULL + 1442695040888963407ULL;
+}
+
 #endif // #ifndef TYPES_H_INCLUDED
 
 #include "tune.h" // Global visibility to tuning setup