Use a per-thread array for generated moves
authorMarco Costalba <mcostalba@gmail.com>
Thu, 26 Sep 2013 17:25:50 +0000 (19:25 +0200)
committerMarco Costalba <mcostalba@gmail.com>
Fri, 27 Sep 2013 06:44:36 +0000 (08:44 +0200)
This greately reduces stack usage and is a
prerequisite for next patch.

Verified with 40K games both in single and SMP
case that there are no regressions.

No functional change.

src/movepick.cpp
src/movepick.h
src/thread.cpp
src/thread.h

index 643c836..a54398c 100644 (file)
@@ -75,7 +75,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
 
   assert(d > DEPTH_ZERO);
 
-  cur = end = moves;
+  cur = end = moves = pos.this_thread()->get_moves_array();
   endBadCaptures = moves + MAX_MOVES - 1;
   countermoves = cm;
   ss = s;
@@ -91,10 +91,11 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
 }
 
 MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
-                       Square sq) : pos(p), history(h), cur(moves), end(moves) {
+                       Square sq) : pos(p), history(h) {
 
   assert(d <= DEPTH_ZERO);
 
+  cur = end = moves = pos.this_thread()->get_moves_array();
   if (p.checkers())
       stage = EVASION;
 
@@ -123,10 +124,11 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
 }
 
 MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, PieceType pt)
-                       : pos(p), history(h), cur(moves), end(moves) {
+                       : pos(p), history(h) {
 
   assert(!pos.checkers());
 
+  cur = end = moves = pos.this_thread()->get_moves_array();
   stage = PROBCUT;
 
   // In ProbCut we generate only captures better than parent's captured piece
@@ -139,6 +141,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Piece
   end += (ttMove != MOVE_NONE);
 }
 
+MovePicker::~MovePicker() { pos.this_thread()->free_moves_array(); }
 
 /// score() assign a numerical move ordering score to each move in a move list.
 /// The moves with highest scores will be picked first.
index c444615..f3839bf 100644 (file)
@@ -87,6 +87,7 @@ public:
   MovePicker(const Position&, Move, Depth, const HistoryStats&, Square);
   MovePicker(const Position&, Move, const HistoryStats&, PieceType);
   MovePicker(const Position&, Move, Depth, const HistoryStats&, Move*, Search::Stack*);
+ ~MovePicker();
 
   template<bool SpNode> Move next_move();
 
@@ -103,8 +104,7 @@ private:
   ExtMove killers[4];
   Square recaptureSquare;
   int captureThreshold, stage;
-  ExtMove *cur, *end, *endQuiets, *endBadCaptures;
-  ExtMove moves[MAX_MOVES];
+  ExtMove *moves, *cur, *end, *endQuiets, *endBadCaptures;
 };
 
 #endif // #ifndef MOVEPICK_H_INCLUDED
index 7d85db8..c385f05 100644 (file)
@@ -83,10 +83,11 @@ void ThreadBase::wait_for(volatile const bool& b) {
 Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC
 
   searching = false;
-  maxPly = splitPointsSize = 0;
+  maxPly = splitPointsSize = curPage = 0;
   activeSplitPoint = NULL;
   activePosition = NULL;
   idx = Threads.size();
+  movePages.resize(MAX_PLY_PLUS_6 * MAX_MOVES);
 }
 
 
index 56d000f..6454826 100644 (file)
@@ -115,6 +115,8 @@ struct Thread : public ThreadBase {
   virtual void idle_loop();
   bool cutoff_occurred() const;
   bool is_available_to(const Thread* master) const;
+  ExtMove* get_moves_array() { return &movePages[curPage += MAX_MOVES]; }
+  void free_moves_array() { curPage -= MAX_MOVES; }
 
   template <bool Fake>
   void split(Position& pos, const Search::Stack* ss, Value alpha, Value beta, Value* bestValue, Move* bestMove,
@@ -125,6 +127,8 @@ struct Thread : public ThreadBase {
   Endgames endgames;
   Pawns::Table pawnsTable;
   Position* activePosition;
+  std::vector<ExtMove> movePages;
+  int curPage;
   size_t idx;
   int maxPly;
   SplitPoint* volatile activeSplitPoint;