1
0
Fork 0
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:
Marco Costalba 2010-10-31 10:55:28 +01:00
parent 49a6fee4fa
commit d74025a34e
9 changed files with 68 additions and 89 deletions

View file

@ -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();
} }
} }

View file

@ -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);

View file

@ -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];
} }

View file

@ -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);

View file

@ -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)

View file

@ -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);
} }

View file

@ -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)

View file

@ -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;

View file

@ -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