Revert thread_local stuff
authorMarco Costalba <mcostalba@gmail.com>
Fri, 6 Apr 2012 17:36:46 +0000 (18:36 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Fri, 6 Apr 2012 17:47:55 +0000 (18:47 +0100)
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 <mcostalba@gmail.com>
src/benchmark.cpp
src/endgame.cpp
src/evaluate.cpp
src/position.cpp
src/position.h
src/search.cpp
src/thread.cpp
src/thread.h
src/types.h
src/uci.cpp

index 6ac64d4309b1c0531b1c32ff61371343e0bee849..f42c0e6c312460742dd944d1765398bd2f001788 100644 (file)
@@ -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;
 
index 65f0f409de3df7daa8b38ae0636f3dc69323c236..5e021f1132917aa36d397a1f090f71938c72cb99 100644 (file)
@@ -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<typename M>
index 515405ca5fe935b16d0eef5fedd103910e9b4968..9806b34bf09dc8e2c72d8e47c6a15830ed6214fd 100644 (file)
@@ -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
index 47b08ec0ad3044600d0f583fc67d930b59f246cb..3a0f8b1c90f8bba670b942488b87966092cefd69 100644 (file)
@@ -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++)
index 2db3d9653cafb86ca88d994d94c537d4ba081b11..b59e5923e3efab97c8733aa0fe12fd2a02910d51 100644 (file)
@@ -84,14 +84,19 @@ struct StateInfo {
 ///    * A counter for detecting 50 move rule draws.
 
 class Position {
+
+  // No copy c'tor or assignment operator allowed
+  Position(const Position&);
+  Position& operator=(const Position&);
+
 public:
   Position() {}
-  Position(const Position& p) { *this = p; }
-  Position(const std::string& f, bool c960) { from_fen(f, c960); }
-  Position& operator=(const 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 SkipRepetition> 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)
index ebbff3a4a966adfeb3461df1e25ab3edb1b96d50..920310da713d1fbacc11c9ad60334c49a82b5aa0 100644 (file)
@@ -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;
index 7b9a4f327823a4e0e60bcf9492d972ea0ccaa16d..fe7a669b8e66f989d990e89f9e24127afe1848f4 100644 (file)
 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();
 
index e03578eef8db488c34e23fde3a95157fbd8102f1..3eb8fc9cfe4d8f001a5ae8a4d4685a39cc6539f5 100644 (file)
@@ -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)
index 2a3b41fab8f7ee234852deb6b9498f97fd72a031..031cb0babda381b50f1643a9dfe2a945a3a12a02 100644 (file)
 #  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
index dd4040d732397c8752d5d9096b520afb280f7967..c6da2fc4851acee54e5b60f140cb054d3066e5f5 100644 (file)
@@ -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)