From c2fc80e5d16339266b5bf6687fa843ff65de3b3e Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Fri, 6 Apr 2012 18:36:46 +0100 Subject: [PATCH] Revert thread_local stuff Unfortunatly accessing thread local variable is much slower than object data (see previous patch log msg), so we have to revert to old code to avoid speed regression. No functional change. Signed-off-by: Marco Costalba --- src/benchmark.cpp | 2 +- src/endgame.cpp | 2 +- src/evaluate.cpp | 4 ++-- src/position.cpp | 20 ++++++++++++-------- src/position.h | 21 ++++++++++++++++----- src/search.cpp | 6 +++--- src/thread.cpp | 14 ++++---------- src/thread.h | 3 +-- src/types.h | 6 ------ src/uci.cpp | 4 ++-- 10 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 6ac64d430..f42c0e6c3 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -107,7 +107,7 @@ void benchmark(istringstream& is) { for (size_t i = 0; i < fens.size(); i++) { - Position pos(fens[i], false); + Position pos(fens[i], false, NULL); cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl; diff --git a/src/endgame.cpp b/src/endgame.cpp index 65f0f409d..5e021f113 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -77,7 +77,7 @@ namespace { string fen = sides[0] + char('0' + int(8 - code.length())) + sides[1] + "/8/8/8/8/8/8/8 w - - 0 10"; - return Position(fen, false).material_key(); + return Position(fen, false, NULL).material_key(); } template diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 515405ca5..9806b34bf 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -371,7 +371,7 @@ Value do_evaluate(const Position& pos, Value& margin) { margins[WHITE] = margins[BLACK] = VALUE_ZERO; // Probe the material hash table - ei.mi = this_thread->materialTable.probe(pos); + ei.mi = pos.this_thread()->materialTable.probe(pos); score += ei.mi->material_value(); // 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 - ei.pi = this_thread->pawnTable.probe(pos); + ei.pi = pos.this_thread()->pawnTable.probe(pos); score += ei.pi->pawns_value(); // Initialize attack and king safety bitboards diff --git a/src/position.cpp b/src/position.cpp index 47b08ec0a..3a0f8b1c9 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -92,17 +92,19 @@ CheckInfo::CheckInfo(const Position& pos) { } -/// Position::operator=() creates a copy of 'pos'. We want the new born Position +/// Position::copy() creates a copy of 'pos'. 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::operator=(const Position& pos) { +void Position::copy(const Position& pos, Thread* th) { memcpy(this, &pos, sizeof(Position)); startState = *st; st = &startState; + thisThread = th; nodes = 0; - return *this; + + assert(pos_is_ok()); } @@ -110,7 +112,7 @@ Position& Position::operator=(const Position& pos) { /// string. This function is not very robust - make sure that input FENs are /// 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. @@ -226,6 +228,7 @@ void Position::from_fen(const string& fenStr, bool isChess960) { st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); chess960 = isChess960; + thisThread = th; assert(pos_is_ok()); } @@ -328,7 +331,7 @@ void Position::print(Move move) const { if (move) { - Position p(*this); + Position p(*this, thisThread); cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move); } @@ -895,8 +898,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI } // Prefetch pawn and material hash tables - prefetch((char*)this_thread->pawnTable.entries[st->pawnKey]); - prefetch((char*)this_thread->materialTable.entries[st->materialKey]); + prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]); + prefetch((char*)thisThread->materialTable.entries[st->materialKey]); // Update incremental scores st->psqScore += psq_delta(piece, from, to); @@ -1538,9 +1541,10 @@ void Position::init() { void Position::flip() { // Make a copy of current position before to start changing - const Position pos(*this); + const Position pos(*this, thisThread); clear(); + thisThread = pos.this_thread(); // Board for (Square s = SQ_A1; s <= SQ_H8; s++) diff --git a/src/position.h b/src/position.h index 2db3d9653..b59e5923e 100644 --- a/src/position.h +++ b/src/position.h @@ -84,14 +84,19 @@ struct StateInfo { /// * A counter for detecting 50 move rule draws. class Position { -public: - Position() {} - Position(const Position& p) { *this = p; } - Position(const std::string& f, bool c960) { from_fen(f, c960); } + + // No copy c'tor or assignment operator allowed + Position(const Position&); Position& operator=(const Position&); +public: + Position() {} + Position(const Position& p, Thread* t) { copy(p, t); } + Position(const std::string& f, bool c960, Thread* t) { from_fen(f, c960, t); } + // Text input/output - void from_fen(const std::string& fen, bool isChess960); + void copy(const Position& pos, Thread* th); + void from_fen(const std::string& fen, bool isChess960, Thread* th); const std::string to_fen() const; void print(Move m = MOVE_NONE) const; @@ -171,6 +176,7 @@ public: Color side_to_move() const; int startpos_ply_counter() const; bool is_chess960() const; + Thread* this_thread() const; int64_t nodes_searched() const; void set_nodes_searched(int64_t n); template bool is_draw() const; @@ -218,6 +224,7 @@ private: int64_t nodes; int startPosPly; Color sideToMove; + Thread* thisThread; StateInfo* st; int chess960; @@ -427,4 +434,8 @@ inline PieceType Position::captured_piece_type() const { return st->capturedType; } +inline Thread* Position::this_thread() const { + return thisThread; +} + #endif // !defined(POSITION_H_INCLUDED) diff --git a/src/search.cpp b/src/search.cpp index ebbff3a4a..920310da7 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -332,7 +332,7 @@ finalize: // but if we are pondering or in infinite search, we shouldn't print the best // move before we are told to do so. if (!Signals.stop && (Limits.ponder || Limits.infinite)) - 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 cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960) @@ -543,7 +543,7 @@ namespace { bool isPvMove, inCheck, singularExtensionNode, givesCheck; bool captureOrPromotion, dangerous, doFullDepthSearch; int moveCount = 0, playedMoveCount = 0; - Thread* thisThread = this_thread; + Thread* thisThread = pos.this_thread(); SplitPoint* sp = NULL; refinedValue = bestValue = value = -VALUE_INFINITE; @@ -1825,7 +1825,7 @@ void Thread::idle_loop(SplitPoint* sp_master) { lock_release(Threads.splitLock); Stack ss[MAX_PLY_PLUS_2]; - Position pos(*sp->pos); + Position pos(*sp->pos, this); memcpy(ss, sp->ss - 1, 4 * sizeof(Stack)); (ss+1)->sp = sp; diff --git a/src/thread.cpp b/src/thread.cpp index 7b9a4f327..fe7a669b8 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -28,22 +28,17 @@ using namespace Search; ThreadsManager Threads; // Global object -THREAD_LOCAL Thread* this_thread; // Thread local variable namespace { extern "C" { // start_routine() is the C function which is called when a new thread // is launched. It is a wrapper to member function pointed by start_fn. - long start_routine(Thread* th) { - - this_thread = th; // Save pointer into thread local storage - (th->*(th->start_fn))(); - return 0; - } + long start_routine(Thread* th) { (th->*(th->start_fn))(); return 0; } } } + // Thread c'tor starts a newly-created thread of execution that will call // the idle loop function pointed by start_fn going immediately to sleep. @@ -210,7 +205,6 @@ void ThreadsManager::init() { lock_init(splitLock); timer = new Thread(&Thread::timer_loop); threads.push_back(new Thread(&Thread::main_loop)); - this_thread = main_thread(); // Use main thread's resources read_uci_options(); } @@ -313,7 +307,7 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta, assert(beta <= VALUE_INFINITE); assert(depth > DEPTH_ZERO); - Thread* master = this_thread; + Thread* master = pos.this_thread(); if (master->splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD) return bestValue; @@ -440,7 +434,7 @@ void ThreadsManager::start_searching(const Position& pos, const LimitsType& limi Signals.stopOnPonderhit = Signals.firstRootMove = false; Signals.stop = Signals.failedLowAtRoot = false; - RootPosition = pos; + RootPosition.copy(pos, main_thread()); Limits = limits; RootMoves.clear(); diff --git a/src/thread.h b/src/thread.h index e03578eef..3eb8fc9cf 100644 --- a/src/thread.h +++ b/src/thread.h @@ -119,7 +119,7 @@ public: bool use_sleeping_threads() const { return useSleepingThreads; } int min_split_depth() const { return minimumSplitDepth; } int size() const { return (int)threads.size(); } - Thread* main_thread() const { return threads[0]; } + Thread* main_thread() { return threads[0]; } void wake_up() const; void sleep() const; @@ -146,6 +146,5 @@ private: }; extern ThreadsManager Threads; -extern THREAD_LOCAL Thread* this_thread; #endif // !defined(THREAD_H_INCLUDED) diff --git a/src/types.h b/src/types.h index 2a3b41fab..031cb0bab 100644 --- a/src/types.h +++ b/src/types.h @@ -64,12 +64,6 @@ # define FORCE_INLINE inline #endif -#if defined(__GNUC__) -# define THREAD_LOCAL __thread -#else -# define THREAD_LOCAL __declspec(thread) -#endif - #if defined(USE_POPCNT) const bool HasPopCnt = true; #else diff --git a/src/uci.cpp b/src/uci.cpp index dd4040d73..c6da2fc48 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -56,7 +56,7 @@ namespace { void uci_loop(const string& args) { - Position pos(StartFEN, false); // The root position + Position pos(StartFEN, false, Threads.main_thread()); // The root position string cmd, token; while (token != "quit") @@ -167,7 +167,7 @@ namespace { else return; - pos.from_fen(fen, Options["UCI_Chess960"]); + pos.from_fen(fen, Options["UCI_Chess960"], Threads.main_thread()); // Parse move list (if any) while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)