From: Marco Costalba Date: Mon, 15 Dec 2008 21:13:42 +0000 (+0100) Subject: Introduce beta counters to order moves at ply one X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=c831b0054426df008278bb09db2541f7db25c293 Introduce beta counters to order moves at ply one Instead of number of searched nodes use the number of opponent beta-cutoff occurred under the move subtree. After 570 games 1+0 we have: +150 =288 -132 (+11 ELO) Signed-off-by: Marco Costalba --- diff --git a/src/search.cpp b/src/search.cpp index f80d5ccb..6f2c48c9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -47,6 +47,23 @@ namespace { /// Types + // The BetaCounterType class is used to order moves at ply one. + // Apart for the first one that has its score, following moves + // normally have score -VALUE_INFINITE, so are ordered according + // to the number of beta cutoffs occurred under their subtree during + // the last iteration. + + struct BetaCounterType { + + BetaCounterType(); + void clear(); + void add(Color us, Depth d, int threadID); + void read(Color us, int64_t& our, int64_t& their); + + int64_t hits[THREAD_MAX][2]; + }; + + // The RootMove class is used for moves at the root at the tree. For each // root move, we store a score, a node count, and a PV (really a refutation // in the case of moves which fail low). @@ -60,6 +77,7 @@ namespace { Value score; int64_t nodes, cumulativeNodes; Move pv[PLY_MAX_PLUS_2]; + int64_t ourBeta, theirBeta; }; @@ -74,6 +92,7 @@ namespace { inline Value get_move_score(int moveNum) const; inline void set_move_score(int moveNum, Value score); inline void set_move_nodes(int moveNum, int64_t nodes); + inline void set_beta_counters(int moveNum, int64_t our, int64_t their); void set_move_pv(int moveNum, const Move pv[]); inline Move get_move_pv(int moveNum, int i) const; inline int64_t get_move_cumulative_nodes(int moveNum) const; @@ -177,9 +196,10 @@ namespace { int NodesSincePoll; int NodesBetweenPolls = 30000; - // Iteration counter + // Iteration counters int Iteration; bool LastIterations; + BetaCounterType BetaCounter; // Scores and number of times the best move changed for each iteration: Value ValueByIteration[PLY_MAX_PLUS_2]; @@ -774,6 +794,9 @@ namespace { // are used to sort the root moves at the next iteration. nodes = nodes_searched(); + // Reset beta cut-off counters + BetaCounter.clear(); + // Pick the next root move, and print the move and the move number to // the standard output. move = ss[0].currentMove = rml.get_move(i); @@ -829,6 +852,11 @@ namespace { // sort the root moves at the next iteration. rml.set_move_nodes(i, nodes_searched() - nodes); + // Remember the beta-cutoff statistics + int64_t our, their; + BetaCounter.read(pos.side_to_move(), our, their); + rml.set_beta_counters(i, our, their); + assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE); if (value <= alpha && i >= MultiPV) @@ -1079,6 +1107,7 @@ namespace { else if (bestValue >= beta) { + BetaCounter.add(pos.side_to_move(), depth, threadID); Move m = ss[ply].pv[ply]; if (ok_to_history(pos, m)) // Only non capture moves are considered { @@ -1355,6 +1384,7 @@ namespace { TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_UPPER); else { + BetaCounter.add(pos.side_to_move(), depth, threadID); Move m = ss[ply].pv[ply]; if (ok_to_history(pos, m)) // Only non capture moves are considered { @@ -1753,6 +1783,32 @@ namespace { lock_release(&(sp->lock)); } + /// The BetaCounterType class + + BetaCounterType::BetaCounterType() { clear(); } + + void BetaCounterType::clear() { + + for (int i = 0; i < THREAD_MAX; i++) + hits[i][WHITE] = hits[i][BLACK] = 0ULL; + } + + void BetaCounterType::add(Color us, Depth d, int threadID) { + + // Weighted count based on depth + hits[threadID][us] += int(d); + } + + void BetaCounterType::read(Color us, int64_t& our, int64_t& their) { + + our = their = 0UL; + for (int i = 0; i < THREAD_MAX; i++) + { + our += hits[i][us]; + their += hits[i][opposite_color(us)]; + } + } + /// The RootMove class @@ -1772,7 +1828,7 @@ namespace { if (score != m.score) return (score < m.score); - return nodes <= m.nodes; + return theirBeta <= m.theirBeta; } /// The RootMoveList class @@ -1835,6 +1891,11 @@ namespace { moves[moveNum].cumulativeNodes += nodes; } + inline void RootMoveList::set_beta_counters(int moveNum, int64_t our, int64_t their) { + moves[moveNum].ourBeta = our; + moves[moveNum].theirBeta = their; + } + void RootMoveList::set_move_pv(int moveNum, const Move pv[]) { int j; for(j = 0; pv[j] != MOVE_NONE; j++)