1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-03 01:59:36 +00:00

Reformat lazy smp code

Just a first quick pass. Probably Skill and MultiPV
need some work too.

No functional change.
This commit is contained in:
Marco Costalba 2015-10-06 21:45:12 +02:00
parent 713604a3d4
commit b01ad9ba18
5 changed files with 73 additions and 82 deletions

View file

@ -238,8 +238,8 @@ void MovePicker::generate_next_stage() {
/// a new pseudo legal move every time it is called, until there are no more moves /// a new pseudo legal move every time it is called, until there are no more moves
/// left. It picks the move with the biggest value from a list of generated moves /// left. It picks the move with the biggest value from a list of generated moves
/// taking care not to return the ttMove if it has already been searched. /// taking care not to return the ttMove if it has already been searched.
template<>
Move MovePicker::next_move<false>() { Move MovePicker::next_move() {
Move move; Move move;

View file

@ -92,7 +92,7 @@ public:
MovePicker(const Position&, Move, const HistoryStats&, const CounterMovesHistoryStats&, Value); MovePicker(const Position&, Move, const HistoryStats&, const CounterMovesHistoryStats&, Value);
MovePicker(const Position&, Move, Depth, const HistoryStats&, const CounterMovesHistoryStats&, Move, Search::Stack*); MovePicker(const Position&, Move, Depth, const HistoryStats&, const CounterMovesHistoryStats&, Move, Search::Stack*);
template<bool SpNode> Move next_move(); Move next_move();
private: private:
template<GenType> void score(); template<GenType> void score();

View file

@ -106,7 +106,7 @@ namespace {
assert(newPv.size() >= 3); assert(newPv.size() >= 3);
// Keep track of how many times in a row 3rd ply remains stable // Keep track of how many times in a row 3rd ply remains stable
stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0; stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
if (!std::equal(newPv.begin(), newPv.begin() + 3, pv)) if (!std::equal(newPv.begin(), newPv.begin() + 3, pv))
@ -182,7 +182,8 @@ void Search::reset () {
TT.clear(); TT.clear();
CounterMovesHistory.clear(); CounterMovesHistory.clear();
for (Thread* th : Threads) { for (Thread* th : Threads)
{
th->History.clear(); th->History.clear();
th->Countermoves.clear(); th->Countermoves.clear();
} }
@ -225,9 +226,10 @@ template uint64_t Search::perft<true>(Position& pos, Depth depth);
void Search::think() { void Search::think() {
MainThread* mth = Threads.main(); // Shorthand Position& rootPos = Threads.main()->pos;
Color us = mth->pos.side_to_move(); Search::RootMoveVector& rootMoves = Threads.main()->rootMoves;
Time.init(Limits, us, mth->pos.game_ply(), now()); Color us = rootPos.side_to_move();
Time.init(Limits, us, rootPos.game_ply(), now());
int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
DrawValue[ us] = VALUE_DRAW - Value(contempt); DrawValue[ us] = VALUE_DRAW - Value(contempt);
@ -246,21 +248,21 @@ void Search::think() {
TB::ProbeDepth = DEPTH_ZERO; TB::ProbeDepth = DEPTH_ZERO;
} }
if (mth->rootMoves.empty()) if (rootMoves.empty())
{ {
mth->rootMoves.push_back(RootMove(MOVE_NONE)); rootMoves.push_back(RootMove(MOVE_NONE));
sync_cout << "info depth 0 score " sync_cout << "info depth 0 score "
<< UCI::value(mth->pos.checkers() ? -VALUE_MATE : VALUE_DRAW) << UCI::value(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
<< sync_endl; << sync_endl;
} }
else else
{ {
if (TB::Cardinality >= mth->pos.count<ALL_PIECES>(WHITE) if (TB::Cardinality >= rootPos.count<ALL_PIECES>(WHITE)
+ mth->pos.count<ALL_PIECES>(BLACK)) + rootPos.count<ALL_PIECES>(BLACK))
{ {
// If the current root position is in the tablebases then RootMoves // If the current root position is in the tablebases then RootMoves
// contains only moves that preserve the draw or win. // contains only moves that preserve the draw or win.
TB::RootInTB = Tablebases::root_probe(mth->pos, mth->rootMoves, TB::Score); TB::RootInTB = Tablebases::root_probe(rootPos, rootMoves, TB::Score);
if (TB::RootInTB) if (TB::RootInTB)
TB::Cardinality = 0; // Do not probe tablebases during the search TB::Cardinality = 0; // Do not probe tablebases during the search
@ -268,7 +270,7 @@ void Search::think() {
else // If DTZ tables are missing, use WDL tables as a fallback else // If DTZ tables are missing, use WDL tables as a fallback
{ {
// Filter out moves that do not preserve a draw or win // Filter out moves that do not preserve a draw or win
TB::RootInTB = Tablebases::root_probe_wdl(mth->pos, mth->rootMoves, TB::Score); TB::RootInTB = Tablebases::root_probe_wdl(rootPos, rootMoves, TB::Score);
// Only probe during search if winning // Only probe during search if winning
if (TB::Score <= VALUE_DRAW) if (TB::Score <= VALUE_DRAW)
@ -277,7 +279,7 @@ void Search::think() {
if (TB::RootInTB) if (TB::RootInTB)
{ {
TB::Hits = mth->rootMoves.size(); TB::Hits = rootMoves.size();
if (!TB::UseRule50) if (!TB::UseRule50)
TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1 TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1
@ -286,15 +288,14 @@ void Search::think() {
} }
} }
// Prepare the threads.
for (Thread* th : Threads) for (Thread* th : Threads)
{ {
th->maxPly = 0; th->maxPly = 0;
th->rootDepth = DEPTH_ZERO; th->depth = DEPTH_ZERO;
if (th != mth) { if (th != Threads.main())
Position pos(mth->pos, th); {
th->pos = pos; th->pos = Position(rootPos, th);
th->rootMoves = mth->rootMoves; th->rootMoves = rootMoves;
} }
th->notify_one(); // Wake up all the threads th->notify_one(); // Wake up all the threads
} }
@ -320,22 +321,21 @@ void Search::think() {
if (!Signals.stop && (Limits.ponder || Limits.infinite)) if (!Signals.stop && (Limits.ponder || Limits.infinite))
{ {
Signals.stopOnPonderhit = true; Signals.stopOnPonderhit = true;
mth->pos.this_thread()->wait_for(Signals.stop); rootPos.this_thread()->wait_for(Signals.stop);
} }
sync_cout << "bestmove " << UCI::move(mth->rootMoves[0].pv[0], mth->pos.is_chess960()); sync_cout << "bestmove " << UCI::move(rootMoves[0].pv[0], rootPos.is_chess960());
if (mth->rootMoves[0].pv.size() > 1 || mth->rootMoves[0].extract_ponder_from_tt(mth->pos)) if (rootMoves[0].pv.size() > 1 || rootMoves[0].extract_ponder_from_tt(rootPos))
std::cout << " ponder " << UCI::move(mth->rootMoves[0].pv[1], mth->pos.is_chess960()); std::cout << " ponder " << UCI::move(rootMoves[0].pv[1], rootPos.is_chess960());
std::cout << sync_endl; std::cout << sync_endl;
} }
// Thread::id_loop() is the main iterative deepening loop. It calls search() repeatedly // Thread::id_loop() is the main iterative deepening loop. It calls search()
// with increasing depth until the allocated thinking time has been consumed, // repeatedly with increasing depth until the allocated thinking time has been
// user stops the search, or the maximum search depth is reached. // consumed, user stops the search, or the maximum search depth is reached.
void Thread::id_loop() { void Thread::id_loop() {
@ -352,8 +352,8 @@ void Thread::id_loop() {
EasyMove.clear(); EasyMove.clear();
} }
Stack *ss = stack+2; // To allow referencing (ss-2) and (ss+2) Stack* ss = stack+2; // To allow referencing (ss-2) and (ss+2)
std::memset(stack, 0, 5 * sizeof(Stack)); std::memset(ss-2, 0, 5 * sizeof(Stack));
bestValue = delta = alpha = -VALUE_INFINITE; bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE; beta = VALUE_INFINITE;
@ -371,27 +371,23 @@ void Thread::id_loop() {
// Iterative deepening loop until requested to stop or target depth reached // Iterative deepening loop until requested to stop or target depth reached
while (true) while (true)
{ {
// Set up our new depth. // Set up our new depth
// The main thread modifies other threads rootDepth, // The main thread modifies other threads rootDepth, if it is <= main
// if it is <= main thread depth. The new depth will take effect // thread depth. The new depth will take effect after the other thread
// after the other thread returns to id_loop(). // returns to id_loop().
if (this == Threads.main()) { if (this == Threads.main())
++rootDepth; {
for (Thread* th : Threads) { ++depth;
if (th != this) { for (Thread* th : Threads)
if (th->rootDepth <= rootDepth) { if (th != this && th->depth <= depth)
th->rootDepth = rootDepth + (Depth)(((th->idx - 1) / 2) + 1); th->depth = depth + ONE_PLY + Depth(th->idx - 1) / 2;
}
}
}
}
else {
// This can cause a thread to search with the same depth for many iterations.
rootDepth = Threads.main()->rootDepth + (Depth)(((this->idx - 1) / 2) + 1);
} }
else
// This can cause a thread to search with the same depth for many iterations
depth = Threads.main()->depth + ONE_PLY + Depth(this->idx - 1) / 2;
if (rootDepth >= DEPTH_MAX || Signals.stop || (Limits.depth && rootDepth > Limits.depth)) if (depth >= DEPTH_MAX || Signals.stop || (Limits.depth && depth > Limits.depth))
break; break;
// Age out PV variability metric // Age out PV variability metric
@ -407,25 +403,19 @@ void Thread::id_loop() {
for (PVIdx = 0; PVIdx < multiPV && !Signals.stop; ++PVIdx) for (PVIdx = 0; PVIdx < multiPV && !Signals.stop; ++PVIdx)
{ {
// Reset aspiration window starting size // Reset aspiration window starting size
if (rootDepth >= 5 * ONE_PLY) if (depth >= 5 * ONE_PLY)
{ {
delta = Value(16); delta = Value(16);
alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE); alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE);
beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE); beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE);
} }
/*
sync_cout << "*T" << idx << " - I'm starting iteration " << rootDepth << ".";
std::cout << " We are searching ";
for (Thread* th : Threads)
std::cout << th->rootDepth << " ";
std::cout << "." << sync_endl;
*/
// Start with a small aspiration window and, in the case of a fail // Start with a small aspiration window and, in the case of a fail
// high/low, re-search with a bigger window until we're not failing // high/low, re-search with a bigger window until we're not failing
// high/low anymore. // high/low anymore.
while (true) while (true)
{ {
bestValue = search<Root>(pos, ss, alpha, beta, rootDepth, false); bestValue = search<Root>(pos, ss, alpha, beta, depth, false);
// Bring the best move to the front. It is critical that sorting // Bring the best move to the front. It is critical that sorting
// is done with a stable algorithm because all the values but the // is done with a stable algorithm because all the values but the
@ -447,13 +437,14 @@ void Thread::id_loop() {
if (Signals.stop) if (Signals.stop)
break; break;
if (this == Threads.main()) { if (this == Threads.main())
{
// When failing high/low give some update (without cluttering // When failing high/low give some update (without cluttering
// the UI) before a re-search. // the UI) before a re-search.
if (multiPV == 1 if (multiPV == 1
&& (bestValue <= alpha || bestValue >= beta) && (bestValue <= alpha || bestValue >= beta)
&& Time.elapsed() > 3000) && Time.elapsed() > 3000)
sync_cout << UCI::pv(pos, rootDepth, alpha, beta) << sync_endl; sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
} }
// In case of failing low/high increase aspiration window and // In case of failing low/high increase aspiration window and
@ -462,7 +453,9 @@ void Thread::id_loop() {
{ {
beta = (alpha + beta) / 2; beta = (alpha + beta) / 2;
alpha = std::max(bestValue - delta, -VALUE_INFINITE); alpha = std::max(bestValue - delta, -VALUE_INFINITE);
if (this == Threads.main()) {
if (this == Threads.main())
{
Signals.failedLowAtRoot = true; Signals.failedLowAtRoot = true;
Signals.stopOnPonderhit = false; Signals.stopOnPonderhit = false;
} }
@ -491,14 +484,14 @@ void Thread::id_loop() {
<< " time " << Time.elapsed() << sync_endl; << " time " << Time.elapsed() << sync_endl;
else if (PVIdx + 1 == multiPV || Time.elapsed() > 3000) else if (PVIdx + 1 == multiPV || Time.elapsed() > 3000)
sync_cout << UCI::pv(pos, rootDepth, alpha, beta) << sync_endl; sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
} }
if (this != Threads.main()) if (this != Threads.main())
continue; continue;
// If skill level is enabled and time is up, pick a sub-optimal best move // If skill level is enabled and time is up, pick a sub-optimal best move
if (skill.enabled() && skill.time_to_pick(rootDepth)) if (skill.enabled() && skill.time_to_pick(depth))
skill.pick_best(multiPV); skill.pick_best(multiPV);
// Have we found a "mate in x"? // Have we found a "mate in x"?
@ -513,7 +506,7 @@ void Thread::id_loop() {
if (!Signals.stop && !Signals.stopOnPonderhit) if (!Signals.stop && !Signals.stopOnPonderhit)
{ {
// Take some extra time if the best move has changed // Take some extra time if the best move has changed
if (rootDepth > 4 * ONE_PLY && multiPV == 1) if (depth > 4 * ONE_PLY && multiPV == 1)
Time.pv_instability(BestMoveChanges); Time.pv_instability(BestMoveChanges);
// Stop the search if only one legal move is available or all // Stop the search if only one legal move is available or all
@ -560,13 +553,13 @@ namespace {
TT.new_search(); TT.new_search();
// Start search for the other threads. // Start search for the other threads
for (Thread* th : Threads) for (Thread* th : Threads)
th->searching = true; th->searching = true;
Threads.main()->id_loop(); Threads.main()->id_loop();
// Force a quicker exit of fixed depth searches. // Force a quicker exit of fixed depth searches
Signals.stop = true; Signals.stop = true;
// Wait until all threads have finished. // Wait until all threads have finished.
@ -579,6 +572,7 @@ namespace {
size_t multiPV = Options["MultiPV"]; size_t multiPV = Options["MultiPV"];
Skill skill(Options["Skill Level"]); Skill skill(Options["Skill Level"]);
// If skill level is enabled, swap best PV line with the sub-optimal one // If skill level is enabled, swap best PV line with the sub-optimal one
if (skill.enabled()) if (skill.enabled())
std::swap(Threads.main()->rootMoves[0], *std::find(Threads.main()->rootMoves.begin(), std::swap(Threads.main()->rootMoves[0], *std::find(Threads.main()->rootMoves.begin(),
@ -816,7 +810,7 @@ namespace {
MovePicker mp(pos, ttMove, thisThread->History, CounterMovesHistory, PieceValue[MG][pos.captured_piece_type()]); MovePicker mp(pos, ttMove, thisThread->History, CounterMovesHistory, PieceValue[MG][pos.captured_piece_type()]);
CheckInfo ci(pos); CheckInfo ci(pos);
while ((move = mp.next_move<false>()) != MOVE_NONE) while ((move = mp.next_move()) != MOVE_NONE)
if (pos.legal(move, ci.pinned)) if (pos.legal(move, ci.pinned))
{ {
ss->currentMove = move; ss->currentMove = move;
@ -865,7 +859,7 @@ moves_loop: // When in check search starts from here
// Step 11. Loop through moves // Step 11. Loop through moves
// Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs // Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move<false>()) != MOVE_NONE) while ((move = mp.next_move()) != MOVE_NONE)
{ {
assert(is_ok(move)); assert(is_ok(move));
@ -1046,8 +1040,8 @@ moves_loop: // When in check search starts from here
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE); assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
// Step 18. Check for new best move // Step 18. Check for new best move
// Finished searching the move. If a stop or a cutoff occurred, the return // Finished searching the move. If a stop occurred, the return value of
// value of the search cannot be trusted, and we return immediately without // the search cannot be trusted, and we return immediately without
// updating best move, PV and TT. // updating best move, PV and TT.
if (Signals.stop) if (Signals.stop)
return VALUE_ZERO; return VALUE_ZERO;
@ -1265,7 +1259,7 @@ moves_loop: // When in check search starts from here
CheckInfo ci(pos); CheckInfo ci(pos);
// Loop through the moves until no moves remain or a beta cutoff occurs // Loop through the moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move<false>()) != MOVE_NONE) while ((move = mp.next_move()) != MOVE_NONE)
{ {
assert(is_ok(move)); assert(is_ok(move));
@ -1452,11 +1446,11 @@ moves_loop: // When in check search starts from here
Move Skill::pick_best(size_t multiPV) { Move Skill::pick_best(size_t multiPV) {
// PRNG sequence should be non-deterministic, so we seed it with the time at init // PRNG sequence should be non-deterministic, so we seed it with the time at init
MainThread* mth = Threads.main(); // Shorthand const Search::RootMoveVector& rootMoves = Threads.main()->rootMoves;
static PRNG rng(now()); static PRNG rng(now());
// RootMoves are already sorted by score in descending order // RootMoves are already sorted by score in descending order
int variance = std::min(mth->rootMoves[0].score - mth->rootMoves[multiPV - 1].score, PawnValueMg); int variance = std::min(rootMoves[0].score - rootMoves[multiPV - 1].score, PawnValueMg);
int weakness = 120 - 2 * level; int weakness = 120 - 2 * level;
int maxScore = -VALUE_INFINITE; int maxScore = -VALUE_INFINITE;
@ -1466,13 +1460,13 @@ moves_loop: // When in check search starts from here
for (size_t i = 0; i < multiPV; ++i) for (size_t i = 0; i < multiPV; ++i)
{ {
// This is our magic formula // This is our magic formula
int push = ( weakness * int(mth->rootMoves[0].score - mth->rootMoves[i].score) int push = ( weakness * int(rootMoves[0].score - rootMoves[i].score)
+ variance * (rng.rand<unsigned>() % weakness)) / 128; + variance * (rng.rand<unsigned>() % weakness)) / 128;
if (mth->rootMoves[i].score + push > maxScore) if (rootMoves[i].score + push > maxScore)
{ {
maxScore = mth->rootMoves[i].score + push; maxScore = rootMoves[i].score + push;
best = mth->rootMoves[i].pv[0]; best = rootMoves[i].pv[0];
} }
} }
return best; return best;
@ -1610,7 +1604,6 @@ void Thread::idle_loop() {
} }
/// check_time() is called by the timer thread when the timer triggers. It is /// check_time() is called by the timer thread when the timer triggers. It is
/// used to print debug info and, more importantly, to detect when we are out of /// used to print debug info and, more importantly, to detect when we are out of
/// available time and thus stop the search. /// available time and thus stop the search.

View file

@ -209,7 +209,6 @@ uint64_t ThreadPool::nodes_searched() {
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
StateStackPtr& states) { StateStackPtr& states) {
main()->join(); main()->join();
Signals.stopOnPonderhit = Signals.firstRootMove = false; Signals.stopOnPonderhit = Signals.firstRootMove = false;

View file

@ -73,13 +73,12 @@ struct Thread : public ThreadBase {
int maxPly; int maxPly;
volatile bool searching; volatile bool searching;
// Data per thread.
Position pos; Position pos;
Search::RootMoveVector rootMoves; Search::RootMoveVector rootMoves;
Search::Stack stack[MAX_PLY+4]; Search::Stack stack[MAX_PLY+4];
HistoryStats History; HistoryStats History;
MovesStats Countermoves; MovesStats Countermoves;
Depth rootDepth; Depth depth;
}; };