diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 45304671..ee112804 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -59,7 +59,9 @@ static const string Defaults[] = { void benchmark(int argc, char* argv[]) { + std::vector searchMoves(1, MOVE_NONE); vector fenList; + Search::LimitsType limits; int64_t totalNodes; int time; @@ -76,11 +78,11 @@ void benchmark(int argc, char* argv[]) { // Search should be limited by nodes, time or depth ? if (valType == "nodes") - Search::Limits.maxNodes = atoi(valStr.c_str()); + limits.maxNodes = atoi(valStr.c_str()); else if (valType == "time") - Search::Limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms + limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms else - Search::Limits.maxDepth = atoi(valStr.c_str()); + limits.maxDepth = atoi(valStr.c_str()); // Do we need to load positions from a given FEN file? if (fenFile != "default") @@ -105,30 +107,28 @@ void benchmark(int argc, char* argv[]) { fenList.push_back(Defaults[i]); // Ok, let's start the benchmark ! - Search::RootMoves.push_back(MOVE_NONE); totalNodes = 0; time = get_system_time(); for (size_t i = 0; i < fenList.size(); i++) { Position pos(fenList[i], false, 0); - Search::RootPosition = &pos; cerr << "\nBench position: " << i + 1 << '/' << fenList.size() << endl; if (valType == "perft") { - int64_t cnt = Search::perft(pos, Search::Limits.maxDepth * ONE_PLY); + int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY); - cerr << "\nPerft " << Search::Limits.maxDepth + cerr << "\nPerft " << limits.maxDepth << " nodes counted: " << cnt << endl; totalNodes += cnt; } else { - Threads.start_thinking(false); - totalNodes += pos.nodes_searched(); + Threads.start_thinking(pos, limits, searchMoves, false); + totalNodes += Search::RootPosition.nodes_searched(); } } diff --git a/src/position.cpp b/src/position.cpp index 0f6a3feb..2f18427d 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -97,7 +97,7 @@ CheckInfo::CheckInfo(const Position& pos) { /// or the FEN string, we want the new born Position object do not depend /// on any external data so we detach state pointer from the source one. -Position::Position(const Position& pos, int th) { +void Position::copy(const Position& pos, int th) { memcpy(this, &pos, sizeof(Position)); threadID = th; diff --git a/src/position.h b/src/position.h index 7842ed8b..e4b6bd0f 100644 --- a/src/position.h +++ b/src/position.h @@ -84,16 +84,17 @@ struct StateInfo { class Position { - // No defaul, copy c'tor or assignment allowed, default c'tor will not be - // generated anyhow because of user-defined c'tors. + // No copy c'tor or assignment operator allowed Position(const Position&); Position& operator=(const Position&); public: - Position(const Position& pos, int threadID); - Position(const std::string& fen, bool isChess960, int threadID); + Position() {} + Position(const Position& pos, int th) { copy(pos, th); } + Position(const std::string& fen, bool isChess960, int th); // Text input/output + void copy(const Position& pos, int th); void from_fen(const std::string& fen, bool isChess960); const std::string to_fen() const; void print(Move m = MOVE_NONE) const; diff --git a/src/search.cpp b/src/search.cpp index 6615a1ef..037c44dd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -50,7 +50,7 @@ namespace Search { volatile SignalsType Signals; LimitsType Limits; std::vector RootMoves; - Position* RootPosition; + Position RootPosition; } namespace { @@ -362,7 +362,7 @@ void Search::think() { static Book book; // Defined static to initialize the PRNG only once - Position& pos = *RootPosition; + Position& pos = RootPosition; // Save "search start" time and reset elapsed time to zero elapsed_search_time(get_system_time()); diff --git a/src/search.h b/src/search.h index 4f98cc76..abf7221d 100644 --- a/src/search.h +++ b/src/search.h @@ -54,6 +54,7 @@ namespace Search { struct LimitsType { + LimitsType() { memset(this, 0, sizeof(LimitsType)); } bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); } int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder; @@ -66,7 +67,7 @@ struct SignalsType { extern volatile SignalsType Signals; extern LimitsType Limits; extern std::vector RootMoves; -extern Position* RootPosition; +extern Position RootPosition; extern void init(); extern int64_t perft(Position& pos, Depth depth); diff --git a/src/thread.cpp b/src/thread.cpp index 536f22c1..06646a7b 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -423,37 +423,26 @@ void Thread::main_loop() { } -// ThreadsManager::wait_end_of_search() blocks UI thread until main thread has -// returned to sleep in main_loop(). It is needed becuase xboard sends immediately -// new position to search after a "stop" due to ponder miss. - -void ThreadsManager::wait_end_of_search() { - - Thread& main = threads[0]; - - lock_grab(&main.sleepLock); - - while (!main.do_sleep) - cond_wait(&sleepCond, &main.sleepLock); - - lock_release(&main.sleepLock); -} - - // ThreadsManager::start_thinking() is used by UI thread to wake up the main // thread parked in main_loop() and starting a new search. If asyncMode is true // then function returns immediately, otherwise caller is blocked waiting for // the search to finish. -void ThreadsManager::start_thinking(bool asyncMode) { - +void ThreadsManager::start_thinking(const Position& pos, const Search::LimitsType& limits, + const std::vector& searchMoves, bool asyncMode) { Thread& main = threads[0]; - // Wait main thread has finished before to launch a new search - wait_end_of_search(); - lock_grab(&main.sleepLock); + // Wait main thread has finished before to launch a new search + while (!main.do_sleep) + cond_wait(&sleepCond, &main.sleepLock); + + // Copy input arguments to Search global variables + Search::RootPosition.copy(pos, 0); + Search::Limits = limits; + Search::RootMoves = searchMoves; + // Reset signals before to start the search memset((void*)&Search::Signals, 0, sizeof(Search::Signals)); diff --git a/src/thread.h b/src/thread.h index 95ec1292..0a38caae 100644 --- a/src/thread.h +++ b/src/thread.h @@ -116,11 +116,10 @@ public: void read_uci_options(); bool available_slave_exists(int master) const; bool split_point_finished(SplitPoint* sp) const; - - void start_thinking(bool asyncMode = true); void set_timer(int msec); void wait_for_stop_or_ponderhit(); - void wait_end_of_search(); + void start_thinking(const Position& pos, const Search::LimitsType& limits, + const std::vector& searchMoves, bool asyncMode); template Value split(Position& pos, SearchStack* ss, Value alpha, Value beta, Value bestValue, diff --git a/src/uci.cpp b/src/uci.cpp index 57a31ad6..306819bb 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -72,7 +72,6 @@ void uci_loop() { quit = (token == "quit"); Search::Signals.stop = true; Threads[0].wake_up(); // In case is waiting for stop or ponderhit - Threads.wait_end_of_search(); // Block here until search finishes } else if (cmd == "ponderhit") @@ -206,18 +205,16 @@ namespace { void go(Position& pos, istringstream& is) { string token; + Search::LimitsType limits; + std::vector searchMoves; int time[] = { 0, 0 }, inc[] = { 0, 0 }; - memset(&Search::Limits, 0, sizeof(Search::Limits)); - Search::RootMoves.clear(); - Search::RootPosition = &pos; - while (is >> token) { if (token == "infinite") - Search::Limits.infinite = true; + limits.infinite = true; else if (token == "ponder") - Search::Limits.ponder = true; + limits.ponder = true; else if (token == "wtime") is >> time[WHITE]; else if (token == "btime") @@ -227,23 +224,22 @@ namespace { else if (token == "binc") is >> inc[BLACK]; else if (token == "movestogo") - is >> Search::Limits.movesToGo; + is >> limits.movesToGo; else if (token == "depth") - is >> Search::Limits.maxDepth; + is >> limits.maxDepth; else if (token == "nodes") - is >> Search::Limits.maxNodes; + is >> limits.maxNodes; else if (token == "movetime") - is >> Search::Limits.maxTime; + is >> limits.maxTime; else if (token == "searchmoves") while (is >> token) - Search::RootMoves.push_back(move_from_uci(pos, token)); + searchMoves.push_back(move_from_uci(pos, token)); } + searchMoves.push_back(MOVE_NONE); + limits.time = time[pos.side_to_move()]; + limits.increment = inc[pos.side_to_move()]; - Search::RootMoves.push_back(MOVE_NONE); - Search::Limits.time = time[pos.side_to_move()]; - Search::Limits.increment = inc[pos.side_to_move()]; - - Threads.start_thinking(); + Threads.start_thinking(pos, limits, searchMoves, true); }