1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Remove global TB variables from search.cpp

Follow up cleanup of #4968, removes the global variables from search and
instead uses a dedicated tb config struct.

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

No functional change
This commit is contained in:
Disservin 2024-01-14 14:29:12 +01:00
parent 32e46fc47f
commit a5675f19d8
6 changed files with 89 additions and 75 deletions

View file

@ -44,15 +44,13 @@ Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(PieceType pt, Bitboard table[], Magic magics[]); void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
}
// Returns the bitboard of target square for the given step // Returns the bitboard of target square for the given step
// from the given square. If the step is off the board, returns empty bitboard. // from the given square. If the step is off the board, returns empty bitboard.
inline Bitboard safe_destination(Square s, int step) { Bitboard safe_destination(Square s, int step) {
Square to = Square(s + step); Square to = Square(s + step);
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0); return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
} }
}
// Returns an ASCII representation of a bitboard suitable // Returns an ASCII representation of a bitboard suitable
// to be printed to standard output. Useful for debugging. // to be printed to standard output. Useful for debugging.

View file

@ -29,7 +29,6 @@
#include <iostream> #include <iostream>
#include <utility> #include <utility>
#include "bitboard.h"
#include "evaluate.h" #include "evaluate.h"
#include "misc.h" #include "misc.h"
#include "movegen.h" #include "movegen.h"
@ -46,14 +45,6 @@
namespace Stockfish { namespace Stockfish {
namespace Tablebases {
int Cardinality;
bool RootInTB;
bool UseRule50;
Depth ProbeDepth;
}
namespace TB = Tablebases; namespace TB = Tablebases;
using Eval::evaluate; using Eval::evaluate;
@ -237,7 +228,7 @@ void Search::Worker::start_searching() {
if (bestThread != this) if (bestThread != this)
sync_cout << UCI::pv(*bestThread, main_manager()->tm.elapsed(threads.nodes_searched()), sync_cout << UCI::pv(*bestThread, main_manager()->tm.elapsed(threads.nodes_searched()),
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(), threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
TB::RootInTB) tbConfig.rootInTB)
<< sync_endl; << sync_endl;
sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960()); sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960());
@ -379,7 +370,7 @@ void Search::Worker::iterative_deepening() {
&& mainThread->tm.elapsed(threads.nodes_searched()) > 3000) && mainThread->tm.elapsed(threads.nodes_searched()) > 3000)
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()), sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(), threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
TB::RootInTB) tbConfig.rootInTB)
<< sync_endl; << sync_endl;
// In case of failing low/high increase aspiration window and // In case of failing low/high increase aspiration window and
@ -414,7 +405,7 @@ void Search::Worker::iterative_deepening() {
|| mainThread->tm.elapsed(threads.nodes_searched()) > 3000)) || mainThread->tm.elapsed(threads.nodes_searched()) > 3000))
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()), sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(), threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
TB::RootInTB) tbConfig.rootInTB)
<< sync_endl; << sync_endl;
} }
@ -659,13 +650,13 @@ Value Search::Worker::search(
} }
// Step 5. Tablebases probe // Step 5. Tablebases probe
if (!rootNode && !excludedMove && TB::Cardinality) if (!rootNode && !excludedMove && tbConfig.cardinality)
{ {
int piecesCount = pos.count<ALL_PIECES>(); int piecesCount = pos.count<ALL_PIECES>();
if (piecesCount <= TB::Cardinality if (piecesCount <= tbConfig.cardinality
&& (piecesCount < TB::Cardinality || depth >= TB::ProbeDepth) && pos.rule50_count() == 0 && (piecesCount < tbConfig.cardinality || depth >= tbConfig.probeDepth)
&& !pos.can_castle(ANY_CASTLING)) && pos.rule50_count() == 0 && !pos.can_castle(ANY_CASTLING))
{ {
TB::ProbeState err; TB::ProbeState err;
TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err); TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err);
@ -678,7 +669,7 @@ Value Search::Worker::search(
{ {
thisThread->tbHits.fetch_add(1, std::memory_order_relaxed); thisThread->tbHits.fetch_add(1, std::memory_order_relaxed);
int drawScore = TB::UseRule50 ? 1 : 0; int drawScore = tbConfig.useRule50 ? 1 : 0;
Value tbValue = VALUE_TB - ss->ply; Value tbValue = VALUE_TB - ss->ply;
@ -1962,53 +1953,5 @@ bool RootMove::extract_ponder_from_tt(const TranspositionTable& tt, Position& po
return pv.size() > 1; return pv.size() > 1;
} }
void Tablebases::rank_root_moves(const OptionsMap& options,
Position& pos,
Search::RootMoves& rootMoves) {
RootInTB = false;
UseRule50 = bool(options["Syzygy50MoveRule"]);
ProbeDepth = int(options["SyzygyProbeDepth"]);
Cardinality = int(options["SyzygyProbeLimit"]);
bool dtz_available = true;
// Tables with fewer pieces than SyzygyProbeLimit are searched with
// ProbeDepth == DEPTH_ZERO
if (Cardinality > MaxCardinality)
{
Cardinality = MaxCardinality;
ProbeDepth = 0;
}
if (Cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
{
// Rank moves using DTZ tables
RootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"]);
if (!RootInTB)
{
// DTZ tables are missing; try to rank moves using WDL tables
dtz_available = false;
RootInTB = root_probe_wdl(pos, rootMoves, options["Syzygy50MoveRule"]);
}
}
if (RootInTB)
{
// Sort moves according to TB rank
std::stable_sort(rootMoves.begin(), rootMoves.end(),
[](const RootMove& a, const RootMove& b) { return a.tbRank > b.tbRank; });
// Probe during search only if DTZ is not available and we are winning
if (dtz_available || rootMoves[0].tbScore <= VALUE_DRAW)
Cardinality = 0;
}
else
{
// Clean up if root_probe() and root_probe_wdl() have failed
for (auto& m : rootMoves)
m.tbRank = 0;
}
}
} // namespace Stockfish } // namespace Stockfish

View file

@ -29,6 +29,7 @@
#include "misc.h" #include "misc.h"
#include "movepick.h" #include "movepick.h"
#include "position.h" #include "position.h"
#include "syzygy/tbprobe.h"
#include "timeman.h" #include "timeman.h"
#include "types.h" #include "types.h"
@ -48,7 +49,6 @@ class UCI;
namespace Search { namespace Search {
// Stack struct keeps track of the information we need to remember from nodes // Stack struct keeps track of the information we need to remember from nodes
// shallower and deeper in the tree during the search. Each search thread has // shallower and deeper in the tree during the search. Each search thread has
// its own array of Stack objects, indexed by the current ply. // its own array of Stack objects, indexed by the current ply.
@ -238,6 +238,8 @@ class Worker {
// The main thread has a SearchManager, the others have a NullSearchManager // The main thread has a SearchManager, the others have a NullSearchManager
std::unique_ptr<ISearchManager> manager; std::unique_ptr<ISearchManager> manager;
Tablebases::Config tbConfig;
const OptionsMap& options; const OptionsMap& options;
ThreadPool& threads; ThreadPool& threads;
TranspositionTable& tt; TranspositionTable& tt;

View file

@ -18,7 +18,6 @@
#include "tbprobe.h" #include "tbprobe.h"
#include <sys/stat.h>
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
@ -32,6 +31,7 @@
#include <mutex> #include <mutex>
#include <sstream> #include <sstream>
#include <string_view> #include <string_view>
#include <sys/stat.h>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -42,6 +42,7 @@
#include "../position.h" #include "../position.h"
#include "../search.h" #include "../search.h"
#include "../types.h" #include "../types.h"
#include "../ucioption.h"
#ifndef _WIN32 #ifndef _WIN32
#include <fcntl.h> #include <fcntl.h>
@ -1680,4 +1681,60 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, boo
return true; return true;
} }
Config Tablebases::rank_root_moves(const OptionsMap& options,
Position& pos,
Search::RootMoves& rootMoves) {
Config config;
if (rootMoves.empty())
return config;
config.rootInTB = false;
config.useRule50 = bool(options["Syzygy50MoveRule"]);
config.probeDepth = int(options["SyzygyProbeDepth"]);
config.cardinality = int(options["SyzygyProbeLimit"]);
bool dtz_available = true;
// Tables with fewer pieces than SyzygyProbeLimit are searched with
// probeDepth == DEPTH_ZERO
if (config.cardinality > MaxCardinality)
{
config.cardinality = MaxCardinality;
config.probeDepth = 0;
}
if (config.cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
{
// Rank moves using DTZ tables
config.rootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"]);
if (!config.rootInTB)
{
// DTZ tables are missing; try to rank moves using WDL tables
dtz_available = false;
config.rootInTB = root_probe_wdl(pos, rootMoves, options["Syzygy50MoveRule"]);
}
}
if (config.rootInTB)
{
// Sort moves according to TB rank
std::stable_sort(
rootMoves.begin(), rootMoves.end(),
[](const Search::RootMove& a, const Search::RootMove& b) { return a.tbRank > b.tbRank; });
// Probe during search only if DTZ is not available and we are winning
if (dtz_available || rootMoves[0].tbScore <= VALUE_DRAW)
config.cardinality = 0;
}
else
{
// Clean up if root_probe() and root_probe_wdl() have failed
for (auto& m : rootMoves)
m.tbRank = 0;
}
return config;
}
} // namespace Stockfish } // namespace Stockfish

View file

@ -20,16 +20,30 @@
#define TBPROBE_H #define TBPROBE_H
#include <string> #include <string>
#include <vector>
#include "../search.h"
namespace Stockfish { namespace Stockfish {
class Position; class Position;
class OptionsMap; class OptionsMap;
using Depth = int;
namespace Search {
struct RootMove;
using RootMoves = std::vector<RootMove>;
}
} }
namespace Stockfish::Tablebases { namespace Stockfish::Tablebases {
struct Config {
int cardinality = 0;
bool rootInTB = false;
bool useRule50 = false;
Depth probeDepth = 0;
};
enum WDLScore { enum WDLScore {
WDLLoss = -2, // Loss WDLLoss = -2, // Loss
WDLBlessedLoss = -1, // Loss, but draw under 50-move rule WDLBlessedLoss = -1, // Loss, but draw under 50-move rule
@ -54,7 +68,7 @@ WDLScore probe_wdl(Position& pos, ProbeState* result);
int probe_dtz(Position& pos, ProbeState* result); int probe_dtz(Position& pos, ProbeState* result);
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50); bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50);
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50); bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50);
void rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves); Config rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves);
} // namespace Stockfish::Tablebases } // namespace Stockfish::Tablebases

View file

@ -181,8 +181,7 @@ void ThreadPool::start_thinking(const OptionsMap& options,
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
rootMoves.emplace_back(m); rootMoves.emplace_back(m);
if (!rootMoves.empty()) Tablebases::Config tbConfig = Tablebases::rank_root_moves(options, pos, rootMoves);
Tablebases::rank_root_moves(options, pos, rootMoves);
// After ownership transfer 'states' becomes empty, so if we stop the search // After ownership transfer 'states' becomes empty, so if we stop the search
// and call 'go' again without setting a new position states.get() == nullptr. // and call 'go' again without setting a new position states.get() == nullptr.
@ -205,6 +204,7 @@ void ThreadPool::start_thinking(const OptionsMap& options,
th->worker->rootMoves = rootMoves; th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState); th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
th->worker->rootState = setupStates->back(); th->worker->rootState = setupStates->back();
th->worker->tbConfig = tbConfig;
} }
main_thread()->start_searching(); main_thread()->start_searching();