1
0
Fork 0
Commit Graph

1713 Commits (c33af32dada1be9f6aed851e8cf87599203e2eb2)

Author SHA1 Message Date
Joost VandeVondele c33af32dad Measure nodes after search finished.
Only affects nmpsec in the multithreaded case.

No functional change.
2017-09-29 16:39:12 +02:00
GuardianRM 0e949ac2c9 Tweak statScore condition
The first change (ss->statScore >= 0) does nothing.

The second change ((ss-1)->statScore >= 0 ) has a massive change.
(ss-1)->statScore is not set until (ss-1) begins to apply LMR to moves.
So we now increase the reduction for bad quiets when our opponent is
running through the first captures and the hash move.

STC
LLR: 2.95 (-2.94,2.94) [0.00,4.00]
Total: 57762 W: 10533 L: 10181 D: 37048

LTC
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 19973 W: 2662 L: 2480 D: 14831

Bench: 5037819
2017-09-22 16:48:08 +02:00
syzygy ba4e215493 Let ss->ply denote the number of plies from the root to the current node
This patch lets ss->ply be equal to 0 at the root of the search.

Currently, the root has ss->ply == 1, which is less intuitive:

- Setting the rootNode bool has to check (ss-1)->ply == 0.

- All mate values are off by one: the code seems to assume that mated-in-0
  is -VALUE_MATE, mate-1-in-ply is VALUE_MATE-1, mated-in-2-ply is VALUE_MATE+2, etc.
  But the mate_in() and mated_in() functions are called with ss->ply, which is 1 in
  at the root.

- The is_draw() function currently needs to explain why it has "ply - 1 > i" instead
  of simply "ply > i".

- The ss->ply >= MAX_PLY tests in search() and qsearch() already assume that
  ss->ply == 0 at the root. If we start at ss->ply == 1, it would make more sense to
  go up to and including ss->ply == MAX_PLY, so stop at ss->ply > MAX_PLY. See also
  the asserts testing for 0 <= ss->ply && ss->ply < MAX_PLY.

The reason for ss->ply == 1 at the root is the line "ss->ply = (ss-1)->ply + 1" at
the start for search() and qsearch(). By replacing this with "(ss+1)->ply = ss->ply + 1"
we keep ss->ply == 0 at the root. Note that search() already clears killers in (ss+2),
so there is no danger in accessing ss+1.

I have NOT changed pv[MAX_PLY + 1] to pv[MAX_PLY + 2] in search() and qsearch().
It seems to me that MAX_PLY + 1 is exactly right:

- MAX_PLY entries for ss->ply running from 0 to MAX_PLY-1, and 1 entry for the
  final MOVE_NONE.

I have verified that mate scores are reported correctly. (They were already reported
correctly due to the extra ply being rounded down when converting to moves.)

The value of seldepth output to the user should probably not change, so I add 1 to it.
(Humans count from 1, computers from 0.)

A small optimisation I did not include: instead of setting ss->ply in every invocation
of search() and qsearch(), it could be set once for all plies at the start of
Thread::search(). This saves a couple of instructions per node.

No functional change (unless the search searches a branch MAX_PLY deep), so bench
does not change.
2017-09-17 10:44:10 +02:00
VoyagerOne 3ac47c84d3 Streamlline reduction based on movecount
Use MoveCount History only at quiet moves and simply reduce
reduction by one depth instead of increasing moveCount in formula.

STC:
LLR: 2.96 (-2.94,2.94) [0.00,4.00]
Total: 27511 W: 5171 L: 4919 D: 17421

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,4.00]
Total: 92337 W: 12135 L: 11748 D: 68454

Bench: 6351176
2017-09-05 11:03:50 +02:00
Joost VandeVondele e385f194e9 Fix uninitialized memory usage
After increasing the number of threads, the histories were not cleared,
resulting in uninitialized memory usage.

This patch fixes this by clearing threads histories in Thread c'tor as
is the idomatic way.

This fixes issue 1227

No functional change.
2017-09-01 20:16:56 +02:00
VoyagerOne 7b4c9852e1 Adjust moveCount history only at LMR
STC:
LLR: 3.32 (-2.94,2.94) [-3.00,1.00]
Total: 17584 W: 3277 L: 3131 D: 11176

LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 26412 W: 3447 L: 3334 D: 19631

Bench: 5417521
2017-08-31 08:53:37 +02:00
Joost VandeVondele d5f883ab29 Improve multi-threaded mate finding
If any thread found a 'mate in x' stop the search. Previously only
mainThread would do so. Requires the bestThread selection to be
adjusted to always prefer mate scores, even if the search depth is less.

