mirror of
https://github.com/sockspls/badfish
synced 2025-07-11 19:49:14 +00:00
Use a Thread instead of an array index
No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
0439a79566
commit
673bc5526f
9 changed files with 76 additions and 82 deletions
|
@ -107,7 +107,7 @@ void benchmark(istringstream& is) {
|
||||||
|
|
||||||
for (size_t i = 0; i < fens.size(); i++)
|
for (size_t i = 0; i < fens.size(); i++)
|
||||||
{
|
{
|
||||||
Position pos(fens[i], false, 0);
|
Position pos(fens[i], false, NULL);
|
||||||
|
|
||||||
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
|
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace {
|
||||||
string fen = sides[0] + char('0' + int(8 - code.length()))
|
string fen = sides[0] + char('0' + int(8 - code.length()))
|
||||||
+ sides[1] + "/8/8/8/8/8/8/8 w - - 0 10";
|
+ sides[1] + "/8/8/8/8/8/8/8 w - - 0 10";
|
||||||
|
|
||||||
return Position(fen, false, 0).material_key();
|
return Position(fen, false, NULL).material_key();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename M>
|
template<typename M>
|
||||||
|
|
|
@ -371,7 +371,7 @@ Value do_evaluate(const Position& pos, Value& margin) {
|
||||||
margins[WHITE] = margins[BLACK] = VALUE_ZERO;
|
margins[WHITE] = margins[BLACK] = VALUE_ZERO;
|
||||||
|
|
||||||
// Probe the material hash table
|
// Probe the material hash table
|
||||||
ei.mi = Threads[pos.this_thread()].materialTable.probe(pos);
|
ei.mi = pos.this_thread().materialTable.probe(pos);
|
||||||
score += ei.mi->material_value();
|
score += ei.mi->material_value();
|
||||||
|
|
||||||
// If we have a specialized evaluation function for the current material
|
// If we have a specialized evaluation function for the current material
|
||||||
|
@ -383,7 +383,7 @@ Value do_evaluate(const Position& pos, Value& margin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probe the pawn hash table
|
// Probe the pawn hash table
|
||||||
ei.pi = Threads[pos.this_thread()].pawnTable.probe(pos);
|
ei.pi = pos.this_thread().pawnTable.probe(pos);
|
||||||
score += ei.pi->pawns_value();
|
score += ei.pi->pawns_value();
|
||||||
|
|
||||||
// Initialize attack and king safety bitboards
|
// Initialize attack and king safety bitboards
|
||||||
|
|
|
@ -92,33 +92,27 @@ CheckInfo::CheckInfo(const Position& pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Position c'tors. Here we always create a copy of the original position
|
/// Position::copy() creates a copy of 'pos'. We want the new born Position
|
||||||
/// or the FEN string, we want the new born Position object do not depend
|
/// object do not depend on any external data so we detach state pointer from
|
||||||
/// on any external data so we detach state pointer from the source one.
|
/// the source one.
|
||||||
|
|
||||||
void Position::copy(const Position& pos, int th) {
|
void Position::copy(const Position& pos, Thread* th) {
|
||||||
|
|
||||||
memcpy(this, &pos, sizeof(Position));
|
memcpy(this, &pos, sizeof(Position));
|
||||||
startState = *st;
|
startState = *st;
|
||||||
st = &startState;
|
st = &startState;
|
||||||
threadID = th;
|
thisThread = th;
|
||||||
nodes = 0;
|
nodes = 0;
|
||||||
|
|
||||||
assert(pos_is_ok());
|
assert(pos_is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
Position::Position(const string& fen, bool isChess960, int th) {
|
|
||||||
|
|
||||||
from_fen(fen, isChess960);
|
|
||||||
threadID = th;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Position::from_fen() initializes the position object with the given FEN
|
/// Position::from_fen() initializes the position object with the given FEN
|
||||||
/// string. This function is not very robust - make sure that input FENs are
|
/// string. This function is not very robust - make sure that input FENs are
|
||||||
/// correct (this is assumed to be the responsibility of the GUI).
|
/// correct (this is assumed to be the responsibility of the GUI).
|
||||||
|
|
||||||
void Position::from_fen(const string& fenStr, bool isChess960) {
|
void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) {
|
||||||
/*
|
/*
|
||||||
A FEN string defines a particular position using only the ASCII character set.
|
A FEN string defines a particular position using only the ASCII character set.
|
||||||
|
|
||||||
|
@ -234,6 +228,7 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
|
||||||
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||||
st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
|
st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
|
||||||
chess960 = isChess960;
|
chess960 = isChess960;
|
||||||
|
thisThread = th;
|
||||||
|
|
||||||
assert(pos_is_ok());
|
assert(pos_is_ok());
|
||||||
}
|
}
|
||||||
|
@ -336,7 +331,7 @@ void Position::print(Move move) const {
|
||||||
|
|
||||||
if (move)
|
if (move)
|
||||||
{
|
{
|
||||||
Position p(*this, this_thread());
|
Position p(*this, thisThread);
|
||||||
cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move);
|
cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,8 +898,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefetch pawn and material hash tables
|
// Prefetch pawn and material hash tables
|
||||||
prefetch((char*)Threads[threadID].pawnTable.entries[st->pawnKey]);
|
prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]);
|
||||||
prefetch((char*)Threads[threadID].materialTable.entries[st->materialKey]);
|
prefetch((char*)thisThread->materialTable.entries[st->materialKey]);
|
||||||
|
|
||||||
// Update incremental scores
|
// Update incremental scores
|
||||||
st->psqScore += psq_delta(piece, from, to);
|
st->psqScore += psq_delta(piece, from, to);
|
||||||
|
@ -1546,10 +1541,10 @@ void Position::init() {
|
||||||
void Position::flip() {
|
void Position::flip() {
|
||||||
|
|
||||||
// Make a copy of current position before to start changing
|
// Make a copy of current position before to start changing
|
||||||
const Position pos(*this, threadID);
|
const Position pos(*this, thisThread);
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
threadID = pos.this_thread();
|
thisThread = &pos.this_thread();
|
||||||
|
|
||||||
// Board
|
// Board
|
||||||
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
for (Square s = SQ_A1; s <= SQ_H8; s++)
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
/// The checkInfo struct is initialized at c'tor time and keeps info used
|
/// The checkInfo struct is initialized at c'tor time and keeps info used
|
||||||
/// to detect if a move gives check.
|
/// to detect if a move gives check.
|
||||||
class Position;
|
class Position;
|
||||||
|
class Thread;
|
||||||
|
|
||||||
struct CheckInfo {
|
struct CheckInfo {
|
||||||
|
|
||||||
|
@ -90,12 +91,12 @@ class Position {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Position() {}
|
Position() {}
|
||||||
Position(const Position& pos, int th) { copy(pos, th); }
|
Position(const Position& p, Thread* t) { copy(p, t); }
|
||||||
Position(const std::string& fen, bool isChess960, int th);
|
Position(const std::string& f, bool c960, Thread* t) { from_fen(f, c960, t); }
|
||||||
|
|
||||||
// Text input/output
|
// Text input/output
|
||||||
void copy(const Position& pos, int th);
|
void copy(const Position& pos, Thread* th);
|
||||||
void from_fen(const std::string& fen, bool isChess960);
|
void from_fen(const std::string& fen, bool isChess960, Thread* th);
|
||||||
const std::string to_fen() const;
|
const std::string to_fen() const;
|
||||||
void print(Move m = MOVE_NONE) const;
|
void print(Move m = MOVE_NONE) const;
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ public:
|
||||||
Color side_to_move() const;
|
Color side_to_move() const;
|
||||||
int startpos_ply_counter() const;
|
int startpos_ply_counter() const;
|
||||||
bool is_chess960() const;
|
bool is_chess960() const;
|
||||||
int this_thread() const;
|
Thread& this_thread() const;
|
||||||
int64_t nodes_searched() const;
|
int64_t nodes_searched() const;
|
||||||
void set_nodes_searched(int64_t n);
|
void set_nodes_searched(int64_t n);
|
||||||
template<bool SkipRepetition> bool is_draw() const;
|
template<bool SkipRepetition> bool is_draw() const;
|
||||||
|
@ -223,7 +224,7 @@ private:
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
int startPosPly;
|
int startPosPly;
|
||||||
Color sideToMove;
|
Color sideToMove;
|
||||||
int threadID;
|
Thread* thisThread;
|
||||||
StateInfo* st;
|
StateInfo* st;
|
||||||
int chess960;
|
int chess960;
|
||||||
|
|
||||||
|
@ -433,8 +434,8 @@ inline PieceType Position::captured_piece_type() const {
|
||||||
return st->capturedType;
|
return st->capturedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Position::this_thread() const {
|
inline Thread& Position::this_thread() const {
|
||||||
return threadID;
|
return *thisThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(POSITION_H_INCLUDED)
|
#endif // !defined(POSITION_H_INCLUDED)
|
||||||
|
|
|
@ -332,7 +332,7 @@ finalize:
|
||||||
// but if we are pondering or in infinite search, we shouldn't print the best
|
// but if we are pondering or in infinite search, we shouldn't print the best
|
||||||
// move before we are told to do so.
|
// move before we are told to do so.
|
||||||
if (!Signals.stop && (Limits.ponder || Limits.infinite))
|
if (!Signals.stop && (Limits.ponder || Limits.infinite))
|
||||||
Threads[pos.this_thread()].wait_for_stop_or_ponderhit();
|
pos.this_thread().wait_for_stop_or_ponderhit();
|
||||||
|
|
||||||
// Best move could be MOVE_NONE when searching on a stalemate position
|
// Best move could be MOVE_NONE when searching on a stalemate position
|
||||||
cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960)
|
cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960)
|
||||||
|
@ -530,7 +530,6 @@ namespace {
|
||||||
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
|
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
|
||||||
assert((alpha == beta - 1) || PvNode);
|
assert((alpha == beta - 1) || PvNode);
|
||||||
assert(depth > DEPTH_ZERO);
|
assert(depth > DEPTH_ZERO);
|
||||||
assert(pos.this_thread() >= 0 && pos.this_thread() < Threads.size());
|
|
||||||
|
|
||||||
Move movesSearched[MAX_MOVES];
|
Move movesSearched[MAX_MOVES];
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
|
@ -544,7 +543,7 @@ namespace {
|
||||||
bool isPvMove, inCheck, singularExtensionNode, givesCheck;
|
bool isPvMove, inCheck, singularExtensionNode, givesCheck;
|
||||||
bool captureOrPromotion, dangerous, doFullDepthSearch;
|
bool captureOrPromotion, dangerous, doFullDepthSearch;
|
||||||
int moveCount = 0, playedMoveCount = 0;
|
int moveCount = 0, playedMoveCount = 0;
|
||||||
Thread& thread = Threads[pos.this_thread()];
|
Thread& thread = pos.this_thread();
|
||||||
SplitPoint* sp = NULL;
|
SplitPoint* sp = NULL;
|
||||||
|
|
||||||
refinedValue = bestValue = value = -VALUE_INFINITE;
|
refinedValue = bestValue = value = -VALUE_INFINITE;
|
||||||
|
@ -847,7 +846,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
{
|
{
|
||||||
Signals.firstRootMove = (moveCount == 1);
|
Signals.firstRootMove = (moveCount == 1);
|
||||||
|
|
||||||
if (pos.this_thread() == 0 && SearchTime.elapsed() > 2000)
|
if (&thread == Threads.main_thread() && SearchTime.elapsed() > 2000)
|
||||||
cout << "info depth " << depth / ONE_PLY
|
cout << "info depth " << depth / ONE_PLY
|
||||||
<< " currmove " << move_to_uci(move, Chess960)
|
<< " currmove " << move_to_uci(move, Chess960)
|
||||||
<< " currmovenumber " << moveCount + PVIdx << endl;
|
<< " currmovenumber " << moveCount + PVIdx << endl;
|
||||||
|
@ -1054,7 +1053,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
if ( !SpNode
|
if ( !SpNode
|
||||||
&& depth >= Threads.min_split_depth()
|
&& depth >= Threads.min_split_depth()
|
||||||
&& bestValue < beta
|
&& bestValue < beta
|
||||||
&& Threads.available_slave_exists(pos.this_thread())
|
&& Threads.available_slave_exists(thread)
|
||||||
&& !Signals.stop
|
&& !Signals.stop
|
||||||
&& !thread.cutoff_occurred())
|
&& !thread.cutoff_occurred())
|
||||||
bestValue = Threads.split<FakeSplit>(pos, ss, alpha, beta, bestValue, &bestMove,
|
bestValue = Threads.split<FakeSplit>(pos, ss, alpha, beta, bestValue, &bestMove,
|
||||||
|
@ -1131,7 +1130,6 @@ split_point_start: // At split points actual search starts from here
|
||||||
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
|
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
|
||||||
assert((alpha == beta - 1) || PvNode);
|
assert((alpha == beta - 1) || PvNode);
|
||||||
assert(depth <= DEPTH_ZERO);
|
assert(depth <= DEPTH_ZERO);
|
||||||
assert(pos.this_thread() >= 0 && pos.this_thread() < Threads.size());
|
|
||||||
|
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
Move ttMove, move, bestMove;
|
Move ttMove, move, bestMove;
|
||||||
|
@ -1827,8 +1825,8 @@ void Thread::idle_loop(SplitPoint* sp_master) {
|
||||||
lock_release(Threads.splitLock);
|
lock_release(Threads.splitLock);
|
||||||
|
|
||||||
Stack ss[MAX_PLY_PLUS_2];
|
Stack ss[MAX_PLY_PLUS_2];
|
||||||
Position pos(*sp->pos, threadID);
|
Position pos(*sp->pos, this);
|
||||||
int master = sp->master;
|
Thread* master = sp->master;
|
||||||
|
|
||||||
memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
|
memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
|
||||||
(ss+1)->sp = sp;
|
(ss+1)->sp = sp;
|
||||||
|
@ -1847,7 +1845,7 @@ void Thread::idle_loop(SplitPoint* sp_master) {
|
||||||
assert(is_searching);
|
assert(is_searching);
|
||||||
|
|
||||||
is_searching = false;
|
is_searching = false;
|
||||||
sp->slavesMask &= ~(1ULL << threadID);
|
sp->slavesMask &= ~(1ULL << idx);
|
||||||
sp->nodes += pos.nodes_searched();
|
sp->nodes += pos.nodes_searched();
|
||||||
|
|
||||||
// After releasing the lock we cannot access anymore any SplitPoint
|
// After releasing the lock we cannot access anymore any SplitPoint
|
||||||
|
@ -1858,9 +1856,9 @@ void Thread::idle_loop(SplitPoint* sp_master) {
|
||||||
// Wake up master thread so to allow it to return from the idle loop in
|
// Wake up master thread so to allow it to return from the idle loop in
|
||||||
// case we are the last slave of the split point.
|
// case we are the last slave of the split point.
|
||||||
if ( Threads.use_sleeping_threads()
|
if ( Threads.use_sleeping_threads()
|
||||||
&& threadID != master
|
&& this != master
|
||||||
&& !Threads[master].is_searching)
|
&& !master->is_searching)
|
||||||
Threads[master].wake_up();
|
master->wake_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ Thread::Thread(Fn fn) {
|
||||||
maxPly = splitPointsCnt = 0;
|
maxPly = splitPointsCnt = 0;
|
||||||
curSplitPoint = NULL;
|
curSplitPoint = NULL;
|
||||||
start_fn = fn;
|
start_fn = fn;
|
||||||
threadID = Threads.size();
|
idx = Threads.size();
|
||||||
|
|
||||||
do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_searching()
|
do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_searching()
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ Thread::Thread(Fn fn) {
|
||||||
|
|
||||||
if (!thread_create(handle, start_routine, this))
|
if (!thread_create(handle, start_routine, this))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to create thread number " << threadID << std::endl;
|
std::cerr << "Failed to create thread number " << idx << std::endl;
|
||||||
::exit(EXIT_FAILURE);
|
::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,13 +173,13 @@ bool Thread::cutoff_occurred() const {
|
||||||
|
|
||||||
|
|
||||||
// Thread::is_available_to() checks whether the thread is available to help the
|
// Thread::is_available_to() checks whether the thread is available to help the
|
||||||
// thread with threadID "master" at a split point. An obvious requirement is that
|
// thread 'master' at a split point. An obvious requirement is that thread must
|
||||||
// thread must be idle. With more than two threads, this is not sufficient: If
|
// be idle. With more than two threads, this is not sufficient: If the thread is
|
||||||
// the thread is the master of some active split point, it is only available as a
|
// the master of some active split point, it is only available as a slave to the
|
||||||
// slave to the threads which are busy searching the split point at the top of
|
// slaves which are busy searching the split point at the top of slaves split
|
||||||
// "slave"'s split point stack (the "helpful master concept" in YBWC terminology).
|
// point stack (the "helpful master concept" in YBWC terminology).
|
||||||
|
|
||||||
bool Thread::is_available_to(int master) const {
|
bool Thread::is_available_to(const Thread& master) const {
|
||||||
|
|
||||||
if (is_searching)
|
if (is_searching)
|
||||||
return false;
|
return false;
|
||||||
|
@ -190,7 +190,7 @@ bool Thread::is_available_to(int master) const {
|
||||||
|
|
||||||
// No active split points means that the thread is available as a slave for any
|
// No active split points means that the thread is available as a slave for any
|
||||||
// other thread otherwise apply the "helpful master" concept if possible.
|
// other thread otherwise apply the "helpful master" concept if possible.
|
||||||
return !spCnt || (splitPoints[spCnt - 1].slavesMask & (1ULL << master));
|
return !spCnt || (splitPoints[spCnt - 1].slavesMask & (1ULL << master.idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,11 +275,9 @@ void ThreadsManager::sleep() const {
|
||||||
|
|
||||||
|
|
||||||
// available_slave_exists() tries to find an idle thread which is available as
|
// available_slave_exists() tries to find an idle thread which is available as
|
||||||
// a slave for the thread with threadID 'master'.
|
// a slave for the thread 'master'.
|
||||||
|
|
||||||
bool ThreadsManager::available_slave_exists(int master) const {
|
bool ThreadsManager::available_slave_exists(const Thread& master) const {
|
||||||
|
|
||||||
assert(master >= 0 && master < size());
|
|
||||||
|
|
||||||
for (int i = 0; i < size(); i++)
|
for (int i = 0; i < size(); i++)
|
||||||
if (threads[i]->is_available_to(master))
|
if (threads[i]->is_available_to(master))
|
||||||
|
@ -309,19 +307,18 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
assert(beta <= VALUE_INFINITE);
|
assert(beta <= VALUE_INFINITE);
|
||||||
assert(depth > DEPTH_ZERO);
|
assert(depth > DEPTH_ZERO);
|
||||||
|
|
||||||
int master = pos.this_thread();
|
Thread& master = pos.this_thread();
|
||||||
Thread& masterThread = *threads[master];
|
|
||||||
|
|
||||||
if (masterThread.splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD)
|
if (master.splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD)
|
||||||
return bestValue;
|
return bestValue;
|
||||||
|
|
||||||
// Pick the next available split point from the split point stack
|
// Pick the next available split point from the split point stack
|
||||||
SplitPoint* sp = &masterThread.splitPoints[masterThread.splitPointsCnt++];
|
SplitPoint* sp = &master.splitPoints[master.splitPointsCnt++];
|
||||||
|
|
||||||
sp->parent = masterThread.curSplitPoint;
|
sp->parent = master.curSplitPoint;
|
||||||
sp->master = master;
|
sp->master = &master;
|
||||||
sp->cutoff = false;
|
sp->cutoff = false;
|
||||||
sp->slavesMask = 1ULL << master;
|
sp->slavesMask = 1ULL << master.idx;
|
||||||
sp->depth = depth;
|
sp->depth = depth;
|
||||||
sp->bestMove = *bestMove;
|
sp->bestMove = *bestMove;
|
||||||
sp->threatMove = threatMove;
|
sp->threatMove = threatMove;
|
||||||
|
@ -335,9 +332,9 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
sp->nodes = 0;
|
sp->nodes = 0;
|
||||||
sp->ss = ss;
|
sp->ss = ss;
|
||||||
|
|
||||||
assert(masterThread.is_searching);
|
assert(master.is_searching);
|
||||||
|
|
||||||
masterThread.curSplitPoint = sp;
|
master.curSplitPoint = sp;
|
||||||
int slavesCnt = 0;
|
int slavesCnt = 0;
|
||||||
|
|
||||||
// Try to allocate available threads and ask them to start searching setting
|
// Try to allocate available threads and ask them to start searching setting
|
||||||
|
@ -370,11 +367,11 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
// their work at this split point.
|
// their work at this split point.
|
||||||
if (slavesCnt || Fake)
|
if (slavesCnt || Fake)
|
||||||
{
|
{
|
||||||
masterThread.idle_loop(sp);
|
master.idle_loop(sp);
|
||||||
|
|
||||||
// In helpful master concept a master can help only a sub-tree of its split
|
// In helpful master concept a master can help only a sub-tree of its split
|
||||||
// point, and because here is all finished is not possible master is booked.
|
// point, and because here is all finished is not possible master is booked.
|
||||||
assert(!masterThread.is_searching);
|
assert(!master.is_searching);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have returned from the idle loop, which means that all threads are
|
// We have returned from the idle loop, which means that all threads are
|
||||||
|
@ -383,9 +380,9 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
lock_grab(sp->lock); // To protect sp->nodes
|
lock_grab(sp->lock); // To protect sp->nodes
|
||||||
lock_grab(splitLock);
|
lock_grab(splitLock);
|
||||||
|
|
||||||
masterThread.is_searching = true;
|
master.is_searching = true;
|
||||||
masterThread.splitPointsCnt--;
|
master.splitPointsCnt--;
|
||||||
masterThread.curSplitPoint = sp->parent;
|
master.curSplitPoint = sp->parent;
|
||||||
pos.set_nodes_searched(pos.nodes_searched() + sp->nodes);
|
pos.set_nodes_searched(pos.nodes_searched() + sp->nodes);
|
||||||
*bestMove = sp->bestMove;
|
*bestMove = sp->bestMove;
|
||||||
|
|
||||||
|
@ -417,11 +414,11 @@ void ThreadsManager::set_timer(int msec) {
|
||||||
|
|
||||||
void ThreadsManager::wait_for_search_finished() {
|
void ThreadsManager::wait_for_search_finished() {
|
||||||
|
|
||||||
Thread* main = threads[0];
|
Thread* t = main_thread();
|
||||||
lock_grab(main->sleepLock);
|
lock_grab(t->sleepLock);
|
||||||
cond_signal(main->sleepCond); // In case is waiting for stop or ponderhit
|
cond_signal(t->sleepCond); // In case is waiting for stop or ponderhit
|
||||||
while (!main->do_sleep) cond_wait(sleepCond, main->sleepLock);
|
while (!t->do_sleep) cond_wait(sleepCond, t->sleepLock);
|
||||||
lock_release(main->sleepLock);
|
lock_release(t->sleepLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,7 +434,7 @@ void ThreadsManager::start_searching(const Position& pos, const LimitsType& limi
|
||||||
Signals.stopOnPonderhit = Signals.firstRootMove = false;
|
Signals.stopOnPonderhit = Signals.firstRootMove = false;
|
||||||
Signals.stop = Signals.failedLowAtRoot = false;
|
Signals.stop = Signals.failedLowAtRoot = false;
|
||||||
|
|
||||||
RootPosition.copy(pos, 0);
|
RootPosition.copy(pos, main_thread());
|
||||||
Limits = limits;
|
Limits = limits;
|
||||||
RootMoves.clear();
|
RootMoves.clear();
|
||||||
|
|
||||||
|
@ -445,6 +442,6 @@ void ThreadsManager::start_searching(const Position& pos, const LimitsType& limi
|
||||||
if (searchMoves.empty() || count(searchMoves.begin(), searchMoves.end(), ml.move()))
|
if (searchMoves.empty() || count(searchMoves.begin(), searchMoves.end(), ml.move()))
|
||||||
RootMoves.push_back(RootMove(ml.move()));
|
RootMoves.push_back(RootMove(ml.move()));
|
||||||
|
|
||||||
threads[0]->do_sleep = false;
|
main_thread()->do_sleep = false;
|
||||||
threads[0]->wake_up();
|
main_thread()->wake_up();
|
||||||
}
|
}
|
||||||
|
|
11
src/thread.h
11
src/thread.h
|
@ -31,6 +31,8 @@
|
||||||
const int MAX_THREADS = 32;
|
const int MAX_THREADS = 32;
|
||||||
const int MAX_SPLITPOINTS_PER_THREAD = 8;
|
const int MAX_SPLITPOINTS_PER_THREAD = 8;
|
||||||
|
|
||||||
|
class Thread;
|
||||||
|
|
||||||
struct SplitPoint {
|
struct SplitPoint {
|
||||||
|
|
||||||
// Const data after split point has been setup
|
// Const data after split point has been setup
|
||||||
|
@ -39,7 +41,7 @@ struct SplitPoint {
|
||||||
Depth depth;
|
Depth depth;
|
||||||
Value beta;
|
Value beta;
|
||||||
int nodeType;
|
int nodeType;
|
||||||
int master;
|
Thread* master;
|
||||||
Move threatMove;
|
Move threatMove;
|
||||||
|
|
||||||
// Const pointers to shared data
|
// Const pointers to shared data
|
||||||
|
@ -76,7 +78,7 @@ public:
|
||||||
|
|
||||||
void wake_up();
|
void wake_up();
|
||||||
bool cutoff_occurred() const;
|
bool cutoff_occurred() const;
|
||||||
bool is_available_to(int master) const;
|
bool is_available_to(const Thread& master) const;
|
||||||
void idle_loop(SplitPoint* sp_master);
|
void idle_loop(SplitPoint* sp_master);
|
||||||
void idle_loop() { idle_loop(NULL); } // Hack to allow storing in start_fn
|
void idle_loop() { idle_loop(NULL); } // Hack to allow storing in start_fn
|
||||||
void main_loop();
|
void main_loop();
|
||||||
|
@ -86,7 +88,7 @@ public:
|
||||||
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
||||||
MaterialTable materialTable;
|
MaterialTable materialTable;
|
||||||
PawnTable pawnTable;
|
PawnTable pawnTable;
|
||||||
int threadID;
|
int idx;
|
||||||
int maxPly;
|
int maxPly;
|
||||||
Lock sleepLock;
|
Lock sleepLock;
|
||||||
WaitCondition sleepCond;
|
WaitCondition sleepCond;
|
||||||
|
@ -117,11 +119,12 @@ public:
|
||||||
bool use_sleeping_threads() const { return useSleepingThreads; }
|
bool use_sleeping_threads() const { return useSleepingThreads; }
|
||||||
int min_split_depth() const { return minimumSplitDepth; }
|
int min_split_depth() const { return minimumSplitDepth; }
|
||||||
int size() const { return (int)threads.size(); }
|
int size() const { return (int)threads.size(); }
|
||||||
|
Thread* main_thread() { return threads[0]; }
|
||||||
|
|
||||||
void wake_up() const;
|
void wake_up() const;
|
||||||
void sleep() const;
|
void sleep() const;
|
||||||
void read_uci_options();
|
void read_uci_options();
|
||||||
bool available_slave_exists(int master) const;
|
bool available_slave_exists(const Thread& master) const;
|
||||||
void set_timer(int msec);
|
void set_timer(int msec);
|
||||||
void wait_for_search_finished();
|
void wait_for_search_finished();
|
||||||
void start_searching(const Position& pos, const Search::LimitsType& limits,
|
void start_searching(const Position& pos, const Search::LimitsType& limits,
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace {
|
||||||
|
|
||||||
void uci_loop(const string& args) {
|
void uci_loop(const string& args) {
|
||||||
|
|
||||||
Position pos(StartFEN, false, 0); // The root position
|
Position pos(StartFEN, false, Threads.main_thread()); // The root position
|
||||||
string cmd, token;
|
string cmd, token;
|
||||||
|
|
||||||
while (token != "quit")
|
while (token != "quit")
|
||||||
|
@ -167,7 +167,7 @@ namespace {
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pos.from_fen(fen, Options["UCI_Chess960"]);
|
pos.from_fen(fen, Options["UCI_Chess960"], Threads.main_thread());
|
||||||
|
|
||||||
// Parse move list (if any)
|
// Parse move list (if any)
|
||||||
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)
|
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)
|
||||||
|
|
Loading…
Add table
Reference in a new issue