summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
6809b57)
Detach from the UI thread the input arguments used by
the search threads so that the UI thread is able to receive
and process any command sent by the GUI while other threads
keep searching.
With this patch there is no more need to block the UI
thread after a "stop", so it is a more reliable and
robust solution than the previous patch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
void benchmark(int argc, char* argv[]) {
void benchmark(int argc, char* argv[]) {
+ std::vector<Move> searchMoves(1, MOVE_NONE);
+ Search::LimitsType limits;
int64_t totalNodes;
int time;
int64_t totalNodes;
int time;
// Search should be limited by nodes, time or depth ?
if (valType == "nodes")
// 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")
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
- 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")
// Do we need to load positions from a given FEN file?
if (fenFile != "default")
fenList.push_back(Defaults[i]);
// Ok, let's start the benchmark !
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);
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")
{
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
{
<< " 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();
/// 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.
/// 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;
memcpy(this, &pos, sizeof(Position));
threadID = th;
- // 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&);
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);
+ 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;
void from_fen(const std::string& fen, bool isChess960);
const std::string to_fen() const;
void print(Move m = MOVE_NONE) const;
volatile SignalsType Signals;
LimitsType Limits;
std::vector<Move> RootMoves;
volatile SignalsType Signals;
LimitsType Limits;
std::vector<Move> RootMoves;
- Position* RootPosition;
static Book book; // Defined static to initialize the PRNG only once
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());
// Save "search start" time and reset elapsed time to zero
elapsed_search_time(get_system_time());
+ LimitsType() { memset(this, 0, sizeof(LimitsType)); }
bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); }
int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder;
bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); }
int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder;
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<Move> RootMoves;
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<Move> RootMoves;
-extern Position* RootPosition;
+extern Position RootPosition;
extern void init();
extern int64_t perft(Position& pos, Depth depth);
extern void init();
extern int64_t perft(Position& pos, Depth depth);
-// 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.
// 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<Move>& searchMoves, bool asyncMode) {
Thread& main = threads[0];
Thread& main = threads[0];
+ lock_grab(&main.sleepLock);
+
// Wait main thread has finished before to launch a new search
// Wait main thread has finished before to launch a new search
+ while (!main.do_sleep)
+ cond_wait(&sleepCond, &main.sleepLock);
- lock_grab(&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));
// Reset signals before to start the search
memset((void*)&Search::Signals, 0, sizeof(Search::Signals));
void read_uci_options();
bool available_slave_exists(int master) const;
bool split_point_finished(SplitPoint* sp) const;
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 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<Move>& searchMoves, bool asyncMode);
template <bool Fake>
Value split(Position& pos, SearchStack* ss, Value alpha, Value beta, Value bestValue,
template <bool Fake>
Value split(Position& pos, SearchStack* ss, Value alpha, Value beta, Value bestValue,
quit = (token == "quit");
Search::Signals.stop = true;
Threads[0].wake_up(); // In case is waiting for stop or ponderhit
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")
}
else if (cmd == "ponderhit")
void go(Position& pos, istringstream& is) {
string token;
void go(Position& pos, istringstream& is) {
string token;
+ Search::LimitsType limits;
+ std::vector<Move> searchMoves;
int time[] = { 0, 0 }, inc[] = { 0, 0 };
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")
while (is >> token)
{
if (token == "infinite")
- Search::Limits.infinite = true;
+ limits.infinite = true;
else if (token == "ponder")
else if (token == "ponder")
- Search::Limits.ponder = true;
else if (token == "wtime")
is >> time[WHITE];
else if (token == "btime")
else if (token == "wtime")
is >> time[WHITE];
else if (token == "btime")
else if (token == "binc")
is >> inc[BLACK];
else if (token == "movestogo")
else if (token == "binc")
is >> inc[BLACK];
else if (token == "movestogo")
- is >> Search::Limits.movesToGo;
+ is >> limits.movesToGo;
else if (token == "depth")
else if (token == "depth")
- is >> Search::Limits.maxDepth;
else if (token == "nodes")
else if (token == "nodes")
- is >> Search::Limits.maxNodes;
else if (token == "movetime")
else if (token == "movetime")
- is >> Search::Limits.maxTime;
else if (token == "searchmoves")
while (is >> token)
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);