StateInfo st;
Move ttMove, move;
Value staticValue, bestValue, value, futilityBase, futilityValue;
- bool isCheck, enoughMaterial, moveIsCheck;
+ bool isCheck, enoughMaterial, moveIsCheck, evasionPrunable;
const TTEntry* tte = NULL;
int moveCount = 0;
bool pvNode = (beta - alpha != 1);
}
}
- // Don't search captures and checks with negative SEE values
- if ( !isCheck
+ // Detect blocking evasions that are candidate to be pruned
+ evasionPrunable = isCheck
+ && bestValue != -VALUE_INFINITE
+ && !pos.move_is_capture(move)
+ && pos.type_of_piece_on(move_from(move)) != KING
+ && !pos.can_castle(pos.side_to_move());
+
+ // Don't search moves with negative SEE values
+ if ( (!isCheck || evasionPrunable)
&& move != ttMove
&& !move_is_promotion(move)
&& pos.see_sign(move) < 0)
break;
// New best move?
- lock_grab(&(sp->lock));
- if (value > sp->bestValue && !thread_should_stop(threadID))
+ if (value > sp->bestValue) // Less then 2% of cases
{
- sp->bestValue = value;
- if (value > sp->alpha)
+ lock_grab(&(sp->lock));
+ if (value > sp->bestValue && !thread_should_stop(threadID))
{
- // Ask threads to stop before to modify sp->alpha
- if (value >= sp->beta)
+ sp->bestValue = value;
+ if (value > sp->alpha)
{
- for (int i = 0; i < ActiveThreads; i++)
- if (i != threadID && (i == sp->master || sp->slaves[i]))
- Threads[i].stop = true;
+ // Ask threads to stop before to modify sp->alpha
+ if (value >= sp->beta)
+ {
+ for (int i = 0; i < ActiveThreads; i++)
+ if (i != threadID && (i == sp->master || sp->slaves[i]))
+ Threads[i].stop = true;
- sp->finished = true;
- }
+ sp->finished = true;
+ }
- sp->alpha = value;
+ sp->alpha = value;
- sp_update_pv(sp->parentSstack, ss, sp->ply);
- if (value == value_mate_in(sp->ply + 1))
- ss[sp->ply].mateKiller = move;
- }
- // If we are at ply 1, and we are searching the first root move at
- // ply 0, set the 'Problem' variable if the score has dropped a lot
- // (from the computer's point of view) since the previous iteration.
- if ( sp->ply == 1
- && Iteration >= 2
- && -value <= IterationInfo[Iteration-1].value - ProblemMargin)
- Problem = true;
+ sp_update_pv(sp->parentSstack, ss, sp->ply);
+ if (value == value_mate_in(sp->ply + 1))
+ ss[sp->ply].mateKiller = move;
+ }
+ // If we are at ply 1, and we are searching the first root move at
+ // ply 0, set the 'Problem' variable if the score has dropped a lot
+ // (from the computer's point of view) since the previous iteration.
+ if ( sp->ply == 1
+ && Iteration >= 2
+ && -value <= IterationInfo[Iteration-1].value - ProblemMargin)
+ Problem = true;
+ }
+ lock_release(&(sp->lock));
}
- lock_release(&(sp->lock));
}
lock_grab(&(sp->lock));
if (!Threads[slave].idle || slave == master)
return false;
- if (Threads[slave].activeSplitPoints == 0)
+ // Make a local copy to be sure doesn't change under our feet
+ int localActiveSplitPoints = Threads[slave].activeSplitPoints;
+
+ if (localActiveSplitPoints == 0)
// No active split points means that the thread is available as
// a slave for any other thread.
return true;
if (ActiveThreads == 2)
return true;
- // Apply the "helpful master" concept if possible
- if (SplitPointStack[slave][Threads[slave].activeSplitPoints - 1].slaves[master])
+ // Apply the "helpful master" concept if possible. Use localActiveSplitPoints
+ // that is known to be > 0, instead of Threads[slave].activeSplitPoints that
+ // could have been set to 0 by another thread leading to an out of bound access.
+ if (SplitPointStack[slave][localActiveSplitPoints - 1].slaves[master])
return true;
return false;
splitPoint->slaves[i] = 0;
Threads[master].idle = false;
+ Threads[master].stop = false;
Threads[master].splitPoint = splitPoint;
// Allocate available threads setting idle flag to false
if (thread_is_available(i, master))
{
Threads[i].idle = false;
+ Threads[i].stop = false;
Threads[i].splitPoint = splitPoint;
splitPoint->slaves[i] = 1;
splitPoint->cpus++;
// We can release the lock because master and slave threads are already booked
lock_release(&MPLock);
- // Copy the tail of current search stack to the master thread
- memcpy(splitPoint->sstack[master] + ply - 1, sstck + ply - 1, 3 * sizeof(SearchStack));
-
// Tell the threads that they have work to do. This will make them leave
- // their idle loop. Also copy search stack tail for each slave thread.
+ // their idle loop. But before copy search stack tail for each thread.
for (int i = 0; i < ActiveThreads; i++)
- {
- if (splitPoint->slaves[i])
- memcpy(splitPoint->sstack[i] + ply - 1, sstck + ply - 1, 3 * sizeof(SearchStack));
-
if (i == master || splitPoint->slaves[i])
{
- Threads[i].stop = false;
+ memcpy(splitPoint->sstack[i] + ply - 1, sstck + ply - 1, 3 * sizeof(SearchStack));
Threads[i].workIsWaiting = true; // This makes the slave to exit from idle_loop()
}
- }
// Everything is set up. The master thread enters the idle loop, from
// which it will instantly launch a search, because its workIsWaiting