It would be nice if a future patch could use some of the macros at
the top of the file to unify the code between the distincts SIMD
instruction sets (of course, unifying the Relu will be the challenge).
Trained with pytorch using the master branch and recommended settings,
the data used is the previous 64B binpack enhanced with a 2B binpack
generated using an opening book of positions for with the static eval
is significantly different from d9 search.
book : https://drive.google.com/file/d/1rHcKY5rv34kwku6g89OhnE8Bkfq3UWau/view?usp=sharing
book generation: https://github.com/vondele/Stockfish/commit/3ce43ab0c4ce09c1fc5bca5ca27a248e67fddd24
binpack : https://drive.google.com/file/d/1rHcKY5rv34kwku6g89OhnE8Bkfq3UWau/view?usp=sharing
J. Oster [Mon, 31 May 2021 15:46:40 +0000 (17:46 +0200)]
Pre-initialize ss->ply
We pre-initialize ss->ply over the whole stack. There is no need
to re-assign the same value(s) over and over again while searching.
Probably a tiny speedup on longer searches.
1. it simplifies away the so-called "lazy" path in the NNUE evaluation internals,
where we trusted the psqt head alone to avoid the costly "positional" head in
some cases;
2. it raises a little bit the NNUEThreshold1 in evaluate.cpp (from 682 to 800),
which increases the limit where we switched from NNUE eval to Classical eval.
Both effects increase the number of positional evaluations done by our new net
architecture, but the results of our tests below seem to indicate that the loss
of speed will be compensated by the gain of eval quality.
Tomasz Sobczyk [Tue, 25 May 2021 11:09:40 +0000 (13:09 +0200)]
Expose the lazy threshold for the feature transformer PSQT as a parameter.
Definition of the lazy threshold moved to evaluate.cpp where all others are.
Lazy threshold only used for real searches, not used for the "eval" call.
This preserves the purity of NNUE evaluation, which is useful to verify
consistency between the engine and the NNUE trainer.
Sometimes change the (materialist, positional) balance
Our new nets output two values for the side to move in the last layer.
We can interpret the first value as a material evaluation of the
position, and the second one as the dynamic, positional value of the
location of pieces.
This patch changes the balance for the (materialist, positional) parts
of the score from (128, 128) to (121, 135) when the piece material is
equal between the two players, but keeps the standard (128, 128) balance
when one player is at least an exchange up.
The Tempo variable was introduced 10 years ago in our search because the
classical evaluation function was antisymmetrical in White and Black by design
to gain speed:
Eval(White to play) = -Eval(Black to play)
Nowadays our neural networks know which side is to play in a position when
they evaluate a position and are trained on real games, so the neural network
encodes the advantage of moving as an output of search. This patch shows that
the Tempo variable is not necessary anymore.
We also tried a match (20000 games) at STC using purely classical, result was neutral:
https://tests.stockfishchess.org/tests/view/60a4eebcce8ea25a3ef03db5
Note: there are two locations left in search.cpp where we assume antisymmetry
of evaluation (in relation with a speed optimization for null moves in lines
770 and 1439), but as the values are just used for heuristic pruning this
approximation should not hurt too much because the order of magnitude is still
true most of the time.
Vizvezdenec [Wed, 19 May 2021 17:57:04 +0000 (20:57 +0300)]
Simplify usage of LMR for captures
This patch simplifies a lot of "enablers" for LMR when move is a capture or promotion.
After it we will have only 2 conditions - if node is a cutNode
or if it's an allNode that was not in PV,
so all captures or promotions wouldn't go thru LMR at any PVnodes.
Vizvezdenec [Tue, 18 May 2021 07:02:20 +0000 (10:02 +0300)]
Do more continuation history based pruning
This patch increases lmrDepth threshold for continuation history based pruning in search.
This part of code for a long time was known to be really TC sensitive - decreasing
this threshold easily passed lower time controls but failed badly at LTC,
on the other hand it increase was part of a tuning that resulted
in being negative at STC but was +12 elo at 180+1.8.
After recent simplification of special conditions that sometimes
increase it from 4 to 5 it was logical to overall test at longer
time controls if 5 is better than 4 with deeper searches.
The network has been trained (by vondele) using the https://github.com/glinscott/nnue-pytorch/ trainer (started by glinscott),
specifically the branch https://github.com/Sopel97/nnue-pytorch/tree/experiment_56.
The data used are in 64 billion positions (193GB total) generated and scored with the current master net
d8: https://drive.google.com/file/d/1hOOYSDKgOOp38ZmD0N4DV82TOLHzjUiF/view?usp=sharing
d9: https://drive.google.com/file/d/1VlhnHL8f-20AXhGkILujnNXHwy9T-MQw/view?usp=sharing
d10: https://drive.google.com/file/d/1ZC5upzBYMmMj1gMYCkt6rCxQG0GnO3Kk/view?usp=sharing
fishtest_d9: https://drive.google.com/file/d/1GQHt0oNgKaHazwJFTRbXhlCN3FbUedFq/view?usp=sharing
This network also contains a few architectural changes with respect to the current master:
Size changed from 256x2-32-32-1 to 512x2-16-32-1
~15-20% slower
~2x larger
adds a special path for 16 valued ClippedReLU
fixes affine transform code for 16 inputs/outputs, buy using InputDimensions instead of PaddedInputDimensions
this is safe now because the inputs are processed in groups of 4 in the current affine transform code
The feature set changed from HalfKP to HalfKAv2
Includes information about the kings like HalfKA
Packs king features better, resulting in 8% size reduction compared to HalfKA
The board is flipped for the black's perspective, instead of rotated like in the current master
PSQT values for each feature
the feature transformer now outputs a part that is fowarded directly to the output and allows learning piece values more directly than the previous network architecture. The effect is visible for high imbalance positions, where the current master network outputs evaluations skewed towards zero.
8 PSQT values per feature, chosen based on (popcount(pos.pieces()) - 1) / 4
initialized to classical material values on the start of the training
8 subnetworks (512x2->16->32->1), chosen based on (popcount(pos.pieces()) - 1) / 4
only one subnetwork is evaluated for any position, no or marginal speed loss
A diagram of the network is available: https://user-images.githubusercontent.com/8037982/118656988-553a1700-b7eb-11eb-82ef-56a11cbebbf2.png
A more complete description: https://github.com/glinscott/nnue-pytorch/blob/master/docs/nnue.md
- Comment for Countemove pruning -> Continuation history
- Fix comment in input_slice.h
- Shorter lines in Makefile
- Comment for scale factor
- Fix comment for pinners in see_ge()
- Change Thread.id() signature to size_t
- Trailing space in reprosearch.sh
- Add Douglas Matos Gomes to the AUTHORS file
- Introduce comment for undo_null_move()
- Use Stockfish coding style for export_net()
- Change date in AUTHORS file
Vizvezdenec [Fri, 14 May 2021 21:55:45 +0000 (00:55 +0300)]
Simplification for countermoves based pruning
Simplify away two extra conditions in countermoves based pruning.
These conditions (both of them) were introduced quite a long time ago
via speculative LTCs and seem to no longer bring any benefit.
E2K: added support for MCST Elbrus 2000 CPU architecture
e2k (Elbrus 2000) - this is a VLIW/EPIC architecture,
the like Intel Itanium (IA-64) architecture.
The architecture has half native / half software support
for most Intel/AMD SIMD (e.g. MMX/SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2/AES/AVX/AVX2 & 3DNow!/SSE4a/XOP/FMA4) via intrinsics.
Tomasz Sobczyk [Fri, 7 May 2021 10:24:12 +0000 (12:24 +0200)]
Exporting the currently loaded network file
This PR adds an ability to export any currently loaded network.
The export_net command now takes an optional filename parameter.
If the loaded net is not the embedded net the filename parameter is required.
Two changes were required to support this:
* the "architecture" string, which is really just a some kind of description in the net, is now saved into netDescription on load and correctly saved on export.
* the AffineTransform scrambles weights for some architectures and sparsifies them, such that retrieving the index is hard. This is solved by having a temporary scrambled<->unscrambled index lookup table when loading the network, and the actual index is saved for each individual weight that makes it to canSaturate16. This increases the size of the canSaturate16 entries by 6 bytes.
Vizvezdenec [Wed, 5 May 2021 16:03:20 +0000 (19:03 +0300)]
Cleanup of likelyFailLow logic
This patch broadens and simplifies definition of PvNode that is likely to fail low.
New definition can be described as following "If node was already researched
at depth >= current depth and failed low there" which is more logical than the
previous version and takes less space + allows to not recompute it every time during move loop.
Introduce variable tempo for nnue depending on logarithm of estimated
strength, where strength is the product of time and number of threads.
The original idea here was that NNUE is best with a slightly different
tempo value to classical, since its style of play is slightly different.
It turns out that the best tempo for NNUE varies with strength of play,
so a formula is used which gives about 19 for STC and 24 for LTC under
current fishtest settings.
This patch simplifies QUIET_CHECKS pawn move generator by merging discovery check
move generator with direct check move generator. It also simplifies emptySquares
instantiation. In addition, I added a comment in generate_moves() to clarify Check
branches.
Tomasz Sobczyk [Sat, 24 Apr 2021 13:08:11 +0000 (15:08 +0200)]
Cleanup and simplify NNUE code.
A lot of optimizations happend since the NNUE was introduced
and since then some parts of the code were left unused. This
got to the point where asserts were have to be made just to
let people know that modifying something will not have any
effects or may even break everything due to the assumptions
being made. Removing these parts removes those inexisting
"false dependencies". Additionally:
* append_changed_indices now takes the king pos and stateinfo
explicitly, no more misleading pos parameter
* IndexList is removed in favor of a generic ValueList.
Feature transformer just instantiates the type it needs.
* The update cost and refresh requirement is deferred to the
feature set once again, but now doesn't go through the whole
FeatureSet machinery and just calls HalfKP directly.
* accumulator no longer has a singular dimension.
* The PS constants and the PieceSquareIndex array are made local
to the HalfKP feature set because they are specific to it and
DO differ for other feature sets.
* A few names are changed to more descriptive
NNUE evaluation is incapable of recognizing trivially drawn bishop endgames
(the wrong-colored rook pawn), which are in fact ubiquitous and stock standard
in chess analysis. Switching off NNUE evaluation in KBPs vs KPs endgames is
a measure that stops Stockfish from trading down to a drawn version of these
endings when we presumably have advantage. The patch is able to edge over master
in endgame positions.
Patch tested for Elo gain with the "endgame.epd" book, and verified for
non-regression with our usual book (see the pull request for details).
Verified for correctness of `EVASIONS` by running perft:
```
./stockfish b3nch 16 1 6 default perft (replace 3 by e in b3nch)
Nodes searched : 71608931810
```
Also tested for correctness on Chess960 with a similar code shown here:
https://github.com/official-stockfish/Stockfish/pull/3418#issuecomment-816630295
This patch removes the recently introduced distanceFromPv logic, and replaces
it with following logic: if reduction of moves with low movecount is really
negative, we search them deeper than the first move.
This patch increases the weight of pawns in the scale factor applied
to the output of the NNUE evaluation. This has the effect that Stockfish
will try a little bit harder to keep more pawns in position where the
engine has the advantage, and exchange more pawns in bad positions.
bmc4 [Tue, 30 Mar 2021 03:42:45 +0000 (00:42 -0300)]
Simplify King Evasion
Simplify away the removal of some illegal `KING`-evasion moves during move
generation. Verified for correctness by running perft on the following positions:
Tomasz Sobczyk [Sat, 27 Feb 2021 10:52:18 +0000 (11:52 +0100)]
Allow using Intel SDE for PGO builds.
The software development emulator (SDE) allows to run binaries compiled
for architectures not supported by the actual CPU. This is useful to
do PGO builds for newer architectures. The SDE can currently be obtained from
https://software.intel.com/content/www/us/en/develop/articles/intel-software-development-emulator.html
This patch introduces a new optional makefile argument SDE_PATH.
If not empty it should contain the path to the sde executable
Guy Vreuls [Sat, 13 Mar 2021 16:40:07 +0000 (17:40 +0100)]
Use reference instead of pointer for pop_lsb() signature
This patch changes the pop_lsb() signature from Square pop_lsb(Bitboard*) to
Square pop_lsb(Bitboard&). This is more idomatic for C++ style signatures.
Vizvezdenec [Mon, 15 Mar 2021 18:05:01 +0000 (19:05 +0100)]
Add a specific FRC correction from classical to NNUE
our net currently is not trained on FRC games, and so doesn't know about the important pattern of a bishop that is cornered in FRC.
This patch introduces a term we have in the classical evaluation for this case, and adds it to the NNUE eval.
Since fishtest doesn't support FRC right now, the patch was tested locally at STC conditions,
starting from the book of FRC starting positions.
Score of master vs patch: 993 - 2226 - 6781 [0.438] 10000
Which corresponds to approximately 40 Elo
The patch passes non-regression testing for traditional chess (where it adds one branch).
bmc4 [Mon, 15 Mar 2021 19:06:42 +0000 (16:06 -0300)]
Change definition of between_bb()
We remark that in current master, most of our use cases for between_bb() can be
optimized if the second parameter of the function is added to the segment. So we
change the definition of between_bb(s1, s2) such that it excludes s1 but includes s2.
We also use a precomputed array for between_bb() for another small speed gain
(see https://tests.stockfishchess.org/tests/view/604d09f72433018de7a389fb).
Vizvezdenec [Thu, 11 Mar 2021 11:51:20 +0000 (14:51 +0300)]
Remove advanced_pawn_push()
Continuation of work by @topologist: we now do futility pruning and movecount
pruning in qsearch() for pawn pushes up to the 7th rank. So the condition to
avoid the pruning is if the move is a promotion or not. This allows to get rid
of the advanced_pawn_push() function in position.h alltogether.
bmc4 [Tue, 16 Mar 2021 19:51:31 +0000 (20:51 +0100)]
Introduce least_significant_square_bb()
Introducing least_significant_square_bb(). It is a function that returns a value equal
to square_bb(lsb(bb)), but it uses fewer instruction. It should speed up more on older
processors like armv7-a Clang.
bmc4 [Fri, 5 Mar 2021 11:57:43 +0000 (08:57 -0300)]
Use Bitboard over Square in movegen
It uses pos.checkers() on target when movegen is the type of EVASION.
It simplify the code. And it's also expected a slightly speed up,
because Bitboard is more direct when doing bitwise.
Antoine Champion [Sat, 30 Jan 2021 08:50:04 +0000 (09:50 +0100)]
Clean functions returning by const values
The codebase contains multiple functions returning by const-value.
This patch is a small cleanup making those function returns
by value instead, removing the const specifier.
We introduce a metric for each internal node in search, called DistanceFromPV.
This distance indicated how far the current node is from the principal variation.
We then use this distance to search the nodes which are close to the PV a little
deeper (up to 4 plies deeper than the PV): this improves the quality of the search
at these nodes and bring better updates for the PV during search.
Vizvezdenec [Sat, 20 Feb 2021 21:48:08 +0000 (22:48 +0100)]
Introduce ProbCut for check evasions
The idea of this patch can be described as follows: if we are in check
and the transposition table move is a capture that returns a value
far above beta, we can assume that the opponent just blundered a piece
by giving check, and we return the transposition table value. This is
similar to the usual probCut logic for quiet moves, but with a different
threshold.
The committed version has an additional fix to never return unproven wins
in the tablebase range or the mate range. This fix passed tests for non-
regression at STC and LTC:
Vizvezdenec [Fri, 19 Feb 2021 07:32:12 +0000 (10:32 +0300)]
Tune search parameters (with Unai Corzo)
The values used in this patch are taken from a SPSA parameter tuning session
originated by Unai Corzo (@unaiic), but the final difference of his tune was
multiplied x2 by hand. Most of the credits should go to him :-)
It is our pleasure to release Stockfish 13 to chess fans worldwide.
As usual, downloads are freely available at
https://stockfishchess.org
The Stockfish project builds on a thriving community of enthusiasts
who contribute their expertise, time, and resources to build a free
and open-source chess engine that is robust, widely available, and
very strong. We would like to thank them all!
The good news first: from now on, our users can expect more frequent
high-quality releases of Stockfish! Sadly, this decision has been
triggered by the start of sales of the Fat Fritz 2 engine by ChessBase,
which is a copy of a very recent development version of Stockfish
with minor modifications. We refer to our statement on Fat Fritz 2[1]
and a community blog[2] for further information.
This version of Stockfish is significantly stronger than any of its
predecessors. Stockfish 13 outperforms Stockfish 12 by at least
35 Elo[3]. When playing against a one-year-old Stockfish, it wins 60
times more game pairs than it loses[4]. This release features an NNUE
network retrained on billions of positions, much faster network
evaluation code, and significantly improved search heuristics, as
well as additional evaluation tweaks. In the course of its development,
this version has won the superfinals of the TCEC Season 19 and
TCEC Season 20.
Going forward, the Leela Chess Zero and Stockfish teams will join
forces to demonstrate our commitment to open source chess engines and
training tools, and open data. We are convinced that our free and
open-source chess engines serve the chess community very well.
Stay safe and enjoy chess!
The Stockfish team
[1] https://blog.stockfishchess.org/post/643239805544792064/statement-on-fat-fritz-2
[2] https://lichess.org/blog/YCvy7xMAACIA8007/fat-fritz-2-is-a-rip-off
[3] https://tests.stockfishchess.org/tests/view/602bcccf7f517a561bc49b11
[4] https://tests.stockfishchess.org/tests/view/600fbb9c735dd7f0f0352d59
• reorder some sections of the README file
• add reference to the AUTHORS file
• rename Syzygybases to Syzygy tablebases
• add pointer to the Discord channel
• more precise info about the GPLv3 licence
Vizvezdenec [Thu, 11 Feb 2021 07:45:16 +0000 (10:45 +0300)]
PV-Nodes likely to fail low
Do not decrease reduction at pv-nodes which are likely to fail low.
The idea of this patch can be described as following: during the search, if a node
on the principal variation was re-searched in non-pv search and this re-search got
a value which was much lower than alpha, then we can assume that this pv-node is
likely to fail low again, and we can reduce more aggressively at this node.
mattginsberg [Thu, 11 Feb 2021 21:29:28 +0000 (22:29 +0100)]
Better code for hash table generation
This patch removes some magic numbers in TT bit management and introduce proper
constants in the code, to improve documentation and ease further modifications.
This patch give a small bonus to incite the attacking side to keep more
pawns on the board.
A consequence of this bonus is that Stockfish will tend to play positions
slightly more closed on average than master, especially when it believes
that it has an advantage.
To lower the risk of blockades where Stockfish start shuffling without
progress, we also implement a progressive decrease of the evaluation
value with the 50 moves counter (along with the necessary aging of the
transposition table to reduce the impact of the Graph History Interaction
problem): since the evaluation decreases during shuffling phases, the
engine will tend to examine the consequences of pawn breaks faster during
the search.