mirror of
https://github.com/sockspls/badfish
synced 2025-07-11 11:39:15 +00:00
Update nodes after a do_move()
And also store the node counter in Position and not in Thread. This will allow to properly count nodes also in sub trees with SMP active. This requires a surprisingly high number of changes in a lot of places to make it work properly. No functional change but node count changed for obvious reasons. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
49a6fee4fa
commit
d74025a34e
9 changed files with 68 additions and 89 deletions
|
@ -161,7 +161,7 @@ void benchmark(const string& commandLine) {
|
||||||
} else {
|
} else {
|
||||||
if (!think(pos, false, false, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
|
if (!think(pos, false, false, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
|
||||||
break;
|
break;
|
||||||
totalNodes += nodes_searched();
|
totalNodes += pos.nodes_searched();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,13 +121,12 @@ CheckInfo::CheckInfo(const Position& pos) {
|
||||||
/// or the FEN string, we want the new born Position object do not depend
|
/// 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.
|
/// on any external data so we detach state pointer from the source one.
|
||||||
|
|
||||||
Position::Position(int th) : threadID(th) {}
|
|
||||||
|
|
||||||
Position::Position(const Position& pos, int th) {
|
Position::Position(const Position& pos, int th) {
|
||||||
|
|
||||||
memcpy(this, &pos, sizeof(Position));
|
memcpy(this, &pos, sizeof(Position));
|
||||||
detach(); // Always detach() in copy c'tor to avoid surprises
|
detach(); // Always detach() in copy c'tor to avoid surprises
|
||||||
threadID = th;
|
threadID = th;
|
||||||
|
nodes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position::Position(const string& fen, int th) {
|
Position::Position(const string& fen, int th) {
|
||||||
|
@ -752,6 +751,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||||
assert(is_ok());
|
assert(is_ok());
|
||||||
assert(move_is_ok(m));
|
assert(move_is_ok(m));
|
||||||
|
|
||||||
|
nodes++;
|
||||||
Key key = st->key;
|
Key key = st->key;
|
||||||
|
|
||||||
// Copy some fields of old state to our new StateInfo object except the
|
// Copy some fields of old state to our new StateInfo object except the
|
||||||
|
@ -1479,6 +1479,7 @@ void Position::clear() {
|
||||||
memset(st, 0, sizeof(StateInfo));
|
memset(st, 0, sizeof(StateInfo));
|
||||||
st->epSquare = SQ_NONE;
|
st->epSquare = SQ_NONE;
|
||||||
startPosPlyCounter = 0;
|
startPosPlyCounter = 0;
|
||||||
|
nodes = 0;
|
||||||
|
|
||||||
memset(byColorBB, 0, sizeof(Bitboard) * 2);
|
memset(byColorBB, 0, sizeof(Bitboard) * 2);
|
||||||
memset(byTypeBB, 0, sizeof(Bitboard) * 8);
|
memset(byTypeBB, 0, sizeof(Bitboard) * 8);
|
||||||
|
|
|
@ -146,7 +146,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
explicit Position(int threadID);
|
|
||||||
Position(const Position& pos, int threadID);
|
Position(const Position& pos, int threadID);
|
||||||
Position(const std::string& fen, int threadID);
|
Position(const std::string& fen, int threadID);
|
||||||
|
|
||||||
|
@ -278,8 +277,9 @@ public:
|
||||||
|
|
||||||
// Reset the gamePly variable to 0
|
// Reset the gamePly variable to 0
|
||||||
void reset_game_ply();
|
void reset_game_ply();
|
||||||
|
|
||||||
void inc_startpos_ply_counter();
|
void inc_startpos_ply_counter();
|
||||||
|
int64_t nodes_searched() const;
|
||||||
|
void set_nodes_searched(int64_t n);
|
||||||
|
|
||||||
// Position consistency check, for debugging
|
// Position consistency check, for debugging
|
||||||
bool is_ok(int* failedStep = NULL) const;
|
bool is_ok(int* failedStep = NULL) const;
|
||||||
|
@ -338,6 +338,7 @@ private:
|
||||||
bool isChess960;
|
bool isChess960;
|
||||||
int startPosPlyCounter;
|
int startPosPlyCounter;
|
||||||
int threadID;
|
int threadID;
|
||||||
|
int64_t nodes;
|
||||||
StateInfo* st;
|
StateInfo* st;
|
||||||
|
|
||||||
// Static variables
|
// Static variables
|
||||||
|
@ -355,6 +356,14 @@ private:
|
||||||
//// Inline functions
|
//// Inline functions
|
||||||
////
|
////
|
||||||
|
|
||||||
|
inline int64_t Position::nodes_searched() const {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Position::set_nodes_searched(int64_t n) {
|
||||||
|
nodes = n;
|
||||||
|
}
|
||||||
|
|
||||||
inline Piece Position::piece_on(Square s) const {
|
inline Piece Position::piece_on(Square s) const {
|
||||||
return board[s];
|
return board[s];
|
||||||
}
|
}
|
||||||
|
|
12
src/san.cpp
12
src/san.cpp
|
@ -322,7 +322,7 @@ const string line_to_san(const Position& pos, Move line[], int startColumn, bool
|
||||||
/// It is used to write search information to the log file (which is created
|
/// It is used to write search information to the log file (which is created
|
||||||
/// when the UCI parameter "Use Search Log" is "true").
|
/// when the UCI parameter "Use Search Log" is "true").
|
||||||
|
|
||||||
const string pretty_pv(const Position& pos, int time, int depth, uint64_t nodes,
|
const string pretty_pv(const Position& pos, int time, int depth,
|
||||||
Value score, ValueType type, Move pv[]) {
|
Value score, ValueType type, Move pv[]) {
|
||||||
|
|
||||||
const uint64_t K = 1000;
|
const uint64_t K = 1000;
|
||||||
|
@ -341,12 +341,12 @@ const string pretty_pv(const Position& pos, int time, int depth, uint64_t nodes,
|
||||||
s << std::setw(8) << time_string(time) << " ";
|
s << std::setw(8) << time_string(time) << " ";
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
if (nodes < M)
|
if (pos.nodes_searched() < M)
|
||||||
s << std::setw(8) << nodes / 1 << " ";
|
s << std::setw(8) << pos.nodes_searched() / 1 << " ";
|
||||||
else if (nodes < K * M)
|
else if (pos.nodes_searched() < K * M)
|
||||||
s << std::setw(7) << nodes / K << "K ";
|
s << std::setw(7) << pos.nodes_searched() / K << "K ";
|
||||||
else
|
else
|
||||||
s << std::setw(7) << nodes / M << "M ";
|
s << std::setw(7) << pos.nodes_searched() / M << "M ";
|
||||||
|
|
||||||
// PV
|
// PV
|
||||||
s << line_to_san(pos, pv, 30, true);
|
s << line_to_san(pos, pv, 30, true);
|
||||||
|
|
|
@ -39,6 +39,6 @@
|
||||||
extern const std::string move_to_san(Position& pos, Move m);
|
extern const std::string move_to_san(Position& pos, Move m);
|
||||||
extern Move move_from_san(const Position& pos, const std::string& str);
|
extern Move move_from_san(const Position& pos, const std::string& str);
|
||||||
extern const std::string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines);
|
extern const std::string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines);
|
||||||
extern const std::string pretty_pv(const Position& pos, int time, int depth, uint64_t nodes, Value score, ValueType type, Move pv[]);
|
extern const std::string pretty_pv(const Position& pos, int time, int depth, Value score, ValueType type, Move pv[]);
|
||||||
|
|
||||||
#endif // !defined(SAN_H_INCLUDED)
|
#endif // !defined(SAN_H_INCLUDED)
|
||||||
|
|
112
src/search.cpp
112
src/search.cpp
|
@ -75,10 +75,7 @@ namespace {
|
||||||
|
|
||||||
int active_threads() const { return ActiveThreads; }
|
int active_threads() const { return ActiveThreads; }
|
||||||
void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
|
void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
|
||||||
void incrementNodeCounter(int threadID) { threads[threadID].nodes++; }
|
|
||||||
|
|
||||||
void resetNodeCounters();
|
|
||||||
int64_t nodes_searched() const;
|
|
||||||
bool available_thread_exists(int master) const;
|
bool available_thread_exists(int master) const;
|
||||||
bool thread_is_available(int slave, int master) const;
|
bool thread_is_available(int slave, int master) const;
|
||||||
bool thread_should_stop(int threadID) const;
|
bool thread_should_stop(int threadID) const;
|
||||||
|
@ -86,12 +83,10 @@ namespace {
|
||||||
void idle_loop(int threadID, SplitPoint* sp);
|
void idle_loop(int threadID, SplitPoint* sp);
|
||||||
|
|
||||||
template <bool Fake>
|
template <bool Fake>
|
||||||
void split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
|
void split(Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
|
||||||
Depth depth, Move threatMove, bool mateThreat, int moveCount, MovePicker* mp, bool pvNode);
|
Depth depth, Move threatMove, bool mateThreat, int moveCount, MovePicker* mp, bool pvNode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void poll();
|
|
||||||
|
|
||||||
int ActiveThreads;
|
int ActiveThreads;
|
||||||
volatile bool AllThreadsShouldExit;
|
volatile bool AllThreadsShouldExit;
|
||||||
Thread threads[MAX_THREADS];
|
Thread threads[MAX_THREADS];
|
||||||
|
@ -273,7 +268,7 @@ namespace {
|
||||||
|
|
||||||
/// Local functions
|
/// Local functions
|
||||||
|
|
||||||
Value id_loop(const Position& pos, Move searchMoves[]);
|
Value id_loop(Position& pos, Move searchMoves[]);
|
||||||
Value root_search(Position& pos, SearchStack* ss, Move* pv, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
|
Value root_search(Position& pos, SearchStack* ss, Move* pv, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
|
||||||
|
|
||||||
template <NodeType PvNode, bool SpNode>
|
template <NodeType PvNode, bool SpNode>
|
||||||
|
@ -305,8 +300,8 @@ namespace {
|
||||||
|
|
||||||
int current_search_time();
|
int current_search_time();
|
||||||
std::string value_to_uci(Value v);
|
std::string value_to_uci(Value v);
|
||||||
int nps();
|
int nps(const Position& pos);
|
||||||
void poll();
|
void poll(const Position& pos);
|
||||||
void ponderhit();
|
void ponderhit();
|
||||||
void wait_for_stop_or_ponderhit();
|
void wait_for_stop_or_ponderhit();
|
||||||
void init_ss_array(SearchStack* ss, int size);
|
void init_ss_array(SearchStack* ss, int size);
|
||||||
|
@ -332,7 +327,6 @@ namespace {
|
||||||
|
|
||||||
void init_threads() { ThreadsMgr.init_threads(); }
|
void init_threads() { ThreadsMgr.init_threads(); }
|
||||||
void exit_threads() { ThreadsMgr.exit_threads(); }
|
void exit_threads() { ThreadsMgr.exit_threads(); }
|
||||||
int64_t nodes_searched() { return ThreadsMgr.nodes_searched(); }
|
|
||||||
|
|
||||||
|
|
||||||
/// init_search() is called during startup. It initializes various lookup tables
|
/// init_search() is called during startup. It initializes various lookup tables
|
||||||
|
@ -398,13 +392,12 @@ int perft(Position& pos, Depth depth)
|
||||||
/// search-related global variables, and calls root_search(). It returns false
|
/// search-related global variables, and calls root_search(). It returns false
|
||||||
/// when a quit command is received during the search.
|
/// when a quit command is received during the search.
|
||||||
|
|
||||||
bool think(const Position& pos, bool infinite, bool ponder, int time[], int increment[],
|
bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[],
|
||||||
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]) {
|
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]) {
|
||||||
|
|
||||||
// Initialize global search variables
|
// Initialize global search variables
|
||||||
StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false;
|
StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false;
|
||||||
NodesSincePoll = 0;
|
NodesSincePoll = 0;
|
||||||
ThreadsMgr.resetNodeCounters();
|
|
||||||
SearchStartTime = get_system_time();
|
SearchStartTime = get_system_time();
|
||||||
ExactMaxTime = maxTime;
|
ExactMaxTime = maxTime;
|
||||||
MaxDepth = maxDepth;
|
MaxDepth = maxDepth;
|
||||||
|
@ -509,16 +502,15 @@ namespace {
|
||||||
// been consumed, the user stops the search, or the maximum search depth is
|
// been consumed, the user stops the search, or the maximum search depth is
|
||||||
// reached.
|
// reached.
|
||||||
|
|
||||||
Value id_loop(const Position& pos, Move searchMoves[]) {
|
Value id_loop(Position& pos, Move searchMoves[]) {
|
||||||
|
|
||||||
Position p(pos, pos.thread());
|
|
||||||
SearchStack ss[PLY_MAX_PLUS_2];
|
SearchStack ss[PLY_MAX_PLUS_2];
|
||||||
Move pv[PLY_MAX_PLUS_2];
|
Move pv[PLY_MAX_PLUS_2];
|
||||||
Move EasyMove = MOVE_NONE;
|
Move EasyMove = MOVE_NONE;
|
||||||
Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
|
Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
|
||||||
|
|
||||||
// Moves to search are verified, copied, scored and sorted
|
// Moves to search are verified, copied, scored and sorted
|
||||||
RootMoveList rml(p, searchMoves);
|
RootMoveList rml(pos, searchMoves);
|
||||||
|
|
||||||
// Handle special case of searching on a mate/stale position
|
// Handle special case of searching on a mate/stale position
|
||||||
if (rml.move_count() == 0)
|
if (rml.move_count() == 0)
|
||||||
|
@ -531,13 +523,13 @@ namespace {
|
||||||
|
|
||||||
// Print RootMoveList startup scoring to the standard output,
|
// Print RootMoveList startup scoring to the standard output,
|
||||||
// so to output information also for iteration 1.
|
// so to output information also for iteration 1.
|
||||||
cout << set960(p.is_chess960()) // Is enough to set once at the beginning
|
cout << set960(pos.is_chess960()) // Is enough to set once at the beginning
|
||||||
<< "info depth " << 1
|
<< "info depth " << 1
|
||||||
<< "\ninfo depth " << 1
|
<< "\ninfo depth " << 1
|
||||||
<< " score " << value_to_uci(rml.move_score(0))
|
<< " score " << value_to_uci(rml.move_score(0))
|
||||||
<< " time " << current_search_time()
|
<< " time " << current_search_time()
|
||||||
<< " nodes " << ThreadsMgr.nodes_searched()
|
<< " nodes " << pos.nodes_searched()
|
||||||
<< " nps " << nps()
|
<< " nps " << nps(pos)
|
||||||
<< " pv " << rml.move(0) << "\n";
|
<< " pv " << rml.move(0) << "\n";
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
|
@ -576,11 +568,11 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search to the current depth, rml is updated and sorted, alpha and beta could change
|
// Search to the current depth, rml is updated and sorted, alpha and beta could change
|
||||||
value = root_search(p, ss, pv, rml, &alpha, &beta);
|
value = root_search(pos, ss, pv, rml, &alpha, &beta);
|
||||||
|
|
||||||
// Write PV to transposition table, in case the relevant entries have
|
// Write PV to transposition table, in case the relevant entries have
|
||||||
// been overwritten during the search.
|
// been overwritten during the search.
|
||||||
insert_pv_in_tt(p, pv);
|
insert_pv_in_tt(pos, pv);
|
||||||
|
|
||||||
if (AbortSearch)
|
if (AbortSearch)
|
||||||
break; // Value cannot be trusted. Break out immediately!
|
break; // Value cannot be trusted. Break out immediately!
|
||||||
|
@ -609,12 +601,11 @@ namespace {
|
||||||
stopSearch = true;
|
stopSearch = true;
|
||||||
|
|
||||||
// Stop search early if one move seems to be much better than the others
|
// Stop search early if one move seems to be much better than the others
|
||||||
int64_t nodes = ThreadsMgr.nodes_searched();
|
|
||||||
if ( Iteration >= 8
|
if ( Iteration >= 8
|
||||||
&& EasyMove == pv[0]
|
&& EasyMove == pv[0]
|
||||||
&& ( ( rml.move_nodes(0) > (nodes * 85) / 100
|
&& ( ( rml.move_nodes(0) > (pos.nodes_searched() * 85) / 100
|
||||||
&& current_search_time() > TimeMgr.available_time() / 16)
|
&& current_search_time() > TimeMgr.available_time() / 16)
|
||||||
||( rml.move_nodes(0) > (nodes * 98) / 100
|
||( rml.move_nodes(0) > (pos.nodes_searched() * 98) / 100
|
||||||
&& current_search_time() > TimeMgr.available_time() / 32)))
|
&& current_search_time() > TimeMgr.available_time() / 32)))
|
||||||
stopSearch = true;
|
stopSearch = true;
|
||||||
|
|
||||||
|
@ -648,8 +639,8 @@ namespace {
|
||||||
wait_for_stop_or_ponderhit();
|
wait_for_stop_or_ponderhit();
|
||||||
else
|
else
|
||||||
// Print final search statistics
|
// Print final search statistics
|
||||||
cout << "info nodes " << ThreadsMgr.nodes_searched()
|
cout << "info nodes " << pos.nodes_searched()
|
||||||
<< " nps " << nps()
|
<< " nps " << nps(pos)
|
||||||
<< " time " << current_search_time() << endl;
|
<< " time " << current_search_time() << endl;
|
||||||
|
|
||||||
// Print the best move and the ponder move to the standard output
|
// Print the best move and the ponder move to the standard output
|
||||||
|
@ -676,14 +667,14 @@ namespace {
|
||||||
if (dbg_show_hit_rate)
|
if (dbg_show_hit_rate)
|
||||||
dbg_print_hit_rate(LogFile);
|
dbg_print_hit_rate(LogFile);
|
||||||
|
|
||||||
LogFile << "\nNodes: " << ThreadsMgr.nodes_searched()
|
LogFile << "\nNodes: " << pos.nodes_searched()
|
||||||
<< "\nNodes/second: " << nps()
|
<< "\nNodes/second: " << nps(pos)
|
||||||
<< "\nBest move: " << move_to_san(p, pv[0]);
|
<< "\nBest move: " << move_to_san(pos, pv[0]);
|
||||||
|
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
p.do_move(pv[0], st);
|
pos.do_move(pv[0], st);
|
||||||
LogFile << "\nPonder move: "
|
LogFile << "\nPonder move: "
|
||||||
<< move_to_san(p, pv[1]) // Works also with MOVE_NONE
|
<< move_to_san(pos, pv[1]) // Works also with MOVE_NONE
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
return rml.move_score(0);
|
return rml.move_score(0);
|
||||||
|
@ -745,7 +736,7 @@ namespace {
|
||||||
FirstRootMove = (i == 0);
|
FirstRootMove = (i == 0);
|
||||||
|
|
||||||
// Save the current node count before the move is searched
|
// Save the current node count before the move is searched
|
||||||
nodes = ThreadsMgr.nodes_searched();
|
nodes = pos.nodes_searched();
|
||||||
|
|
||||||
// Pick the next root move, and print the move and the move number to
|
// Pick the next root move, and print the move and the move number to
|
||||||
// the standard output.
|
// the standard output.
|
||||||
|
@ -866,7 +857,7 @@ namespace {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Remember searched nodes counts for this move
|
// Remember searched nodes counts for this move
|
||||||
rml.add_move_nodes(i, ThreadsMgr.nodes_searched() - nodes);
|
rml.add_move_nodes(i, pos.nodes_searched() - nodes);
|
||||||
|
|
||||||
assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE);
|
assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE);
|
||||||
assert(value < beta);
|
assert(value < beta);
|
||||||
|
@ -908,8 +899,8 @@ namespace {
|
||||||
<< " score " << value_to_uci(rml.move_score(j))
|
<< " score " << value_to_uci(rml.move_score(j))
|
||||||
<< " depth " << (j <= i ? Iteration : Iteration - 1)
|
<< " depth " << (j <= i ? Iteration : Iteration - 1)
|
||||||
<< " time " << current_search_time()
|
<< " time " << current_search_time()
|
||||||
<< " nodes " << ThreadsMgr.nodes_searched()
|
<< " nodes " << pos.nodes_searched()
|
||||||
<< " nps " << nps()
|
<< " nps " << nps(pos)
|
||||||
<< " pv ";
|
<< " pv ";
|
||||||
|
|
||||||
for (int k = 0; rml.move_pv(j, k) != MOVE_NONE && k < PLY_MAX; k++)
|
for (int k = 0; rml.move_pv(j, k) != MOVE_NONE && k < PLY_MAX; k++)
|
||||||
|
@ -991,14 +982,13 @@ namespace {
|
||||||
} else {} // Hack to fix icc's "statement is unreachable" warning
|
} else {} // Hack to fix icc's "statement is unreachable" warning
|
||||||
|
|
||||||
// Step 1. Initialize node and poll. Polling can abort search
|
// Step 1. Initialize node and poll. Polling can abort search
|
||||||
ThreadsMgr.incrementNodeCounter(threadID);
|
|
||||||
ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
|
ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
|
||||||
(ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE;
|
(ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE;
|
||||||
|
|
||||||
if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls)
|
if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls)
|
||||||
{
|
{
|
||||||
NodesSincePoll = 0;
|
NodesSincePoll = 0;
|
||||||
poll();
|
poll(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2. Check for aborted search and immediate draw
|
// Step 2. Check for aborted search and immediate draw
|
||||||
|
@ -1426,6 +1416,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
{
|
{
|
||||||
// Here we have the lock still grabbed
|
// Here we have the lock still grabbed
|
||||||
sp->slaves[threadID] = 0;
|
sp->slaves[threadID] = 0;
|
||||||
|
sp->nodes += pos.nodes_searched();
|
||||||
lock_release(&(sp->lock));
|
lock_release(&(sp->lock));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,7 +1447,6 @@ split_point_start: // At split points actual search starts from here
|
||||||
const TTEntry* tte;
|
const TTEntry* tte;
|
||||||
Value oldAlpha = alpha;
|
Value oldAlpha = alpha;
|
||||||
|
|
||||||
ThreadsMgr.incrementNodeCounter(pos.thread());
|
|
||||||
ss->bestMove = ss->currentMove = MOVE_NONE;
|
ss->bestMove = ss->currentMove = MOVE_NONE;
|
||||||
|
|
||||||
// Check for an instant draw or maximum ply reached
|
// Check for an instant draw or maximum ply reached
|
||||||
|
@ -1917,10 +1907,10 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
// nps() computes the current nodes/second count.
|
// nps() computes the current nodes/second count.
|
||||||
|
|
||||||
int nps() {
|
int nps(const Position& pos) {
|
||||||
|
|
||||||
int t = current_search_time();
|
int t = current_search_time();
|
||||||
return (t > 0 ? int((ThreadsMgr.nodes_searched() * 1000) / t) : 0);
|
return (t > 0 ? int((pos.nodes_searched() * 1000) / t) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1928,7 +1918,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
// looks at the time consumed so far and decides if it's time to abort the
|
// looks at the time consumed so far and decides if it's time to abort the
|
||||||
// search.
|
// search.
|
||||||
|
|
||||||
void poll() {
|
void poll(const Position& pos) {
|
||||||
|
|
||||||
static int lastInfoTime;
|
static int lastInfoTime;
|
||||||
int t = current_search_time();
|
int t = current_search_time();
|
||||||
|
@ -1977,7 +1967,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
if (dbg_show_hit_rate)
|
if (dbg_show_hit_rate)
|
||||||
dbg_print_hit_rate();
|
dbg_print_hit_rate();
|
||||||
|
|
||||||
cout << "info nodes " << ThreadsMgr.nodes_searched() << " nps " << nps()
|
cout << "info nodes " << pos.nodes_searched() << " nps " << nps(pos)
|
||||||
<< " time " << t << endl;
|
<< " time " << t << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1994,7 +1984,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
if ( (Iteration >= 3 && UseTimeManagement && noMoreTime)
|
if ( (Iteration >= 3 && UseTimeManagement && noMoreTime)
|
||||||
|| (ExactMaxTime && t >= ExactMaxTime)
|
|| (ExactMaxTime && t >= ExactMaxTime)
|
||||||
|| (Iteration >= 3 && MaxNodes && ThreadsMgr.nodes_searched() >= MaxNodes))
|
|| (Iteration >= 3 && MaxNodes && pos.nodes_searched() >= MaxNodes))
|
||||||
AbortSearch = true;
|
AbortSearch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2074,8 +2064,8 @@ split_point_start: // At split points actual search starts from here
|
||||||
<< " score " << value_to_uci(value)
|
<< " score " << value_to_uci(value)
|
||||||
<< (value >= beta ? " lowerbound" : value <= alpha ? " upperbound" : "")
|
<< (value >= beta ? " lowerbound" : value <= alpha ? " upperbound" : "")
|
||||||
<< " time " << current_search_time()
|
<< " time " << current_search_time()
|
||||||
<< " nodes " << ThreadsMgr.nodes_searched()
|
<< " nodes " << pos.nodes_searched()
|
||||||
<< " nps " << nps()
|
<< " nps " << nps(pos)
|
||||||
<< " pv ";
|
<< " pv ";
|
||||||
|
|
||||||
for (Move* m = pv; *m != MOVE_NONE; m++)
|
for (Move* m = pv; *m != MOVE_NONE; m++)
|
||||||
|
@ -2088,8 +2078,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
ValueType t = value >= beta ? VALUE_TYPE_LOWER :
|
ValueType t = value >= beta ? VALUE_TYPE_LOWER :
|
||||||
value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT;
|
value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT;
|
||||||
|
|
||||||
LogFile << pretty_pv(pos, current_search_time(), Iteration,
|
LogFile << pretty_pv(pos, current_search_time(), Iteration, value, t, pv) << endl;
|
||||||
ThreadsMgr.nodes_searched(), value, t, pv) << endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2174,25 +2163,6 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
/// The ThreadsManager class
|
/// The ThreadsManager class
|
||||||
|
|
||||||
// resetNodeCounters(), resetBetaCounters(), searched_nodes() and
|
|
||||||
// get_beta_counters() are getters/setters for the per thread
|
|
||||||
// counters used to sort the moves at root.
|
|
||||||
|
|
||||||
void ThreadsManager::resetNodeCounters() {
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_THREADS; i++)
|
|
||||||
threads[i].nodes = 0ULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t ThreadsManager::nodes_searched() const {
|
|
||||||
|
|
||||||
int64_t result = 0ULL;
|
|
||||||
for (int i = 0; i < ActiveThreads; i++)
|
|
||||||
result += threads[i].nodes;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// idle_loop() is where the threads are parked when they have no work to do.
|
// idle_loop() is where the threads are parked when they have no work to do.
|
||||||
// The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
|
// The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
|
||||||
|
@ -2446,20 +2416,20 @@ split_point_start: // At split points actual search starts from here
|
||||||
// call search().When all threads have returned from search() then split() returns.
|
// call search().When all threads have returned from search() then split() returns.
|
||||||
|
|
||||||
template <bool Fake>
|
template <bool Fake>
|
||||||
void ThreadsManager::split(const Position& p, SearchStack* ss, int ply, Value* alpha,
|
void ThreadsManager::split(Position& pos, SearchStack* ss, int ply, Value* alpha,
|
||||||
const Value beta, Value* bestValue, Depth depth, Move threatMove,
|
const Value beta, Value* bestValue, Depth depth, Move threatMove,
|
||||||
bool mateThreat, int moveCount, MovePicker* mp, bool pvNode) {
|
bool mateThreat, int moveCount, MovePicker* mp, bool pvNode) {
|
||||||
assert(p.is_ok());
|
assert(pos.is_ok());
|
||||||
assert(ply > 0 && ply < PLY_MAX);
|
assert(ply > 0 && ply < PLY_MAX);
|
||||||
assert(*bestValue >= -VALUE_INFINITE);
|
assert(*bestValue >= -VALUE_INFINITE);
|
||||||
assert(*bestValue <= *alpha);
|
assert(*bestValue <= *alpha);
|
||||||
assert(*alpha < beta);
|
assert(*alpha < beta);
|
||||||
assert(beta <= VALUE_INFINITE);
|
assert(beta <= VALUE_INFINITE);
|
||||||
assert(depth > DEPTH_ZERO);
|
assert(depth > DEPTH_ZERO);
|
||||||
assert(p.thread() >= 0 && p.thread() < ActiveThreads);
|
assert(pos.thread() >= 0 && pos.thread() < ActiveThreads);
|
||||||
assert(ActiveThreads > 1);
|
assert(ActiveThreads > 1);
|
||||||
|
|
||||||
int i, master = p.thread();
|
int i, master = pos.thread();
|
||||||
Thread& masterThread = threads[master];
|
Thread& masterThread = threads[master];
|
||||||
|
|
||||||
lock_grab(&MPLock);
|
lock_grab(&MPLock);
|
||||||
|
@ -2489,7 +2459,8 @@ split_point_start: // At split points actual search starts from here
|
||||||
splitPoint.bestValue = *bestValue;
|
splitPoint.bestValue = *bestValue;
|
||||||
splitPoint.mp = mp;
|
splitPoint.mp = mp;
|
||||||
splitPoint.moveCount = moveCount;
|
splitPoint.moveCount = moveCount;
|
||||||
splitPoint.pos = &p;
|
splitPoint.pos = &pos;
|
||||||
|
splitPoint.nodes = 0;
|
||||||
splitPoint.parentSstack = ss;
|
splitPoint.parentSstack = ss;
|
||||||
for (i = 0; i < ActiveThreads; i++)
|
for (i = 0; i < ActiveThreads; i++)
|
||||||
splitPoint.slaves[i] = 0;
|
splitPoint.slaves[i] = 0;
|
||||||
|
@ -2545,6 +2516,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
*bestValue = splitPoint.bestValue;
|
*bestValue = splitPoint.bestValue;
|
||||||
masterThread.activeSplitPoints--;
|
masterThread.activeSplitPoints--;
|
||||||
masterThread.splitPoint = splitPoint.parent;
|
masterThread.splitPoint = splitPoint.parent;
|
||||||
|
pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes);
|
||||||
|
|
||||||
lock_release(&MPLock);
|
lock_release(&MPLock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,7 @@ extern void init_search();
|
||||||
extern void init_threads();
|
extern void init_threads();
|
||||||
extern void exit_threads();
|
extern void exit_threads();
|
||||||
extern int perft(Position& pos, Depth depth);
|
extern int perft(Position& pos, Depth depth);
|
||||||
extern int64_t nodes_searched();
|
extern bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[],
|
||||||
extern bool think(const Position& pos, bool infinite, bool ponder, int time[], int increment[],
|
|
||||||
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]);
|
int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]);
|
||||||
|
|
||||||
#endif // !defined(SEARCH_H_INCLUDED)
|
#endif // !defined(SEARCH_H_INCLUDED)
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct SplitPoint {
|
||||||
|
|
||||||
// Shared data
|
// Shared data
|
||||||
Lock lock;
|
Lock lock;
|
||||||
|
volatile int64_t nodes;
|
||||||
volatile Value alpha;
|
volatile Value alpha;
|
||||||
volatile Value bestValue;
|
volatile Value bestValue;
|
||||||
volatile int moveCount;
|
volatile int moveCount;
|
||||||
|
@ -84,7 +85,6 @@ enum ThreadState
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Thread {
|
struct Thread {
|
||||||
uint64_t nodes;
|
|
||||||
volatile ThreadState state;
|
volatile ThreadState state;
|
||||||
SplitPoint* volatile splitPoint;
|
SplitPoint* volatile splitPoint;
|
||||||
volatile int activeSplitPoints;
|
volatile int activeSplitPoints;
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace {
|
||||||
// The root position. This is set up when the user (or in practice, the GUI)
|
// The root position. This is set up when the user (or in practice, the GUI)
|
||||||
// sends the "position" UCI command. The root position is sent to the think()
|
// sends the "position" UCI command. The root position is sent to the think()
|
||||||
// function when the program receives the "go" command.
|
// function when the program receives the "go" command.
|
||||||
Position RootPosition(0);
|
Position RootPosition(StartPositionFEN, 0);
|
||||||
|
|
||||||
// Local functions
|
// Local functions
|
||||||
bool handle_command(const string& command);
|
bool handle_command(const string& command);
|
||||||
|
@ -82,7 +82,6 @@ namespace {
|
||||||
|
|
||||||
void uci_main_loop() {
|
void uci_main_loop() {
|
||||||
|
|
||||||
RootPosition.from_fen(StartPositionFEN);
|
|
||||||
string command;
|
string command;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -312,14 +311,13 @@ namespace {
|
||||||
|
|
||||||
string token;
|
string token;
|
||||||
int depth, tm, n;
|
int depth, tm, n;
|
||||||
Position pos(RootPosition, RootPosition.thread());
|
|
||||||
|
|
||||||
if (!(uip >> depth))
|
if (!(uip >> depth))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tm = get_system_time();
|
tm = get_system_time();
|
||||||
|
|
||||||
n = perft(pos, depth * ONE_PLY);
|
n = perft(RootPosition, depth * ONE_PLY);
|
||||||
|
|
||||||
tm = get_system_time() - tm;
|
tm = get_system_time() - tm;
|
||||||
std::cout << "\nNodes " << n
|
std::cout << "\nNodes " << n
|
||||||
|
|
Loading…
Add table
Reference in a new issue