I've tried to collect some data for this patch. On 30 cores, mate finding
seems 5-30% faster on average. It is not so easy to get numbers for this,
as the time to find a mate fluctuates significantly with multi-threaded runs,
so it is an average over 100 searches for the same position. Furthermore,
hash size and position make a difference as well.

Bench: 5965302
2017-08-26 09:53:34 +02:00
Joost VandeVondele 5ef94eb970 Use moveCount history for reduction
Use less reduction for moves with larger moveCount if your
opponent did an unexpected (== high moveCount) move in the
previous ply... unexpected moves might need unexpected answers.

passed STC:
http://tests.stockfishchess.org/tests/view/599f08cc0ebc5916ff64aace
LLR: 2.97 (-2.94,2.94) [0.00,5.00]
Total: 9638 W: 1889 L: 1720 D: 6029

passed LTC:
http://tests.stockfishchess.org/tests/view/599f1e5c0ebc5916ff64aadc
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 28308 W: 3742 L: 3533 D: 21033

Bench: 5747429
2017-08-26 09:30:42 +02:00
Stéphane Nicolet 002bf4d8db Avoid constructing an empty tuple in qsearch
Avoid constructing, passing as a parameter and binding a useless empty tuple of pointers in the qsearch move picker constructor.

Also reformat the scoring function in movepicker.cpp and do some cleaning in evaluate.cpp while there.

No functional change.
2017-08-22 10:16:19 +02:00
Marco Costalba 7aa7dfd4df Fix some Clang warnings
Found by Clang in extra verbose mode :-)

No functional change.
2017-08-19 14:32:31 +02:00
Marco Costalba 45e254a0a0 Restore perft
Rewrite perft to be placed naturally inside new
bench code. In particular we don't have special
custom code to run perft anymore but perft is
just a new parameter of 'go' command.

So user API is now changed, old style command:

$perft 5

becomes

$go perft 4

No functional change.
2017-08-18 09:04:38 -07:00
Joost VandeVondele daf0fe1f57 Collect more corrections to optimum/maximum
The only call site of Time.maximum() corrected by 10.
Do this directly in remaining().

Ponder increased Time.optimum by 25% in init(). Idem.
Delete unused includes.

No functional change.
2017-08-18 08:38:40 -07:00
Marco Costalba c3e964f35e Run clang-tidy 'modernize'
Some warnings after a run of:

$ clang-tidy-3.8 -checks='modernize-*' *.cpp syzygy/*.cpp -header-filter=.* -- -std=c++11

I have not fixed all suggestions, for instance I still prefer
to declare the type instead of a spread use of 'auto'. I also
perfer good old 'typedef' to the new 'using' form.

I have not fixed some warnings in the last functions of
syzygy code because those are still the original functions
and need to be completely rewritten anyhow.

Thanks to erbsenzaehler for the original idea.

No functional change.
2017-08-13 05:46:21 -07:00
Marco Costalba df6cb446ea Thread code reformat
Simplify out low level sync stuff (mutex
and friends) and avoid to use them directly
in many functions.

Also some renaming and better comment while
there.

No functional change.
2017-08-13 04:41:59 -07:00
Joost VandeVondele 2783203428 Simplify finished search in ponder/infinite mode.
In this rare case (e.g. go infinite on a stalemate),
just spin till ponderhit/stop comes.

The Thread::wait() is a renmant of the old YBWC
code, today with lazy SMP, threads don't need to
wait when outside of their idle loop.

No functional change.
2017-08-10 22:42:52 -07:00
Marco Costalba 66c5eaebd8 Re-apply the fix for Limits::ponder race
But this time correctly set Threads.ponder

We avoid using 'limits' for passing pondering
flag because we don't want to have 2 ponder
variables in search scope: Search::Limits.ponder
and Threads.ponder. This would be confusing also
because limits.ponder is set at the beginning of
the search and never changes, instead Threads.ponder
can change value asynchronously during search.

No functional change.
2017-08-10 12:47:31 -07:00
Marco Costalba 44236f4ed9 Revert "Fix a race on Limits::ponder"
This reverts commit 5410424e3d.

After the commit pondering is broken, so revert for now. I will
resubmit with a proper fix.

The issue is mine, Joost original code is correct.

No functional change.
2017-08-10 10:59:38 -07:00
Joost VandeVondele 5410424e3d Fix a race on Limits::ponder
Limits::ponder was used as a signal between uci and search threads,
but is not an atomic variable, leading to the following race as
flagged by a sanitized binary.

Expect input:
```
 spawn  ./stockfish
 send "uci\n"
 expect "uciok"
 send "setoption name Ponder value true\n"
 send "go wtime 4000 btime 4000\n"
 expect "bestmove"
 send "position startpos e2e4 d7d5\n"
 send "go wtime 4000 btime 4000 ponder\n"
 sleep 0.01
 send "ponderhit\n"
 expect "bestmove"
 send "quit\n"
 expect eof
```

Race:
```
WARNING: ThreadSanitizer: data race (pid=7191)
  Read of size 4 at 0x0000005c2260 by thread T1:

  Previous write of size 4 at 0x0000005c2260 by main thread:

  Location is global 'Search::Limits' of size 88 at 0x0000005c2220 (stockfish+0x0000005c2260)
```

The reason of teh race is that ponder is not just set in UCI go()
assignment but also is signaled by an async ponderhit in uci.cpp:

      else if (token == "ponderhit")
          Search::Limits.ponder = 0; // Switch to normal search

The fix is to add an atomic bool to the threads structure to
signal the ponder status, letting Search::Limits to reflect just
what was passed to 'go'.

No functional change.
2017-08-10 10:46:46 -07:00
Marco Costalba 750dfa0521 Fix some races and clarify the code
Better split code that should be run at
startup from code run at ucinewgame. Also
fix several races when 'bench', 'perft' and
'ucinewgame' are sent just after 'bestomve'
from the engine threads are still running.

Also use a specific UI thread instead of
main thread when setting up the Position
object used by UI uci loop. This fixes a
race when sending 'eval' command while searching.

We accept a race on 'setoption' to allow the
GUI to change an option while engine is searching
withouth stalling the pipe. Note that changing an
option while searchingg is anyhow not mandated by
UCI protocol.

No functional change.
2017-08-10 10:19:56 -07:00
AndyGrant dbc984d9f8 Make variable naming consistent
moved_piece is the only variable in search not using camel case
2017-08-10 10:04:30 -07:00
Joost VandeVondele b40e45c1cc Remove Stack/thread dependence in movepick
as a lower level routine, movepicker should not depend on the
search stack or the thread class, removing a circular dependency.
Instead of copying the search stack into the movepicker object,
as well as accessing the thread class for one of the histories,
pass the required fields explicitly to the constructor (removing
the need for thread.h and implicitly search.h in movepick.cpp).
The signature is thus longer, but more explicit:

Also some renaming of histories structures while there.

passed STC [-3,1], suggesting a small elo impact:

LLR: 3.13 (-2.94,2.94) [-3.00,1.00]
Total: 381053 W: 68071 L: 68551 D: 244431
elo =   -0.438 +-    0.660 LOS:    9.7%

No functional change.
2017-08-06 01:45:54 -07:00
VoyagerOne 722e1e0da6 Remove redundant if-statements
No functional change

Closes #1173
2017-07-27 02:14:18 -07:00
VoyagerOne a6ae2d3a31 Simplify aspiration window
Don't modify alpha window on fail-high

Bench: 5875983

Closes #1172
2017-07-23 17:25:23 -07:00
joergoster 377d77dbe9 Provide selective search depth info for each pv move
No functional change

Closes #1166
2017-07-13 16:30:03 -07:00
Joost VandeVondele 36a93d90f7 Move stop signal to Threads
Instead of having Signals in the search namespace,
make the stop variables part of the Threads structure.
This moves more of the shared (atomic) variables towards
the thread-related structures, making their role more clear.

No functional change

Closes #1149
2017-07-13 16:08:37 -07:00
Marco Costalba 802fca6fdd Don't uselessy share rootDepth
It is not needed becuase the only case is a real special
one (bench on depth with many threads) and can be easily
rewritten to avoid sharing rootDepth.

Verified with ThreadSanitizer.

No functional change.

Closes #1159
2017-07-02 22:06:47 -07:00
Marco Costalba 05513a6641 Only main thread checks time
The main change of the patch is that now time check
is done only by main thread. In the past, before lazy
SMP, we needed all the threds to check for available
time because main thread could have been blocked on
a split point, now this is no more the case and main
thread can do the job alone, greatly simplifying the logic.

Verified for regression testing on STC with 7 threads:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 11895 W: 1741 L: 1608 D: 8546

No functional change.

Closes #1152
2017-06-28 17:03:35 -07:00
VoyagerOne 77342126d8 Increase reduction if tt-move is a capture
The idea is that chances are the tt-move is best and will be difficult to raise alpha when playing a quiet move.

STC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 7582 W: 1415 L: 1259 D: 4908

LTC:
LLR: 2.97 (-2.94,2.94) [0.00,5.00]
Total: 59553 W: 7885 L: 7573 D: 44095

Bench: 5725676

Closes #1147
2017-06-21 14:06:05 -07:00
Joona Kiiski 336901fdb0 Revert "Prefetch earlier in qsearch()"
This reverts commit b73016bb41.

No functional change

Closes #1144
2017-06-21 13:45:03 -07:00
Joost VandeVondele 3cb0200459 Fix four data races.
the nodes, tbHits, rootDepth and lastInfoTime variables are read by multiple threads, but not declared atomic, leading to data races as found by -fsanitize=thread. This patch fixes this issue. It is based on top of the CI-threading branch (PR #1129), and should fix the corresponding CI error messages.

The patch passed an STC check for no regression:

http://tests.stockfishchess.org/tests/view/5925d5590ebc59035df34b9f
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 169597 W: 29938 L: 30066 D: 109593

Whereas rootDepth and lastInfoTime are not performance critical, nodes and tbHits are. Indeed, an earlier version using relaxed atomic updates on the latter two variables failed STC testing (http://tests.stockfishchess.org/tests/view/592001700ebc59035df34924), which can be shown to be due to x86-32 (http://tests.stockfishchess.org/tests/view/592330ac0ebc59035df34a89). Indeed, the latter have no instruction to atomically update a 64bit variable. The proposed solution thus uses a variable in Position that is accessed only by one thread, which is copied every few thousand nodes to the shared variable in Thread.

No functional change.

Closes #1130
Closes #1129
2017-06-21 13:37:58 -07:00
Alain SAVARD 2c237da546 Misc coding style fixes
a few comment and blank fixes.

No functional change

Closes #1141
2017-06-16 19:55:30 -07:00
snicolet b73016bb41 Prefetch earlier in qsearch()
Closes #1139
2017-06-16 19:52:38 -07:00
Marco Costalba 27ba611a3d Better naming in endgame code
And small clean-up of magic bitboards code.

No functional change.

Closes #1138
2017-06-16 19:33:44 -07:00
Brian Sheppard f907d5b7d9 Move depth calculation in probCut
The change passed an STC regression:

LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 59350 W: 10793 L: 10738 D: 37819

I verified that there was no change in performance on my machine, but of course YMMV:

Results for 40 tests for each version:

                Base      Test      Diff
        Mean    2014338   2016121   -1783
        StDev   62655     63441     3860

p-value: 0.678
speedup: 0.001

No functional change.

Closes #1137
2017-06-16 19:30:19 -07:00
Joost VandeVondele ebc563059c Call TT.new_search() earlier.
TT.new_search() was being called by mainThread in Thread::search(). However, mainThread is the last to start searching, and helper threads could reach a measured rootDepth 10 (on 64 cores) before mainThread increments the TT generation. Fixed by moving the call to MaintThread::search() before helper threads start searching.

No functional change.

Closes #1134
2017-06-16 19:20:01 -07:00
Marco Costalba ecd3218b6b History code rewrite (#1122)
Rearrange and rename all history heuristic code. Naming
is now based on chessprogramming.wikispaces.com conventions
and the relations among the various heuristics are now more
clear and consistent.

No functional change.
2017-05-26 08:42:50 +02:00
VoyagerOne 1d31065e1d Evasion Pruning Tweak
Use moveCount to decide when to prune for evasion pruning

STC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 24476 W: 4518 L: 4289 D: 15669

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 18362 W: 2476 L: 2298 D: 13588

Bench: 6469989

Closes #1120
2017-05-21 18:27:57 -07:00
Joost VandeVondele 732aa34e3d Fix memory access in Search::clear()
Fixes a bug in Search::clear, where the filling of CounterMoveStats&, overwrote (currently presumably unused) memory because sizeof(cm) returns the size in bytes, whereas elements was needed.

No functional change

Closes #1119
2017-05-17 18:15:01 -07:00
Joost VandeVondele 7edd1f7ccd Execute an implied ucinewgame at startup
execute an implied ucinewgame upon entering the UCI::loop,
to make sure that searches starting with and without an (optional) ucinewgame
command yield the same search.

This is needed now that seach::clear() initializes tables to non-zero default values.

No functional change

Closes #1101
Closes #1104
2017-05-15 18:54:13 -07:00
Marco Costalba 0c1f119069 Default argument for see_ge()
No functional change.

Closes #1111
2017-05-10 18:20:45 +02:00
joergoster 8b15961349 Fix multiPV issue #502
In general, this patch handles the cases where we don't have a valid score for each PV line in a multiPV search. This can happen if the search has been stopped in an unfortunate moment while still in the aspiration loop. The patch consists of two parts.

Part 1: The new PVIdx was already part of the k-best pv's in the last iteration, and we therefore have a valid pv and score to output from the last iteration. This is taken care of with:

      bool updated = (i <= PVIdx && rootMoves[i].score != -VALUE_INFINITE);

Case 2: The new PVIdx was NOT part of the k-best pv's in the last iteration, and we have no valid pv and score to output. Not from the current nor from the previous iteration. To avoid this, we are now also considering the previous score when sorting, so that the PV lines with no actual but with a valid previous score are pushed up again, and the previous score can be displayed.

  bool operator<(const RootMove& m) const {
    return m.score != score ? m.score < score : m.previousScore < previousScore; } // Descending sort

I also added an assertion in UCI::value() to possibly catch similar issues earlier.

No functional change.

Closes #502
Closes #1074
2017-05-03 19:46:40 -07:00
VoyagerOne a18c2c2c3f Don't do InCheck Pruning at the root of QS
STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 34603 W: 6441 L: 6167 D: 21995

LTC:
LLR: 2.97 (-2.94,2.94) [0.00,5.00]
Total: 24474 W: 3274 L: 3076 D: 18124

Bench: 5934421

Closes #1089
2017-04-28 20:40:45 -07:00
Joost VandeVondele d06a8d0c18 Zero unused constant
No functional change

Closes #1081
2017-04-25 17:21:36 -07:00
Marco Costalba b48439e906 Assorted code style issues
I have removed the check for

 pieceCount[PAWN] > FILE_NB

because totally useless.

No functional change.
2017-04-24 09:49:44 +02:00
Joost VandeVondele 9da3b44ddc Use int instead of Value for history related stats.
history related scores are not related to evaluation based scores.
For example, can easily exceed the range -VALUE_INFINITE,VALUE_INFINITE.
As such the current type is confusing, and a plain int is a better match.

tested for no regression:

STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 43693 W: 7909 L: 7827 D: 27957

No functional change.

Closes #1070
2017-04-23 07:59:28 -07:00
Joost VandeVondele ced29248c9 simplify logic for history based pruning
STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 34255 W: 6292 L: 6194 D: 21769

LTC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 89914 W: 11769 L: 11739 D: 66406

Bench: 6581936

Closes #1066
2017-04-20 11:28:11 -07:00
VoyagerOne 9d3ed9ed2e Move-Count Formula Tweak
STC:
LLR: 3.18 (-2.94,2.94) [0.00,4.00]
Total: 55004 W: 10289 L: 9930 D: 34785

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,4.00]
Total: 48184 W: 6401 L: 6128 D: 35655

Bench: 5960754
2017-04-17 09:22:10 -07:00
joergoster 72a501c6fe Fix zugzwang pruning issues
By adding pos.non_pawn_material(pos.side_to_move()) as a precondition in step 13,
which is already in use in Futility Pruning (child node) and Null Move Pruning for similar reasons.

Pawn endgames, especially those with only 1 or 2 pawns, are simply heavily influenced by zugzwang situations.

Since we are using a bitbase for KPK endgames, I see no reason to accept buggy evals as shown in #760

Patch looks neutral at STC
LLR: 2.32 (-2.94,2.94) [-3.00,1.00]
Total: 79580 W: 10789 L: 10780 D: 58011

and LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 27071 W: 3502 L: 3390 D: 20179

Bench: 6259071

Closes #1051
Closes #760
2017-04-07 17:15:00 -07:00
VoyagerOne 35b77b120e Standardize stat penalty
STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 90631 W: 16325 L: 16323 D: 57983

LTC:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 97679 W: 12779 L: 12759 D: 72141

Bench: 6340591

Closes #1053
2017-04-07 17:02:31 -07:00
VoyagerOne ebe021f6a5 Don't update TT at excluded move ply
STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 38906 W: 7125 L: 6835 D: 24946

LTC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 28600 W: 3752 L: 3543 D: 21305

Bench:  6861050

Closes #1048
2017-04-02 20:32:54 -07:00