Compare commits

..

402 Commits

Author SHA1 Message Date
Joost VandeVondele 758f9c9350 Stockfish 15.1
Official release version of Stockfish 15.1

Bench: 3467381

---

Today, we have the pleasure to announce Stockfish 15.1.

As usual, downloads will be freely available at stockfishchess.org/download

*Elo gain and competition results*

With this release, version 5 of the NNUE neural net architecture has
been introduced, and the training data has been extended to include
Fischer random chess (FRC) positions. As a result, Elo gains are largest
for FRC, reaching up to 50 Elo for doubly randomized FRC[1] (DFRC).
More importantly, also for standard chess this release progressed and
will win two times more game pairs than it loses[2] against
Stockfish 15. Stockfish continues to win in a dominating way[3] all
chess engine tournaments, including the TCEC Superfinal, Cup, FRC, DFRC,
and Swiss as well as the CCC Bullet, Blitz, and Rapid events.

*New evaluation*

This release also introduces a new convention for the evaluation that
is reported by search. An evaluation of +1 is now no longer tied to the
value of one pawn, but to the likelihood of winning the game. With
a +1 evaluation, Stockfish has now a 50% chance of winning the game
against an equally strong opponent. This convention scales down
evaluations a bit compared to Stockfish 15 and allows for consistent
evaluations in the future.

*ChessBase settlement*

In this release period, the Stockfish team has successfully enforced
its GPL license against ChessBase. This has been an intense process that
included filing a lawsuit[4], a court hearing[5], and finally
negotiating a settlement[6] that established that ChessBase infringed on
the license by not distributing the Stockfish derivatives Fat Fritz 2
and Houdini 6 as free software, and that ensures ChessBase will respect
the Free Software principles in the future. This settlement has been
covered by major chess sites (see e.g. lichess.org[7] and chess.com[8]),
and we are proud that it has been hailed as a ‘historic violation
settlement[9]’ by the Software Freedom Conservancy.

*Thank you*

The Stockfish project builds on a thriving community of enthusiasts
(thanks everybody!) that contribute their expertise, time, and resources
to build a free and open-source chess engine that is robust, widely
available, and very strong. We invite our chess fans to join the
fishtest testing framework and programmers to contribute to the
project[10].

The Stockfish team

[1] https://tests.stockfishchess.org/tests/view/638a6170d2b9c924c4c62cb4
[2] https://tests.stockfishchess.org/tests/view/638a4dd7d2b9c924c4c6297b
[3] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results
[4] https://stockfishchess.org/blog/2021/our-lawsuit-against-chessbase/
[5] https://stockfishchess.org/blog/2022/public-court-hearing-soon/
[6] https://stockfishchess.org/blog/2022/chessbase-stockfish-agreement/
[7] https://lichess.org/blog/Y3u1mRAAACIApBVn/settlement-reached-in-stockfish-v-chessbase
[8] https://www.chess.com/news/view/chessbase-stockfish-reach-settlement
[9] https://sfconservancy.org/news/2022/nov/28/sfc-named-trusted-party-in-gpl-case/
[10] https://stockfishchess.org/get-involved/
2022-12-04 14:17:15 +01:00
Joost VandeVondele d60f5de967 Fix bestThread selection
If multiple threads have the same best move,
pick the thread with the largest contribution to the confidence vote.
This thread will later be used to display PV, so this patch is
about user-friendliness and/or least surprises, it non-functional for playing strenght.

closes https://github.com/official-stockfish/Stockfish/pull/4246

No functional change
2022-12-02 20:06:59 +01:00
VoyagerOne c7118fb46d Simply do full sort on captures.
STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 42712 W: 11413 L: 11203 D: 20096
Ptnml(0-2): 145, 4661, 11544, 4851, 155
https://tests.stockfishchess.org/tests/view/6384df57d2b9c924c4c53900

LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 239072 W: 64065 L: 64067 D: 110940
Ptnml(0-2): 106, 23735, 71859, 23727, 109
https://tests.stockfishchess.org/tests/view/63851120d2b9c924c4c541ee

closes https://github.com/official-stockfish/Stockfish/pull/4249

Bench: 3467381
2022-12-02 20:05:50 +01:00
VoyagerOne 6a6faac04d Remove PvNode Parameter for cutoff LMR
STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 198520 W: 52673 L: 52632 D: 93215
Ptnml(0-2): 645, 22241, 53499, 22178, 697
https://tests.stockfishchess.org/tests/view/63746e8f9849fa7a36a6698f

LTC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 253568 W: 67487 L: 67501 D: 118580
Ptnml(0-2): 109, 25222, 76141, 25198, 114
https://tests.stockfishchess.org/tests/view/63839859d2b9c924c4c4feb7

closes https://github.com/official-stockfish/Stockfish/pull/4248

Bench: 3733322
2022-12-02 20:03:49 +01:00
Guenther Demetz f5a31b7e57 Correctly output lowerbound/upperbound in threaded searches
fixes the lowerbound/upperbound output by taking the alpha,beta bracket
into account also if a bestThread is selected that is different from the master thread.

Instead of keeping track which bounds where used in the specific search,
in this version we simply store the quality (exact, upperbound,
lowerbound) of the score along with the actual score as information on
rootMove.

closes https://github.com/official-stockfish/Stockfish/pull/4239

No functional change
2022-11-23 21:45:06 +01:00
peregrineshahin 1370127fcd Simplify both quiet check evasions' conditions
passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/6370b647f1b748d4819e0b64
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 162904 W: 43249 L: 43171 D: 76484
Ptnml(0-2): 491, 17089, 46220, 17155, 497

closes https://github.com/official-stockfish/Stockfish/pull/4228

No functional change
2022-11-23 21:36:22 +01:00
VoyagerOne 85ae65db1d Skip full depth search in LMR depending on depth
dynamically adjust newDepth, and skip full depth search if newDepth doesn't exceed the previous search depth.
This affects the used newDepth for future searches, and influences the stat bonus for the move.

Passed STC:
https://tests.stockfishchess.org/tests/view/63795500aa34433735bc1cfe
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 112776 W: 30082 L: 29663 D: 53031
Ptnml(0-2): 352, 12453, 30423, 12744, 416

Passed LTC:
https://tests.stockfishchess.org/tests/view/6379ea39aa34433735bc2f9b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 83576 W: 22559 L: 22169 D: 38848
Ptnml(0-2): 38, 8011, 25303, 8395, 41

closes https://github.com/official-stockfish/Stockfish/pull/4240

Bench: 4390318
2022-11-23 21:25:14 +01:00
Joost VandeVondele d8f3209fb4 Update Top CPU Contributors
list as of 2022-11-19. Thanks!

closes https://github.com/official-stockfish/Stockfish/pull/4234

No functional change
2022-11-20 10:00:42 +01:00
Joost VandeVondele 3411631162 Update WDL model for current SF
This updates the WDL model based on the LTC statistics  (2M games).

Relatively small change, note that this also adjusts the NormalizeToPawnValue (now 361),
to keep win prob at 50% for 100cp.

closes https://github.com/official-stockfish/Stockfish/pull/4236

No functional change.
2022-11-20 09:59:35 +01:00
Joost VandeVondele d756d97a66 Fix a missing conversion
This conversion to cp was overlooked.

closes https://github.com/official-stockfish/Stockfish/pull/4235

No functional change
2022-11-20 09:58:07 +01:00
VoyagerOne 41c6a74d37 Simplification away Cutoff Reset
STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 150184 W: 39913 L: 39819 D: 70452
Ptnml(0-2): 493, 16796, 40474, 16782, 547
https://tests.stockfishchess.org/tests/view/63723e9e54d69a2f33911d3c

LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 58880 W: 15890 L: 15717 D: 27273
Ptnml(0-2): 35, 5765, 17659, 5954, 27
https://tests.stockfishchess.org/tests/view/6373baf49849fa7a36a65427

closes https://github.com/official-stockfish/Stockfish/pull/4231

Bench: 4035152
2022-11-19 09:29:04 +01:00
Michael Chaly 219fa2f0a7 Do shallower search in case of lmr being not successful enough
In case of a move passing LMR but it results being not too far from
the current best search result produce a full depth search with reduced depth.

Original idea by lonfom169 .

Passed STC:
https://tests.stockfishchess.org/tests/view/6373409b54d69a2f33913fbd
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 169504 W: 45351 L: 44848 D: 79305
Ptnml(0-2): 598, 18853, 45353, 19344, 604

Passed LTC:
https://tests.stockfishchess.org/tests/view/6374c58528e3405283eb8d2d
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 51144 W: 13802 L: 13471 D: 23871
Ptnml(0-2): 19, 4928, 15362, 5229, 34

closes https://github.com/official-stockfish/Stockfish/pull/4230

bench 4277005
2022-11-19 09:23:26 +01:00
disservin 6c1df553fa speedup CI
Github Actions allows us to use up to 20 workers.
This way we can launch multiple different checks
at the same time and optimize the overall time
the CI takes a bit.

closes https://github.com/official-stockfish/Stockfish/pull/4223

No functional change
2022-11-07 21:42:04 +01:00
disservin a413900791 Remove trend
Simplify trend away.

passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/63642a63a90afcecbd1cb887
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 130000 W: 34683 L: 34567 D: 60750
Ptnml(0-2): 455, 14424, 35135, 14522, 464

passed Non-regression LTC:
https://tests.stockfishchess.org/tests/view/636566fda90afcecbd1cded9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 81592 W: 21938 L: 21787 D: 37867
Ptnml(0-2): 42, 8035, 24490, 8188, 41

closes https://github.com/official-stockfish/Stockfish/pull/4222

Bench: 4239512
2022-11-07 08:00:05 +01:00
disservin e048d11825 Change versioning and save binaries as CI artifacts
For development versions of Stockfish, the version will now look like
dev-20221107-dca9a0533
indicating a development version, the date of the last commit,
and the git SHA of that commit. If git is not available,
the fallback is the date of compilation. Releases will continue to be
versioned as before.

Additionally, this PR extends the CI to create binary artifacts,
i.e. pushes to master will automatically build Stockfish and upload
the binaries to github.

closes https://github.com/official-stockfish/Stockfish/pull/4220

No functional change
2022-11-07 07:56:58 +01:00
Joost VandeVondele ad2aa8c06f Normalize evaluation
Normalizes the internal value as reported by evaluate or search
to the UCI centipawn result used in output. This value is derived from
the win_rate_model() such that Stockfish outputs an advantage of
"100 centipawns" for a position if the engine has a 50% probability to win
from this position in selfplay at fishtest LTC time control.

The reason to introduce this normalization is that our evaluation is, since NNUE,
no longer related to the classical parameter PawnValueEg (=208). This leads to
the current evaluation changing quite a bit from release to release, for example,
the eval needed to have 50% win probability at fishtest LTC (in cp and internal Value):

June 2020  :   113cp (237)
June 2021  :   115cp (240)
April 2022 :   134cp (279)
July 2022  :   167cp (348)

With this patch, a 100cp advantage will have a fixed interpretation,
i.e. a 50% win chance. To keep this value steady, it will be needed to update the win_rate_model()
from time to time, based on fishtest data. This analysis can be performed with
a set of scripts currently available at https://github.com/vondele/WLD_model

fixes https://github.com/official-stockfish/Stockfish/issues/4155
closes https://github.com/official-stockfish/Stockfish/pull/4216

No functional change
2022-11-05 09:15:53 +01:00
Joost VandeVondele 61a2cb84a6 Mark variable as potentially unused
fixes CI when compiled with -Werror

closes https://github.com/official-stockfish/Stockfish/pull/4221

No functional change
2022-11-05 09:15:14 +01:00
kurt22i d09653df0d Adjust reduction less at medium depths
This patch dampens the reduction increase/decrease from statScore at mid-range depths.
Inspired by patterns noticed in this tune: https://tests.stockfishchess.org/tests/view/635188930e5f47a8d0ffe8f5

Passed STC:
https://tests.stockfishchess.org/tests/view/63599dfd6b27ef94d9ec04af
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 87464 W: 23519 L: 23134 D: 40811
Ptnml(0-2): 319, 9599, 23524, 9958, 332

Passed LTC:
https://tests.stockfishchess.org/tests/view/635a73046b27ef94d9ec2313
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 154792 W: 41746 L: 41214 D: 71832
Ptnml(0-2): 79, 15181, 46349, 15703, 84

closes https://github.com/official-stockfish/Stockfish/pull/4213

Bench 4271738
2022-10-30 16:19:09 +01:00
Joost VandeVondele f154ed7a2d Update MacOS CI
move to 12 following actions runner update deprecation
(see https://github.com/actions/runner-images/issues/5583)

closes https://github.com/official-stockfish/Stockfish/pull/4212

No functional change
2022-10-30 16:17:49 +01:00
Clausable 8333b2a94c Fix README typos, update AUTHORS
closes https://github.com/official-stockfish/Stockfish/pull/4208

No functional change
2022-10-27 08:15:46 +02:00
dav1312 a5500edc55 Add issue template
Add an issue template using GitHub's form schema
https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema

closes https://github.com/official-stockfish/Stockfish/pull/4210

No functional change.
2022-10-26 20:28:12 +02:00
Michael Chaly 4ec8945eaf Use TT moves more often in qsearch
During the recapture phase of quiescence search (where we limit the generated moves to recaptures on the last seen capture square),
the move picker will now emit the tt move, even if the tt move is not a recapture.

Passed STC :
https://tests.stockfishchess.org/tests/view/6350df2928d3a71cb1eef838
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 90280 W: 24001 L: 23845 D: 42434
Ptnml(0-2): 273, 9779, 24941, 9813, 334

Passed LTC :
https://tests.stockfishchess.org/tests/view/6351308b28d3a71cb1ef06ce
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 104504 W: 27937 L: 27807 D: 48760
Ptnml(0-2): 54, 10378, 31260, 10504, 56

closes https://github.com/official-stockfish/Stockfish/pull/4206

Bench: 4540268
2022-10-23 20:22:04 +02:00
Clement 5604b255e6 Add RISC-V 64-bit support
adds a riscv64 target architecture to the Makefile to support RISC-V 64-bit.
Compiled and tested on VisionFive 2 board.

closes https://github.com/official-stockfish/Stockfish/pull/4205

No functional change.
2022-10-23 20:18:08 +02:00
disservin 804394b939 enable bit manipulation instruction set 1
bmi1 enables the use of _blsr_u64 for pop_lsb, and is availabe when avx2 is.

verified a small speedup (0.2 - 0.6%)

closes https://github.com/official-stockfish/Stockfish/pull/4202

No functional change
2022-10-23 20:08:18 +02:00
MinetaS 234d2156fd Apply -flto-partition=one / -flto=full
This patch fixes a potential bug derived from an incompatibility between LTO and top-level assembly code (INCBIN).

Passed non-regression STC (master e90341f):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119352 W: 31986 L: 31862 D: 55504
Ptnml(0-2): 439, 12624, 33400, 12800, 413
https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b

closes https://github.com/official-stockfish/Stockfish/pull/4201

No functional change
2022-10-23 19:58:47 +02:00
Rodrigo Roim 79c5f3a692 Fix tablebase probe for dtz >1000 w/o 50 move rule
For qn4N1/6R1/3K4/8/B2k4/8/8/8 w - - 0 1, white loses with DTZ 1034.
See https://syzygy-tables.info/?fen=qn4N1/6R1/3K4/8/B2k4/8/8/8_w_-_-_0_1

Prior to this fix, due to a too small hard-coded value, Stockfish interpreted this as winning.
The new value picked (1<<18) is large enough to deal with the largest DTZ values that can be stored in the current syzygy format.

closes https://github.com/official-stockfish/Stockfish/pull/4187

No functional change.
2022-10-16 12:58:48 +02:00
xoto10 9be2977da7 Adjust timeman constants
Adjust timeman constants to use more time in early part of game.

STC @ 10+0.1 th 1 :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 93984 W: 25177 L: 24787 D: 44020
Ptnml(0-2): 350, 10096, 25729, 10448, 369
https://tests.stockfishchess.org/tests/live_elo/6339077135f43d649ff6162a

LTC @ 60+0.6 th 1 :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 329368 W: 88953 L: 88093 D: 152322
Ptnml(0-2): 170, 31457, 100594, 32269, 194
https://tests.stockfishchess.org/tests/live_elo/6339baed35f43d649ff63142

Sudden death 10+0 :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 20400 W: 5908 L: 5588 D: 8904
Ptnml(0-2): 177, 2252, 5128, 2360, 283
https://tests.stockfishchess.org/tests/live_elo/6347c9384bc7650f07549ba7

Sudden death 10+0, no adjudication :
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 17920 W: 4755 L: 4442 D: 8723
Ptnml(0-2): 137, 1985, 4466, 2172, 200
https://tests.stockfishchess.org/tests/live_elo/634806e84bc7650f0754a639

closes https://github.com/official-stockfish/Stockfish/pull/4188

No functional change
2022-10-16 11:51:41 +02:00
Stéphane Nicolet d6b6360ff5 Tweak the formula for NNUE complexity
Joint work by Ofek Shochat and Stéphane Nicolet.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 93288 W: 24996 L: 24601 D: 43691
Ptnml(0-2): 371, 10263, 24989, 10642, 379
https://tests.stockfishchess.org/tests/view/63448f4f4bc7650f07541987

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 84168 W: 22771 L: 22377 D: 39020
Ptnml(0-2): 47, 8181, 25234, 8575, 47
https://tests.stockfishchess.org/tests/view/6345186d4bc7650f07542fbd

================

It seems there are two effects with this patch:

effect A :

If Stockfish is winning at root, we have optimism > 0 for all leaves in
the search tree where Stockfish is to move. There, if (psq - nnue) > 0
(ie if the advantage is more materialistic than positional), then the
product D = optimism * (psq - nnue) will be positive, nnueComplexity will
increase, and the eval will increase from SF point of view.

So the effect A is that if Stockfish is winning at root, she will slightly
favor in the search tree (in other words, search more) the positions where
she can convert her advantage via materialist means.

effect B :

If Stockfish is losing at root, we have optimism > 0 for all leaves in
the search tree where the opponent is to move. There, if (psq - nnue) < 0
(ie if the opponent advantage is more positional than materialistic), then
the product D = optimism * (psq-nnue) will be negative, nnueComplexity will
decrease, and the eval will decrease from the opponent point of view.

So the effect B is that Stockfish will slightly favor in the search tree
(search more) the branches where she can defend by slowly reducing the
opponent positional advantage.

=================

closes https://github.com/official-stockfish/Stockfish/pull/4195

bench: 4673898
2022-10-16 11:49:07 +02:00
Dubslow f97a86e213 Remove depth condition from razoring
The eval condition depends on depth anyways, so this patch is nearly (not quite) non-functional

passed STC:
https://tests.stockfishchess.org/tests/view/63428169fb7ccb2ea9be2629
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 185992 W: 49612 L: 49558 D: 86822
Ptnml(0-2): 618, 19956, 51842, 19914, 666

passed LTC:
https://tests.stockfishchess.org/tests/view/634418b14bc7650f07540760
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 126816 W: 34147 L: 34043 D: 58626
Ptnml(0-2): 74, 11941, 39281, 12031, 81

closes https://github.com/official-stockfish/Stockfish/pull/4196

bench 4148700
2022-10-16 11:45:16 +02:00
mstembera 93f71ecfe1 Optimize make_index() using templates and lookup tables.
https://tests.stockfishchess.org/tests/view/634517e54bc7650f07542f99
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 642672 W: 171819 L: 170658 D: 300195
Ptnml(0-2): 2278, 68077, 179416, 69336, 2229

this also introduces `-flto-partition=one` as suggested by MinetaS (Syine Mineta)
to avoid linking errors due to LTO on 32 bit mingw. This change was tested in isolation as well

https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119352 W: 31986 L: 31862 D: 55504
Ptnml(0-2): 439, 12624, 33400, 12800, 413

closes https://github.com/official-stockfish/Stockfish/pull/4199

No functional change
2022-10-16 11:42:19 +02:00
Stefan Geschwentner e90341f9c9 Tweak history initialization
Simplify initialization of continuation history by using everywhere the same starting value.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 90952 W: 24312 L: 24153 D: 42487
Ptnml(0-2): 356, 10168, 24290, 10285, 377
https://tests.stockfishchess.org/tests/view/633948f235f43d649ff61fd0

LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 162416 W: 43540 L: 43466 D: 75410
Ptnml(0-2): 77, 16289, 48417, 16333, 92
https://tests.stockfishchess.org/tests/view/6339ee8a35f43d649ff63986

closes  https://github.com/official-stockfish/Stockfish/pull/4186

Bench: 4156027
2022-10-08 18:09:02 +02:00
Giacomo Lorenzetti d5271af0ee Remove old line in "Futility pruning for captures"
The line is no longer needed after https://github.com/official-stockfish/Stockfish/commit/910cf8b21839eb9f1991934a5436eea112021723.
This patch incidentally applies "Futility Pruning for Captures" also in case of en-passant, changing the bench signature.

Passed STC:
https://tests.stockfishchess.org/tests/view/6332c1f1208c26088697b731
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 68760 W: 18440 L: 18256 D: 32064
Ptnml(0-2): 267, 7530, 18595, 7728, 260

Passed LTC:
https://tests.stockfishchess.org/tests/view/633312e9208c26088697c59b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 455552 W: 121910 L: 122123 D: 211519
Ptnml(0-2): 253, 45439, 136600, 45236, 248

closes https://github.com/official-stockfish/Stockfish/pull/4185

Bench: 4374521
2022-10-08 18:07:30 +02:00
Joost VandeVondele da937e219e Revert "Mix alpha and statScore for reduction"
This reverts commit 8bab09749d.

In this form the patch reduces mate finding effectiveness, as the large alpha value has negative influence on the reductions.

see also https://github.com/official-stockfish/Stockfish/pull/4183

Bench: 4114228
2022-10-05 22:59:05 +02:00
FauziAkram 8bab09749d Mix alpha and statScore for reduction
Idea by @xoto10, and tuning by @FauziAkram.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 57832 W: 15540 L: 15199 D: 27093
Ptnml(0-2): 207, 6343, 15477, 6680, 209
https://tests.stockfishchess.org/tests/view/6338db6f35f43d649ff60fdc

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 50968 W: 13770 L: 13440 D: 23758
Ptnml(0-2): 25, 4905, 15306, 5211, 37
https://tests.stockfishchess.org/tests/view/6339777035f43d649ff62686

Links to the tuning sessions:
https://tests.stockfishchess.org/tests/view/63345725a004bed9a2e47b28
https://tests.stockfishchess.org/tests/view/63345728a004bed9a2e47b2a

closes https://github.com/official-stockfish/Stockfish/pull/4183

Bench: 4426602
2022-10-04 01:07:27 +02:00
disservin f436bf77ad Use less reduction for escaping moves
This patch reuses the threatenedPieces variable (which is calculated in movepicker)
to reduce less in the search tree the moves which escape a capture.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 314352 W: 84042 L: 83328 D: 146982
Ptnml(0-2): 1105, 35084, 84207, 35552, 1228
https://tests.stockfishchess.org/tests/view/63355f37a004bed9a2e4a17f

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 90752 W: 24556 L: 24147 D: 42049
Ptnml(0-2): 59, 8855, 27123, 9296, 43
https://tests.stockfishchess.org/tests/view/63383a7735f43d649ff5fa8b

closes https://github.com/official-stockfish/Stockfish/pull/4181

bench: 4114228
2022-10-03 11:50:31 +02:00
peregrineshahin 232bf19be4 Simplify both position calls in useClassical
Simplify the use of classical evaluation when using default settings to only be dependent on piece count and decisive PSQ

passed STC:
https://tests.stockfishchess.org/tests/view/632d32a7006ef9eb96d86ce9
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108048 W: 28904 L: 28763 D: 50381
Ptnml(0-2): 383, 12060, 29006, 12183, 392

passed LTC:
https://tests.stockfishchess.org/tests/view/632d705a006ef9eb96d87649
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 76600 W: 20671 L: 20516 D: 35413
Ptnml(0-2): 34, 7533, 23023, 7664, 46

Inspired by sorais, credit to him.

closes https://github.com/official-stockfish/Stockfish/pull/4177

bench  4173163
2022-09-27 07:54:36 +02:00
Brad Knox 4339a756ac Update README.md
Adding some svg icons and additional information, insert links as references

closes https://github.com/official-stockfish/Stockfish/pull/4176

No functional change
2022-09-27 07:52:38 +02:00
Torsten Hellwig 70e51a5bc8 Always output hashfull
This removes the restriction that no hashfull information is printed within the first second of a search.
On modern systems, a non-zero value is returned within 6 ms with default settings.

passed STC:
https://tests.stockfishchess.org/tests/view/63277b08b9c0caa5f4a798e4
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 290096 W: 77505 L: 77561 D: 135030
Ptnml(0-2): 1008, 30713, 81592, 30797, 938

closes https://github.com/official-stockfish/Stockfish/pull/4174

No functional change
2022-09-27 07:48:05 +02:00
mstembera 29295ecfd3 Simplify EVASIONS scoring
remove some multipliers & adjust, doesn't change the move ordering

STC https://tests.stockfishchess.org/tests/view/6325c1c9b9c0caa5f4a759ae
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 192760 W: 51528 L: 51482 D: 89750
Ptnml(0-2): 642, 20490, 54148, 20380, 720

Credit to locutus2

closes https://github.com/official-stockfish/Stockfish/pull/4171

No functional change
2022-09-27 07:44:46 +02:00
mstembera dc0c441b7c Prioritize checks in movepicker
give a little bonus for moving pieces to squares where they give check

STC: https://tests.stockfishchess.org/tests/view/631da742162491686d2e40b5
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 80072 W: 21753 L: 21368 D: 36951
Ptnml(0-2): 421, 8876, 21075, 9225, 439

LTC: https://tests.stockfishchess.org/tests/view/631dd9e6b85daa436625de1d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 263480 W: 70916 L: 70158 D: 122406
Ptnml(0-2): 322, 26156, 78029, 26908, 325

similar ideas have been tested by Viz and Guenther

closes https://github.com/official-stockfish/Stockfish/pull/4165

bench: 4326572
2022-09-17 09:30:52 +02:00
atumanian 154e7afed0 Simplify trend and optimism.
This patch simplifies the formulas used to compute the trend and optimism values before each search iteration.
As a side effect, this removes the parameters which make the relationship between the displayed evaluation value
and the expected game result asymmetric.

I've also provided links to the results of isotonic regression analysis of the relationship between the evaluation and game result (statistical data and a graph) for both tests, which demonstrate that the new version has a more symmetric relationship:

STC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3548954)
LTC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3626311)
See also https://github.com/official-stockfish/Stockfish/issues/4142

passed STC:
https://tests.stockfishchess.org/tests/view/6313f44b8202a039920e27e6
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108016 W: 28903 L: 28760 D: 50353
Ptnml(0-2): 461, 12075, 28850, 12104, 518

passed LTC:
https://tests.stockfishchess.org/tests/view/631de45db85daa436625dfe6
LLR: 3.01 (-2.94,2.94) <-1.75,0.25>
Total: 34792 W: 9412 L: 9209 D: 16171
Ptnml(0-2): 24, 3374, 10397, 3577, 24

Furthermore, this does not measurably impact Elo strength against weaker engines,
as demonstrated in a match of master and patch vs SF13:

This patch vs SF 13:
https://tests.stockfishchess.org/tests/view/631fa34ae1612778c344c6eb
Elo: 141.66 +-1.2 (95%) LOS: 100.0%
Total: 100000 W: 48182 L: 9528 D: 42290
Ptnml(0-2): 96, 1426, 13277, 30130, 5071
nElo: 284.13 +-3.3 (95%) PairsRatio: 23.13

Master vs SF 13:
https://tests.stockfishchess.org/tests/view/631fa3ece1612778c344c6ff
Elo: 143.26 +-1.2 (95%) LOS: 100.0%
Total: 100000 W: 48525 L: 9479 D: 41996
Ptnml(0-2): 94, 1537, 13098, 29771, 5500
nElo: 281.70 +-3.3 (95%) PairsRatio: 21.63

closes: https://github.com/official-stockfish/Stockfish/pull/4163

Bench: 4425574
2022-09-17 09:13:07 +02:00
Joost VandeVondele 5a871e174f Explicitly annotate a few variables
as [[maybe_unused]], avoiding the (void)foo trick.

closes https://github.com/official-stockfish/Stockfish/pull/4162

No functional change
2022-09-17 09:05:35 +02:00
mstembera 82bb21dc7a Optimize AVX2 path in NNUE evaluation
always selecting AffineTransform specialization for small inputs.

A related patch was tested as

Initially tested as a simplification
STC https://tests.stockfishchess.org/tests/view/6317c3f437f41b13973d6dff
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 58072 W: 15619 L: 15425 D: 27028
Ptnml(0-2): 241, 6191, 15992, 6357, 255

Elo gain speedup test
STC https://tests.stockfishchess.org/tests/view/63181c1b37f41b13973d79dc
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 184496 W: 49922 L: 49401 D: 85173
Ptnml(0-2): 851, 19397, 51208, 19964, 828

and this patch gained in testing

speedup        = +0.0071
P(speedup > 0) =  1.0000
on CPU: 16 x AMD Ryzen 9 3950X

closes https://github.com/official-stockfish/Stockfish/pull/4158

No functional change
2022-09-11 14:19:57 +02:00
Michael Chaly 1591e5ac3b Do less singular extensions for former PVnode
Patch is a reintroduction of logic what was simplified a while ago
in a slightly different form. Do bigger extension offset in
case of non-pv node having a pv.

passed STC
https://tests.stockfishchess.org/tests/view/631977c048f27688a06e66d5
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 23296 W: 6404 L: 6108 D: 10784
Ptnml(0-2): 88, 2539, 6118, 2795, 108

passed LTC
https://tests.stockfishchess.org/tests/view/631989cb48f27688a06e696c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 235592 W: 63890 L: 63188 D: 108514
Ptnml(0-2): 275, 23392, 69804, 24006, 319

closes https://github.com/official-stockfish/Stockfish/pull/4159

Bench: 3993611
2022-09-11 14:15:54 +02:00
Dubslow 9fa258ee1d Razor also on PV nodes
Simplification introduced by xoto10

blue LTC vs new master:
https://tests.stockfishchess.org/tests/view/631ad4ef9cfa5e9b648d1b4e
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 59184 W: 16002 L: 15828 D: 27354
Ptnml(0-2): 65, 5777, 17747, 5925, 78

blue STC vs old master:
https://tests.stockfishchess.org/tests/view/6306b87b902a848543334c25
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 213944 W: 57184 L: 57159 D: 99601
Ptnml(0-2): 877, 23448, 58331, 23405, 911

blue LTC vs old master:
https://tests.stockfishchess.org/tests/view/63070e6b902a8485433357e7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 192080 W: 52050 L: 52006 D: 88024
Ptnml(0-2): 232, 18981, 57611, 18943, 273

closes https://github.com/official-stockfish/Stockfish/pull/4147

bench 4208975
2022-09-11 14:13:24 +02:00
Michael Chaly eaf2c8207f Further LTC tuning of search parameters
Tuning done by bigpenor with some hand adjustments on top by Viz.

Had a good performance at fixed games 180+1.8:
https://tests.stockfishchess.org/tests/view/631836b437f41b13973d7da1
Elo: 1.35 +-1.2 (95%) LOS: 98.6%
Total: 60000 W: 16422 L: 16189 D: 27389
Ptnml(0-2): 39, 5335, 18992, 5622, 12
nElo: 3.13 +-2.8 (95%) PairsRatio: 1.05

Passed 60+0.6 8 threads SPRT:
https://tests.stockfishchess.org/tests/view/631ba0ff74bc4fe483a99db3
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 29712 W: 8301 L: 8039 D: 13372
Ptnml(0-2): 12, 2318, 9925, 2598, 3

closes https://github.com/official-stockfish/Stockfish/pull/4160

bench 3938073
2022-09-11 14:05:39 +02:00
FauziAkram 5eeb96d0e7 VLTC tuning
Tuning some parameters that scale well with longer time control:

Failed STC:
https://tests.stockfishchess.org/tests/view/6313424d8202a039920e130a
LLR: -2.94 (-2.94,2.94) <-1.75,0.25>
Total: 42680 W: 11231 L: 11540 D: 19909
Ptnml(0-2): 191, 5008, 11232, 4737, 172

Passed LTC:
https://tests.stockfishchess.org/tests/view/6311e2cd874169ca52ae7933
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 53448 W: 14782 L: 14437 D: 24229
Ptnml(0-2): 101, 5214, 15740, 5577, 92

Passed VLTC:
https://tests.stockfishchess.org/tests/view/6312530cfa99a92e3002c927
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 123336 W: 33465 L: 33007 D: 56864
Ptnml(0-2): 38, 11466, 38204, 11920, 40

closes https://github.com/official-stockfish/Stockfish/pull/4154

Bench: 5609606
2022-09-07 07:38:04 +02:00
Joost VandeVondele a4d18d23a9 Provide network download fallback
in case the base infrastructure for providing the networks

https://tests.stockfishchess.org/nns

is down, use an alternate github repo for downloading networks during the build.

fixes #4149
fixes #4140

closes https://github.com/official-stockfish/Stockfish/pull/4151

No functional change
2022-09-07 07:32:53 +02:00
Joost VandeVondele dddf8fc2b4 Increase the maximum number of threads to 1024
relatively soon servers with 512 threads will be available 'quite commonly',
anticipate even more threads, and increase our current maximum from 512 to 1024.

closes https://github.com/official-stockfish/Stockfish/pull/4152

No functional change.
2022-09-07 07:31:48 +02:00
dav1312 97860cb575 Disable ARM CI tests
Temporarily disable ARM CI tests until a mitigation is implemented

closes https://github.com/official-stockfish/Stockfish/pull/4148

No functional change.
2022-08-29 19:15:14 +02:00
mstembera 02ef1f4496 Make key_after() more consistent with key()
STC: https://tests.stockfishchess.org/tests/view/62f8547123d42b50a8dac674
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 176640 W: 47699 L: 47189 D: 81752
Ptnml(0-2): 776, 18599, 49129, 18971, 845

A bug fix plus non functional speed optimization. Position::key_after(Move m) is now
consistent with Position::key() thus prefetching correct TT entries which speeds things up.
Related PR #3759

closes https://github.com/official-stockfish/Stockfish/pull/4130

No functional change
2022-08-17 19:56:15 +02:00
Joost VandeVondele 15ac117ac4 Simplify the use of classical eval
no benefit of the fallback term (exercised rarely).
Cleanup the associated code.

passed STC
https://tests.stockfishchess.org/tests/view/62f62c2b6f0a08af9f776367
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 67832 W: 18334 L: 18148 D: 31350
Ptnml(0-2): 369, 7171, 18609, 7439, 328

passed LTC
https://tests.stockfishchess.org/tests/view/62f68beb6f0a08af9f77710e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 104664 W: 28363 L: 28233 D: 48068
Ptnml(0-2): 169, 10162, 31511, 10350, 140

closes https://github.com/official-stockfish/Stockfish/pull/4132

Bench: 6079565
2022-08-15 18:01:37 +02:00
Michael Chaly 5f290352cd Simplify away smp adjustment in TT use
Passed STC
https://tests.stockfishchess.org/tests/view/62f7d81f23d42b50a8dab568
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 98160 W: 26307 L: 26165 D: 45688
Ptnml(0-2): 201, 10282, 27960, 10448, 189

Passed LTC
https://tests.stockfishchess.org/tests/view/62f8d1a623d42b50a8dad4fb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 81544 W: 22346 L: 22200 D: 36998
Ptnml(0-2): 44, 7542, 25446, 7704, 36

closes https://github.com/official-stockfish/Stockfish/pull/4131

No functional change (single threaded).
2022-08-15 17:54:56 +02:00
mckx00 3370f69881 Make LMR code easier to follow
Remove flags doFullDepthSearch and didLMR, and reorder instruction.

Small measured speedup.

Closes https://github.com/official-stockfish/Stockfish/pull/4129

No functional change.
2022-08-15 17:51:51 +02:00
mstembera 4568f6369b Report longest PV lines for multithreaded search
In case several threads find the same bestmove,
report the longest PV line found.

closes https://github.com/official-stockfish/Stockfish/pull/4126

No functional change.
2022-08-15 17:46:27 +02:00
Joost VandeVondele 1054a483ca Remove an unneeded randomization of evals.
most of the effect comes from the randomization of 3-folds.

passed STC:
https://tests.stockfishchess.org/tests/view/62e697e97e84186e5d19af6f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 572976 W: 153168 L: 153539 D: 266269
Ptnml(0-2): 2505, 64783, 152364, 64250, 2586

passed LTC:
https://tests.stockfishchess.org/tests/view/62ee5977523c86dcd6957154
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 704808 W: 191212 L: 191680 D: 321916
Ptnml(0-2): 1340, 70579, 208972, 70235, 1278

closes https://github.com/official-stockfish/Stockfish/pull/4128

Bench: 5868987
2022-08-12 14:30:33 +02:00
Stefan Geschwentner 0a01dd044f Cleanup code
This PR includes following cleanups:
- Remove the unused depth variable in the thread class.
- cleanup ValueList (added from mstembera)

closes https://github.com/official-stockfish/Stockfish/pull/4127

No functional change.
2022-08-12 14:29:40 +02:00
Joost VandeVondele e639c45577 Update WDL model for current SF
This updates the WDL model based on the LTC statistics for the two weeks (3M games).

for old results see:

https://github.com/official-stockfish/Stockfish/pull/3981
https://github.com/official-stockfish/Stockfish/pull/3582
https://github.com/official-stockfish/Stockfish/pull/2778

closes https://github.com/official-stockfish/Stockfish/pull/4115

No functional change.
2022-08-06 13:57:30 +02:00
Joost VandeVondele 7cc929f437 Update CPU contributors list
Thanks for your contributions!

closes https://github.com/official-stockfish/Stockfish/pull/4116

No functional change
2022-08-06 13:53:55 +02:00
lonfom169 b8f4903fbb Reintroduce singularQuietLMR
STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 88912 W: 23972 L: 23580 D: 41360
Ptnml(0-2): 365, 9820, 23712, 10176, 383
https://tests.stockfishchess.org/tests/view/62e9537a400addce2c13399b

LTC:
LLR: 2.97 (-2.94,2.94) <0.50,2.50>
Total: 85672 W: 23607 L: 23192 D: 38873
Ptnml(0-2): 219, 8316, 25365, 8703, 233
https://tests.stockfishchess.org/tests/view/62e9a174400addce2c1346e4

closes https://github.com/official-stockfish/Stockfish/pull/4122

Bench: 5921315
2022-08-06 13:52:36 +02:00
Stefan Geschwentner 675f6a038b Tweak history updates
In general the history update bonus is slightly decreased by 11% which gives a slower saturation speed.
In addition only for main history the divisor is halfed (used history values are doubled to maintain same maximum)
which have an effect in the opposite direction on saturation speed.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 157088 W: 42673 L: 42168 D: 72247
Ptnml(0-2): 857, 17346, 41642, 17833, 866
https://tests.stockfishchess.org/tests/view/62e5517ab383a712b13867c5

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 325592 W: 88705 L: 87753 D: 149134
Ptnml(0-2): 594, 32288, 96076, 33248, 590
https://tests.stockfishchess.org/tests/view/62e5e4f4b383a712b1387d53

closes https://github.com/official-stockfish/Stockfish/pull/4119

Bench: 5518728
2022-08-06 13:50:01 +02:00
Michael Chaly 582c88ee94 Do more TT cutoffs in case of exact bound
The idea is that these TT entries are considered move valuable in TT replacement scheme - they are always overwriting other entries. So it makes sence for them to produce more aggressive cutoffs.

passed STC
https://tests.stockfishchess.org/tests/view/62e4d407b383a712b1385410
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 96632 W: 26045 L: 25659 D: 44928
Ptnml(0-2): 434, 10635, 25770, 11065, 412

passed LTC
https://tests.stockfishchess.org/tests/view/62e523e2b383a712b1386193
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 77960 W: 21363 L: 20989 D: 35608
Ptnml(0-2): 190, 7591, 23009, 8035, 155

closes https://github.com/official-stockfish/Stockfish/pull/4114

bench 5820568
2022-07-31 11:03:28 +02:00
Dubslow 18389e269d remove useClassical depth condition
passed STC:
https://tests.stockfishchess.org/tests/view/62e0c3e98e4fa6ae472695ed
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 293568 W: 78934 L: 79151 D: 135483
Ptnml(0-2): 1344, 31488, 81366, 31213, 1373

passed LTC:
https://tests.stockfishchess.org/tests/view/62e190aa8e4fa6ae4726b5b5
LLR: 2.98 (-2.94,2.94) <-2.25,0.25>
Total: 187392 W: 50971 L: 51028 D: 85393
Ptnml(0-2): 384, 17801, 57369, 17772, 370

other attempts to otherwise tune this parameter failed, bounds 6,7,10,11 failed STC, 8 passed STC but failed LTC

closes https://github.com/official-stockfish/Stockfish/pull/4112

bench 5796377
2022-07-31 11:00:31 +02:00
Dubslow c4a644922d Simplify reduction condition for cutNodes
LMR: for cutNodes, dont exclude killer moves. This was a prelude to reducing
allNodes, altho that's failed so far.

STC https://tests.stockfishchess.org/tests/view/62d64ad147ae1768b34a27c3
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 37064 W: 10044 L: 9889 D: 17131
Ptnml(0-2): 162, 4115, 9828, 4260, 167

LTC https://tests.stockfishchess.org/tests/view/62d66cc047ae1768b34a2b14
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 39832 W: 10796 L: 10659 D: 18377
Ptnml(0-2): 69, 3969, 11706, 4100, 72

closes https://github.com/official-stockfish/Stockfish/pull/4109

bench: 5697891
2022-07-24 09:18:38 +02:00
Joost VandeVondele 4b4b7d1209 Update default net to nn-ad9b42354671.nnue
using trainer branch https://github.com/glinscott/nnue-pytorch/pull/208 with a slightly
tweaked loss function (power 2.5 instead of 2.6), otherwise same training as in
the previous net update https://github.com/official-stockfish/Stockfish/pull/4100

passed STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 367536 W: 99465 L: 98573 D: 169498
Ptnml(0-2): 1820, 40994, 97117, 42148, 1689
https://tests.stockfishchess.org/tests/view/62cc43fe50dcbecf5fc1c5b8

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 25032 W: 6802 L: 6553 D: 11677
Ptnml(0-2): 40, 2424, 7341, 2669, 42
https://tests.stockfishchess.org/tests/view/62ce5f421dacb46e4d5fd277

closes https://github.com/official-stockfish/Stockfish/pull/4107

Bench: 5905619
2022-07-13 18:01:20 +02:00
Michael Chaly 95d24b77df Simplify away some unneeded code in time management
The lower bound of the clamp is never used since complexity can't be negative and thus is unneeded.

closes https://github.com/official-stockfish/Stockfish/pull/4105

No functional change
2022-07-13 18:00:39 +02:00
Joost VandeVondele 2e02dd7936 Limit the researching at same depth.
If the elapsed time is close to the available time, the time management thread can signal that the next iterations should be searched at the same depth (Threads.increaseDepth = false). While the rootDepth increases, the adjustedDepth is kept constant with the searchAgainCounter.

In exceptional cases, when threading is used and the master thread, which controls the time management, signals to not increaseDepth, but by itself takes a long time to finish the iteration, the helper threads can search repeatedly at the same depth. This search finishes more and more quickly, leading to helper threads that report a rootDepth of MAX_DEPTH (245). The latter is not optimal as it is confusing for the user, stops search on these threads, and leads to an incorrect bias in the thread voting scheme. Probably with only a small impact on strength.

This behavior was observed almost two years ago,
see https://github.com/official-stockfish/Stockfish/issues/2717

This patch fixes #2717 by ensuring the effective depth increases at once every four iterations,
even in increaseDepth is false.

Depth 245 searches (for non-trivial positions) were indeed absent with this patch,
but frequent with master in the tests below:
https://discord.com/channels/435943710472011776/813919248455827515/994872720800088095
Total pgns: 2173
Base: 2867
Patch: 0

it passed non-regression testing in various setups:

SMP STC:
https://tests.stockfishchess.org/tests/view/62bfecc96178ffe6394ba036
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 37288 W: 10171 L: 10029 D: 17088
Ptnml(0-2): 75, 3777, 10793, 3929, 70

SMP LTC:
https://tests.stockfishchess.org/tests/view/62c08f6f49b62510394be066
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 190568 W: 52125 L: 52186 D: 86257
Ptnml(0-2): 70, 17854, 59504, 17779, 77

LTC:
https://tests.stockfishchess.org/tests/view/62c08b6049b62510394bdfb6
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 48120 W: 13204 L: 13083 D: 21833
Ptnml(0-2): 54, 4458, 14919, 4571, 58

Special thanks to miguel-I,  Disservin, ruicoelhopedro and others for analysing the problem,
the data, and coming up with the key insight, needed to fix this longstanding issue.

closes https://github.com/official-stockfish/Stockfish/pull/4104

Bench: 5182295
2022-07-09 10:58:04 +02:00
Dubslow aa18b68033 Time mgmt fix division.
oversight changed the corresponding float division to integer division in a previous tune https://github.com/official-stockfish/Stockfish/commit/442c40b43de8ede1e424efa674c8d45322e3b43c it is stronger to keep the original float division.

green LTC: https://tests.stockfishchess.org/tests/view/62bf34bc0340fb1e0cc934e7
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 38952 W: 10738 L: 10467 D: 17747
Ptnml(0-2): 46, 3576, 11968, 3833, 53

yellow STC: https://tests.stockfishchess.org/tests/view/62bff6506178ffe6394ba1d1
LLR: -2.95 (-2.94,2.94) <0.00,2.50>
Total: 226960 W: 61265 L: 61062 D: 104633
Ptnml(0-2): 938, 24398, 62582, 24647, 915

further slightly tweaked tests confirm this Elo gain.

closes https://github.com/official-stockfish/Stockfish/pull/4097

No functional change
2022-07-09 10:53:17 +02:00
Michael Chaly c2aaaa65f9 Simplify away FRC correction term
Since new net is trained partially using FRC data this part of adjustment that penalises bishops that are locked in the corner is no longer needed - net should "know" this things itself much better.

STC on FRC book :
https://tests.stockfishchess.org/tests/view/62c3031b9e7d9997a12d852f
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 22048 W: 3003 L: 2845 D: 16200
Ptnml(0-2): 96, 1778, 7149, 1874, 127

LTC on FRC book :
https://tests.stockfishchess.org/tests/view/62c32e939e7d9997a12d8c5e
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 36784 W: 3138 L: 3037 D: 30609
Ptnml(0-2): 36, 1842, 14537, 1939, 38

STC on DFRC book :
https://tests.stockfishchess.org/tests/view/62c32efb9e7d9997a12d8c6f
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 20424 W: 3903 L: 3721 D: 12800
Ptnml(0-2): 172, 1984, 5724, 2154, 178

LTC on DFRC book :
https://tests.stockfishchess.org/tests/view/62c358c79e7d9997a12d9319
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 53784 W: 7581 L: 7480 D: 38723
Ptnml(0-2): 87, 3887, 18856, 3962, 100

closes https://github.com/official-stockfish/Stockfish/pull/4101

bench 5182295
2022-07-05 13:55:50 +02:00
Joost VandeVondele 85f8ee6199 Update default net to nn-3c0054ea9860.nnu
First things first...

this PR is being made from court. Today, Tord and Stéphane, with broad support
of the developer community are defending their complaint, filed in Munich, against ChessBase.
With their products Houdini 6 and Fat Fritz 2, both Stockfish derivatives,
ChessBase violated repeatedly the Stockfish GPLv3 license. Tord and Stéphane have terminated
their license with ChessBase permanently. Today we have the opportunity to present
our evidence to the judge and enforce that termination. To read up, have a look at our blog post
https://stockfishchess.org/blog/2022/public-court-hearing-soon/ and
https://stockfishchess.org/blog/2021/our-lawsuit-against-chessbase/

This PR introduces a net trained with an enhanced data set and a modified loss function in the trainer.
A slight adjustment for the scaling was needed to get a pass on standard chess.

passed STC:
https://tests.stockfishchess.org/tests/view/62c0527a49b62510394bd610
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 135008 W: 36614 L: 36152 D: 62242
Ptnml(0-2): 640, 15184, 35407, 15620, 653

passed LTC:
https://tests.stockfishchess.org/tests/view/62c17e459e7d9997a12d458e
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 28864 W: 8007 L: 7749 D: 13108
Ptnml(0-2): 47, 2810, 8466, 3056, 53

Local testing at a fixed 25k nodes resulted in
Test run1026/easy_train_data/experiments/experiment_2/training/run_0/nn-epoch799.nnue
localElo: 4.2  +-      1.6

The real strength of the net is in FRC and DFRC chess where it gains significantly.

Tested at STC with slightly different scaling:
FRC:
https://tests.stockfishchess.org/tests/view/62c13a4002ba5d0a774d20d4
Elo: 29.78 +-3.4 (95%) LOS: 100.0%
Total: 10000 W: 2007 L: 1152 D: 6841
Ptnml(0-2): 31, 686, 2804, 1355, 124
nElo: 59.24 +-6.9 (95%) PairsRatio: 2.06

DFRC:
https://tests.stockfishchess.org/tests/view/62c13a5702ba5d0a774d20d9
Elo: 55.25 +-3.9 (95%) LOS: 100.0%
Total: 10000 W: 2984 L: 1407 D: 5609
Ptnml(0-2): 51, 636, 2266, 1779, 268
nElo: 96.95 +-7.2 (95%) PairsRatio: 2.98

Tested at LTC with identical scaling:
FRC:
https://tests.stockfishchess.org/tests/view/62c26a3c9e7d9997a12d6caf
Elo: 16.20 +-2.5 (95%) LOS: 100.0%
Total: 10000 W: 1192 L: 726 D: 8082
Ptnml(0-2): 10, 403, 3727, 831, 29
nElo: 44.12 +-6.7 (95%) PairsRatio: 2.08

DFRC:
https://tests.stockfishchess.org/tests/view/62c26a539e7d9997a12d6cb2
Elo: 40.94 +-3.0 (95%) LOS: 100.0%
Total: 10000 W: 2215 L: 1042 D: 6743
Ptnml(0-2): 10, 410, 3053, 1451, 76
nElo: 92.77 +-6.9 (95%) PairsRatio: 3.64

This is due to the mixing in a significant fraction of DFRC training data in the final training round. The net is
trained using the easy_train.py script in the following way:

```
python easy_train.py \
     --training-dataset=../Leela-dfrc_n5000.binpack \
     --experiment-name=2 \
     --nnue-pytorch-branch=vondele/nnue-pytorch/lossScan4 \
     --additional-training-arg=--param-index=2 \
     --start-lambda=1.0 \
     --end-lambda=0.75 \
     --gamma=0.995 \
     --lr=4.375e-4 \
     --start-from-engine-test-net True \
     --tui=False \
     --seed=$RANDOM \
     --max_epoch=800 \
     --auto-exit-timeout-on-training-finished=900 \
     --network-testing-threads 8  \
     --num-workers 12
```

where the data set used (Leela-dfrc_n5000.binpack) is a combination of our previous best data set (mix of Leela and some SF data) and DFRC data, interleaved to form:
The data is available in https://drive.google.com/drive/folders/1S9-ZiQa_3ApmjBtl2e8SyHxj4zG4V8gG?usp=sharing
Leela mix: https://drive.google.com/file/d/1JUkMhHSfgIYCjfDNKZUMYZt6L5I7Ra6G/view?usp=sharing
DFRC: https://drive.google.com/file/d/17vDaff9LAsVo_1OfsgWAIYqJtqR8aHlm/view?usp=sharing

The training branch used is
https://github.com/vondele/nnue-pytorch/commits/lossScan4
A PR to the main trainer repo will be made later. This contains a revised loss function, now computing the loss from the score based on the win rate model, which is a more accurate representation than what we had before. Scaling constants are tweaked there as well.

closes https://github.com/official-stockfish/Stockfish/pull/4100

Bench: 5186781
2022-07-04 15:42:34 +02:00
Dubslow 442c40b43d Use NNUE complexity in search, retune related parameters
This builds on ideas of xoto10 and mstembera to use more output from NNUE in the search algorithm.

passed STC:
https://tests.stockfishchess.org/tests/view/62ae454fe7ee5525ef88a957
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 89208 W: 24127 L: 23753 D: 41328
Ptnml(0-2): 400, 9886, 23642, 10292, 384

passed LTC:
https://tests.stockfishchess.org/tests/view/62acc6ddd89eb6cf1e0750a1
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 56352 W: 15430 L: 15115 D: 25807
Ptnml(0-2): 44, 5501, 16782, 5794, 55

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench 5332964
2022-06-20 08:30:57 +02:00
Dubslow 5304b561ab LMR: remove deeper
...apparently it wasn't doing much anymore. inspired by rufish's recent attempts to improve this.

passed STC:
https://tests.stockfishchess.org/tests/view/62abca2cd89eb6cf1e072c04
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 85576 W: 22766 L: 22683 D: 40127
Ptnml(0-2): 362, 9607, 22741, 9742, 336

passed LTC:
https://tests.stockfishchess.org/tests/view/62ac90ffd89eb6cf1e07488f
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 48248 W: 13018 L: 12896 D: 22334
Ptnml(0-2): 32, 4773, 14400, 4879, 40

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench 5578988
2022-06-20 08:25:50 +02:00
bmc4 4d6a11a04c Don't change ttPv at probCut
STC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 35672 W: 9618 L: 9462 D: 16592
Ptnml(0-2): 151, 3890, 9601, 4040, 154
https://tests.stockfishchess.org/tests/view/62ab03f750949cfc241b1965

LTC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 54160 W: 14626 L: 14511 D: 25023
Ptnml(0-2): 42, 5414, 16056, 5523, 45
https://tests.stockfishchess.org/tests/view/62ab5e6fd89eb6cf1e071b87

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench: 5798229
2022-06-20 08:24:07 +02:00
bmc4 6edc29d720 Simplify away condition in ttSave in probCut
Remove condition for tte->save in probCut so it always saves on probCut cutoff.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 47848 W: 12921 L: 12782 D: 22145
Ptnml(0-2): 207, 5340, 12715, 5431, 231
https://tests.stockfishchess.org/tests/view/62a1f7c87bd8e641e44436f7

LTC:
LLR: 2.97 (-2.94,2.94) <-2.25,0.25>
Total: 132736 W: 35895 L: 35881 D: 60960
Ptnml(0-2): 109, 13384, 39360, 13414, 101
https://tests.stockfishchess.org/tests/view/62a2421a7bd8e641e444434f

closes https://github.com/official-stockfish/Stockfish/pull/4069

bench: 5845802
2022-06-16 07:12:01 +02:00
mstembera 2d5dcf3d18 Minor simplifications and cleanup in search
STC: https://tests.stockfishchess.org/tests/view/629d6775593a4a9b6482c1ec
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 77416 W: 20683 L: 20589 D: 36144
Ptnml(0-2): 317, 8690, 20620, 8744, 337

LTC: https://tests.stockfishchess.org/tests/view/629db4be593a4a9b6482ceef
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 106544 W: 28752 L: 28705 D: 49087
Ptnml(0-2): 97, 10692, 31641, 10751, 91

closes https://github.com/official-stockfish/Stockfish/pull/4059

Bench: 5913510
2022-06-16 07:06:43 +02:00
ppigazzini d54b85b4bd Restore NDKv21 for GitHub Actions
GitHub updated the versions of NDK installed on the Actions runners
breaking the ARM tests.
Restore the NDKv21 using the GitHub suggested mitigation, see:
https://github.com/actions/virtual-environments/issues/5595

closes https://github.com/official-stockfish/Stockfish/pull/4077

No functional change
2022-06-16 07:03:52 +02:00
candirufish 00297cfef0 Use qsearch on step 11 if depth is equal to or below 0
larger reduction of depth if no TT entry is found, and go in qsearch as needed.

stc:
https://tests.stockfishchess.org/tests/view/629dfacd593a4a9b6482db72
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 31920 W: 8591 L: 8322 D: 15007
Ptnml(0-2): 127, 3551, 8376, 3738, 168

ltc:
https://tests.stockfishchess.org/tests/view/629e304e593a4a9b6482e451
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 17488 W: 4842 L: 4614 D: 8032
Ptnml(0-2): 13, 1670, 5151, 1896, 14

closes https://github.com/official-stockfish/Stockfish/pull/4056

Bench: 5870283
2022-06-07 08:34:14 +02:00
Boštjan Mejak 809849fa27 Wording of help output and comments.
Improved the output text that is diplayed when executing the 'help' command.
Also, some comments were fixed along the way.

closes https://github.com/official-stockfish/Stockfish/pull/4048
closes https://github.com/official-stockfish/Stockfish/pull/4044

No functional change
2022-06-07 08:30:07 +02:00
Dubslow 90cf8e7d2b Remove LMR condition for complex pos
Inspired by Kia's similar test: https://tests.stockfishchess.org/tests/view/6292898c1e7cd5f29966fbe0

Passed STC:
https://tests.stockfishchess.org/tests/view/62941588b0d5a7d1b780ed4b
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 266872 W: 70850 L: 71033 D: 124989
Ptnml(0-2): 1180, 30114, 70941, 30111, 1090

Passed LTC:
https://tests.stockfishchess.org/tests/view/62964a754628d33daa24f062
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 70160 W: 18756 L: 18662 D: 32742
Ptnml(0-2): 42, 6976, 20950, 7070, 42

closes https://github.com/official-stockfish/Stockfish/pull/4047

Bench 6237567
2022-06-02 07:49:31 +02:00
xoto10 7f1333ccf8 Blend nnue complexity with classical.
Following mstembera's test of the complexity value derived from nnue values,
this change blends that idea with the old complexity calculation.

STC 10+0.1:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 42320 W: 11436 L: 11148 D: 19736
Ptnml(0-2): 209, 4585, 11263, 4915, 188
https://tests.stockfishchess.org/tests/live_elo/6295c9239c8c2fcb2bad7fd9

LTC 60+0.6:
LLR: 2.98 (-2.94,2.94) <0.50,3.00>
Total: 34600 W: 9393 L: 9125 D: 16082
Ptnml(0-2): 32, 3323, 10319, 3597, 29
https://tests.stockfishchess.org/tests/view/6295fd5d9c8c2fcb2bad88cf

closes https://github.com/official-stockfish/Stockfish/pull/4046

Bench 6078140
2022-06-02 07:47:23 +02:00
candirufish 653bd0817c cutnode and movecount lmr extension simplification
Passed STC
https://tests.stockfishchess.org/tests/view/6294133cb0d5a7d1b780ece3
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 41072 W: 11052 L: 10908 D: 19112
Ptnml(0-2): 153, 4324, 11461, 4422, 176

Passed LTC
ltc: https://tests.stockfishchess.org/tests/view/62947ae6b0d5a7d1b780fe86
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 102736 W: 27509 L: 27459 D: 47768
Ptnml(0-2): 98, 9734, 31669, 9754, 113

closes https://github.com/official-stockfish/Stockfish/pull/4045

Bench: 6410652
2022-06-02 07:44:22 +02:00
Michael Chaly 8fadbcf1b2 Add info about elo gained from some heuristics
Add info about qsearch and impact of main and continuation histories.

Based on these tests:
https://tests.stockfishchess.org/tests/view/62946ffcb0d5a7d1b780fc7e
https://tests.stockfishchess.org/tests/view/628facb71e7cd5f299669534
https://tests.stockfishchess.org/tests/view/628eade11e7cd5f299666f2e

closes https://github.com/official-stockfish/Stockfish/pull/4041

No functional change.
2022-06-02 07:43:14 +02:00
xoto10 4c7de9e8ab Adjust scale param higher
xoto10's scaleopt tune resulted in a yellow LTC, but the main parameter shift looked almost exactly like the tune rate reduction schedule,
so further increases of that param were tried. Joint work xoto10 and dubslow.

passed LTC:
https://tests.stockfishchess.org/tests/view/628c709372775f382300f03e
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 70112 W: 18932 L: 18584 D: 32596
Ptnml(0-2): 66, 6904, 20757, 7274, 55

failed STC:
https://tests.stockfishchess.org/tests/view/6290e4441e7cd5f29966bdc8
LLR: -2.96 (-2.94,2.94) <0.00,2.50>
Total: 59976 W: 15919 L: 16018 D: 28039
Ptnml(0-2): 250, 6791, 15974, 6754, 219

similar LTC's were yellow
first yellow LTC: https://tests.stockfishchess.org/tests/view/6288a33f817227d3e5c5b05d
double exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e140372775f38230129a6
triple exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e2caf72775f3823012d45

closes https://github.com/official-stockfish/Stockfish/pull/4036

bench 6410652
2022-05-29 19:14:20 +02:00
proukornew 6ede1bed89 Improve handling of variables set in the make environment
removes duplication on the commandline for example in a profile-build

closes https://github.com/official-stockfish/Stockfish/pull/3859

No functional change
2022-05-29 19:04:25 +02:00
Giacomo Lorenzetti 1a168201bd Small speedup in futility_move_count
The speedup is around 0.25% using gcc 11.3.1 (bmi2, nnue bench, depth 16
and 23) while it is neutral using clang (same conditions).

According to `perf` that integer division was one of the most time-consuming
instructions in search (gcc disassembly).

Passed STC:
https://tests.stockfishchess.org/tests/view/628a17fe24a074e5cd59b3aa
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22232 W: 5992 L: 5751 D: 10489
Ptnml(0-2): 88, 2235, 6218, 2498, 77

yellow LTC:
https://tests.stockfishchess.org/tests/view/628a35d7ccae0450e35106f7
LLR: -2.95 (-2.94,2.94) <0.50,3.00>
Total: 320168 W: 85853 L: 85326 D: 148989
Ptnml(0-2): 185, 29698, 99821, 30165, 215

This patch also suggests that UHO STC is sensible to small speedups (< 0.50%).

closes https://github.com/official-stockfish/Stockfish/pull/4032

No functional change
2022-05-29 18:54:19 +02:00
Joost VandeVondele 48df0754bc Add command line flags to link to information
This patch provides command line flags `--help` and `--license` as well as the corresponding `help` and `license` commands.

```
$ ./stockfish --help
Stockfish 200522 by the Stockfish developers (see AUTHORS file)

Stockfish is a powerful chess engine and free software licensed under the GNU GPLv3.
Stockfish is normally used with a separate graphical user interface (GUI).
Stockfish implements the universal chess interface (UCI) to exchange information.
For further information see https://github.com/official-stockfish/Stockfish#readme
or the corresponding README.md and Copying.txt files distributed with this program.

```

The idea is to provide a minimal help that links to the README.md file,
not replicating information that is already available elsewhere.

We use this opportunity to explicitly report the license as well.

closes https://github.com/official-stockfish/Stockfish/pull/4027

No functional change.
2022-05-29 18:46:35 +02:00
Giacomo Lorenzetti f7d1491b3d Assorted small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/3973

No functional change
2022-05-29 18:42:48 +02:00
candirufish cc7bcd5303 Simplify a condition
Principal variation depth late move reduction extension simplification.

stc:
https://tests.stockfishchess.org/tests/view/6285a1d19d18a78568e7fa24
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 428536 W: 113433 L: 113851 D: 201252
Ptnml(0-2): 1671, 48606, 114090, 48272, 1629

ltc:
https://tests.stockfishchess.org/tests/view/62871d20375cdc5de8cf5db3
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 56792 W: 15123 L: 15011 D: 26658
Ptnml(0-2): 42, 5681, 16825, 5819, 29

closes https://github.com/official-stockfish/Stockfish/pull/4028

bench: 6501437
2022-05-21 12:42:33 +02:00
xoto10 22b7909809 Tune scale and optimism.
Tune scale and optimism in effort to make stockfish play more aggressively.

STC @ 10+0.1 th 1:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 27896 W: 7506 L: 7248 D: 13142
Ptnml(0-2): 103, 3047, 7388, 3309, 101
https://tests.stockfishchess.org/tests/live_elo/627fd0cfab44257388ab1f13

LTC @ 60+0.6 th 1:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 65576 W: 17512 L: 17178 D: 30886
Ptnml(0-2): 37, 6397, 19587, 6729, 38
https://tests.stockfishchess.org/tests/live_elo/627ff666ab44257388ab256d

closes https://github.com/official-stockfish/Stockfish/pull/4025

Bench 6407734
2022-05-15 20:20:37 +02:00
disservin 5372f81cc8 SE depth scaling using the previous depth
This patch makes the SE depth condition more robust and allows it to scale with completed depth
from a previous search.

At long TC this patch is almost equivalent to https://github.com/official-stockfish/Stockfish/pull/4016 which had

VLTC:
https://tests.stockfishchess.org/tests/view/626abd7e8707aa698c0093a8
Elo: 2.35 +-1.5 (95%) LOS: 99.9%
Total: 40000 W: 10991 L: 10720 D: 18289
Ptnml(0-2): 8, 3534, 12648, 3799, 11
nElo: 5.47 +-3.4 (95%) PairsRatio: 1.08

VLTC multicore:
https://tests.stockfishchess.org/tests/view/6272a6afc8f14123163c1997
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 86808 W: 24165 L: 23814 D: 38829
Ptnml(0-2): 11, 7253, 28524, 7606, 10

however, it is now also gaining at LTC:

LTC:
https://tests.stockfishchess.org/tests/view/627e7cb523c0c72a05b651a9
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 27064 W: 7285 L: 7046 D: 12733
Ptnml(0-2): 8, 2446, 8390, 2675, 13

and should have nearly no influence at STC as depth 27 is rarely reached.
It was noticed that initializing the threshold with MAX_PLY, had an adverse effect,
possibly because the first move is sensitive to this.

closes https://github.com/official-stockfish/Stockfish/pull/4021
closes https://github.com/official-stockfish/Stockfish/pull/4016

Bench: 6481017
2022-05-14 13:17:35 +02:00
Tomasz Sobczyk c079acc26f Update NNUE architecture to SFNNv5. Update network to nn-3c0aa92af1da.nnue.
Architecture changes:

    Duplicated activation after the 1024->15 layer with squared crelu (so 15->15*2). As proposed by vondele.

Trainer changes:

    Added bias to L1 factorization, which was previously missing (no measurable improvement but at least neutral in principle)
    For retraining linearly reduce lambda parameter from 1.0 at epoch 0 to 0.75 at epoch 800.
    reduce max_skipping_rate from 15 to 10 (compared to vondele's outstanding PR)

Note: This network was trained with a ~0.8% error in quantization regarding the newly added activation function.
      This will be fixed in the released trainer version. Expect a trainer PR tomorrow.

Note: The inference implementation cuts a corner to merge results from two activation functions.
       This could possibly be resolved nicer in the future. AVX2 implementation likely not necessary, but NEON is missing.

First training session invocation:

python3 train.py \
    ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 8 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --max_epochs=400 \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Second training session invocation:

python3 train.py \
    ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
    ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 8 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --start-lambda=1.0 \
    --end-lambda=0.75 \
    --gamma=0.995 \
    --lr=4.375e-4 \
    --max_epochs=800 \
    --resume-from-model /data/sopel/nnue/nnue-pytorch-training/data/exp367/nn-exp367-run3-epoch399.pt \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 27288 W: 7445 L: 7178 D: 12665
Ptnml(0-2): 159, 3002, 7054, 3271, 158
https://tests.stockfishchess.org/tests/view/627e8c001919125939623644

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 21792 W: 5969 L: 5727 D: 10096
Ptnml(0-2): 25, 2152, 6294, 2406, 19
https://tests.stockfishchess.org/tests/view/627f2a855734b18b2e2ece47

closes https://github.com/official-stockfish/Stockfish/pull/4020

Bench: 6481017
2022-05-14 12:47:22 +02:00
Stéphane Nicolet 9eb7b607cf Reduce depth after score improvement at PV nodes
STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 73760 W: 19590 L: 19244 D: 34926
Ptnml(0-2): 285, 8352, 19292, 8634, 317
https://tests.stockfishchess.org/tests/view/626eb2dc9116b52aa83b73da

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 114400 W: 30561 L: 30111 D: 53728
Ptnml(0-2): 68, 11432, 33785, 11812, 103
https://tests.stockfishchess.org/tests/view/626f730859e9c431e0b10b21

closes https://github.com/official-stockfish/Stockfish/pull/4008

bench: 6174823
2022-05-04 07:47:56 +02:00
candirufish a32d2086bc Use fail high count for LMR
Increase reduction if next ply has a lot of fail high else reset count to 0

Passed STC:
https://tests.stockfishchess.org/tests/view/626ea8299116b52aa83b71f6
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 144288 W: 38377 L: 37902 D: 68009
Ptnml(0-2): 565, 16298, 38054, 16551, 676

Passed LTC:
https://tests.stockfishchess.org/tests/view/626fa0fb79f761bab2e382f0
LLR: 2.98 (-2.94,2.94) <0.50,3.00>
Total: 74872 W: 20050 L: 19686 D: 35136
Ptnml(0-2): 51, 7541, 21893, 7895, 56

closes https://github.com/official-stockfish/Stockfish/pull/4006

bench: 7084802
2022-05-03 17:58:01 +02:00
Stefan Geschwentner 285a79eaa0 Simplify time management.
Replace the best move instability adjustment factor by a simpler version which doesn't have a dependency on the iteration depth.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30800 W: 8232 L: 8073 D: 14495
Ptnml(0-2): 101, 3309, 8444, 3422, 124
https://tests.stockfishchess.org/tests/view/6266c77bc5b924ba22908d30

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 61664 W: 16375 L: 16272 D: 29017
Ptnml(0-2): 40, 5869, 18897, 6000, 26
https://tests.stockfishchess.org/tests/view/6266fc39b3d1812808915f23

closes https://github.com/official-stockfish/Stockfish/pull/3999

Bench: 7729968
2022-05-03 17:54:23 +02:00
candirufish e1f12aa4e6 Negative extension for ttMove that is less than alpha and value
in the context of singular extensions

Passed STC:
https://tests.stockfishchess.org/tests/view/626047e8b03f22647441ade0
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 50296 W: 13410 L: 13108 D: 23778
Ptnml(0-2): 196, 5548, 13370, 5826, 208

Passed LTC:
https://tests.stockfishchess.org/tests/view/6260a513b03f22647441b970
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 83896 W: 22433 L: 22054 D: 39409
Ptnml(0-2): 49, 8273, 24938, 8626, 62

closes https://github.com/official-stockfish/Stockfish/pull/3995

bench: 7729968
2022-04-22 08:17:22 +02:00
Michael Chaly e41f727f0f Simplify away best move count logic
the only place where it was used it was true with >99% probability so it seemed to not be doing much any more.

Passed STC:
https://tests.stockfishchess.org/tests/view/625f4778d00da81c22dd4c93
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 85152 W: 22487 L: 22406 D: 40259
Ptnml(0-2): 313, 9035, 23818, 9078, 332

Passed LTC:
https://tests.stockfishchess.org/tests/view/625ff1f1b03f22647441a215
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 66776 W: 17768 L: 17673 D: 31335
Ptnml(0-2): 46, 6200, 20792, 6313, 37

close https://github.com/official-stockfish/Stockfish/pull/3993

bench 7280798
2022-04-22 08:09:40 +02:00
Joost VandeVondele 6e0680efa0 Update default net to nn-d0b74ce1e5eb.nnue
train a net using training data with a
heavier weight on positions having 16 pieces on the board. More specifically,
with a relative weight of `i * (32-i)/(16 * 16)+1` (where i is the number of pieces on the board).

This is done with the trainer branch https://github.com/glinscott/nnue-pytorch/pull/173

The command used is:
```
python train.py $datafile $datafile $restarttype $restartfile --gpus 1 --threads 4 --num-workers 12 --random-fen-skipping=3 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --features=HalfKAv2_hm^   --lambda=1.00  --max_epochs=$epochs --seed $RANDOM --default_root_dir exp/run_$i
```
The datafile is T60T70wIsRightFarseerT60T74T75T76.binpack, the restart is from the master net.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22728 W: 6197 L: 5945 D: 10586
Ptnml(0-2): 105, 2453, 6001, 2695, 110
https://tests.stockfishchess.org/tests/view/625cf944ff677a888877cd90

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 35664 W: 9535 L: 9264 D: 16865
Ptnml(0-2): 30, 3524, 10455, 3791, 32
https://tests.stockfishchess.org/tests/view/625d3c32ff677a888877d7ca

closes https://github.com/official-stockfish/Stockfish/pull/3989

Bench: 7269563
2022-04-19 19:59:04 +02:00
Joost VandeVondele c4db7fd1f9 Restore development version
No functional change.
2022-04-18 23:05:24 +02:00
Joost VandeVondele e6e324eb28 Stockfish 15
Official release version of Stockfish 15

Bench: 8129754

---

A new major release of Stockfish is now available at https://stockfishchess.org

Stockfish 15 continues to push the boundaries of chess, providing unrivalled
analysis and playing strength. In our testing, Stockfish 15 is ahead of
Stockfish 14 by 36 Elo points and wins nine times more game pairs than it
loses[1].

Improvements to the engine have made it possible for Stockfish to end up
victorious in tournaments at all sorts of time controls ranging from bullet to
classical and even at Fischer random chess[2]. At CCC, Stockfish won all of
the latest tournaments: CCC 16 Bullet, Blitz and Rapid, CCC 960 championship,
and the CCC 17 Rapid. At TCEC, Stockfish won the Season 21, Cup 9, FRC 4 and
in the current Season 22 superfinal, at the time of writing, has won 16 game
pairs and not yet lost a single one.

This progress is the result of a dedicated team of developers that comes up
with new ideas and improvements. For Stockfish 15, we tested nearly 13000
different changes and retained the best 200. These include the fourth
generation of our NNUE network architecture, as well as various search
improvements. To perform these tests, contributors provide CPU time for
testing, and in the last year, they have collectively played roughly a
billion chess games. In the last few years, our distributed testing
framework, Fishtest, has been operated superbly and has been developed and
improved extensively. This work by Pasquale Pigazzini, Tom Vijlbrief, Michel
Van den Bergh, and various other developers[3] is an essential part of the
success of the Stockfish project.

Indeed, the Stockfish project builds on a thriving community of enthusiasts
to offer a free and open-source chess engine that is robust, widely
available, and very strong. We invite our chess fans to join the Fishtest
testing framework and programmers to contribute to the project[4].

The Stockfish team

[1] https://tests.stockfishchess.org/tests/view/625d156dff677a888877d1be
[2] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results
[3] https://github.com/glinscott/fishtest/blob/master/AUTHORS
[4] https://stockfishchess.org/get-involved/
2022-04-18 22:03:20 +02:00
KJE-98 df2f7e7527 Decrease LMR at PV nodes with low depth.
This patch lessens the Late Move Reduction at PV nodes with low depth. Previously the affect of depth on LMR was independant of nodeType. The idea behind this patch is that at PV nodes, LMR at low depth is will miss out on potential alpha-raising moves.

Passed STC:
https://tests.stockfishchess.org/tests/view/625aa867d3367522c4b8965c
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 19360 W: 5252 L: 5006 D: 9102
Ptnml(0-2): 79, 2113, 5069, 2321, 98

Passed LTC:
https://tests.stockfishchess.org/tests/view/625ae844d3367522c4b8a009
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 39264 W: 10636 L: 10357 D: 18271
Ptnml(0-2): 18, 3928, 11473, 4183, 30

closes https://github.com/official-stockfish/Stockfish/pull/3985

bench: 8129754
2022-04-17 21:38:05 +02:00
FauziAkram c25d4c4887 Tuning classical and NNUE scaling terms
changes to parameters in both classical and NNUE scaling, following up from an earlier successful #3958

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 23936 W: 6490 L: 6234 D: 11212
Ptnml(0-2): 107, 2610, 6306, 2810, 135
https://tests.stockfishchess.org/tests/view/625820aa33c40bb9d964e6ae

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 50376 W: 13629 L: 13327 D: 23420
Ptnml(0-2): 20, 4979, 14920, 5217, 52
https://tests.stockfishchess.org/tests/view/62584592c1d7f5008a33a4d1

closes https://github.com/official-stockfish/Stockfish/pull/3982

Bench: 6964954
2022-04-16 08:41:51 +02:00
Joost VandeVondele c3b67faf98 Update WDL model for current SF
This updates the WDL model based on the LTC statistics for the last month (8M games).

for old results see:
https://github.com/official-stockfish/Stockfish/pull/3582
https://github.com/official-stockfish/Stockfish/pull/2778

the model changed a bit from the past, some images to follow in the PR

closes https://github.com/official-stockfish/Stockfish/pull/3981

No functional change.
2022-04-16 08:36:37 +02:00
Joost VandeVondele 319af5cf0a Update CPU contributors
closes https://github.com/official-stockfish/Stockfish/pull/3979

No functional change
2022-04-16 08:35:31 +02:00
Topologist 19a90b45bc Use NNUE in low piece endgames close to the root.
This patch enforces that NNUE evaluation is used for endgame positions at shallow depth (depth <= 9).
Classic evaluation will still be used for high imbalance positions when the depth is high or there are many pieces.

Passed STC:
https://tests.stockfishchess.org/tests/view/624c193b3a8a6ac93892dc27
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 255840 W: 68024 L: 67362 D: 120454
Ptnml(0-2): 1074, 27089, 70926, 27763, 1068

Passed LTC:
https://tests.stockfishchess.org/tests/view/624e8675e9e7821808467f77
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 67088 W: 17784 L: 17454 D: 31850
Ptnml(0-2): 45, 6209, 20715, 6521, 54

closes https://github.com/official-stockfish/Stockfish/pull/3978

bench: 6602222
2022-04-12 17:43:50 +02:00
mstembera 9f6bcb38c0 Minor cleanups
simplify and relocate to position.cpp some of the recent threat calculations used in the movepicker.

passed STC:
https://tests.stockfishchess.org/tests/view/62468c301f682ea45ce3b3b9
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 76544 W: 20247 L: 20152 D: 36145
Ptnml(0-2): 327, 8113, 21317, 8168, 347

closes https://github.com/official-stockfish/Stockfish/pull/3972

No functional change
2022-04-01 10:55:11 +02:00
Topologist 471d93063a Play more positional in endgames
This patch chooses the delta value (which skews the nnue evaluation between positional and materialistic)
depending on the material: If the material is low, delta will be higher and the evaluation is shifted
to the positional value. If the material is high, the evaluation will be shifted to the psqt value.
I don't think slightly negative values of delta should be a concern.

Passed STC:
https://tests.stockfishchess.org/tests/view/62418513b3b383e86185766f
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 28808 W: 7832 L: 7564 D: 13412
Ptnml(0-2): 147, 3186, 7505, 3384, 182

Passed LTC:
https://tests.stockfishchess.org/tests/view/62419137b3b383e861857842
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 58632 W: 15776 L: 15450 D: 27406
Ptnml(0-2): 42, 5889, 17149, 6173, 63

closes https://github.com/official-stockfish/Stockfish/pull/3971

Bench: 7588855
2022-03-28 22:43:52 +02:00
Michael Chaly 08e0f52b77 In movepicker increase priority for moves that evade a capture
This idea is a mix of koivisto idea of threat history and heuristic that
was simplified some time ago in LMR - decreasing reduction for moves that evade a capture.
Instead of doing so in LMR this patch does it in movepicker - to do this it
calculates squares that are attacked by different piece types and pieces that are located
on this squares and boosts up weight of moves that make this pieces land on a square that is not under threat.
Boost is greater for pieces with bigger material values.
Special thanks to koivisto and seer authors for explaining me ideas behind threat history.

Passed STC:
https://tests.stockfishchess.org/tests/view/62406e473b32264b9aa1478b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 19816 W: 5320 L: 5072 D: 9424
Ptnml(0-2): 86, 2165, 5172, 2385, 100

Passed LTC:
https://tests.stockfishchess.org/tests/view/62407f2e3b32264b9aa149c8
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 51200 W: 13805 L: 13500 D: 23895
Ptnml(0-2): 44, 5023, 15164, 5322, 47

closes https://github.com/official-stockfish/Stockfish/pull/3970

bench 7736491
2022-03-28 22:37:09 +02:00
Giacomo Lorenzetti 910cf8b218 Remove pos.capture_or_promotion()
This patch replaces `pos.capture_or_promotion()` with `pos.capture()`
and comes after a few attempts with elo-gaining bounds, two of which
failed yellow at LTC
(https://tests.stockfishchess.org/tests/view/622f8f0cc9e950cbfc237024
and
https://tests.stockfishchess.org/tests/view/62319a8bb3b498ba71a6b2dc).

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/623aff7eea447151c74828d3
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 246864 W: 65462 L: 65618 D: 115784
Ptnml(0-2): 1201, 28116, 65001, 27866, 1248

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/623c1fdcea447151c7484fb0
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30120 W: 8125 L: 7978 D: 14017
Ptnml(0-2): 22, 2993, 8881, 3144, 20

closes https://github.com/official-stockfish/Stockfish/pull/3968

Bench: 6847732
2022-03-25 20:14:00 +01:00
Stefan Geschwentner e31f97e3ba Remove ttPv tree shrinking.
Via the ttPv flag an implicit tree of current and former PV nodes is maintained. In addition this tree is grown or shrinked at the leafs dependant on the search results. But now the shrinking step has been removed.

As the frequency of ttPv nodes decreases with depth the shown scaling behavior (STC barely passed but LTC scales well) of the tests was expected.

STC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 270408 W: 71593 L: 71785 D: 127030
Ptnml(0-2): 1339, 31024, 70630, 30912, 1299
https://tests.stockfishchess.org/tests/view/622fbf9dc9e950cbfc2376d6

LTC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 34368 W: 9135 L: 8992 D: 16241
Ptnml(0-2): 28, 3423, 10135, 3574, 24
https://tests.stockfishchess.org/tests/view/62305257c9e950cbfc238964

closes https://github.com/official-stockfish/Stockfish/pull/3963

Bench: 7044203
2022-03-19 13:40:35 +01:00
mstembera f3a2296e59 Small cleanups (2)
- fix a small compile error under MSVC
- improve sigmoid comment and assert
- fix formatting in README.md

closes https://github.com/official-stockfish/Stockfish/pull/3960

No functional change
2022-03-13 08:17:02 +01:00
Giacomo Lorenzetti 004ea2c25e Small cleanups
Delete cast to int in movepick.
update AUTHORS.
adjust assert in sigmoid.
fix spelling mistakes in README

closes https://github.com/official-stockfish/Stockfish/pull/3922
closes https://github.com/official-stockfish/Stockfish/pull/3948
closes https://github.com/official-stockfish/Stockfish/pull/3942

No functional change
2022-03-12 09:38:34 +01:00
FauziAkram 45f2416db4 Improvements in Evaluation
adjust parameters in classical evaluation and NNUE scaling.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 37104 W: 9983 L: 9701 D: 17420
Ptnml(0-2): 154, 4187, 9651, 4343, 217
https://tests.stockfishchess.org/tests/view/6228cb13a9d47c8160e885ba

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 266792 W: 71101 L: 70295 D: 125396
Ptnml(0-2): 214, 26928, 78353, 27640, 261
https://tests.stockfishchess.org/tests/view/6228d3c4a9d47c8160e887b0

closes https://github.com/official-stockfish/Stockfish/pull/3958

Bench: 6739741
2022-03-12 09:25:58 +01:00
Michael Chaly eae0f8dd06 Decrease reductions in Lmr for some Pv nodes
This patch makes us reduce less in Lmr at pv nodes in case of static eval being far away from static evaluation of position.
Idea is that if it's the case then probably position is pretty complex so we can't be sure about how reliable LMR is so we need to reduce less.

Passed STC:
https://tests.stockfishchess.org/tests/view/6226276aa9d47c8160e81220
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 262696 W: 69944 L: 69239 D: 123513
Ptnml(0-2): 1399, 29702, 68436, 30417, 1394

Passed LTC:
https://tests.stockfishchess.org/tests/view/6226b002a9d47c8160e82b91
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 64008 W: 17320 L: 16982 D: 29706
Ptnml(0-2): 60, 6378, 18811, 6674, 81

closes https://github.com/official-stockfish/Stockfish/pull/3957

bench 6678390
2022-03-08 20:19:42 +01:00
Ben Chaney 270a0e737f Generalize the feature transform to use vec_t macros
This commit generalizes the feature transform to use vec_t macros
that are architecture defined instead of using a seperate code path for each one.

It should make some old architectures (MMX, including improvements by Fanael) faster
and make further such improvements easier in the future.

Includes some corrections to CI for mingw.

closes https://github.com/official-stockfish/Stockfish/pull/3955
closes https://github.com/official-stockfish/Stockfish/pull/3928

No functional change
2022-03-02 23:39:08 +01:00
Giacomo Lorenzetti 4ac7d726ec Sort captures
This patch (partially) sort captures in analogy to quiet moves. All
three movepickers are affected, hence `depth` is added as an argument in
probcut's.

Passed STC:
https://tests.stockfishchess.org/tests/view/621a4576da649bba32ef6fd4
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 103848 W: 27884 L: 27473 D: 48491
Ptnml(0-2): 587, 11691, 26974, 12068, 604

Passed LTC:
https://tests.stockfishchess.org/tests/view/621aaa5bda649bba32ef7c2d
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 212032 W: 56420 L: 55739 D: 99873
Ptnml(0-2): 198, 21310, 62348, 21933, 227

closes https://github.com/official-stockfish/Stockfish/pull/3952

Bench: 6833580
2022-03-01 17:51:37 +01:00
Tomasz Sobczyk 174b038bf3 Use dynamic allocation for evaluation scratch TLS buffer.
fixes #3946 an issue related with the toolchain as found in xcode 12 on macOS,
related to previous commit 5f781d36.

closes https://github.com/official-stockfish/Stockfish/pull/3950

No functional change
2022-03-01 17:51:02 +01:00
mstembera 5f781d366e Clean up and simplify some nnue code.
Remove some unnecessary code and it's execution during inference. Also the change on line 49 in nnue_architecture.h results in a more efficient SIMD code path through ClippedReLU::propagate().

passed STC:
https://tests.stockfishchess.org/tests/view/6217d3bfda649bba32ef25d5
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 12056 W: 3281 L: 3092 D: 5683
Ptnml(0-2): 55, 1213, 3312, 1384, 64

passed STC SMP:
https://tests.stockfishchess.org/tests/view/6217f344da649bba32ef295e
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 27376 W: 7295 L: 7137 D: 12944
Ptnml(0-2): 52, 2859, 7715, 3003, 59

closes https://github.com/official-stockfish/Stockfish/pull/3944

No functional change

bench: 6820724
2022-02-25 08:37:57 +01:00
Michael Chaly 27139dedac Adjust usage of LMR for 2nd move in move ordering
Current master prohibits usage of LMR for 2nd move at rootNode. This patch also disables LMR for 2nd move not only at rootNode but also at first PvNode that is a reply to rootNode.

passed STC:
https://tests.stockfishchess.org/tests/view/620e8c9026f5b17ec885143a
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 54096 W: 14305 L: 13996 D: 25795
Ptnml(0-2): 209, 6075, 14192, 6342, 230

passed LTC:
https://tests.stockfishchess.org/tests/view/620eb327b1792e8985f81fb8
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 110864 W: 29602 L: 29156 D: 52106
Ptnml(0-2): 112, 11147, 32455, 11619, 99

closes https://github.com/official-stockfish/Stockfish/pull/3940

bench 6820724
2022-02-20 23:01:22 +01:00
Joost VandeVondele abef3e86f4 Fix clang warning on unused variable
mark variable as used.

fixes https://github.com/official-stockfish/Stockfish/issues/3900
closes https://github.com/official-stockfish/Stockfish/pull/3941

No functional change
2022-02-20 22:59:19 +01:00
ppigazzini 2da1d1bf57 Add ARM NDK to Github Actions matrix
- set the variable only for the required tests to keep simple the yml file
- use NDK 21.x until will be fixed the Stockfish static build problem
  with NDK 23.x
- set the test for armv7, armv7-neon, armv8 builds:
  - use armv7a-linux-androideabi21-clang++ compiler for armv7 armv7-neon
  - enforce a static build
  - silence the Warning for the unused compilation flag "-pie" with
    the static build, otherwise the Github workflow stops
  - use qemu to bench the build and get the signature

Many thanks to @pschneider1968 that made all the hard work with NDK :)

closes https://github.com/official-stockfish/Stockfish/pull/3924

No functional change
2022-02-20 22:56:11 +01:00
Michael Chaly 84b1940fca Tune search at very long time control
This patch is a result of tuning done by user @candirufish after 150k games.

Since the tuned values were really interesting and touched heuristics
that are known for their non-linear scaling I decided to run limited
games LTC match, even if the STC test was really bad (which was expected).
After seeing the results of the LTC match, I also run a VLTC (very long
time control) SPRTtest, which passed.

The main difference is in extensions: this patch allows much more
singular/double extensions, both in terms of allowing them at lower
depths and with lesser margins.

Failed STC:
https://tests.stockfishchess.org/tests/view/620d66643ec80158c0cd3b46
LLR: -2.94 (-2.94,2.94) <0.00,2.50>
Total: 4968 W: 1194 L: 1398 D: 2376
Ptnml(0-2): 47, 633, 1294, 497, 13

Performed well at LTC in a fixed-length match:
https://tests.stockfishchess.org/tests/view/620d66823ec80158c0cd3b4a
ELO: 3.36 +-1.8 (95%) LOS: 100.0%
Total: 30000 W: 7966 L: 7676 D: 14358
Ptnml(0-2): 36, 2936, 8755, 3248, 25

Passed VLTC SPRT test:
https://tests.stockfishchess.org/tests/view/620da11a26f5b17ec884f939
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 4400 W: 1326 L: 1127 D: 1947
Ptnml(0-2): 13, 309, 1348, 526, 4

closes https://github.com/official-stockfish/Stockfish/pull/3937

Bench: 6318903
2022-02-17 20:45:21 +01:00
Michael Chaly 3ec6e1d245 Big search tuning (version 2)
One more tuning - this one includes newly introduced heuristics and
some other parameters that were not included in previous one. Result
of 400k games at 20+0.2 "as is". Tuning is continuing since there is
probably a lot more elo to gain.

STC:
https://tests.stockfishchess.org/tests/view/620782edd71106ed12a497d1
LLR: 2.99 (-2.94,2.94) <0.00,2.50>
Total: 38504 W: 10260 L: 9978 D: 18266
Ptnml(0-2): 142, 4249, 10230, 4447, 184

LTC:
https://tests.stockfishchess.org/tests/view/6207a243d71106ed12a49d07
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 25176 W: 6793 L: 6546 D: 11837
Ptnml(0-2): 20, 2472, 7360, 2713, 23

closes https://github.com/official-stockfish/Stockfish/pull/3931

Bench: 4784796
2022-02-13 01:05:27 +01:00
Tomasz Sobczyk cb9c2594fc Update architecture to "SFNNv4". Update network to nn-6877cd24400e.nnue.
Architecture:

The diagram of the "SFNNv4" architecture:
https://user-images.githubusercontent.com/8037982/153455685-cbe3a038-e158-4481-844d-9d5fccf5c33a.png

The most important architectural changes are the following:

* 1024x2 [activated] neurons are pairwise, elementwise multiplied (not quite pairwise due to implementation details, see diagram), which introduces a non-linearity that exhibits similar benefits to previously tested sigmoid activation (quantmoid4), while being slightly faster.
* The following layer has therefore 2x less inputs, which we compensate by having 2 more outputs. It is possible that reducing the number of outputs might be beneficial (as we had it as low as 8 before). The layer is now 1024->16.
* The 16 outputs are split into 15 and 1. The 1-wide output is added to the network output (after some necessary scaling due to quantization differences). The 15-wide is activated and follows the usual path through a set of linear layers. The additional 1-wide output is at least neutral, but has shown a slightly positive trend in training compared to networks without it (all 16 outputs through the usual path), and allows possibly an additional stage of lazy evaluation to be introduced in the future.

Additionally, the inference code was rewritten and no longer uses a recursive implementation. This was necessitated by the splitting of the 16-wide intermediate result into two, which was impossible to do with the old implementation with ugly hacks. This is hopefully overall for the better.

First session:

The first session was training a network from scratch (random initialization). The exact trainer used was slightly different (older) from the one used in the second session, but it should not have a measurable effect. The purpose of this session is to establish a strong network base for the second session. Small deviations in strength do not harm the learnability in the second session.

The training was done using the following command:

python3 train.py \
    /home/sopel/nnue/nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    /home/sopel/nnue/nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 4 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --gamma=0.992 \
    --lr=8.75e-4 \
    --max_epochs=400 \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Every 20th net was saved and its playing strength measured against some baseline at 25k nodes per move with pure NNUE evaluation (modified binary). The exact setup is not important as long as it's consistent. The purpose is to sift good candidates from bad ones.

The dataset can be found https://drive.google.com/file/d/1UQdZN_LWQ265spwTBwDKo0t1WjSJKvWY/view

Second session:

The second training session was done starting from the best network (as determined by strength testing) from the first session. It is important that it's resumed from a .pt model and NOT a .ckpt model. The conversion can be performed directly using serialize.py

The LR schedule was modified to use gamma=0.995 instead of gamma=0.992 and LR=4.375e-4 instead of LR=8.75e-4 to flatten the LR curve and allow for longer training. The training was then running for 800 epochs instead of 400 (though it's possibly mostly noise after around epoch 600).

The training was done using the following command:

The training was done using the following command:

python3 train.py \
        /data/sopel/nnue/nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
        /data/sopel/nnue/nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
        --gpus "$3," \
        --threads 4 \
        --num-workers 4 \
        --batch-size 16384 \
        --progress_bar_refresh_rate 20 \
        --random-fen-skipping 3 \
        --features=HalfKAv2_hm^ \
        --lambda=1.0 \
        --gamma=0.995 \
        --lr=4.375e-4 \
        --max_epochs=800 \
        --resume-from-model /data/sopel/nnue/nnue-pytorch-training/data/exp295/nn-epoch399.pt \
        --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$run_id

In particular note that we now use lambda=1.0 instead of lambda=0.8 (previous nets), because tests show that WDL-skipping introduced by vondele performs better with lambda=1.0. Nets were being saved every 20th epoch. In total 16 runs were made with these settings and the best nets chosen according to playing strength at 25k nodes per move with pure NNUE evaluation - these are the 4 nets that have been put on fishtest.

The dataset can be found either at ftp://ftp.chessdb.cn/pub/sopel/data_sf/T60T70wIsRightFarseerT60T74T75T76.binpack in its entirety (download might be painfully slow because hosted in China) or can be assembled in the following way:

Get the https://github.com/official-stockfish/Stockfish/blob/5640ad48ae5881223b868362c1cbeb042947f7b4/script/interleave_binpacks.py script.
Download T60T70wIsRightFarseer.binpack https://drive.google.com/file/d/1_sQoWBl31WAxNXma2v45004CIVltytP8/view
Download farseerT74.binpack http://trainingdata.farseer.org/T74-May13-End.7z
Download farseerT75.binpack http://trainingdata.farseer.org/T75-June3rd-End.7z
Download farseerT76.binpack http://trainingdata.farseer.org/T76-Nov10th-End.7z
Run python3 interleave_binpacks.py T60T70wIsRightFarseer.binpack farseerT74.binpack farseerT75.binpack farseerT76.binpack T60T70wIsRightFarseerT60T74T75T76.binpack

Tests:

STC: https://tests.stockfishchess.org/tests/view/6203fb85d71106ed12a407b7
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 16952 W: 4775 L: 4521 D: 7656
Ptnml(0-2): 133, 1818, 4318, 2076, 131

LTC: https://tests.stockfishchess.org/tests/view/62041e68d71106ed12a40e85
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 14944 W: 4138 L: 3907 D: 6899
Ptnml(0-2): 21, 1499, 4202, 1728, 22

closes https://github.com/official-stockfish/Stockfish/pull/3927

Bench: 4919707
2022-02-10 19:54:31 +01:00
Michael Chaly b0b31558a2 Big search tuning
Most credits for this patch should go to @candirufish.
Based on his big search tuning (1M games at 20+0.1s)

https://tests.stockfishchess.org/tests/view/61fc7a6ed508ec6a1c9f4b7d

with some hand polishing on top of it, which includes :

a) correcting trend sigmoid - for some reason original tuning resulted in it being negative. This heuristic was proven to be worth some elo for years so reversing it sign is probably some random artefact;
b) remove changes to continuation history based pruning - this heuristic historically was really good at providing green STCs and then failing at LTC miserably if we tried to make it more strict, original tuning was done at short time control and thus it became more strict - which doesn't scale to longer time controls;
c) remove changes to improvement - not really indended :).

passed STC
https://tests.stockfishchess.org/tests/view/6203526e88ae2c84271c2ee2
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 16840 W: 4604 L: 4363 D: 7873
Ptnml(0-2): 82, 1780, 4449, 2033, 76

passed LTC
https://tests.stockfishchess.org/tests/view/620376e888ae2c84271c35d4
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 17232 W: 4771 L: 4542 D: 7919
Ptnml(0-2): 14, 1655, 5048, 1886, 13

closes https://github.com/official-stockfish/Stockfish/pull/3926

bench 5030992
2022-02-09 17:17:00 +01:00
Michael Chaly 08ac4e9db5 Do less depth reduction in null move pruning for complex positions
This patch makes us reduce less depth in null move pruning if complexity is high enough.
Thus, null move pruning now depends in two distinct ways on complexity,
while being the only search heuristic that exploits complexity so far.

passed STC
https://tests.stockfishchess.org/tests/view/61fde60fd508ec6a1c9f7754
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 170000 W: 45555 L: 45027 D: 79418
Ptnml(0-2): 760, 19352, 44359, 19658, 871

passed LTC
https://tests.stockfishchess.org/tests/view/61fe91febf46cb834cbd5c90
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 145272 W: 39182 L: 38651 D: 67439
Ptnml(0-2): 127, 14864, 42157, 15327, 161

closes https://github.com/official-stockfish/Stockfish/pull/3923

bench 4461945
2022-02-07 17:30:35 +01:00
Michael Chaly 4d3950c6eb Reintroduce razoring
Razoring was simplified away some years ago, this patch reintroduces it in a slightly different form.
Now for low depths if eval is far below alpha we check if qsearch can push it above alpha - and if it can't we return a fail low.

passed STC
https://tests.stockfishchess.org/tests/view/61fbf968d508ec6a1c9f3274
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 226120 W: 61106 L: 60472 D: 104542
Ptnml(0-2): 1118, 25592, 59080, 26078, 1192

passed LTC
https://tests.stockfishchess.org/tests/view/61fcc569d508ec6a1c9f5617
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 113128 W: 30851 L: 30397 D: 51880
Ptnml(0-2): 114, 11483, 32926, 11917, 124

closes https://github.com/official-stockfish/Stockfish/pull/3921

bench 4684080
2022-02-05 07:40:21 +01:00
Michael Chaly 95d7369e54 Introduce movecount pruning for quiet check evasions in qsearch
Idea of this patch is that we usually don't consider quiet check evasions as "good" ones and prefer capture based ones instead. So it makes sense to think that if in qsearch 2 quiet check evasions failed to produce anything good 3rd and further ones wouldn't be good either.

passed STC
https://tests.stockfishchess.org/tests/view/61fc1b1ed508ec6a1c9f397c
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 58800 W: 15947 L: 15626 D: 27227
Ptnml(0-2): 273, 6568, 15462, 6759, 338

passed LTC
https://tests.stockfishchess.org/tests/view/61fcc56dd508ec6a1c9f5619
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 89544 W: 24208 L: 23810 D: 41526
Ptnml(0-2): 81, 9038, 26134, 9440, 79

closes https://github.com/official-stockfish/Stockfish/pull/3920

bench 4830082
2022-02-05 07:38:30 +01:00
ppigazzini e178a09c47 Drop sse from target "x86-32"
have maximal compatibility on legacy target arch, now supporting AMD Athlon

The old behavior can anyway be selected by the user if needed, for example

make -j profile-build ARCH=x86-32 sse=yes

fixes #3904
closes https://github.com/official-stockfish/Stockfish/pull/3918

No functional change
2022-02-05 07:33:34 +01:00
Michael Chaly 50200de5af Cleanup and update CPU contributors
closes https://github.com/official-stockfish/Stockfish/pull/3917

No functional change
2022-02-05 07:30:09 +01:00
Michael Chaly 90d051952f Do stats updates after LMR for captures
Since captures that are in LMR use continuation histories of corresponding quiet moves it makes sense to update this histories if this capture passes LMR by analogy to existing logic for quiet moves.

Passed STC
https://tests.stockfishchess.org/tests/view/61f367eef7fba9f1a4f1318b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 208464 W: 56006 L: 55407 D: 97051
Ptnml(0-2): 964, 23588, 54655, 23935, 1090

Passed LTC
https://tests.stockfishchess.org/tests/view/61f41e34f7fba9f1a4f15241
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 69144 W: 18793 L: 18441 D: 31910
Ptnml(0-2): 65, 6982, 20142, 7302, 81

closes https://github.com/official-stockfish/Stockfish/pull/3910

bench 4637392
2022-01-29 08:58:12 +01:00
Michael Chaly 8b4afcf8f7 Scale child node futility pruning with previous move history.
Idea is to do more futility pruning if previous move has bad histories and less if it has good histories.

passed STC
https://tests.stockfishchess.org/tests/view/61e3757fbabab931824e0db7
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 156816 W: 42282 L: 41777 D: 72757
Ptnml(0-2): 737, 17775, 40913, 18212, 771

passed LTC
https://tests.stockfishchess.org/tests/view/61e43496928632f7813a5535
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 349968 W: 94612 L: 93604 D: 161752
Ptnml(0-2): 300, 35934, 101550, 36858, 342

closes https://github.com/official-stockfish/Stockfish/pull/3903

bench 4720954
2022-01-25 07:27:52 +01:00
pschneider1968 bddd38c45e Fix Makefile for Android NDK cross-compile
For cross-compiling to Android on windows, the Makefile needs some tweaks.

Tested with Android NDK 23.1.7779620 and 21.4.7075529, using
Windows 10 with clean MSYS2 environment (i.e. no MINGW/GCC/Clang
toolchain in PATH) and Fedora 35, with build target:
build ARCH=armv8 COMP=ndk

The resulting binary runs fine inside Droidfish on my Samsung
Galaxy Note20 Ultra and Samsung Galaxy Tab S7+

Other builds tested to exclude regressions: MINGW64/Clang64 build
on Windows; MINGW64 cross build, native Clang and GCC builds on Fedora.

wiki docs https://github.com/glinscott/fishtest/wiki/Cross-compiling-Stockfish-for-Android-on-Windows-and-Linux

closes https://github.com/official-stockfish/Stockfish/pull/3901

No functional change
2022-01-25 07:27:23 +01:00
J. Oster 9083050be6 Simplify limiting extensions.
Replace the current method for limiting extensions to avoid search getting stuck
with a much simpler method.

the test position in https://github.com/official-stockfish/Stockfish/commit/73018a03375b4b72ee482eb5a4a2152d7e4f0aac
can still be searched without stuck search.

fixes #3815 where the search now makes progress with rootDepth

shows robust behavior in a d10 search for 1M positions.

passed STC
https://tests.stockfishchess.org/tests/view/61e303e3babab931824dfb18
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 57568 W: 15449 L: 15327 D: 26792
Ptnml(0-2): 243, 6211, 15779, 6283, 268

passed LTC
https://tests.stockfishchess.org/tests/view/61e3586cbabab931824e091c
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 128200 W: 34632 L: 34613 D: 58955
Ptnml(0-2): 124, 12559, 38710, 12588, 119

closes https://github.com/official-stockfish/Stockfish/pull/3899

Bench: 4550528
2022-01-22 10:48:24 +01:00
Joost VandeVondele 77cf5704b6 Revert -flto=auto on mingw
causes issues on some installations (glinscott/fishtest#1255).

closes https://github.com/official-stockfish/Stockfish/pull/3898

No functional change
2022-01-20 18:34:16 +01:00
ppigazzini 67062637f4 Improve Makefile for Windows native builds
A Windows Native Build (WNB) can be done:
 - on Windows, using a recent mingw-w64 g++/clang compiler
   distributed by msys2, cygwin and others
 - on Linux, using mingw-w64 g++ to cross compile

Improvements:
 - check for a WNB in a proper way and set a variable to simplify the code
 - set the proper EXE for a WNB
 - use the proper name for the mingw-w64 clang compiler
 - use the static linking for a WNB
 - use wine to make a PGO cross compile on Linux (also with Intel SDE)
 - enable the LTO build for mingw-w64 g++ compiler
 - set `lto=auto` to use the make's job server, if available, or otherwise
   to fall back to autodetection of the number of CPU threads
 - clean up all the temporary LTO files saved in the local directory

Tested on:
 - msys2 MINGW64 (g++), UCRT64 (g++), MINGW32 (g++), CLANG64 (clang)
   environments
 - cygwin mingw-w64 g++
 - Ubuntu 18.04 & 21.10 mingw-w64 PGO cross compile (also with Intel SDE)

closes #3891

No functional change
2022-01-19 22:26:20 +01:00
ppigazzini 48bf1a386f Add msys2 Clang x86_64 to GitHub Action matrix
Also use Windows Server 2022 virtual environment for msys2 builds.

closes https://github.com/official-stockfish/Stockfish/pull/3893

No functional change
2022-01-19 19:21:10 +01:00
Rui Coelho 2b0372319d Use average complexity for time management
This patch is a variant of the idea by locutus2 (https://tests.stockfishchess.org/tests/view/61e1f24cb1f9959fe5d88168) to adjust the total time depending on the average complexity of the position.

Passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 39664 W: 10765 L: 10487 D: 18412
Ptnml(0-2): 162, 4213, 10837, 4425, 195
https://tests.stockfishchess.org/tests/view/61e2df8b65a644da8c9ea708

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 127656 W: 34505 L: 34028 D: 59123
Ptnml(0-2): 116, 12435, 38261, 12888, 128
https://tests.stockfishchess.org/tests/view/61e31db5babab931824dff5e

closes https://github.com/official-stockfish/Stockfish/pull/3892

Bench: 4464962
2022-01-17 19:48:23 +01:00
proukornew d11101e4c6 Improve logic on mingw
There is no need to point g++, if we explicitly choose mingw.

Now for cygwin:

make COMP=mingw ARCH=x86-64-modern build

closes https://github.com/official-stockfish/Stockfish/pull/3860

No functional change
2022-01-17 19:47:32 +01:00
Rui Coelho 7678d63cf2 Use complexity in search
This patch uses the complexity measure (from #3875) as a heuristic for null move pruning.
Hopefully, there may be room to use it in other pruning techniques.
I would like to thank vondele and locutus2 for the feedback and suggestions during testing.

Passed STC
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 35000 W: 9624 L: 9347 D: 16029
Ptnml(0-2): 156, 3894, 9137, 4143, 170
https://tests.stockfishchess.org/tests/view/61dda784c65bf87d6c45ab80

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 230776 W: 64227 L: 63454 D: 103095
Ptnml(0-2): 1082, 23100, 66380, 23615, 1211
https://tests.stockfishchess.org/tests/view/61ddd0cf3ddbc32543e72c2b

Closes https://github.com/official-stockfish/Stockfish/pull/3890

Bench: 4464962
2022-01-13 22:25:01 +01:00
pschneider1968 c5d45d3220 Fix Makefile for compilation with clang on Windows
use static compilation and
added exclusion of -latomic for Clang/MSYS2 as per ppigazzini's suggestion

fixes #3872

closes https://github.com/official-stockfish/Stockfish/pull/3873

No functional change
2022-01-13 22:17:27 +01:00
Michael Chaly 44b1ba89a9 Adjust pruning constants
This patch is a modification of original tuning done by vondele that failed yellow.
Value differences are divided by 2.

Passed STC
https://tests.stockfishchess.org/tests/view/61d918239fea7913d9c64cdf
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 98968 W: 26248 L: 25858 D: 46862
Ptnml(0-2): 392, 11085, 26156, 11443, 408

Passed LTC
https://tests.stockfishchess.org/tests/view/61d99e3c9fea7913d9c663e4
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 215232 W: 58191 L: 57492 D: 99549
Ptnml(0-2): 271, 22124, 62138, 22801, 282

closes https://github.com/official-stockfish/Stockfish/pull/3885

bench 4572746
2022-01-10 19:35:53 +01:00
Joost VandeVondele c5a280c012 Tune FRC trapped Bishop patch
now that fishtest can deal with FRC, retune this correction.

Add an additional fen to bench with cornered B and N.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 49672 W: 7358 L: 7082 D: 35232
Ptnml(0-2): 241, 4329, 15458, 4529, 279
https://tests.stockfishchess.org/tests/view/61d8b7bf9fea7913d9c63cb7

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 86688 W: 8308 L: 8007 D: 70373
Ptnml(0-2): 92, 4943, 32989, 5212, 108
https://tests.stockfishchess.org/tests/view/61d92dcb9fea7913d9c650ad

closes https://github.com/official-stockfish/Stockfish/pull/3884

Bench: 4326560
2022-01-09 15:49:19 +01:00
Joost VandeVondele 9ad0ea7382 Tune a few parameters related to evaluation
based on a SPSA tune (using Autoselect)
https://tests.stockfishchess.org/tests/view/61d5aa63a314fed318a57046

passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 61960 W: 16640 L: 16316 D: 29004
Ptnml(0-2): 278, 6934, 16204, 7314, 250
https://tests.stockfishchess.org/tests/view/61d7fe4af5fd40f357469a8d

passed LTC:
LLR: 2.97 (-2.94,2.94) <0.50,3.00>
Total: 79408 W: 21994 L: 21618 D: 35796
Ptnml(0-2): 106, 7887, 23331, 8285, 95
https://tests.stockfishchess.org/tests/view/61d836b7f5fd40f35746a3d5

closes https://github.com/official-stockfish/Stockfish/pull/3883

Bench: 4266621
2022-01-08 08:44:49 +01:00
Stéphane Nicolet 2efda17c2a Update AUTHORS and CPU contributors files
closes https://github.com/official-stockfish/Stockfish/pull/3882

No functional change
2022-01-08 08:43:14 +01:00
Brad Knox ad926d34c0 Update copyright years
Happy New Year!

closes https://github.com/official-stockfish/Stockfish/pull/3881

No functional change
2022-01-06 15:45:45 +01:00
lonfom169 0b41887527 Simplify away rangeReduction
Remove rangeReduction, introduced in [#3717](https://github.com/official-stockfish/Stockfish/pull/3717),
as it seemingly doesn't bring enough ELO anymore. It might be interesting to add
new forms of reduction or tune the reduction formula in the future.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 45008 W: 12114 L: 11972 D: 20922
Ptnml(0-2): 174, 5031, 11952, 5173, 174
https://tests.stockfishchess.org/tests/view/61d08b7b069ca917749c9f6f

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30792 W: 8235 L: 8086 D: 14471
Ptnml(0-2): 24, 3162, 8882, 3297, 31
https://tests.stockfishchess.org/tests/view/61d0a6ad069ca917749ca420

closes https://github.com/official-stockfish/Stockfish/pull/3878

Bench: 4048312
2022-01-02 17:49:44 +01:00
lonfom169 061f98a9e3 Smooth out doDeeperSearch
Adjust threshold based on the difference between newDepth and LMR depth.
With more reduction, bigger fail-high is required in order to perform the deeper search.

STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 93576 W: 24133 L: 23758 D: 45685
Ptnml(0-2): 260, 10493, 24935, 10812, 288
https://tests.stockfishchess.org/tests/view/61cbb5cee68b2a714b6eaf09

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 109280 W: 28198 L: 27754 D: 53328
Ptnml(0-2): 60, 11225, 31637, 11647, 71
https://tests.stockfishchess.org/tests/view/61cc03fee68b2a714b6ec091

closes https://github.com/official-stockfish/Stockfish/pull/3877

Bench: 4464723
2021-12-31 07:44:15 +01:00
Stéphane Nicolet 1066119083 Tweak optimism with complexity
This patch increases the optimism bonus for "complex positions", where the
complexity is measured as the absolute value of the difference between material
and the sophisticated NNUE evaluation (idea by Joost VandeVondele).

Also rename some variables in evaluate() while there.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 88392 W: 23150 L: 22781 D: 42461
Ptnml(0-2): 318, 9961, 23257, 10354, 306
https://tests.stockfishchess.org/tests/view/61cbbedee68b2a714b6eb110

passed LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 37848 W: 10043 L: 9766 D: 18039
Ptnml(0-2): 26, 3815, 10961, 4100, 22
https://tests.stockfishchess.org/tests/view/61cc0cc3e68b2a714b6ec28c

Closes https://github.com/official-stockfish/Stockfish/pull/3875
Follow-up from https://github.com/official-stockfish/Stockfish/commit/a5a89b27c8e3225fb453d603bc4515d32bb351c3

Bench: 4125221
2021-12-30 11:59:23 +01:00
bmc4 93b14a17d1 Don't direct prune a move if it's a retake
STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 36304 W: 9499 L: 9226 D: 17579
Ptnml(0-2): 96, 4102, 9508, 4325, 121
https://tests.stockfishchess.org/tests/view/61c7069ae68b2a714b6dca27

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 93824 W: 24478 L: 24068 D: 45278
Ptnml(0-2): 70, 9644, 27082, 10038, 78
https://tests.stockfishchess.org/tests/view/61c725fee68b2a714b6dcfa2

closes https://github.com/official-stockfish/Stockfish/pull/3871

Bench: 4106806
2021-12-27 16:43:44 +01:00
Joost VandeVondele 7d82f0d1f4 Update default net to nn-ac07bd334b62.nnue
Trained with essentially the same data as provided and used by Farseer (mbabigian)
for the previous master net.

T60T70wIsRightFarseerT60T74T75T76.binpack (99GB):
['T60T70wIsRightFarseer.binpack', 'farseerT74.binpack', 'farseerT75.binpack', 'farseerT76.binpack']
using the trainer branch tweakLR1PR (https://github.com/glinscott/nnue-pytorch/pull/158) and
`--gpus 1 --threads 4 --num-workers 4 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 12 --features=HalfKAv2_hm^   --lambda=1.00` options

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 108280 W: 28042 L: 27636 D: 52602
Ptnml(0-2): 328, 12382, 28401, 12614, 415
https://tests.stockfishchess.org/tests/view/61bcd8c257a0d0f327c34fbd

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 259296 W: 66974 L: 66175 D: 126147
Ptnml(0-2): 146, 27096, 74452, 27721, 233
https://tests.stockfishchess.org/tests/view/61bda70957a0d0f327c37817

closes https://github.com/official-stockfish/Stockfish/pull/3870

Bench: 4633875
2021-12-22 11:02:34 +01:00
Michael Chaly 0a6168089d Fall back to NNUE if classical evaluation is much lower than threshold
The idea is that if classical eval returns a value much lower than the threshold of
its usage it most likely means that position isn't that simple
so we need the more precise NNUE evaluation.

passed STC:
https://tests.stockfishchess.org/tests/view/61bf3e7557a0d0f327c3c47a
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 108072 W: 28007 L: 27604 D: 52461
Ptnml(0-2): 352, 12147, 28650, 12520, 367

passed LTC:
https://tests.stockfishchess.org/tests/view/61c0581657a0d0f327c3fa0c
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 155096 W: 40392 L: 39841 D: 74863
Ptnml(0-2): 88, 15983, 44843, 16558, 76

closes https://github.com/official-stockfish/Stockfish/pull/3869

bench 4310422
2021-12-22 08:18:35 +01:00
bmc4 88f17a814d Update Elo estimates for terms in search
This updates estimates from 2yr ago #2401, and adds missing terms.
All tests run at 10+0.1 (STC), 20000 games, error bars +- 1.8 Elo, book 8moves_v3.png.

A table of Elo values with the links to the corresponding tests can be found at the PR

closes https://github.com/official-stockfish/Stockfish/pull/3868

Non-functional Change
2021-12-21 13:47:57 +01:00
bmc4 22e92d23d2 Remove Capture history pruning
Fixed number of games. (book: 8moves_v3.png):
ELO: -0.69 +-1.8 (95%) LOS: 22.1%
Total: 20000 W: 1592 L: 1632 D: 16776
Ptnml(0-2): 44, 1194, 7566, 1150, 46
https://tests.stockfishchess.org/tests/view/61bb8eb657a0d0f327c30ce8

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 139976 W: 36039 L: 36036 D: 67901
Ptnml(0-2): 435, 16138, 36885, 16049, 481
https://tests.stockfishchess.org/tests/view/61be731857a0d0f327c39ea2

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 70656 W: 18284 L: 18189 D: 34183
Ptnml(0-2): 34, 7317, 20529, 7416, 32
https://tests.stockfishchess.org/tests/view/61bf39b657a0d0f327c3c37b

closes https://github.com/official-stockfish/Stockfish/pull/3867

bench: 4281737
2021-12-21 13:42:33 +01:00
bmc4 2c30956a13 Remove Capture Extension
This revert the patch #3692, probably can be simplified after the introduction of #3838.

Fixed-game test:
ELO: -1.41 +-1.8 (95%) LOS: 5.9%
Total: 20000 W: 1552 L: 1633 D: 16815
Ptnml(0-2): 38, 1242, 7517, 1169, 34
https://tests.stockfishchess.org/tests/view/61bc1a2057a0d0f327c32a3c

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 44528 W: 11619 L: 11478 D: 21431
Ptnml(0-2): 146, 5020, 11771, 5201, 126
https://tests.stockfishchess.org/tests/view/61bc638c57a0d0f327c338fe

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 34136 W: 8847 L: 8704 D: 16585
Ptnml(0-2): 23, 3475, 9925, 3626, 19
https://tests.stockfishchess.org/tests/view/61bcb24257a0d0f327c34813

closes https://github.com/official-stockfish/Stockfish/pull/3863

Bench: 4054695
2021-12-21 13:40:57 +01:00
Stéphane Nicolet 74776dbcd5 Simplification in evaluate_nnue.cpp
Removes the test on non-pawn-material before applying the positional/materialistic bonus.

Passed STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 46904 W: 12197 L: 12059 D: 22648
Ptnml(0-2): 170, 5243, 12479, 5399, 161
https://tests.stockfishchess.org/tests/view/61be57cf57a0d0f327c3999d

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 18760 W: 4958 L: 4790 D: 9012
Ptnml(0-2): 14, 1942, 5301, 2108, 15
https://tests.stockfishchess.org/tests/view/61bed1fb57a0d0f327c3afa9

closes https://github.com/official-stockfish/Stockfish/pull/3866

Bench: 4826206
2021-12-19 15:44:01 +01:00
George Sobala ca51b45649 Fixes build failure on Apple M1 Silicon
This pull request selectively avoids `-mdynamic-no-pic` for gcc on Apple Silicon
(there was no problem with the default clang compiler).

fixes https://github.com/official-stockfish/Stockfish/issues/3847
closes https://github.com/official-stockfish/Stockfish/pull/3850

No functional change
2021-12-19 11:43:18 +01:00
Michael Chaly fb7d3ab32e Reintroduce futility pruning for captures
This is a reintroduction of an idea that was simplified away approximately 1 year ago.
There are some tweaks to it :
a) exclude promotions;
b) exclude Pv Nodes from it - Pv Nodes logic for captures is really different from non Pv nodes so it makes a lot of sense;
c) use a big grain of capture history - idea is taken from my recent patches in futility pruning.

passed STC
https://tests.stockfishchess.org/tests/view/61bd90f857a0d0f327c373b7
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 86640 W: 22474 L: 22110 D: 42056
Ptnml(0-2): 268, 9732, 22963, 10082, 275

passed LTC
https://tests.stockfishchess.org/tests/view/61be094457a0d0f327c38aa3
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 23240 W: 6079 L: 5838 D: 11323
Ptnml(0-2): 14, 2261, 6824, 2512, 9

https://github.com/official-stockfish/Stockfish/pull/3864

bench 4493723
2021-12-19 08:03:41 +01:00
Michael Chaly 0a318cdddf Adjust reductions based on current node delta and root delta
This patch is a follow up of previous 2 patches that introduced more reductions for PV nodes with low delta and more pruning for nodes with low delta. Instead of writing separate heuristics now it adjust reductions based on delta / rootDelta - it allows to remove 3 separate adjustements of pruning/LMR in different places and also makes reduction dependence on delta and rootDelta smoother. Also now it works for all pruning heuristics and not just 2.

Passed STC
https://tests.stockfishchess.org/tests/view/61ba9b6c57a0d0f327c2d48b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 79192 W: 20513 L: 20163 D: 38516
Ptnml(0-2): 238, 8900, 21024, 9142, 292

passed LTC
https://tests.stockfishchess.org/tests/view/61baf77557a0d0f327c2eb8e
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 158400 W: 41134 L: 40572 D: 76694
Ptnml(0-2): 101, 16372, 45745, 16828, 154

closes https://github.com/official-stockfish/Stockfish/pull/3862

bench 4651538
2021-12-18 17:19:21 +01:00
George Sobala 939b694bfd Fix for profile-build failure using gcc on MacOS
Fixes https://github.com/official-stockfish/Stockfish/issues/3846 ,
where the profiling SF binary generated by GCC on MacOS would launch
but failed to quit. Tested with gcc-8, gcc9, gcc10, gcc-11.

The problem can be fixed by adding -fvisibility=hidden to the compiler
flags, see for example the following piece of Apple documentation:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

For instance this now works:
   make -j8 profile-build ARCH=x86-64-avx2 COMP=gcc COMPCXX=g++-11

No functional change
2021-12-17 18:52:09 +01:00
pb00067 dc5d9bdfee Remove lowPly history
Seems that after pull request #3731 (Capping stat bonus at 2000) this
heuristic is no longer useful.

STC:
https://tests.stockfishchess.org/tests/view/61b8d0e2dffbe89a35815444
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30672 W: 7974 L: 7812 D: 14886
Ptnml(0-2): 106, 3436, 8072, 3634, 88

LTC:
https://tests.stockfishchess.org/tests/view/61b8e90cdffbe89a35815a67
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 42448 W: 10884 L: 10751 D: 20813
Ptnml(0-2): 23, 4394, 12267, 4507, 33

closes https://github.com/official-stockfish/Stockfish/pull/3853

bench: 4474950
2021-12-17 18:37:41 +01:00
bmc4 0889210262 Simplify away singularQuietLMR
While at it, we also update the Elo estimate of reduction at non-PV nodes
(source: https://tests.stockfishchess.org/tests/view/61acf97156fcf33bce7d6303 )

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 243632 W: 62874 L: 63022 D: 117736
Ptnml(0-2): 810, 28024, 64249, 27970, 763
https://tests.stockfishchess.org/tests/view/61b8b1b7dffbe89a35814c0d

LTC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 91392 W: 23520 L: 23453 D: 44419
Ptnml(0-2): 51, 9568, 26387, 9643, 47
https://tests.stockfishchess.org/tests/view/61b97316dffbe89a35817da7

closes https://github.com/official-stockfish/Stockfish/pull/3854

bench: 4217785
2021-12-17 18:22:48 +01:00
farseer 3bea736a2a Update default net to nn-4401e826ebcc.nnue
Using data T60 12/1/20 to 11/2/2021, T74 4/22/21 to 7/27/21, T75 6/3/21 to 10/16/21, T76
(half of the randomly interleaved dataset due to a mistake merging) 11/10/21 to 11/21/21,
wrongIsRight_nodes5000pv2.binpack, and WrongIsRight-Reloaded.binpack combined and shuffled
position by position.

Trained with LR=4.375e-4 and WDL filtering enabled:

python train.py --smart-fen-skipping --random-fen-skipping 0 --features=HalfKAv2_hm^
--lambda=1.0 --max_epochs=800 --seed 910688689 --batch-size 16384
--progress_bar_refresh_rate 30 --threads 4 --num-workers 4 --gpus 1
--resume-from-model C:\msys64\home\Mike\nnue-pytorch\9b3d.pt
E:\trainingdata\T60-T74-T75-T76-WiR-WiRR-PbyP.binpack
E:\trainingdata\T60-T74-T75-T76-WiR-WiRR-PbyP.binpack

Passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 41848 W: 10962 L: 10676 D: 20210 Elo +2.16
Ptnml(0-2): 142, 4699, 11016, 4865, 202
https://tests.stockfishchess.org/tests/view/61ba886857a0d0f327c2cfd6

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 27776 W: 7208 L: 6953 D: 13615 Elo + 3.00
Ptnml(0-2): 14, 2808, 8007, 3027, 32
https://tests.stockfishchess.org/tests/view/61baae4d57a0d0f327c2d96f

closes https://github.com/official-stockfish/Stockfish/pull/3856

Bench: 4667591
2021-12-17 18:12:47 +01:00
Joost VandeVondele c6edf33f53 Remove NNUE scaling term
remove pawns scaling, probably correlated with piece scaling, and might be less useful with the recent improved nets. Might allow for another tune of the scaling params.

passed STC
https://tests.stockfishchess.org/tests/view/61afdb2e56fcf33bce7df31a
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 280864 W: 72198 L: 72399 D: 136267
Ptnml(0-2): 854, 32356, 74346, 31889, 987

passed LTC
https://tests.stockfishchess.org/tests/view/61b233a606b4c2dcb1b16140
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 400136 W: 102669 L: 103012 D: 194455
Ptnml(0-2): 212, 42005, 116047, 41522, 282

closes https://github.com/official-stockfish/Stockfish/pull/3851

Bench: 4735679
2021-12-14 13:41:12 +01:00
Joost VandeVondele ea1ddb6aef Update default net to nn-d93927199b3d.nnue
Using the same dataset as before but slightly reduced initial LR as in
https://github.com/vondele/nnue-pytorch/tree/tweakLR1

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 51368 W: 13492 L: 13191 D: 24685
Ptnml(0-2): 168, 5767, 13526, 6042, 181
https://tests.stockfishchess.org/tests/view/61b61f43dffbe89a3580b529

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 45128 W: 11763 L: 11469 D: 21896
Ptnml(0-2): 24, 4583, 13063, 4863, 31
https://tests.stockfishchess.org/tests/view/61b6612edffbe89a3580c447

closes https://github.com/official-stockfish/Stockfish/pull/3848

Bench: 5121336
2021-12-13 07:17:25 +01:00
Stefan Geschwentner d579db34a3 Simplify falling eval time factor.
Remove the difference to previous best score in falling eval calculation. As compensation double the effect of the difference to previous best average score.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 86944 W: 22363 L: 22285 D: 42296
Ptnml(0-2): 273, 9227, 24396, 9301, 275
https://tests.stockfishchess.org/tests/view/61b111ce06b4c2dcb1b11546

LTC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 134944 W: 34606 L: 34596 D: 65742
Ptnml(0-2): 66, 12941, 41456, 12935, 74
https://tests.stockfishchess.org/tests/view/61b19ca206b4c2dcb1b13a8b

closes https://github.com/official-stockfish/Stockfish/pull/3841

Bench: 4729473
2021-12-11 15:56:38 +01:00
Joost VandeVondele 9db6ca8592 Update Top CPU Contributors
closes https://github.com/official-stockfish/Stockfish/pull/3842

No functional change
2021-12-11 15:55:32 +01:00
Michael Chaly 8e82345931 Adjust singular extension depth restriction
This patch is a modification of original idea by lonfom169 which had a good yellow run
- do singular extension search with depth threshold 6 unless this is a PvNode with is a part of a PV line -
for them set threshold to 8 instead.

Passed STC
https://tests.stockfishchess.org/tests/view/61b1080406b4c2dcb1b1128c
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 84352 W: 21917 L: 21555 D: 40880
Ptnml(0-2): 288, 9524, 22185, 9896, 283

Passed LTC
https://tests.stockfishchess.org/tests/view/61b1860a06b4c2dcb1b134a1
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 63520 W: 16575 L: 16237 D: 30708
Ptnml(0-2): 27, 6519, 18350, 6817, 47

https://github.com/official-stockfish/Stockfish/pull/3840

bench 4729473
2021-12-09 20:50:00 +01:00
Stefan Geschwentner 9451419912 Improve transposition table remplacement strategy
Increase chance that PV node replaces old entry in transposition table.

STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 46744 W: 12108 L: 11816 D: 22820
Ptnml(0-2): 156, 5221, 12344, 5477, 174
https://tests.stockfishchess.org/tests/view/61ae068356fcf33bce7d99d0

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 88464 W: 22912 L: 22513 D: 43039
Ptnml(0-2): 84, 9133, 25393, 9544, 78
https://tests.stockfishchess.org/tests/view/61ae973656fcf33bce7db3e1

closes https://github.com/official-stockfish/Stockfish/pull/3839

Bench: 5292488
2021-12-08 17:16:17 +01:00
Michael Chaly c228f3196a Introduce post-lmr extensions
This idea is somewhat similar to extentions in LMR but has a different flavour.
If result of LMR was really good - thus exceeded alpha by some pretty
big given margin, we can extend move after LMR in full depth search with 0 window.
The idea is that this move is probably a fail high with somewhat of a big
probability so extending it makes a lot of sense

passed STC
https://tests.stockfishchess.org/tests/view/61ad45ea56fcf33bce7d74b7
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 59680 W: 15531 L: 15215 D: 28934
Ptnml(0-2): 193, 6711, 15734, 6991, 211

passed LTC
https://tests.stockfishchess.org/tests/view/61ad9ff356fcf33bce7d8646
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 59104 W: 15321 L: 14992 D: 28791
Ptnml(0-2): 53, 6023, 17065, 6364, 47

closes https://github.com/official-stockfish/Stockfish/pull/3838

bench 4881329
2021-12-07 18:15:06 +01:00
Tomasz Sobczyk 4766dfc395 Optimize FT activation and affine transform for NEON.
This patch optimizes the NEON implementation in two ways.

    The activation layer after the feature transformer is rewritten to make it easier for the compiler to see through dependencies and unroll. This in itself is a minimal, but a positive improvement. Other architectures could benefit from this too in the future. This is not an algorithmic change.
    The affine transform for large matrices (first layer after FT) on NEON now utilizes the same optimized code path as >=SSSE3, which makes the memory accesses more sequential and makes better use of the available registers, which allows for code that has longer dependency chains.

Benchmarks from Redshift#161, profile-build with apple clang

george@Georges-MacBook-Air nets % ./stockfish-b82d93 bench 2>&1 | tail -4 (current master)
===========================
Total time (ms) : 2167
Nodes searched  : 4667742
Nodes/second    : 2154011
george@Georges-MacBook-Air nets % ./stockfish-7377b8 bench 2>&1 | tail -4 (this patch)
===========================
Total time (ms) : 1842
Nodes searched  : 4667742
Nodes/second    : 2534061

This is a solid 18% improvement overall, larger in a bench with NNUE-only, not mixed.

Improvement is also observed on armv7-neon (Raspberry Pi, and older phones), around 5% speedup.

No changes for architectures other than NEON.

closes https://github.com/official-stockfish/Stockfish/pull/3837

No functional changes.
2021-12-07 18:08:54 +01:00
Joost VandeVondele b82d93ece4 Update default net to nn-63376713ba63.nnue.
same data set as previous trained nets, tuned the wdl model slightly for training.
https://github.com/vondele/nnue-pytorch/tree/wdlTweak1

passed STC:
https://tests.stockfishchess.org/tests/view/61abe9e456fcf33bce7d2834
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 31720 W: 8385 L: 8119 D: 15216
Ptnml(0-2): 117, 3534, 8273, 3838, 98

passed LTC:
https://tests.stockfishchess.org/tests/view/61ac293756fcf33bce7d36cf
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 136136 W: 35255 L: 34741 D: 66140
Ptnml(0-2): 114, 14217, 38894, 14727, 116

closes https://github.com/official-stockfish/Stockfish/pull/3836

Bench: 4667742
2021-12-07 12:40:48 +01:00
Michael Chaly a3d425cf55 Assign extra bonus for previous move that caused a fail low more often
This patch allows to assign extra bonus for previous move that caused a fail low not only for PvNodes and cutNodes but also fo some allNodes - namely if the best result we could've got from the search is still far below alpha.

passed STC
https://tests.stockfishchess.org/tests/view/61aa26a49e8855bba1a36d96
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 73808 W: 19183 L: 18842 D: 35783
Ptnml(0-2): 251, 8257, 19564, 8564, 268

passed LTC
https://tests.stockfishchess.org/tests/view/61aa7dc29e8855bba1a3814f
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 142416 W: 36717 L: 36192 D: 69507
Ptnml(0-2): 106, 14799, 40862, 15346, 95

closes https://github.com/official-stockfish/Stockfish/pull/3835

bench 4724181
2021-12-06 07:42:04 +01:00
Stefan Geschwentner 7d44b43b3c Tweak history initialization
Initialize continuation history with a slighlty negative value -71 instead of zero.

The idea is, because the most history entries will be later negative anyway, to shift
the starting values a little bit in the "correct" direction. Of course the effect of
initialization dimishes with greater depth so I had the apprehension that the LTC test
would be difficult to pass, but it passed.

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 34520 W: 9076 L: 8803 D: 16641
Ptnml(0-2): 136, 3837, 9047, 4098, 142
https://tests.stockfishchess.org/tests/view/61aa52e39e8855bba1a3776b

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 75568 W: 19620 L: 19254 D: 36694
Ptnml(0-2): 44, 7773, 21796, 8115, 56
https://tests.stockfishchess.org/tests/view/61aa87d39e8855bba1a383a5

closes https://github.com/official-stockfish/Stockfish/pull/3834

Bench: 4674029
2021-12-05 18:13:49 +01:00
Stefan Geschwentner 18f2b12cd0 Tweak time management
Use for adjustment of the falling eval time factor now also the difference
between previous best average score and current best score.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 109216 W: 28296 L: 27900 D: 53020
Ptnml(0-2): 312, 11759, 30148, 11999, 390
https://tests.stockfishchess.org/tests/view/61aafa8d1b31b85bcfa29d9c

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 54096 W: 14091 L: 13787 D: 26218
Ptnml(0-2): 29, 5124, 16447, 5410, 38
https://tests.stockfishchess.org/tests/view/61abbbbd56fcf33bce7d1d64

closes https://github.com/official-stockfish/Stockfish/pull/3833

Bench: 4829419
2021-12-05 17:56:54 +01:00
bmc4 a6a9d828ab Simplifies bestMoveChanges from LMR
As bestMoveChanges is only reset on mainThread and it could change how other
threads search, a multi-threads test was made.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 146776 W: 37934 L: 37941 D: 70901
Ptnml(0-2): 477, 15644, 41173, 15597, 497
https://tests.stockfishchess.org/tests/view/61a8f9f34ed77d629d4ea2d6

LTC:
LLR: 3.11 (-2.94,2.94) <-2.25,0.25>
Total: 114040 W: 29314 L: 29269 D: 55457
Ptnml(0-2): 50, 10584, 35722, 10599, 65
https://tests.stockfishchess.org/tests/view/61a9d4bf9e8855bba1a35c4f

(SMP, 8 threads) STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 23888 W: 6308 L: 6143 D: 11437
Ptnml(0-2): 36, 2557, 6600, 2708, 43
https://tests.stockfishchess.org/tests/view/61ac27a756fcf33bce7d3677

closes https://github.com/official-stockfish/Stockfish/pull/3831

bench: 4829419
2021-12-05 17:50:04 +01:00
Joost VandeVondele 327060232a Update default net to nn-cdf1785602d6.nnue
Same process as in https://github.com/official-stockfish/Stockfish/commit/e4a0c6c75950bf27b6dc32490a1102499643126b
with the training started from the current master net.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 38224 W: 10023 L: 9742 D: 18459
Ptnml(0-2): 133, 4328, 9940, 4547, 164
https://tests.stockfishchess.org/tests/view/61a8611e4ed77d629d4e836e

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 115176 W: 29783 L: 29321 D: 56072
Ptnml(0-2): 68, 12039, 32936, 12453, 92
https://tests.stockfishchess.org/tests/view/61a8963e4ed77d629d4e8d9b

closes https://github.com/official-stockfish/Stockfish/pull/3830

Bench: 4829419
2021-12-04 10:31:22 +01:00
Michael Chaly e4b7403f12 Do more aggressive pruning for some node types
This patch allows more aggressive futility/see based pruning for PV nodes with low delta and non-pv nodes.

Fixes some white space issues.

Passed STC
https://tests.stockfishchess.org/tests/view/61a5ed33d16c530b5dcc27cc
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 182088 W: 47121 L: 46584 D: 88383
Ptnml(0-2): 551, 20687, 48037, 21212, 557

Passed LTC
https://tests.stockfishchess.org/tests/view/61a74dfdbd5c4360bcded0ac
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 87136 W: 22494 L: 22103 D: 42539
Ptnml(0-2): 38, 8918, 25272, 9295, 45

closes https://github.com/official-stockfish/Stockfish/pull/3828
closes https://github.com/official-stockfish/Stockfish/pull/3829

bench 4332259
2021-12-03 08:54:46 +01:00
Gian-Carlo Pascutto c9977aa0a8 Add AVX-VNNI support for Alder Lake and later.
In their infinite wisdom, Intel axed AVX512 from Alder Lake
chips (well, not entirely, but we kind of want to use the Gracemont
cores for chess!) but still added VNNI support.
Confusingly enough, this is not the same as VNNI256 support.

This adds a specific AVX-VNNI target that will use this AVX-VNNI
mode, by prefixing the VNNI instructions with the appropriate VEX
prefix, and avoiding AVX512 usage.

This is about 1% faster on P cores:

Result of  20 runs
==================
base (./clang-bmi2   ) =    3306337  +/- 7519
test (./clang-vnni   ) =    3344226  +/- 7388
diff                   =     +37889  +/- 4153

speedup        = +0.0115
P(speedup > 0) =  1.0000

But a nice 3% faster on E cores:

Result of  20 runs
==================
base (./clang-bmi2   ) =    1938054  +/- 28257
test (./clang-vnni   ) =    1994606  +/- 31756
diff                   =     +56552  +/- 3735

speedup        = +0.0292
P(speedup > 0) =  1.0000

This was measured on Clang 13. GCC 11.2 appears to generate
worse code for Alder Lake, though the speedup on the E cores
is similar.

It is possible to run the engine specifically on the P or E using binding,
for example in linux it is possible to use (for an 8 P + 8 E setup like i9-12900K):
taskset -c 0-15 ./stockfish
taskset -c 16-23 ./stockfish
where the first call binds to the P-cores and the second to the E-cores.

closes https://github.com/official-stockfish/Stockfish/pull/3824

No functional change
2021-12-03 08:51:06 +01:00
bmc4 c1f9a359e8 Correctly reset bestMoveChanges
for searches not using time management (e.g. analysis, fixed node game play etc),
bestMoveChanges was not reset during search iterations. As LMR uses this quantity,
search was somewhat weaker.

Tested using fixed node playing games:
```
./c-chess-cli -each nodes=10000 option.Hash=16 -engine cmd=../Stockfish/src/fix -engine cmd=../Stockfish/src/master -concurrency 6 -openings file=../books/UHO_XXL_+0.90_+1.19.epd -games 10000
Score of Stockfish Fix vs Stockfish Master: 3187 - 3028 - 3785  [0.508] 10000

./c-chess-cli -each nodes=30000 option.Hash=16 -engine cmd=../Stockfish/src/fix -engine cmd=../Stockfish/src/master -concurrency 6 -openings file=../books/UHO_XXL_+0.90_+1.19.epd -games 10000
Score of Stockfish Fix vs Stockfish Master: 2946 - 2834 - 4220  [0.506] 10000
```

closes https://github.com/official-stockfish/Stockfish/pull/3818

bench: 5061979
2021-12-01 18:22:44 +01:00
bmc4 95a2ac1e07 Simplify reduction on rootNode when bestMoveChanges is high
The reduction introduced in #3736 also consider on rootNode, so we don't have to reduce again.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 28736 W: 7494 L: 7329 D: 13913
Ptnml(0-2): 95, 3247, 7503, 3444, 79
https://tests.stockfishchess.org/tests/view/61a3abe01b7fdf52228e74d8

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 47816 W: 12434 L: 12308 D: 23074
Ptnml(0-2): 37, 4972, 13755, 5116, 28
https://tests.stockfishchess.org/tests/view/61a3c3e39f0c43dae1c71d71

closes https://github.com/official-stockfish/Stockfish/pull/3817

bench: 6331638
2021-12-01 18:10:51 +01:00
Michael Ortmann 4b86ef8c4f Fix typos in comments, adjust readme
closes https://github.com/official-stockfish/Stockfish/pull/3822

also adjusts readme as requested in https://github.com/official-stockfish/Stockfish/pull/3816

No functional change
2021-12-01 18:07:30 +01:00
hengyu 64f21ecdae Small clean-up
remove unneeded calculation.

closes https://github.com/official-stockfish/Stockfish/pull/3807

No functional change.
2021-12-01 17:59:20 +01:00
pb00067 282644f141 Remove depth dependence and use same limit (2000) as stat_bonus
STC:
https://tests.stockfishchess.org/tests/view/619df59dc0a4ea18ba95a424
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 83728 W: 21329 L: 21242 D: 41157
Ptnml(0-2): 297, 9669, 21847, 9752, 299

LTC:
https://tests.stockfishchess.org/tests/view/619e64d7c0a4ea18ba95a475
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 79888 W: 20238 L: 20155 D: 39495
Ptnml(0-2): 57, 8391, 22980, 8444, 73

closes https://github.com/official-stockfish/Stockfish/pull/3806

bench: 6792010
2021-12-01 17:55:23 +01:00
noobpwnftw ca3c1c5f3a Enable compilation on older Windows systems
Improve compatibility of the last NUMA patch when running under older versions of Windows,
for instance Windows Server 2003. Reported by user "g3g6" in the following comments:
https://github.com/official-stockfish/Stockfish/commit/7218ec4df9fef1146a451b71f0ed3bfd8123c9f9

Closes https://github.com/official-stockfish/Stockfish/pull/3821

No functional change
2021-11-30 20:57:47 +01:00
Joost VandeVondele e4a0c6c759 Update default net to nn-4f56ecfca5b7.nnue
New net trained with nnue-pytorch, started from a master net on a data set of Leela
(T60.binpack+T74.binpck) Stockfish data (wrongIsRight_nodes5000pv2.binpack), and
Michael Babigian's conversion of T60 Leela data (including TB7 rescoring) (farseer.binpack)
available as a single interleaved binpack:

https://drive.google.com/file/d/1_sQoWBl31WAxNXma2v45004CIVltytP8/view?usp=sharing

The nnue-pytorch branch used is https://github.com/vondele/nnue-pytorch/tree/wdl

passed STC:
https://tests.stockfishchess.org/tests/view/61a3cc729f0c43dae1c71f1b
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 49152 W: 12842 L: 12544 D: 23766
Ptnml(0-2): 154, 5542, 12904, 5804, 172

passed LTC:
https://tests.stockfishchess.org/tests/view/61a43c6260afd064f2d724f1
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 25528 W: 6676 L: 6425 D: 12427
Ptnml(0-2): 9, 2593, 7315, 2832, 15

closes https://github.com/official-stockfish/Stockfish/pull/3816

Bench: 6885242
2021-11-29 12:56:01 +01:00
Michael Chaly af050e5eed Refine futility pruning for parent nodes
This patch is a result of refining of tuning vondele did after
new net passed and some hand-made values adjustements - excluding
changes in other pruning heuristics and rounding value of history
divisor to the nearest power of 2.

With this patch futility pruning becomes more aggressive and
history influence on it is doubled again.

passed STC
https://tests.stockfishchess.org/tests/view/61a2c4c1a26505c2278c150d
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 33848 W: 8841 L: 8574 D: 16433
Ptnml(0-2): 100, 3745, 8988, 3970, 121

passed LTC
https://tests.stockfishchess.org/tests/view/61a327ffa26505c2278c26d9
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 22272 W: 5856 L: 5614 D: 10802
Ptnml(0-2): 12, 2230, 6412, 2468, 14

closes https://github.com/official-stockfish/Stockfish/pull/3814

bench 6302543
2021-11-28 14:25:06 +01:00
Michael Chaly 8bb5a436b2 Adjust usage of history in futility pruning
This patch refines 0ac8aca893 that uses history heuristics in futility pruning.
Now it adds main history of the move to in and also increases effect by factor of 2.

passed STC
https://tests.stockfishchess.org/tests/view/61a156829e83391467a2b2c9
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 68464 W: 17920 L: 17587 D: 32957
Ptnml(0-2): 239, 7711, 18025, 7992, 265

passed LTC
https://tests.stockfishchess.org/tests/view/61a1bde99e83391467a2b305
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 26088 W: 6926 L: 6674 D: 12488
Ptnml(0-2): 18, 2619, 7531, 2845, 31

closes https://github.com/official-stockfish/Stockfish/pull/3812

bench 6804653
2021-11-27 14:47:46 +01:00
Joost VandeVondele 4bb11e823f Tune NNUE scaling params
passed STC:
https://tests.stockfishchess.org/tests/view/61a156f89e83391467a2b2cc
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22816 W: 5896 L: 5646 D: 11274
Ptnml(0-2): 55, 2567, 5961, 2723, 102

passed LTC:
https://tests.stockfishchess.org/tests/view/61a1cf3d9e83391467a2b30b
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 17904 W: 4658 L: 4424 D: 8822
Ptnml(0-2): 6, 1821, 5079, 2025, 21

closes https://github.com/official-stockfish/Stockfish/pull/3811

Bench: 7218806
2021-11-27 14:26:35 +01:00
Joost VandeVondele 9ee58dc7a7 Update default net to nn-3678835b1d3d.nnue
New net trained with nnue-pytorch, started from the master net on a data set of Leela
(T60.binpack+T74.binpck) and Stockfish data (wrongIsRight_nodes5000pv2.binpack),
available as a single interleaved binpack:

https://drive.google.com/file/d/12uWZIA3F2cNbraAzQNb1jgf3tq_6HkTr/view?usp=sharing

The nnue-pytorch branch used is https://github.com/vondele/nnue-pytorch/tree/wdl, which
has the new feature to filter positions based on the likelihood of the current evaluation
leading to the game outcome. It should make it less likely to try to learn from
misevaluated positions. Standard options have been used, starting from the master net:

   --gpus 1 --threads 4 --num-workers 4 --batch-size 16384 --progress_bar_refresh_rate 300
   --smart-fen-skipping --random-fen-skipping 12 --features=HalfKAv2_hm^   --lambda=1.0

Testing with games shows neutral Elo at STC, and good performance at LTC:

STC:
https://tests.stockfishchess.org/tests/view/619eb597c0a4ea18ba95a4dc
ELO: -0.44 +-1.8 (95%) LOS: 31.2%
Total: 40000 W: 10447 L: 10498 D: 19055
Ptnml(0-2): 254, 4576, 10260, 4787, 123

LTC:
https://tests.stockfishchess.org/tests/view/619f6e87c0a4ea18ba95a53f
ELO: 3.30 +-1.8 (95%) LOS: 100.0%
Total: 33062 W: 8560 L: 8246 D: 16256
Ptnml(0-2): 54, 3358, 9352, 3754, 13

passed LTC SPRT:
https://tests.stockfishchess.org/tests/view/61a0864e8967bbf894416e65
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 29376 W: 7663 L: 7396 D: 14317
Ptnml(0-2): 67, 3017, 8205, 3380, 19

closes https://github.com/official-stockfish/Stockfish/pull/3808

Bench: 7011501
2021-11-26 18:16:04 +01:00
Michael Chaly 0ac8aca893 Use fraction of history heuristics in futility pruning
This idea is somewhat of a respin of smth we had in futility pruning and that was simplified away - dependence of it not only on static evaluation of position but also on move history heuristics.
Instead of aborting it when they are high there we use fraction of their sum to adjust static eval pruning criteria.

passed STC
https://tests.stockfishchess.org/tests/view/619bd438c0a4ea18ba95a27d
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 113704 W: 29284 L: 28870 D: 55550
Ptnml(0-2): 357, 12884, 30044, 13122, 445

passed LTC
https://tests.stockfishchess.org/tests/view/619cb8f0c0a4ea18ba95a334
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 147136 W: 37307 L: 36770 D: 73059
Ptnml(0-2): 107, 15279, 42265, 15804, 113

closes https://github.com/official-stockfish/Stockfish/pull/3805

bench 6777918
2021-11-25 19:38:03 +01:00
Stefan Geschwentner 092b27a6d0 Less futility pruning.
Disable futility pruning at former PV nodes stored in the transposition table.

STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 102256 W: 25708 L: 25318 D: 51230
Ptnml(0-2): 276, 11511, 27168, 11893, 280
https://tests.stockfishchess.org/tests/view/61990b3135c7c6348cb602db

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 183304 W: 46027 L: 45408 D: 91869
Ptnml(0-2): 96, 19029, 52778, 19658, 91
https://tests.stockfishchess.org/tests/view/619a0d1b35c7c6348cb603bc

closes https://github.com/official-stockfish/Stockfish/pull/3804

Bench: 7334766
2021-11-23 21:23:28 +01:00
noobpwnftw 7218ec4df9 Revert and fix earlier windows NUMA patch
revert https://github.com/official-stockfish/Stockfish/commit/9048ac00db12a9ac48bff9b9eb145b30ff88d984 due to core spread problem and fix new OS compatibility with another method.

This code assumes that if one NUMA node has more than one processor groups, they are created equal(having equal amount of cores assigned to each of the groups), and also the total number of available cores contained in such groups are equal to the number of available cores within one NUMA node because of how best_node function works.

closes https://github.com/official-stockfish/Stockfish/pull/3798
fixes https://github.com/official-stockfish/Stockfish/pull/3787

No functional change.
2021-11-22 13:31:13 +01:00
Joost VandeVondele a943b1d28d Remove appveyor CI
retire msvc support and corresponding CI. No active development happens on msvc,
and build is much slower or wrong.

gcc (mingw) is our toolchain of choice also on windows, and the latter is tested.

No functional change
2021-11-21 21:56:13 +01:00
Stéphane Nicolet a5a89b27c8 Introduce Optimism
Current master implements a scaling of the raw NNUE output value with a formula
equivalent to 'eval = alpha * NNUE_output', where the scale factor alpha varies
between 1.8 (for early middle game) and 0.9 (for pure endgames). This feature
allows Stockfish to keep material on the board when she thinks she has the advantage,
and to seek exchanges and simplifications when she thinks she has to defend.

This patch slightly offsets the turning point between these two strategies, by adding
to Stockfish's evaluation a small "optimism" value before actually doing the scaling.
The effect is that SF will play a little bit more risky, trying to keep the tension a
little bit longer when she is defending, and keeping even more material on the board
when she has an advantage.

We note that this patch is similar in spirit to the old "Contempt" idea we used to have
in classical Stockfish, but this implementation differs in two key points:

  a) it has been tested as an Elo-gainer against master;

  b) the values output by the search are not changed on average by the implementation
     (in other words, the optimism value changes the tension/exchange strategy, but a
     displayed value of 1.0 pawn has the same signification before and after the patch).

See the old comment https://github.com/official-stockfish/Stockfish/pull/1361#issuecomment-359165141
for some images illustrating the ideas.

-------

finished yellow at STC:
LLR: -2.94 (-2.94,2.94) <0.00,2.50>
Total: 165048 W: 41705 L: 41611 D: 81732
Ptnml(0-2): 565, 18959, 43245, 19327, 428
https://tests.stockfishchess.org/tests/view/61942a3dcd645dc8291c876b

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 121656 W: 30762 L: 30287 D: 60607
Ptnml(0-2): 87, 12558, 35032, 13095, 56
https://tests.stockfishchess.org/tests/view/61962c58cd645dc8291c8877

-------

How to continue from there?

a) the shape (slope and amplitude) of the sigmoid used to compute the optimism value
   could be tweaked to try to gain more Elo, so the parameters of the sigmoid function
   in line 391 of search.cpp could be tuned with SPSA. Manual tweaking is also possible
   using this Desmos page: https://www.desmos.com/calculator/jhh83sqq92

b) in a similar vein, with two recents patches affecting the scaling of the NNUE
   evaluation in evaluate.cpp, now could be a good time to try a round of SPSA tuning
   of the NNUE network;

c) this patch will tend to keep tension in middlegame a little bit longer, so any
   patch improving the defensive aspect of play via search extensions in risky,
   tactical positions would be welcome.

-------

closes https://github.com/official-stockfish/Stockfish/pull/3797

Bench: 6184852
2021-11-21 21:18:08 +01:00
Michael Chaly f5df517145 Simplify Pv nodes related logic in LMR
Instead of having 2 separate conditions for Pv nodes reductions we can actually write them together. Despite it's not being strictly logically the same bench actually doesn't change up to depth 20, so them interacting is really rare and thus it's just a removal of extra PvNode check most of the time.

passed STC:
https://tests.stockfishchess.org/tests/view/618ce27cd7a085ad008ef4e9
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 37488 W: 9424 L: 9279 D: 18785
Ptnml(0-2): 90, 3903, 10634, 4006, 111

passed LTC:
https://tests.stockfishchess.org/tests/view/618d2585d7a085ad008ef527
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 49968 W: 12449 L: 12331 D: 25188
Ptnml(0-2): 27, 4745, 15309, 4889, 14

closes https://github.com/official-stockfish/Stockfish/pull/3792

Bench: 6339548
2021-11-15 18:20:10 +01:00
noobpwnftw 9048ac00db Fix processor group binding under Windows.
Starting with Windows Build 20348 the behavior of the numa API has been changed:
https://docs.microsoft.com/en-us/windows/win32/procthread/numa-support

Old code only worked because there was probably a limit on how many
cores/threads can reside within one NUMA node, and the OS creates extra NUMA
nodes when necessary, however the actual mechanism of core binding is
done by "Processor Groups"(https://docs.microsoft.com/en-us/windows/win32/procthread/processor-groups). With a newer OS, one NUMA node can have many
such "Processor Groups" and we should just consistently use the number
of groups to bind the threads instead of deriving the topology from
the number of NUMA nodes.

This change is required to spread threads on all cores on Windows 11 with
a 3990X CPU. It has only 1 NUMA node with 2 groups of 64 threads each.

closes https://github.com/official-stockfish/Stockfish/pull/3787

No functional change.
2021-11-15 18:19:53 +01:00
Joost VandeVondele 1a5c21dc56 Tune a few NNUE related scaling parameters
passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 102480 W: 26099 L: 25708 D: 50673
Ptnml(0-2): 282, 11637, 27003, 12044, 274
https://tests.stockfishchess.org/tests/view/618820e3d7a085ad008ef1dd

passed LTC
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 165512 W: 41689 L: 41112 D: 82711
Ptnml(0-2): 82, 17255, 47510, 17822, 87
https://tests.stockfishchess.org/tests/view/6188b470d7a085ad008ef239

closes https://github.com/official-stockfish/Stockfish/pull/3784

Bench: 6339548
2021-11-11 00:56:57 +01:00
bmc4 c4a1390f4e Simplify away the Reverse Move penalty
This simplifies the penalty for reverse move introduced in
https://github.com/official-stockfish/Stockfish/pull/2294 .

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 81696 W: 20627 L: 20540 D: 40529
Ptnml(0-2): 221, 9390, 21559, 9437, 241
https://tests.stockfishchess.org/tests/view/618810acd7a085ad008ef1cc

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 44136 W: 11021 L: 10890 D: 22225
Ptnml(0-2): 28, 4570, 12746, 4691, 33
https://tests.stockfishchess.org/tests/view/61885686d7a085ad008ef20b

closes https://github.com/official-stockfish/Stockfish/pull/3781

bench: 6547978
2021-11-08 13:14:18 +01:00
Joost VandeVondele 7b278aab9f Reduce use of lazyEval
In case the evaluation at root is large, discourage the use of lazyEval.

This fixes https://github.com/official-stockfish/Stockfish/issues/3772
or at least improves it significantly. In this case, poor play with large
odds can be observed, in extreme cases leading to a loss despite large
advantage:

r1bq1b1r/ppp3p1/3p1nkp/n3p3/2B1P2N/2NPB3/PPP2PPP/R3K2R b KQ - 5 9

With this patch the poor move is only considered up to depth 13, in master
up to depth 28.

The patch did not pass at LTC with Elo gainer bounds, but with slightly
positive Elo nevertheless (95% LOS).

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 40368 W: 10318 L: 10041 D: 20009
Ptnml(0-2): 103, 4493, 10725, 4750, 113
https://tests.stockfishchess.org/tests/view/61800ad259e71df00dcc420d

LTC:
LLR: -2.94 (-2.94,2.94) <0.50,3.00>
Total: 212288 W: 52997 L: 52692 D: 106599
Ptnml(0-2): 112, 22038, 61549, 22323, 122
https://tests.stockfishchess.org/tests/view/618050d959e71df00dcc426d

closes https://github.com/official-stockfish/Stockfish/pull/3780

Bench: 7127040
2021-11-08 13:03:52 +01:00
Stefan Geschwentner a0259d8ab9 Tweak initial aspiration window.
Maintain for each root move an exponential average of the search value with a weight ratio of 2:1 (new value vs old values). Then the average score is used as the center of the initial aspiration window instead of the previous score.

Stats indicate (see PR) that the deviation for previous score is in general greater than using average score, so later seems a better estimation of the next search value. This is probably the reason this patch succeded besides smoothing the sometimes wild swings in search score. An additional observation is that at higher depth previous score is above but average score below zero. So for average score more/less fail/low highs should be occur than previous score.

STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 59792 W: 15106 L: 14792 D: 29894
Ptnml(0-2): 144, 6718, 15869, 7010, 155
https://tests.stockfishchess.org/tests/view/61841612d7a085ad008eef06

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 46448 W: 11835 L: 11537 D: 23076
Ptnml(0-2): 21, 4756, 13374, 5050, 23
https://tests.stockfishchess.org/tests/view/618463abd7a085ad008eef3e

closes https://github.com/official-stockfish/Stockfish/pull/3776

Bench: 6719976
2021-11-05 22:22:30 +01:00
Joost VandeVondele 45e5e65a28 do not store qsearch positions in TT as exact.
in qsearch don't store positions in TT with the exact flag.

passed STC:
https://tests.stockfishchess.org/tests/view/617f9a29af49befdeee40231
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 155568 W: 39003 L: 39022 D: 77543
Ptnml(0-2): 403, 17854, 41305, 17803, 419

passed LTC:
https://tests.stockfishchess.org/tests/view/6180d47259e71df00dcc42a5
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 79640 W: 19993 L: 19910 D: 39737
Ptnml(0-2): 37, 8356, 22957, 8427, 43

closes https://github.com/official-stockfish/Stockfish/pull/3775

Bench: 7531210
2021-11-05 22:20:37 +01:00
Michael Chaly c2b9134c6e Do more reductions at Pv nodes with low delta
This patch increases reduction for PvNodes that have their delta (difference between beta and alpha) significantly reduced compared to what it was at root.

passed STC
https://tests.stockfishchess.org/tests/view/617f9063af49befdeee40226
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 220840 W: 55752 L: 55150 D: 109938
Ptnml(0-2): 583, 24982, 58712, 25536, 607

passed LTC
https://tests.stockfishchess.org/tests/view/61815de959e71df00dcc42ed
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 79000 W: 19937 L: 19562 D: 39501
Ptnml(0-2): 36, 8190, 22674, 8563, 37

closes https://github.com/official-stockfish/Stockfish/pull/3774

bench: 6717808
2021-11-05 22:18:59 +01:00
lonfom169 11c6cf720d More futility pruning
Expand maximum allowed eval by 50% in futility pruning, above the VALUE_KNOWN_WIN.

STC:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 128208 W: 32534 L: 32192 D: 63482
Ptnml(0-2): 298, 13484, 36216, 13790, 316
https://tests.stockfishchess.org/tests/view/6179c069a9b1d8fbcc4ee716

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 89816 W: 22645 L: 22265 D: 44906
Ptnml(0-2): 41, 8404, 27650, 8760, 53
https://tests.stockfishchess.org/tests/view/617ad728f411ea45cc39f895

closes https://github.com/official-stockfish/Stockfish/pull/3767

bench: 6804175
2021-11-05 22:15:53 +01:00
Joost VandeVondele 5a223afe4c Restore development version
No functional change
2021-11-01 06:28:37 +01:00
xefoci7612 ef4822aa8d Simplify Skill implementation
Currently we handle the UCI_Elo with a double randomization. This
seems not necessary and a bit involuted.

This patch removes the first randomization and unifies the 2 cases.

closes https://github.com/official-stockfish/Stockfish/pull/3769

No functional change.
2021-10-31 22:43:38 +01:00
Michel Van den Bergh 0e89d6e754 Do not output to stderr during the build.
To help with debugging, the worker sends the output of
stderr (suitable truncated) to the action log on the
server, in case a build fails. For this to work it is
important that there is no spurious output to stderr.

closes https://github.com/official-stockfish/Stockfish/pull/3773

No functional change
2021-10-31 22:40:41 +01:00
Stefan Geschwentner a8330d5c3b Do more deeper LMR searches.
At expected cut nodes allow at least one ply deeper LMR search for the first seventh moves.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 42880 W: 10964 L: 10738 D: 21178
Ptnml(0-2): 105, 4565, 11883, 4773, 114
https://tests.stockfishchess.org/tests/view/6179abd7a9b1d8fbcc4ee6f4

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 66872 W: 16930 L: 16603 D: 33339
Ptnml(0-2): 36, 6509, 20024, 6826, 41
https://tests.stockfishchess.org/tests/view/617a30fb2fbca9ca65972b5e

closes https://github.com/official-stockfish/Stockfish/pull/3770

Bench: 6295536
2021-10-31 22:31:55 +01:00
Joost VandeVondele 717d6c5ed5 Widen the aspiration window for larger evals
passed STC
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 36840 W: 9359 L: 9134 D: 18347
Ptnml(0-2): 111, 4130, 9722, 4337, 120
https://tests.stockfishchess.org/tests/view/617c601301c6d0988731d10a

passed LTC
LLR: 2.98 (-2.94,2.94) <0.50,3.50>
Total: 64824 W: 16377 L: 16043 D: 32404
Ptnml(0-2): 27, 6712, 18618, 7010, 45
https://tests.stockfishchess.org/tests/view/617c720d01c6d0988731d114

closes https://github.com/official-stockfish/Stockfish/pull/3768

Bench: 7683058
2021-10-31 22:30:01 +01:00
Joost VandeVondele 7262fd5d14 Stockfish 14.1
Official release version of Stockfish 14.1

Bench: 6334068

---

Today, we have the pleasure to announce Stockfish 14.1.

As usual, downloads will be freely available at stockfishchess.org/download [1].

With Stockfish 14.1 our users get access to the strongest chess engine
available today. In the period leading up to this release, Stockfish
convincingly won several chess engine tournaments, including the TCEC 21
superfinal, the TCEC Cup 9, and the Computer Chess Championship for
Fischer Random Chess (Chess960). In the latter tournament, Stockfish
was undefeated in 599 out of 600 games played.

Compared to Stockfish 14, this release introduces a more advanced NNUE
architecture and various search improvements. In self play testing, using
a book of balanced openings, Stockfish 14.1 wins three times more game
pairs than it loses [2]. At this high level, draws are very common, so the
Elo difference to Stockfish 14 is about 17 Elo. The NNUE evaluation method,
introduced to top level chess with Stockfish 12 about one year ago [3],
has now been adopted by several other strong CPU based chess engines.

The Stockfish project builds on a thriving community of enthusiasts
(thanks everybody!) that contribute their expertise, time, and resources
to build a free and open-source chess engine that is robust,
widely available, and very strong. We invite our chess fans to join the
fishtest testing framework and programmers to contribute to the project [4].

Stay safe and enjoy chess!

The Stockfish team

[1] https://stockfishchess.org/download/
[2] https://tests.stockfishchess.org/tests/view/6175c320af70c2be1788fa2b
[3] https://github.com/official-stockfish/Stockfish/discussions/3628
[4] https://stockfishchess.org/get-involved/
2021-10-28 07:38:19 +02:00
mstembera 385deefd80 Fix sometimes incorrect key for prefetches
STC
https://tests.stockfishchess.org/tests/view/61737b4f6ce927be32558401
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 138712 W: 34914 L: 34942 D: 68856
Ptnml(0-2): 421, 14817, 38894, 14817, 407

Very minor tweak since Position::key() depends on the 50 move rule counter.
Comments: https://github.com/mstembera/Stockfish/commit/cddde31eed505cdf0c4fc8ff96b89f6e39c797e1

closes https://github.com/official-stockfish/Stockfish/pull/3759

No functional change
2021-10-25 12:26:44 +02:00
Joost VandeVondele 2c86ae196d Adjust ButterflyHistory decay parameter
passed STC:
LLR: 2.98 (-2.94,2.94) <-0.50,2.50>
Total: 26680 W: 6807 L: 6593 D: 13280
Ptnml(0-2): 73, 3007, 6989, 3175, 96
https://tests.stockfishchess.org/tests/view/6174094e6ce927be32558441

passed LTC:
LLR: 2.98 (-2.94,2.94) <0.50,3.50>
Total: 21104 W: 5403 L: 5185 D: 10516
Ptnml(0-2): 8, 2160, 6001, 2372, 11
https://tests.stockfishchess.org/tests/view/61744927351812fe5f969864

closes https://github.com/official-stockfish/Stockfish/pull/3761

Bench: 6334068
2021-10-24 22:17:55 +02:00
Stefan Geschwentner 8557f35aa5 Double extend search even more via LMR
Allow now for the first five moves a two plies deeper LMR search.

STC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 99608 W: 25143 L: 25115 D: 49350
Ptnml(0-2): 291, 11444, 26328, 11428, 313
https://tests.stockfishchess.org/tests/view/61718c9438cb9784038af8d7

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 52064 W: 13234 L: 13145 D: 25685
Ptnml(0-2): 35, 5431, 15014, 5514, 38
https://tests.stockfishchess.org/tests/view/6171e13e38cb9784038af928

closes https://github.com/official-stockfish/Stockfish/pull/3760

Bench: 7222293
2021-10-24 22:13:47 +02:00
bmc4 1163d972a9 Simplify LMR multiThread condition
STC (8 threads):
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 110584 W: 27818 L: 27807 D: 54959
Ptnml(0-2): 156, 12089, 30791, 12100, 156
https://tests.stockfishchess.org/tests/view/6172ef436ce927be325583a9

LTC (8 threads):
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 23632 W: 6025 L: 5903 D: 11704
Ptnml(0-2): 5, 2292, 7100, 2414, 5
https://tests.stockfishchess.org/tests/view/6173cf096ce927be32558412

closes https://github.com/official-stockfish/Stockfish/pull/3757

No functional change (in the single-threaded case)
Bench: 6689428
2021-10-24 22:08:28 +02:00
FauziAkram fc8213c7df Tuning of a Null Move Parameter
STC:
LLR: 2.99 (-2.94,2.94) <-0.50,2.50>
Total: 78744 W: 19956 L: 19664 D: 39124
Ptnml(0-2): 259, 9005, 20573, 9255, 280
https://tests.stockfishchess.org/tests/view/6172017a38cb9784038af947

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 68528 W: 17309 L: 16964 D: 34255
Ptnml(0-2): 41, 7194, 19455, 7527, 47
https://tests.stockfishchess.org/tests/view/6172994d38cb9784038af983

closes https://github.com/official-stockfish/Stockfish/pull/3756

bench: 6689428
2021-10-23 12:27:32 +02:00
bmc4 927a84d310 Increase TTdepth acceptance some Threads
Increase TTdepth acceptance only on half of the Threads

STC:
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 19272 W: 4956 L: 4766 D: 9550
Ptnml(0-2): 25, 1989, 5423, 2169, 30
https://tests.stockfishchess.org/tests/view/6172be6238cb9784038af9a7

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 23688 W: 6111 L: 5897 D: 11680
Ptnml(0-2): 2, 2275, 7081, 2479, 7
https://tests.stockfishchess.org/tests/view/6172e32938cb9784038af9c7

closes https://github.com/official-stockfish/Stockfish/pull/3754

No functional change in the single-threaded case
2021-10-23 12:23:29 +02:00
Stefano Cardanobile 2214fcecf7 Rewrite NNUE evaluation adjustments
Make the eval code in the evaluate_nnue.cpp more similar to the rest of the codebase:

* remove multiple variable assignment
* make if conditions explicit and indent on multiple lines

passed STC
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 59032 W: 14834 L: 14751 D: 29447
Ptnml(0-2): 176, 6310, 16459, 6397, 174
https://tests.stockfishchess.org/tests/view/616f250540f619782fd4f76d

closes https://github.com/official-stockfish/Stockfish/pull/3753

No functional change
2021-10-23 12:22:02 +02:00
mstembera 644f6d4790 Simplify away ValueListInserter
plus minor cleanups

STC: https://tests.stockfishchess.org/tests/view/616f059b40f619782fd4f73f
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 84992 W: 21244 L: 21197 D: 42551
Ptnml(0-2): 279, 9005, 23868, 9078, 266

closes https://github.com/official-stockfish/Stockfish/pull/3749

No functional change
2021-10-23 12:21:17 +02:00
Stefan Geschwentner 8a8640a761 Double extend more often via LMR
Allow for first three moves always a two plies deeper LMR search.

STC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 206096 W: 51966 L: 52093 D: 102037
Ptnml(0-2): 664, 23817, 54293, 23530, 744
https://tests.stockfishchess.org/tests/view/616f197d40f619782fd4f75a

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 62384 W: 15567 L: 15492 D: 31325
Ptnml(0-2): 40, 6633, 17777, 6696, 46
https://tests.stockfishchess.org/tests/view/616ffa1b4f0b65a0e231e682

closes https://github.com/official-stockfish/Stockfish/pull/3752

Bench: 6154836
2021-10-21 12:42:30 +02:00
bmc4 42a895d9c9 Simplify null move search condition
Remove `ss->ttPv` condition on null move search condition

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 80832 W: 20276 L: 20221 D: 40335
Ptnml(0-2): 267, 9335, 21168, 9368, 278
https://tests.stockfishchess.org/tests/view/616ed4a0942d40685e3237c6

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 54184 W: 13464 L: 13377 D: 27343
Ptnml(0-2): 37, 5758, 15435, 5805, 57
https://tests.stockfishchess.org/tests/view/616ef71f40f619782fd4f72d

closes https://github.com/official-stockfish/Stockfish/pull/3750

bench: 6201607
2021-10-21 08:43:43 +02:00
bmc4 4af1ae82c6 Adjust TTdepth acceptance on early cutoff
STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 63784 W: 16185 L: 15917 D: 31682
Ptnml(0-2): 231, 7309, 16531, 7603, 218
https://tests.stockfishchess.org/tests/view/616ed03a942d40685e3237c0

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 12728 W: 3268 L: 3072 D: 6388
Ptnml(0-2): 8, 1298, 3563, 1480, 15
https://tests.stockfishchess.org/tests/view/616ef156942d40685e32380a

closes https://github.com/official-stockfish/Stockfish/pull/3748

bench: 7050445
2021-10-19 22:14:39 +02:00
bmc4 b37054c310 Simplify evaluate condition on search
Remove condition for MOVE_NULL on search.

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 47544 W: 11968 L: 11864 D: 23712
Ptnml(0-2): 150, 5535, 12318, 5599, 170
https://tests.stockfishchess.org/tests/view/616e37143799eb91f1f071ee

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 67472 W: 16938 L: 16870 D: 33664
Ptnml(0-2): 49, 7119, 19331, 7189, 48
https://tests.stockfishchess.org/tests/view/616e3fab3799eb91f1f071f1

closes https://github.com/official-stockfish/Stockfish/pull/3746

bench: 5255771
2021-10-19 22:09:47 +02:00
bmc4 67d0616483 Simplify probCutCount away
Simplify away the limitation in number of moves in probCut.

STC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 286768 W: 71888 L: 72133 D: 142747
Ptnml(0-2): 983, 33084, 75471, 32887, 959
https://tests.stockfishchess.org/tests/view/616c9b9b90e1312a3cd0ef0a

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 69312 W: 17243 L: 17176 D: 34893
Ptnml(0-2): 42, 7452, 19614, 7493, 55
https://tests.stockfishchess.org/tests/view/616cebbf4f95b438f7a85f93

closes https://github.com/official-stockfish/Stockfish/pull/3745

bench: 5005810
2021-10-18 21:00:08 +02:00
Stefano Cardanobile f7494961de Reformat Eval::evaluate()
Non functional simplification: the goal of this patch is to make
the style in the evaluate() function similar to the rest of the code.

passed STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 95608 W: 24058 L: 24026 D: 47524
Ptnml(0-2): 292, 10379, 26396, 10479, 258
https://tests.stockfishchess.org/tests/view/616c64fd99b580bf37797e4f

closes https://github.com/official-stockfish/Stockfish/pull/3744

Non-functional change
2021-10-18 20:45:47 +02:00
Stéphane Nicolet 8a74c08928 Remove noLMRExtension flag
This simplification patch removes the noLMRExtension flag. It was introduced in June
(see following link for that commit), but does not seem to be necessary anymore.
Link: https://github.com/official-stockfish/Stockfish/commit/e1f181ee643dcaa92c606b74b3abd23dede136cd

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 21200 W: 5369 L: 5228 D: 10603
Ptnml(0-2): 67, 2355, 5616, 2494, 68
https://tests.stockfishchess.org/tests/view/616c03d299b580bf37797dcb

LTC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 37536 W: 9387 L: 9278 D: 18871
Ptnml(0-2): 23, 3988, 10643, 4085, 29
https://tests.stockfishchess.org/tests/view/616c10f499b580bf37797ddd

closes https://github.com/official-stockfish/Stockfish/pull/3743

Bench: 4792969
2021-10-17 17:54:39 +02:00
Stéphane Nicolet 6847be2c75 Allow some LMR double extensions
Allow some LMR double extensions for the second and third sons of each node.

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 170320 W: 42608 L: 42187 D: 85525
Ptnml(0-2): 516, 19635, 44422, 20086, 501
https://tests.stockfishchess.org/tests/view/616a9e3899b580bf37797cf4

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 74400 W: 18783 L: 18423 D: 37194
Ptnml(0-2): 46, 7812, 21129, 8162, 51
https://tests.stockfishchess.org/tests/view/616b378499b580bf37797d61

closes https://github.com/official-stockfish/Stockfish/pull/3742

Bench: 4877152
2021-10-17 12:29:11 +02:00
Stefano Cardanobile 4231d99ab4 Smooth improving
Smooth dependency on improvement margin in null move search.

STC
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 17384 W: 4468 L: 4272 D: 8644
Ptnml(0-2): 42, 1919, 4592, 2079, 60
https://tests.stockfishchess.org/tests/view/61689b8a1e5f6627cc1c0fdc

LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 45648 W: 11525 L: 11243 D: 22880
Ptnml(0-2): 26, 4731, 13036, 4997, 34
https://tests.stockfishchess.org/tests/view/6168a12c1e5f6627cc1c0fe3

It would be interesting to test if the other pruning/reduction heuristics
in master which are using the improving variable (ie the sign of improvement)
could benefit from a smooth function of the improvement value (or maybe a
Relu of the improvement value).

closes https://github.com/official-stockfish/Stockfish/pull/3740

Bench: 4916775
2021-10-15 14:57:01 +02:00
Joost VandeVondele 580698e5e5 Compute ttCapture earlier
Compute ttCapture earlier, and reuse.

passed STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 74128 W: 18640 L: 18578 D: 36910
Ptnml(0-2): 224, 7970, 20649, 7962, 259
https://tests.stockfishchess.org/tests/view/615dd9fa1a32f4036ac7fc4d

closes https://github.com/official-stockfish/Stockfish/pull/3734

No functional change
2021-10-14 09:58:03 +02:00
bmc4 0bddd942b4 Simplify ttHitAverage away
Simplify ttHitAverage away, which was introduced in the following commit:
[here](https://github.com/BM123499/Stockfish/commit/fe124896b241b4791454fd151da10101ad48f6d7)

A few tweaks with Elo gaining bounds have been tried to keep the code,
but they all failed:
https://tests.stockfishchess.org/tests/view/61656f7683dd501a05b0b292
https://tests.stockfishchess.org/tests/view/6165c0ca83dd501a05b0b2ca
https://tests.stockfishchess.org/tests/view/6165bf9683dd501a05b0b2c8
https://tests.stockfishchess.org/tests/view/6165719483dd501a05b0b29b
https://tests.stockfishchess.org/tests/view/6166c7fd83dd501a05b0b353
https://tests.stockfishchess.org/tests/view/6166c63b83dd501a05b0b350

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 58504 W: 14781 L: 14694 D: 29029
Ptnml(0-2): 175, 6718, 15426, 6711, 222
https://tests.stockfishchess.org/tests/view/6165112c83dd501a05b0b257

LTC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 33480 W: 8448 L: 8332 D: 16700
Ptnml(0-2): 21, 3569, 9447, 3679, 24
https://tests.stockfishchess.org/tests/view/61656fcf83dd501a05b0b294

change https://github.com/official-stockfish/Stockfish/pull/3739

bench: 4540339
2021-10-14 09:47:20 +02:00
Joseph Ellis 673841301b Simplify multi-cut condition
Now that the multi-cut condition is safer, we can avoid the cost of the sub-search.

STC:
https://tests.stockfishchess.org/tests/view/6165fd9283dd501a05b0b2fe
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 18648 W: 4745 L: 4600 D: 9303
Ptnml(0-2): 47, 2111, 4887, 2208, 71

LTC:
https://tests.stockfishchess.org/tests/view/616629ea83dd501a05b0b320
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 41704 W: 10407 L: 10302 D: 20995
Ptnml(0-2): 35, 4425, 11823, 4538, 31

closes https://github.com/official-stockfish/Stockfish/pull/3738

Bench: 5905086
2021-10-13 23:34:23 +02:00
Michael Chaly c8459b18ba Reduce more if multiple moves exceed alpha
Idea of this patch is the following: in case we already have four moves that
exceeded alpha in the current node, the probability of finding fifth should
be reasonably low. Note that four is completely arbitrary - there could and
probably should be some tweaks, both in tweaking best move count threshold
for more reductions and tweaking how they work - for example making more
reductions with best move count linearly.

passed STC:
https://tests.stockfishchess.org/tests/view/615f614783dd501a05b0aee2
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 141816 W: 36056 L: 35686 D: 70074
Ptnml(0-2): 499, 15131, 39273, 15511, 494

passed LTC:
https://tests.stockfishchess.org/tests/view/615fdff683dd501a05b0af35
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 68536 W: 17221 L: 16891 D: 34424
Ptnml(0-2): 38, 6573, 20725, 6885, 47

closes https://github.com/official-stockfish/Stockfish/pull/3736

Bench: 6131513
2021-10-09 09:59:33 +02:00
xoto10 f21a66f70d Small clean-up, Sept 2021
Closes https://github.com/official-stockfish/Stockfish/pull/3485

No functional change
2021-10-07 09:41:57 +02:00
Stéphane Nicolet 54a989930e Capping stat bonus at 2000
This patch updates the stat_bonus() function (used in the history tables to
help move ordering), keeping the same quadratic for small depths but changing
the values for depth >= 9:

The old bonus formula was increasing from zero at depth 1 to 4100 at depth 14,
then used the strange, small value of 73 for all depths >= 15.

The new bonus formula increases from 0 at depth 1 to 2000 at depth 8, then
keeps 2000 for all depths >= 8.

passed STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 169624 W: 42875 L: 42454 D: 84295
Ptnml(0-2): 585, 19340, 44557, 19729, 601
https://tests.stockfishchess.org/tests/view/615bd69e9d256038a969b97c

passed LTC:
LLR: 3.07 (-2.94,2.94) <0.50,3.50>
Total: 37336 W: 9456 L: 9191 D: 18689
Ptnml(0-2): 20, 3810, 10747, 4067, 24
https://tests.stockfishchess.org/tests/view/615c75d99d256038a969b9b2

closes https://github.com/official-stockfish/Stockfish/pull/3731

Bench: 6261865
2021-10-06 12:04:35 +02:00
Joost VandeVondele 329bdbd9cf Improve the Chess960 correction for cornered bishops
As Chess960 patches can not be tested on fishtest, this was locally tuned
and tested:

Elo: 2.36 +- 1.07
LOS: 0.999992

closes https://github.com/official-stockfish/Stockfish/pull/3730

Bench: 5714575
2021-10-06 11:57:34 +02:00
J. Oster 371b522e9e Time-management fix in MultiPV mode.
When playing games in MultiPV mode we must take care to only track the
best move changing for the first PV line. Otherwise, SF will spend most
of its time for the initial moves after the book exit.

This has been observed and reported on Discord, but can also be seen in
games played in Stefan Pohl's MultiPV experiment.

Tested with MultiPV=4.

STC:
https://tests.stockfishchess.org/tests/view/615c24b59d256038a969b990
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 1744 W: 694 L: 447 D: 603
Ptnml(0-2): 32, 125, 358, 278, 79

LTC:
https://tests.stockfishchess.org/tests/view/615c31769d256038a969b993
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 2048 W: 723 L: 525 D: 800
Ptnml(0-2): 10, 158, 511, 314, 31

closes https://github.com/official-stockfish/Stockfish/pull/3729

Bench: 5714575
2021-10-06 11:53:33 +02:00
Michael Chaly 135caee606 Increase reductions with thread count
Respin of multi-thread idea that was simplified away recently: basically doing
more reductions with thread count since Lazy SMP naturally widens search. With
drawish book this idea got simplified away but with less drawish book it again
gains elo, maybe trying to reinstall other ideas that were simplified away
previously can be beneficial.

passed STC
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 39736 W: 10205 L: 9986 D: 19545
Ptnml(0-2): 45, 4254, 11064, 4447, 58
https://tests.stockfishchess.org/tests/view/615750702d02f48db3961b00

passed LTC
LLR: 2.97 (-2.94,2.94) <0.50,3.50>
Total: 60352 W: 15530 L: 15218 D: 29604
Ptnml(0-2): 24, 5900, 18016, 6212, 24
https://tests.stockfishchess.org/tests/view/6157d8935488e26ea5eace7f

closes https://github.com/official-stockfish/Stockfish/pull/3724

Bench 5714575
2021-10-03 11:28:19 +02:00
Michael Chaly 21ad356c09 Extend quiet tt moves at PvNodes
Idea is to extend some quiet ttMoves if a lot of things indicate that
the transposition table move is going to be a good move:

1) move being a killer - so being the best move in nearby node;
2) reply continuation history is really good.

This is basically saying that move is good "in general" in this position,
that it is a good reply to the opponent move and that it was the best in
this position somewhere in search - so extending it makes a lot of sense.
In general in past year we had a lot of extensions of different types,
maybe there is something more in it :)

passed STC
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 42944 W: 10932 L: 10695 D: 21317
Ptnml(0-2): 141, 4869, 11210, 5116, 136
https://tests.stockfishchess.org/tests/view/614cca8e7bdc23e77ceb89f0

passed LTC
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 156848 W: 39473 L: 38893 D: 78482
Ptnml(0-2): 125, 16327, 44913, 16961, 98
https://tests.stockfishchess.org/tests/view/614cf93d7bdc23e77ceb8a13

closes https://github.com/official-stockfish/Stockfish/pull/3719

Bench: 5714575
2021-09-26 06:58:14 +02:00
Stéphane Nicolet 919da65d70 Reduction instead of cutoff
In master, during singular move analysis, when both the transposition value
and a reduced search for the other moves seem to indicate a fail high, we
heuristically prune the whole subtree and return an fail high score.

This patch is a little bit more cautious in this case, and instead of the
risky cutoff, we now search the ttMove with a reduced depth (by two plies).

STC:
https://tests.stockfishchess.org/tests/view/614dafe07bdc23e77ceb8a89
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 46728 W: 11909 L: 11666 D: 23153
Ptnml(0-2): 181, 5288, 12168, 5561, 166

LTC:
https://tests.stockfishchess.org/tests/view/614dc84abe4c07e0ecac3c95
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 74520 W: 18809 L: 18450 D: 37261
Ptnml(0-2): 45, 7735, 21346, 8084, 50

closes https://github.com/official-stockfish/Stockfish/pull/3718

Bench: 5499262
2021-09-25 22:12:17 +02:00
OfekShochat 00e34a758f Range reductions
adding reductions for when the delta between the static eval and the child's eval is consistently low.

passed STC
https://tests.stockfishchess.org/html/live_elo.html?614d7b3c7bdc23e77ceb8a5d
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 88872 W: 22672 L: 22366 D: 43834
Ptnml(0-2): 343, 10150, 23117, 10510, 316

passed LTC
https://tests.stockfishchess.org/html/live_elo.html?614daf3e7bdc23e77ceb8a82
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 24368 W: 6153 L: 5928 D: 12287
Ptnml(0-2): 13, 2503, 6937, 2708, 23

closes https://github.com/official-stockfish/Stockfish/pull/3717

Bench: 5443950
2021-09-24 23:17:48 +02:00
Stéphane Nicolet ff3fa0c664 Tweak doubly singular condition (Topo's patch)
This patch relax a little bit the condition for doubly singular moves
(ie moves that are so forced that we think that they deserve a local
double extension of the search). We lower the margin and allow up to
six such double extensions in the path between the root and the critical
node.

Original idea by Siad Daboul (@TopoIogist) in PR #3709

Tested with the previous commit:

passed STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 33048 W: 8458 L: 8236 D: 16354
Ptnml(0-2): 120, 3701, 8660, 3923, 120
https://tests.stockfishchess.org/tests/view/614b24347bdc23e77ceb88fe

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 54176 W: 13712 L: 13406 D: 27058
Ptnml(0-2): 36, 5653, 15399, 5969, 31
https://tests.stockfishchess.org/tests/view/614b3b727bdc23e77ceb8911

closes https://github.com/official-stockfish/Stockfish/pull/3714

Bench: 5792377
2021-09-23 23:24:28 +02:00
Stéphane Nicolet 73018a0337 Detect search explosions
This patch detects some search explosions (due to double extensions in
search.cpp) which can happen in some pathological positions, and takes
measures to ensure progress in search even for these pathological situations.

While a small number of double extensions can be useful during search
(for example to resolve a tactical sequence), a sustained regime of
double extensions leads to search explosion and a non-finishing search.
See the discussion in https://github.com/official-stockfish/Stockfish/pull/3544
and the issue https://github.com/official-stockfish/Stockfish/issues/3532 .

The implemented algorithm is the following:

a) at each node during search, store the current depth in the stack.
   Double extensions are by definition levels of the stack where the
   depth at ply N is strictly higher than depth at ply N-1.

b) during search, calculate for each thread a running average of the
   number of double extensions in the last 4096 visited nodes.

c) if one thread has more than 2% of double extensions for a sustained
   period of time (6 millions consecutive nodes, or about 4 seconds on
   my iMac), we decide that this thread is in an explosion state and
   we calm down this thread by preventing it to do any double extension
   for the next 6 millions nodes.

To calculate the running averages, we also introduced a auxiliary class
generalizing the computations of ttHitAverage variable we already had in
code. The implementation uses an exponential moving average of period 4096
and resolution 1/1024, and all computations are done with integers for
efficiency.

-----------

Example where the patch solves a search explosion:

```
   ./stockfish
   ucinewgame
   position fen 8/Pk6/8/1p6/8/P1K5/8/6B1 w - - 37 130
   go infinite
```

This algorithm does not affect search in normal, non-pathological positions.
We verified, for instance, that the usual bench is unchanged up to depth 20
at least, and that the node numbers are unchanged for a search of the starting
position at depth 32.

-------------

See https://github.com/official-stockfish/Stockfish/pull/3714

Bench: 5575265
2021-09-23 23:19:06 +02:00
Michael Chaly e8788d1b32 Combo of various parameter tweaks
Combination of parameter tweaks in search, evaluation and time management.
Original patches by snicolet xoto10 lonfom169 and Vizvezdenec.

Includes:

* Use bigger grain of positional evaluation more frequently (up to 1 exchange difference in non-pawn-material);
* More extra time according to increment;
* Increase margin for singular extensions;
* Do more aggresive parent node futility pruning.

Passed STC
https://tests.stockfishchess.org/tests/view/6147deab3733d0e0dd9f313d
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 45488 W: 11691 L: 11450 D: 22347
Ptnml(0-2): 145, 5208, 11824, 5395, 172

Passed LTC
https://tests.stockfishchess.org/tests/view/6147f1d53733d0e0dd9f3141
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 62520 W: 15808 L: 15482 D: 31230
Ptnml(0-2): 43, 6439, 17960, 6785, 33

closes https://github.com/official-stockfish/Stockfish/pull/3710

bench 5575265
2021-09-21 19:48:40 +02:00
xoto10 5b47b4e6c0 Increase optimumTime by 10%
STC 10+0.1 :
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 47032 W: 12078 L: 11841 D: 23113
Ptnml(0-2): 159, 5098, 12746, 5373, 140
https://tests.stockfishchess.org/tests/view/613f9df1f29dda16fcca8731

LTC 60+0.6 :
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 66248 W: 16631 L: 16301 D: 33316
Ptnml(0-2): 44, 6560, 19578, 6906, 36
https://tests.stockfishchess.org/tests/view/6140603d7315e7c73204a4c1

Non-regression tests with other time control styles:

Moves/Time 40/10+0 :
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 51640 W: 13350 L: 13254 D: 25036
Ptnml(0-2): 183, 5770, 13797, 5908, 162
https://tests.stockfishchess.org/tests/view/6141592b7315e7c73204a599

TCEC Style 10+0.01 :
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 20592 W: 5300 L: 5157 D: 10135
Ptnml(0-2): 81, 2240, 5544, 2317, 114
https://tests.stockfishchess.org/tests/view/61425bb27315e7c73204a6a2

Sudden death 15+0 :
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 127104 W: 32728 L: 32741 D: 61635
Ptnml(0-2): 735, 13973, 34149, 13960, 735
https://tests.stockfishchess.org/tests/view/614256a77315e7c73204a699

The first 3 tests were run with an initial version of the code, which was then modified to make the amount of extra time dependent on the size of increment. No increment gives no extra time, and the extra time given increases until an increment of 1% or more of remaining time gives 10% extra thinking time.

closes https://github.com/official-stockfish/Stockfish/pull/3702

Bench 6658747
2021-09-17 08:14:36 +02:00
SFisGOD 723f48dec0 Update default net to nn-13406b1dcbe0.nnue
SPSA 1: https://tests.stockfishchess.org/tests/view/6134abc425b9b35584838572
Parameters: A total of 64 net biases were tuned (hidden layer 1)
Base net: nn-6762d36ad265.nnue
New net: nn-c9fdeea14cb2.nnue

SPSA 2: https://tests.stockfishchess.org/tests/view/61355b7e25b9b3558483860e
Parameters: 256 net weights and 8 net biases (output layer)
Base net: nn-c9fdeea14cb2.nnue
New net: nn-0ddc28184f4c.nnue

SPSA 3: https://tests.stockfishchess.org/tests/view/613737be0cd98ab40c0c9e4e
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-0ddc28184f4c.nnue
New net: nn-2419828bb394.nnue

SPSA 4: https://tests.stockfishchess.org/tests/view/613966ff689039fce12e0fe7
Parameters: A total of 64 net biases were tuned (hidden layer 1)
Base net: nn-2419828bb394.nnue
New net: nn-05d9b1ee3037.nnue

SPSA 5: https://tests.stockfishchess.org/tests/view/613b4a38689039fce12e1209
Parameters: 256 net weights and 8 net biases (output layer)
Base net: nn-05d9b1ee3037.nnue
New net: nn-98c6ce0fc15f.nnue

SPSA 6: https://tests.stockfishchess.org/tests/view/613e331515591e7c9ebc3fe9
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-98c6ce0fc15f.nnue
New net: nn-13406b1dcbe0.nnue

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 82008 W: 21044 L: 20752 D: 40212
Ptnml(0-2): 264, 9341, 21525, 9587, 287
https://tests.stockfishchess.org/tests/view/613f7c6cf29dda16fcca870c

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 182928 W: 46258 L: 45602 D: 91068
Ptnml(0-2): 107, 19448, 51712, 20076, 121
https://tests.stockfishchess.org/tests/view/613fccb97315e7c73204a48c

Closes #3703

Bench: 6658747
2021-09-15 17:50:20 +02:00
xoto10 fd5e77950e Update 2 search parameters after tune.
A tuning run on 3 search parameters was done with 200k games, narrow ranges (50-150%) and a small value for A (3% of total games) :
https://tests.stockfishchess.org/tests/view/613b5f4b689039fce12e1220

STC 10+0.1 :
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 73112 W: 18800 L: 18520 D: 35792
Ptnml(0-2): 205, 8395, 19115, 8597, 244
https://tests.stockfishchess.org/tests/view/613cb8d2689039fce12e1308

LTC 60+0.6 :
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 45616 W: 11604 L: 11321 D: 22691
Ptnml(0-2): 24, 4769, 12946, 5038, 31
https://tests.stockfishchess.org/tests/view/613d07048253e53e97b55b32

closes https://github.com/official-stockfish/Stockfish/pull/3698

Bench 6504816
2021-09-12 18:03:56 +02:00
Michael Chaly 30fdbf4328 Decrease depth for cutnodes with no tt move
By analogy to existing logic of decreasing depth for PvNodes w/o tt move
do the same for cutNodes.

Passed STC
https://tests.stockfishchess.org/tests/view/613abf5a689039fce12e1155
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 90336 W: 23108 L: 22804 D: 44424
Ptnml(0-2): 286, 10316, 23642, 10656, 268

Passed LTC
https://tests.stockfishchess.org/tests/view/613ae330689039fce12e1172
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 37736 W: 9607 L: 9346 D: 18783
Ptnml(0-2): 21, 3917, 10730, 4180, 20

closes https://github.com/official-stockfish/Stockfish/pull/3697

bench 5891181
2021-09-10 11:50:43 +02:00
Stefan Geschwentner b7b6b4ba18 Further improve history updates
Now even double history updates if a search failed low at an expected PV or CUT node.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 30736 W: 7891 L: 7674 D: 15171
Ptnml(0-2): 90, 3477, 8017, 3694, 90
https://tests.stockfishchess.org/tests/view/61364ae30cd98ab40c0c9da5

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 73600 W: 18684 L: 18326 D: 36590
Ptnml(0-2): 41, 7734, 20899, 8078, 48
https://tests.stockfishchess.org/tests/view/6136940f0cd98ab40c0c9df3

closes https://github.com/official-stockfish/Stockfish/pull/3694

Bench: 6030657
2021-09-07 19:59:14 +02:00
Stefan Geschwentner c31fc8d163 Improve history updates
If a search failed low at an expected PV or CUT node do greater history updates.

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 95112 W: 24293 L: 23982 D: 46837
Ptnml(0-2): 285, 10893, 24906, 11170, 302
https://tests.stockfishchess.org/tests/view/6132aa1a2ffb3c36aceb926f

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 116352 W: 29450 L: 28975 D: 57927
Ptnml(0-2): 93, 12263, 32984, 12748, 88
https://tests.stockfishchess.org/tests/view/613394d12ffb3c36aceb92f4

closes https://github.com/official-stockfish/Stockfish/pull/3693

Bench: 6130736
2021-09-06 14:19:47 +02:00
SFisGOD be63ce1bb5 Update default net to nn-6762d36ad265.nnue
SPSA 1: https://tests.stockfishchess.org/tests/view/612cdb1fbb4956d8b78eb5ab
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-fe433fd8c7f6.nnue
New net: nn-5f134823db04.nnue

SPSA 2: https://tests.stockfishchess.org/tests/view/612fcde645091e810014af19
Parameters: A total of 64 net biases were tuned (hidden layer 1)
Base net: nn-5f134823db04.nnue
New net: nn-8eca5dd4e3f7.nnue

SPSA 3: https://tests.stockfishchess.org/tests/view/6130822345091e810014af61
Parameters: 256 net weights and 8 net biases (output layer)
Base net: nn-8eca5dd4e3f7.nnue
New net: nn-4556108e4f00.nnue

SPSA 4: https://tests.stockfishchess.org/tests/view/613287652ffb3c36aceb923c
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-4556108e4f00.nnue
New net: nn-6762d36ad265.nnue

STC:
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 162776 W: 41220 L: 40807 D: 80749
Ptnml(0-2): 517, 18800, 42359, 19177, 535
https://tests.stockfishchess.org/tests/view/6134107125b9b35584838559

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 41056 W: 10428 L: 10156 D: 20472
Ptnml(0-2): 30, 4288, 11618, 4564, 28
https://tests.stockfishchess.org/tests/view/6134ad6525b9b3558483857a

closes https://github.com/official-stockfish/Stockfish/pull/3691

Bench: 5812158
2021-09-06 14:08:22 +02:00
Michael Chaly e404a7d97c Extend captures and promotions
This patch introduces extension for captures and promotions. Every capture or
promotion that is not the first move in the list gets extended at PvNodes and
cutNodes. Special thanks to @locutus2 - all my previous attepmts that failed
on this idea were done only for PvNodes - idea to include also cutNodes was
based on his latest passed patch.

STC
https://tests.stockfishchess.org/tests/view/6134abf325b9b35584838574
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 188920 W: 47754 L: 47304 D: 93862
Ptnml(0-2): 595, 21754, 49344, 22140, 627

LTC
https://tests.stockfishchess.org/tests/view/613521de25b9b355848385d7
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 8768 W: 2283 L: 2098 D: 4387
Ptnml(0-2): 7, 866, 2452, 1053, 6

closes https://github.com/official-stockfish/Stockfish/pull/3692

bench: 5564555
2021-09-06 13:59:17 +02:00
SFisGOD 2807dcfab6 Update default net to nn-735bba95dec0.nnue
SPSA 1: https://tests.stockfishchess.org/tests/view/61286d8b62d20cf82b5ad1bd
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-33495fe25081.nnue
New net: nn-83e3cf2af92b.nnue

SPSA 2: https://tests.stockfishchess.org/tests/view/6129cf2162d20cf82b5ad25f
Parameters: A total of 64 net biases were tuned (hidden layer 1)
Base net: nn-83e3cf2af92b.nnue
New net: nn-69a528eaef35.nnue

SPSA 3: https://tests.stockfishchess.org/tests/view/612a0dcb62d20cf82b5ad2a0
Parameters: 256 net weights and 8 net biases (output layer)
Base net: nn-69a528eaef35.nnue
New net: nn-735bba95dec0.nnue

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 95144 W: 24310 L: 23999 D: 46835
Ptnml(0-2): 232, 11059, 24748, 11232, 301
https://tests.stockfishchess.org/tests/view/612bb3be0fdf40644b4b9996

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 33632 W: 8522 L: 8271 D: 16839
Ptnml(0-2): 18, 3511, 9516, 3744, 27
https://tests.stockfishchess.org/tests/view/612ce5b9bb4956d8b78eb5b3

Closes https://github.com/official-stockfish/Stockfish/pull/3685

Bench: 5600615
2021-08-31 12:56:19 +02:00
VoyagerOne ad357e147a CMH Pruning Tweak
Tweak pruning formula by adding up CMH values.

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 14608 W: 3837 L: 3641 D: 7130
Ptnml(0-2): 27, 1681, 3723, 1815, 58
https://tests.stockfishchess.org/tests/view/612792f362d20cf82b5ad156

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 53520 W: 13580 L: 13276 D: 26664
Ptnml(0-2): 28, 5610, 15183, 5908, 31
https://tests.stockfishchess.org/tests/view/6127d27062d20cf82b5ad191

closes https://github.com/official-stockfish/Stockfish/pull/3682

Bench: 5186641
2021-08-27 21:41:32 +02:00
SFisGOD 69eede7d08 Update default net to nn-33495fe25081.nnue
STC:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 37368 W: 9621 L: 9391 D: 18356
Ptnml(0-2): 117, 4287, 9664, 4481, 135
https://tests.stockfishchess.org/tests/view/612768165318138ee1204977

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 13328 W: 3446 L: 3246 D: 6636
Ptnml(0-2): 11, 1383, 3682, 1571, 17
https://tests.stockfishchess.org/tests/view/6127dc8d62d20cf82b5ad196

Closes https://github.com/official-stockfish/Stockfish/pull/3679

Bench: 5179347
2021-08-27 07:51:26 +02:00
ppigazzini f30f231cbf Use "pedantic" flag also for mingw
This will avoid to run in fishtest a test where the linux machines exit from
the building process and only the windows machines run the test.

See:
https://tests.stockfishchess.org/tests/view/61122d732a8a49ac5be79996
https://github.com/SFisGOD/Stockfish/commit/4e422577d6ebd1f6ecf606189190b8f6fb03f6c9#comments

closes https://github.com/official-stockfish/Stockfish/pull/3671

No functional change.
2021-08-27 07:49:26 +02:00
Joost VandeVondele af0d82792e Fix empty EvalFile option
some GUIs send an empty string for EvalFile, in that case explicitly try the default name

fixes https://github.com/official-stockfish/Stockfish/issues/3675

closes https://github.com/official-stockfish/Stockfish/pull/3678

No functional change.
2021-08-27 07:48:18 +02:00
bmc4 d754ea50a8 Simplify Declaration on Pawn Move Generation
Removes possible micro-optimization in favor of readability.

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 75432 W: 5824 L: 5777 D: 63831
Ptnml(0-2): 178, 4648, 28036, 4657, 197
https://tests.stockfishchess.org/tests/view/611fa7f84977aa1525c9cb75

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 41200 W: 1156 L: 1106 D: 38938
Ptnml(0-2): 13, 981, 18562, 1031, 13
https://tests.stockfishchess.org/tests/view/611fcc694977aa1525c9cb9b

Closes https://github.com/official-stockfish/Stockfish/pull/3669

No functional change
2021-08-22 09:15:19 +02:00
SFisGOD 590447d7a1 Update default net to nn-517c4f68b5df.nnue
SPSA: https://tests.stockfishchess.org/tests/view/611cf0da4977aa1525c9ca03
Parameters: 256 net weights and 8 net biases (output layer)
Base net: nn-ac5605a608d6.nnue
New net: nn-517c4f68b5df.nnue

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 11600 W: 998 L: 851 D: 9751
Ptnml(0-2): 30, 705, 4186, 846, 33
https://tests.stockfishchess.org/tests/view/611f84524977aa1525c9cb5b

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 9360 W: 338 L: 243 D: 8779
Ptnml(0-2): 0, 220, 4151, 303, 6
https://tests.stockfishchess.org/tests/view/611f8c5b4977aa1525c9cb64

closes https://github.com/official-stockfish/Stockfish/pull/3667

Bench: 4844618
2021-08-22 09:09:58 +02:00
candirufish 939ffe454d do more LMR extensions for PV nodes
LMR Pv and depth 6 Extension tweak:

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 52488 W: 1542 L: 1394 D: 49552
Ptnml(0-2): 18, 1253, 23552, 1405, 16
https://tests.stockfishchess.org/tests/view/611e49c34977aa1525c9caa7

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 76216 W: 6000 L: 5784 D: 64432
Ptnml(0-2): 204, 4745, 28006, 4937, 216
https://tests.stockfishchess.org/tests/view/611e0e254977aa1525c9ca89

closes https://github.com/official-stockfish/Stockfish/pull/3666

Bench: 5046381
2021-08-22 09:05:53 +02:00
bmc4 e57d2d9d47 Simplify Null Move Search Reduction
slightly simpler formula for reduction computation.

first round of tests:
STC:
LLR: 2.97 (-2.94,2.94) <-2.50,0.50>
Total: 15632 W: 1319 L: 1204 D: 13109
Ptnml(0-2): 33, 956, 5733, 1051, 43
https://tests.stockfishchess.org/tests/view/60bd03c7457376eb8bcaa600

LTC:
LLR: 3.37 (-2.94,2.94) <-2.50,0.50>
Total: 86296 W: 2814 L: 2779 D: 80703
Ptnml(0-2): 33, 2500, 38039, 2551, 25
https://tests.stockfishchess.org/tests/view/60bd1ff0457376eb8bcaa653

recent tests:
STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 23936 W: 1895 L: 1793 D: 20248
Ptnml(0-2): 40, 1470, 8869, 1526, 63
https://tests.stockfishchess.org/tests/view/611f9b7d4977aa1525c9cb6b

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 62568 W: 1750 L: 1713 D: 59105
Ptnml(0-2): 19, 1560, 28085, 1605, 15
https://tests.stockfishchess.org/tests/view/611fa4814977aa1525c9cb71

functional on high depth

closes https://github.com/official-stockfish/Stockfish/pull/3535

Bench: 5375286
2021-08-22 09:00:15 +02:00
Tomasz Sobczyk 18dcf1f097 Optimize and tidy up affine transform code.
The new network caused some issues initially due to the very narrow neuron set between the first two FC layers. Necessary changes were hacked together to make it work. This patch is a mature approach to make the affine transform code faster, more readable, and easier to maintain should the layer sizes change again.

The following changes were made:

* ClippedReLU always produces a multiple of 32 outputs. This is about as good of a solution for AffineTransform's SIMD requirements as it can get without a bigger rewrite.

* All self-contained simd helpers are moved to a separate file (simd.h). Inline asm is utilized to work around GCC's issues with code generation and register assignment. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101693, https://godbolt.org/z/da76fY1n7

* AffineTransform has 2 specializations. While it's more lines of code due to the boilerplate, the logic in both is significantly reduced, as these two are impossible to nicely combine into one.
 1) The first specialization is for cases when there's >=128 inputs. It uses a different approach to perform the affine transform and can make full use of AVX512 without any edge cases. Furthermore, it has higher theoretical throughput because less loads are needed in the hot path, requiring only a fixed amount of instructions for horizontal additions at the end, which are amortized by the large number of inputs.
 2) The second specialization is made to handle smaller layers where performance is still necessary but edge cases need to be handled. AVX512 implementation for this was ommited by mistake, a remnant from the temporary implementation for the new... This could be easily reintroduced if needed. A slightly more detailed description of both implementations is in the code.

Overall it should be a minor speedup, as shown on fishtest:

passed STC:
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 51520 W: 4074 L: 3888 D: 43558
Ptnml(0-2): 111, 3136, 19097, 3288, 128

and various tests shown in the pull request

closes https://github.com/official-stockfish/Stockfish/pull/3663

No functional change
2021-08-20 08:50:25 +02:00
Tomasz Sobczyk ccf0239bc4 Improve handling of the debug log file.
Fix handling of empty strings in uci options and reassigning of the log file

Fixes https://github.com/official-stockfish/Stockfish/issues/3650

Closes https://github.com/official-stockfish/Stockfish/pull/3655

No functional change
2021-08-20 07:57:09 +02:00
Torsten Hellwig 1946a67567 Update default net to nn-ac5605a608d6.nnue
This net was created with the nnue-pytorch trainer, it used the previous master net as a starting point.

The training data includes all T60 data (https://drive.google.com/drive/folders/1rzZkgIgw7G5vQMLr2hZNiUXOp7z80613), all T74 data (https://drive.google.com/drive/folders/1aFUv3Ih3-A8Vxw9064Kw_FU4sNhMHZU-) and the wrongNNUE_02_d9.binpack (https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq). The Leela data were randomly named and then concatenated. All data was merged into one binpack using interleave_binpacks.py.

python3 train.py \
    ../data/t60_t74_wrong.binpack \
    ../data/t60_t74_wrong.binpack \
    --resume-from-model ../data/nn-e8321e467bf6.pt \
    --gpus 1 \
    --threads 4 \
    --num-workers 1 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 300 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --max_epochs=600 \
    --seed $RANDOM \
    --default_root_dir ../output/exp_24

STC:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 15320 W: 1415 L: 1257 D: 12648
Ptnml(0-2): 50, 1002, 5402, 1152, 54
https://tests.stockfishchess.org/tests/view/611c404a4977aa1525c9c97f

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 9440 W: 345 L: 248 D: 8847
Ptnml(0-2): 3, 222, 4175, 315, 5
https://tests.stockfishchess.org/tests/view/611c6c7d4977aa1525c9c996

LTC with UHO_XXL_+0.90_+1.19.epd:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 6232 W: 1638 L: 1459 D: 3135
Ptnml(0-2): 5, 592, 1744, 769, 6
https://tests.stockfishchess.org/tests/view/611c9b214977aa1525c9c9cb

closes https://github.com/official-stockfish/Stockfish/pull/3664

Bench: 5375286
2021-08-18 09:17:22 +02:00
Joost VandeVondele f10ebc2bdf Regenerate dependencies on code change
fixes https://github.com/official-stockfish/Stockfish/issues/3658

dependencies are now regenerated for each code change, this adds some 1s overhead in compile time, but avoids potential miscompilations or build problems.

closes https://github.com/official-stockfish/Stockfish/pull/3659

No functional change
2021-08-17 21:08:34 +02:00
Tomasz Sobczyk d61d38586e New NNUE architecture and net
Introduces a new NNUE network architecture and associated network parameters

The summary of the changes:

* Position for each perspective mirrored such that the king is on e..h files. Cuts the feature transformer size in half, while preserving enough knowledge to be good. See https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY/edit#heading=h.b40q4rb1w7on.
* The number of neurons after the feature transformer increased two-fold, to 1024x2. This is possibly mostly due to the now very optimized feature transformer update code.
* The number of neurons after the second layer is reduced from 16 to 8, to reduce the speed impact. This, perhaps surprisingly, doesn't harm the strength much. See https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY/edit#heading=h.6qkocr97fezq

The AffineTransform code did not work out-of-the box with the smaller number of neurons after the second layer, so some temporary changes have been made to add a special case for InputDimensions == 8. Also additional 0 padding is added to the output for some archs that cannot process inputs by <=8 (SSE2, NEON). VNNI uses an implementation that can keep all outputs in the registers while reducing the number of loads by 3 for each 16 inputs, thanks to the reduced number of output neurons. However GCC is particularily bad at optimization here (and perhaps why the current way the affine transform is done even passed sprt) (see https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY/edit# for details) and more work will be done on this in the following days. I expect the current VNNI implementation to be improved and extended to other architectures.

The network was trained with a slightly modified version of the pytorch trainer (https://github.com/glinscott/nnue-pytorch); the changes are in https://github.com/glinscott/nnue-pytorch/pull/143

The training utilized 2 datasets.

    dataset A - https://drive.google.com/file/d/1VlhnHL8f-20AXhGkILujnNXHwy9T-MQw/view?usp=sharing
    dataset B - as described in https://github.com/official-stockfish/Stockfish/commit/ba01f4b95448bcb324755f4dd2a632a57c6e67bc

The training process was as following:

    train on dataset A for 350 epochs, take the best net in terms of elo at 20k nodes per move (it's fine to take anything from later stages of training).
    convert the .ckpt to .pt
    --resume-from-model from the .pt file, train on dataset B for <600 epochs, take the best net. Lambda=0.8, applied before the loss function.

The first training command:

python3 train.py \
    ../nnue-pytorch-training/data/large_gensfen_multipvdiff_100_d9.binpack \
    ../nnue-pytorch-training/data/large_gensfen_multipvdiff_100_d9.binpack \
    --gpus "$3," \
    --threads 1 \
    --num-workers 1 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --smart-fen-skipping \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --max_epochs=600 \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

The second training command:

python3 serialize.py \
    --features=HalfKAv2_hm^ \
    ../nnue-pytorch-training/experiment_131/run_6/default/version_0/checkpoints/epoch-499.ckpt \
    ../nnue-pytorch-training/experiment_$1/base/base.pt

python3 train.py \
    ../nnue-pytorch-training/data/michael_commit_b94a65.binpack \
    ../nnue-pytorch-training/data/michael_commit_b94a65.binpack \
    --gpus "$3," \
    --threads 1 \
    --num-workers 1 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --smart-fen-skipping \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=0.8 \
    --max_epochs=600 \
    --resume-from-model ../nnue-pytorch-training/experiment_$1/base/base.pt \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

STC: https://tests.stockfishchess.org/tests/view/611120b32a8a49ac5be798c4

LLR: 2.97 (-2.94,2.94) <-0.50,2.50>
Total: 22480 W: 2434 L: 2251 D: 17795
Ptnml(0-2): 101, 1736, 7410, 1865, 128

LTC: https://tests.stockfishchess.org/tests/view/611152b32a8a49ac5be798ea

LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 9776 W: 442 L: 333 D: 9001
Ptnml(0-2): 5, 295, 4180, 402, 6

closes https://github.com/official-stockfish/Stockfish/pull/3646

bench: 5189338
2021-08-15 12:05:43 +02:00
Joost VandeVondele dabaf2220f Revert futility pruning patches
reverts 09b6d28391 and
dbd7f602d3 that significantly impact mate
finding capabilities. For example on ChestUCI_23102018.epd, at 1M nodes,
the number of mates found is nearly reduced 2x without these depth conditions:

       sf6  2091
       sf7  2093
       sf8  2107
       sf9  2062
      sf10  2208
      sf11  2552
      sf12  2563
      sf13  2509
      sf14  2427
    master  1246
   patched  2467

(script for testing at https://github.com/official-stockfish/Stockfish/files/6936412/matecheck.zip)

closes https://github.com/official-stockfish/Stockfish/pull/3641

fixes https://github.com/official-stockfish/Stockfish/issues/3627

Bench: 5467570
2021-08-05 16:41:07 +02:00
VoyagerOne a1a83f3869 SEE simplification
Simplified SEE formula by removing std::min. Should also be easier to tune.

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 22656 W: 1836 L: 1729 D: 19091
Ptnml(0-2): 54, 1426, 8267, 1521, 60
https://tests.stockfishchess.org/tests/view/610ae62f2a8a49ac5be79449

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 26248 W: 806 L: 744 D: 24698
Ptnml(0-2): 6, 668, 11715, 728, 7
https://tests.stockfishchess.org/tests/view/610b17ad2a8a49ac5be79466

closes https://github.com/official-stockfish/Stockfish/pull/3643

bench:  4915145
2021-08-05 16:32:07 +02:00
SFisGOD 73ef5b8c4a Update default net to nn-46832cfbead3.nnue
SPSA 1: https://tests.stockfishchess.org/tests/view/6100e7f096b86d98abf6a832
Parameters: A total of 256 net weights and 8 net biases were tuned (output layer)
Base net: nn-56a5f1c4173a.nnue
New net: nn-ec3c8e029926.nnue

SPSA 2: https://tests.stockfishchess.org/tests/view/610733caafad2da4f4ae3da7
Parameters: A total of 256 net biases were tuned (hidden layer 2)
Base net: nn-ec3c8e029926.nnue
New net: nn-46832cfbead3.nnue

STC:
LLR: 2.98 (-2.94,2.94) <-0.50,2.50>
Total: 50520 W: 3953 L: 3765 D: 42802
Ptnml(0-2): 138, 3063, 18678, 3235, 146
https://tests.stockfishchess.org/tests/view/610a79692a8a49ac5be793f4

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 57256 W: 1723 L: 1566 D: 53967
Ptnml(0-2): 12, 1442, 25568, 1589, 17
https://tests.stockfishchess.org/tests/view/610ac5bb2a8a49ac5be79434

Closes https://github.com/official-stockfish/Stockfish/pull/3642

Bench: 5359314
2021-08-05 08:52:07 +02:00
Stefan Geschwentner 5cd42f6b0b Simplify new cmh pruning thresholds by using directly a quadratic formula.
This decouples also the stat bonus updates from the threshold which creates less dependencies for tuning of stat bonus parameters.
Perhaps a further fine tuning of the now separated coefficients for constHist[0] and constHist[1] could give further gains.

STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 78384 W: 6134 L: 6090 D: 66160
Ptnml(0-2): 207, 5013, 28705, 5063, 204
https://tests.stockfishchess.org/tests/view/6106d235afad2da4f4ae3d4b

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 38176 W: 1149 L: 1095 D: 35932
Ptnml(0-2): 6, 1000, 17030, 1038, 14
https://tests.stockfishchess.org/tests/view/6107a080afad2da4f4ae3def

closes https://github.com/official-stockfish/Stockfish/pull/3639

Bench: 5098146
2021-08-05 08:47:33 +02:00
VoyagerOne 31ebd918ea Futile pruning simplification
Remove CMH conditions in futile pruning.

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 93520 W: 7165 L: 7138 D: 79217
Ptnml(0-2): 222, 5923, 34427, 5982, 206
https://tests.stockfishchess.org/tests/view/61083104e50a153c346ef8df

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 59072 W: 1746 L: 1706 D: 55620
Ptnml(0-2): 13, 1562, 26353, 1588, 20
https://tests.stockfishchess.org/tests/view/610894f2e50a153c346ef913

closes https://github.com/official-stockfish/Stockfish/pull/3638

Bench: 5229673
2021-08-05 08:44:38 +02:00
VoyagerOne a0fca67da4 CMH Pruning Tweak
replace CounterMovePruneThreshold by a depth dependent threshold

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 35512 W: 2718 L: 2552 D: 30242
Ptnml(0-2): 66, 2138, 13194, 2280, 78
https://tests.stockfishchess.org/tests/view/6104442fafad2da4f4ae3b94

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 36536 W: 1150 L: 1019 D: 34367
Ptnml(0-2): 10, 920, 16278, 1049, 11
https://tests.stockfishchess.org/tests/view/6104b033afad2da4f4ae3bbc

closes https://github.com/official-stockfish/Stockfish/pull/3636

Bench: 5848718
2021-07-31 15:29:19 +02:00
Tomasz Sobczyk 26edf9534a Avoid unnecessary stores in the affine transform
This patch improves the codegen in the AffineTransform::forward function for architectures >=SSSE3. Current code works directly on memory and the compiler cannot see that the stores through outptr do not alias the loads through weights and input32. The solution implemented is to perform the affine transform with local variables as accumulators and only store the result to memory at the end. The number of accumulators required is OutputDimensions / OutputSimdWidth, which means that for the 1024->16 affine transform it requires 4 registers with SSSE3, 2 with AVX2, 1 with AVX512. It also cuts the number of stores required by NumRegs * 256 for each node evaluated. The local accumulators are expected to be assigned to registers, but even if this cannot be done in some case due to register pressure it will help the compiler to see that there is no aliasing between the loads and stores and may still result in better codegen.

See https://godbolt.org/z/59aTKbbYc for codegen comparison.

passed STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 140328 W: 10635 L: 10358 D: 119335
Ptnml(0-2): 302, 8339, 52636, 8554, 333

closes https://github.com/official-stockfish/Stockfish/pull/3634

No functional change
2021-07-30 17:15:52 +02:00
SFisGOD e973eee919 Update default net to nn-56a5f1c4173a.nnue
SPSA 1: https://tests.stockfishchess.org/tests/view/60fd24efd8a6b65b2f3a796e
Parameters: A total of 256 net biases were tuned (hidden layer 2)
New best values: Half of the changes from the tuning run
New net: nn-5992d3ba79f3.nnue

SPSA 2: https://tests.stockfishchess.org/tests/view/60fec7d6d8a6b65b2f3a7aa2
Parameters: A total of 128 net biases were tuned (hidden layer 1)
New best values: Half of the changes from the tuning run
New net: nn-56a5f1c4173a.nnue

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 140392 W: 10863 L: 10578 D: 118951
Ptnml(0-2): 347, 8754, 51718, 9021, 356
https://tests.stockfishchess.org/tests/view/610037e396b86d98abf6a79e

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 14216 W: 454 L: 355 D: 13407
Ptnml(0-2): 4, 323, 6356, 420, 5
https://tests.stockfishchess.org/tests/view/61019995afad2da4f4ae3a3c

Closes #3633

Bench: 4801359
2021-07-29 07:35:13 +02:00
SFisGOD 237ed1ef8f Update default net to nn-26abeed38351.nnue
SPSA: https://tests.stockfishchess.org/tests/view/60fba335d8a6b65b2f3a7891

New best values: Half of the changes from the tuning run.
Setting: nodestime=300 with 10+0.1 (approximate real TC is 2.5 seconds)
The rest is the same as described in #3593

The change from nodestime=600 to 300 was suggested by gekkehenker to prevent time losses for some slow workers
SFisGOD@94cd757#commitcomment-53324840

STC:
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 67448 W: 5241 L: 5036 D: 57171
Ptnml(0-2): 151, 4198, 24827, 4391, 157
https://tests.stockfishchess.org/tests/view/60fd50f2d8a6b65b2f3a798e

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 48752 W: 1504 L: 1358 D: 45890
Ptnml(0-2): 13, 1226, 21754, 1368, 15
https://tests.stockfishchess.org/tests/view/60fd7bb2d8a6b65b2f3a79a9

Closes https://github.com/official-stockfish/Stockfish/pull/3630

Bench:  5124774
2021-07-26 07:52:59 +02:00
Giacomo Lorenzetti 910d26b5c3 Simplification in LMR
This commit removes the `!captureOrPromotion` condition from ttCapture reduction and from good/bad history reduction (similar to #3619).

passed STC:
https://tests.stockfishchess.org/tests/view/60fc734ad8a6b65b2f3a7922
LLR: 2.97 (-2.94,2.94) <-2.50,0.50>
Total: 48680 W: 3855 L: 3776 D: 41049
Ptnml(0-2): 118, 3145, 17744, 3206, 127

passed LTC:
https://tests.stockfishchess.org/tests/view/60fce7d5d8a6b65b2f3a794c
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 86528 W: 2471 L: 2450 D: 81607
Ptnml(0-2): 28, 2203, 38777, 2232, 24

closes https://github.com/official-stockfish/Stockfish/pull/3629

Bench: 4951406
2021-07-26 07:48:58 +02:00
MichaelB7 b939c80513 Update the default net to nn-76a8a7ffb820.nnue.
combined work by Serio Vieri, Michael Byrne, and Jonathan D (aka SFisGod) based on top of previous developments, by restarts from good nets.

Sergio generated the net https://tests.stockfishchess.org/api/nn/nn-d8609abe8caf.nnue:

The initial net nn-d8609abe8caf.nnue is trained by generating around 16B of training data from the last master net nn-9e3c6298299a.nnue, then trained, continuing from the master net, with lambda=0.2 and sampling ratio of 1. Starting with LR=2e-3, dropping LR with a factor of 0.5 until it reaches LR=5e-4. in_scaling is set to 361. No other significant changes made to the pytorch trainer.

Training data gen command (generates in chunks of 200k positions):

generate_training_data min_depth 9 max_depth 11 count 200000 random_move_count 10 random_move_max_ply 80 random_multi_pv 12 random_multi_pv_diff 100 random_multi_pv_depth 8 write_min_ply 10 eval_limit 1500 book noob_3moves.epd output_file_name gendata/$(date +"%Y%m%d-%H%M")_${HOSTNAME}.binpack

PyTorch trainer command (Note that this only trains for 20 epochs, repeatedly train until convergence):

python train.py --features "HalfKAv2^" --max_epochs 20 --smart-fen-skipping --random-fen-skipping 500 --batch-size 8192 --default_root_dir $dir --seed $RANDOM --threads 4 --num-workers 32 --gpus $gpuids --track_grad_norm 2 --gradient_clip_val 0.05 --lambda 0.2 --log_every_n_steps 50 $resumeopt $data $val

See https://github.com/sergiovieri/Stockfish/tree/tools_mod/rl for the scripts used to generate data.

Based on that Michael generated nn-76a8a7ffb820.nnue in the following way:

The net being submitted was trained with the pytorch trainer: https://github.com/glinscott/nnue-pytorch

python train.py i:/bin/all.binpack i:/bin/all.binpack --gpus 1 --threads 4 --num-workers 30 --batch-size 16384 --progress_bar_refresh_rate 30 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^ --auto_lr_find True --lambda=1.0 --max_epochs=240 --seed %random%%random% --default_root_dir exp/run_109 --resume-from-model ./pt/nn-d8609abe8caf.pt

This run is thus started from Segio Vieri's net nn-d8609abe8caf.nnue

all.binpack equaled 4 parts Wrong_NNUE_2.binpack https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq/view?usp=sharing plus two parts of Training_Data.binpack https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing
Each set was concatenated together - making one large Wrong_NNUE 2 binpack and one large Training so the were approximately equal in size. They were then interleaved together. The idea was to give Wrong_NNUE.binpack closer to equal weighting with the Training_Data binpack

model.py modifications:
loss = torch.pow(torch.abs(p - q), 2.6).mean()
LR = 8.0e-5 calculated as follows: 1.5e-3*(.992^360) - the idea here was to take a highly trained net and just use all.binpack as a finishing micro refinement touch for the last 2 Elo or so. This net was discovered on the 59th epoch.
optimizer = ranger.Ranger(train_params, betas=(.90, 0.999), eps=1.0e-7, gc_loc=False, use_gc=False)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.992)
For this micro optimization, I had set the period to "5" in train.py. This changes the checkpoint output so that every 5th checkpoint file is created

The final touches were to adjust the NNUE scale, as was done by Jonathan in tests running at the same time.

passed LTC
https://tests.stockfishchess.org/tests/view/60fa45aed8a6b65b2f3a77a4
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 53040 W: 1732 L: 1575 D: 49733
Ptnml(0-2): 14, 1432, 23474, 1583, 17

passed STC
https://tests.stockfishchess.org/tests/view/60f9fee2d8a6b65b2f3a7775
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 37928 W: 3178 L: 3001 D: 31749
Ptnml(0-2): 100, 2446, 13695, 2623, 100.

closes https://github.com/official-stockfish/Stockfish/pull/3626

Bench: 5169957
2021-07-24 18:04:59 +02:00
Giacomo Lorenzetti a85928e7ec Apply good/bad history reduction also when inCheck
Main idea is that, in some cases, 'in check' situations are not so different from 'not in check' ones.
Trying to use piece count in order to select only a few 'in check' situations have failed LTC testing.
It could be interesting to apply one of those ideas in other parts of the search function.

passed STC:
https://tests.stockfishchess.org/tests/view/60f1b68dd1189bed71812d40
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 53472 W: 4078 L: 4008 D: 45386
Ptnml(0-2): 127, 3297, 19795, 3413, 104

passed LTC:
https://tests.stockfishchess.org/tests/view/60f291e6d1189bed71812de3
LLR: 2.92 (-2.94,2.94) <-2.50,0.50>
Total: 89712 W: 2651 L: 2632 D: 84429
Ptnml(0-2): 60, 2261, 40188, 2294, 53

closes https://github.com/official-stockfish/Stockfish/pull/3619

Bench: 5185789
2021-07-23 19:02:58 +02:00
pb00067 760b7462bc Simplify lowply-history scoring logic
STC:
https://tests.stockfishchess.org/tests/view/60eee559d1189bed71812b16
LLR: 2.97 (-2.94,2.94) <-2.50,0.50>
Total: 33976 W: 2523 L: 2431 D: 29022
Ptnml(0-2): 66, 2030, 12730, 2070, 92

LTC:
https://tests.stockfishchess.org/tests/view/60eefa12d1189bed71812b24
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 107240 W: 3053 L: 3046 D: 101141
Ptnml(0-2): 56, 2668, 48154, 2697, 45

closes https://github.com/official-stockfish/Stockfish/pull/3616

bench: 5199177
2021-07-23 18:53:03 +02:00
Vizvezdenec d957179df7 Prune illegal moves in qsearch earlier
The main idea is that illegal moves influencing search or
qsearch obviously can't be any sort of good. The only reason
why initially legality checks for search and qsearch were done
after they actually can influence some heuristics is because
legality check is expensive computationally. Eventually in
search it was moved to the place where it makes sure that
illegal moves can't influence search.

This patch shows that the same can be done for qsearch + it
passed STC with elo-gaining bounds + it removes 3 lines of code
because one no longer needs to increment/decrement movecount
on illegal moves.

passed STC with elo-gaining bounds
https://tests.stockfishchess.org/tests/view/60f20aefd1189bed71812da0
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 61512 W: 4688 L: 4492 D: 52332
Ptnml(0-2): 139, 3730, 22848, 3874, 165

The same version functionally but with moving condition ever earlier
passed LTC with simplification bounds.
https://tests.stockfishchess.org/tests/view/60f292cad1189bed71812de9
LLR: 2.98 (-2.94,2.94) <-2.50,0.50>
Total: 60944 W: 1724 L: 1685 D: 57535
Ptnml(0-2): 11, 1556, 27298, 1597, 10

closes https://github.com/official-stockfish/Stockfish/pull/3618

bench 4709569
2021-07-23 18:47:30 +02:00
Liam Keegan bc654257e7 Add macOS and windows to CI
- macOS
  - system clang
  - gcc
- windows / msys2
  - mingw 64-bit gcc
  - mingw 32-bit gcc
- minor code fixes to get new CI jobs to pass
  - code: suppress unused-parameter warning on 32-bit windows
  - Makefile: if arch=any on macos, don't specify arch at all

fixes https://github.com/official-stockfish/Stockfish/issues/2958

closes https://github.com/official-stockfish/Stockfish/pull/3623

No functional change
2021-07-23 18:16:05 +02:00
VoyagerOne 36f8d3806b Don't save excluded move eval in TT
STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 17544 W: 1384 L: 1236 D: 14924
Ptnml(0-2): 37, 1031, 6499, 1157, 48
https://tests.stockfishchess.org/tests/view/60ec8d9bd1189bed71812999

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 26136 W: 823 L: 707 D: 24606
Ptnml(0-2): 6, 643, 11656, 755, 8
https://tests.stockfishchess.org/tests/view/60ecb11ed1189bed718129ba

closes https://github.com/official-stockfish/Stockfish/pull/3614

Bench: 5505251
2021-07-13 17:35:20 +02:00
Vizvezdenec dbd7f602d3 Remove second futility pruning depth limit
This patch removes futility pruning lmrDepth limit for futility pruning at parent nodes.
Since it's already capped by margin that is a function of lmrDepth there is no need to extra cap it with lmrDepth.

passed STC
https://tests.stockfishchess.org/tests/view/60e9b5dfd1189bed71812777
LLR: 2.97 (-2.94,2.94) <-2.50,0.50>
Total: 14872 W: 1264 L: 1145 D: 12463
Ptnml(0-2): 37, 942, 5369, 1041, 47

passed LTC
https://tests.stockfishchess.org/tests/view/60e9c635d1189bed71812790
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 40336 W: 1280 L: 1225 D: 37831
Ptnml(0-2): 24, 1057, 17960, 1094, 33

closes https://github.com/official-stockfish/Stockfish/pull/3612

bench: 5064969
2021-07-13 17:33:20 +02:00
pb00067 f4986f4596 SEE: simplify stm variable initialization
Pull #3458 removed the only usage of pos.see_ge() moving pieces that
don't belong to the side to move, so we can simplify this, adding an assert.

closes https://github.com/official-stockfish/Stockfish/pull/3607

No functional change
2021-07-13 17:31:15 +02:00
Vizvezdenec 09b6d28391 Remove futility pruning depth limit
This patch removes futility pruning depth limit for child node futility pruning.
In current master it was double capped by depth and by futility margin, which is also a function of depth, which didn't make much sense.

passed STC
https://tests.stockfishchess.org/tests/view/60e2418f9ea99d7c2d693e64
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 116168 W: 9100 L: 9097 D: 97971
Ptnml(0-2): 319, 7496, 42476, 7449, 344

passed LTC
https://tests.stockfishchess.org/tests/view/60e3374f9ea99d7c2d693f20
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 43304 W: 1282 L: 1231 D: 40791
Ptnml(0-2): 8, 1126, 19335, 1173, 10

closes https://github.com/official-stockfish/Stockfish/pull/3606

bench 4965493
2021-07-13 17:23:30 +02:00
SFisGOD 8fc297c506 Update default net to nn-9e3c6298299a.nnue
Optimization of nn-956480d8378f.nnue using SPSA
https://tests.stockfishchess.org/tests/view/60da2bf63beab81350ac9fe7

Same method as described in PR #3593

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 17792 W: 1525 L: 1372 D: 14895
Ptnml(0-2): 28, 1156, 6401, 1257, 54
https://tests.stockfishchess.org/tests/view/60deffc59ea99d7c2d693c19

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 36544 W: 1245 L: 1109 D: 34190
Ptnml(0-2): 12, 988, 16139, 1118, 15
https://tests.stockfishchess.org/tests/view/60df11339ea99d7c2d693c22

closes https://github.com/official-stockfish/Stockfish/pull/3601

Bench: 4687476
2021-07-03 10:03:32 +02:00
Paul Mulders 516ad1c9bf Allow passing RTLIB=compiler-rt to make
Not all linux users will have libatomic installed.
When using clang as the system compiler with compiler-rt as the default
runtime library instead of libgcc, atomic builtins may be provided by compiler-rt.
This change allows such users to pass RTLIB=compiler-rt to make sure
the build doesn't error out on the missing (unnecessary) libatomic.

closes https://github.com/official-stockfish/Stockfish/pull/3597

No functional change
2021-07-03 09:51:03 +02:00
candirufish ec8dfe7315 no cut node reduction for killer moves.
stc:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 44344 W: 3474 L: 3294 D: 37576
Ptnml(0-2): 117, 2710, 16338, 2890, 117
https://tests.stockfishchess.org/tests/view/60d8ea673beab81350ac9eb8

ltc:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 82600 W: 2638 L: 2441 D: 77521
Ptnml(0-2): 38, 2147, 36749, 2312, 54
https://tests.stockfishchess.org/tests/view/60d9048f3beab81350ac9eed

closes https://github.com/official-stockfish/Stockfish/pull/3600

Bench: 5160239
2021-07-03 09:44:05 +02:00
xoto10 d297d1d8a7 Simplify lazy_skip.
Small speedup by removing operations in lazy_skip.

STC 10+0.1 :
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 55088 W: 4553 L: 4482 D: 46053
Ptnml(0-2): 163, 3546, 20045, 3637, 153
https://tests.stockfishchess.org/tests/view/60daa2cb3beab81350aca04d

LTC 60+0.6 :
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 46136 W: 1457 L: 1407 D: 43272
Ptnml(0-2): 10, 1282, 20442, 1316, 18
https://tests.stockfishchess.org/tests/view/60db0e753beab81350aca08e

closes https://github.com/official-stockfish/Stockfish/pull/3599

Bench 5122403
2021-07-03 09:26:58 +02:00
Stéphane Nicolet b51b094419 Simplify format_cp_aligned_dot()
closes https://github.com/official-stockfish/Stockfish/pull/3583

No functional change
2021-07-03 09:25:16 +02:00
Joost VandeVondele 7cfc1f9b15 Restore development version
No functional change
2021-07-03 09:20:06 +02:00
Joost VandeVondele 773dff0209 Stockfish 14
Official release version of Stockfish 14

Bench: 4770936

---

Today, we have the pleasure to announce Stockfish 14.

As usual, downloads will be freely available at https://stockfishchess.org

The engine is now significantly stronger than just a few months ago,
and wins four times more game pairs than it loses against the previous
release version [0]. Stockfish 14 is now at least 400 Elo ahead of
Stockfish 7, a top engine in 2016 [1]. During the last five years,
Stockfish has thus gained about 80 Elo per year.

Stockfish 14 evaluates positions more accurately than Stockfish 13 as
a result of two major steps forward in defining and training the
efficiently updatable neural network (NNUE) that provides the evaluation
for positions.

First, the collaboration with the Leela Chess Zero team - announced
previously [2] - has come to fruition. The LCZero team has provided a
collection of billions of positions evaluated by Leela that we have
combined with billions of positions evaluated by Stockfish to train the
NNUE net that powers Stockfish 14. The fact that we could use and combine
these datasets freely was essential for the progress made and demonstrates
the power of open source and open data [3].

Second, the architecture of the NNUE network was significantly updated:
the new network is not only larger, but more importantly, it deals better
with large material imbalances and can specialize for multiple phases of
the game [4]. A new project, kick-started by Gary Linscott and
Tomasz Sobczyk, led to a GPU accelerated net trainer written in
pytorch.[5] This tool allows for training high-quality nets in a couple
of hours.

Finally, this release features some search refinements, minor bug
fixes and additional improvements. For example, Stockfish is now about
90 Elo stronger for chess960 (Fischer random chess) at short time control.

The Stockfish project builds on a thriving community of enthusiasts
(thanks everybody!) that contribute their expertise, time, and resources
to build a free and open-source chess engine that is robust, widely
available, and very strong. We invite our chess fans to join the fishtest
testing framework and programmers to contribute to the project on
github [6].

Stay safe and enjoy chess!

The Stockfish team

[0] https://tests.stockfishchess.org/tests/view/60dae5363beab81350aca077
[1] https://nextchessmove.com/dev-builds
[2] https://stockfishchess.org/blog/2021/stockfish-13/
[3] https://lczero.org/blog/2021/06/the-importance-of-open-data/
[4] https://github.com/official-stockfish/Stockfish/commit/e8d64af1
[5] https://github.com/glinscott/nnue-pytorch/
[6] https://stockfishchess.org/get-involved/
2021-07-02 14:53:30 +02:00
Brad Knox 2275923d3c Update Top CPU Contributors
closes https://github.com/official-stockfish/Stockfish/pull/3595

No functional change
2021-06-29 10:24:54 +02:00
SFisGOD 49283d3a66 Update default net to nn-3475407dc199.nnue
Optimization of eight subnetwork output layers of Michael's nn-190f102a22c3.nnue using SPSA
https://tests.stockfishchess.org/tests/view/60d5510642a522cc50282ef3

Parameters: A total of 256 net weights and 8 net biases were tuned
New best values: The raw values at the end of the tuning run were used (800k games, 5 seconds TC)
Settings: default ck value and SPSA A is 30,000 (3.75% of the total number of games)

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 29064 W: 2435 L: 2269 D: 24360
Ptnml(0-2): 72, 1857, 10505, 2029, 69
https://tests.stockfishchess.org/tests/view/60d8ea123beab81350ac9eb6

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 61848 W: 2055 L: 1884 D: 57909
Ptnml(0-2): 18, 1708, 27310, 1861, 27
https://tests.stockfishchess.org/tests/view/60d8f0393beab81350ac9ec6

closes https://github.com/official-stockfish/Stockfish/pull/3593

Bench: 4770936
2021-06-28 21:31:58 +02:00
MichaelB7 b94a651878 Make net nn-956480d8378f.nnue the default
Trained with the pytorch trainer: https://github.com/glinscott/nnue-pytorch

python train.py i:/bin/all.binpack i:/bin/all.binpack --gpus 1 --threads 4 --num-workers 30 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^ --lambda=1.0 --max_epochs=440 --seed %random%%random% --default_root_dir exp/run_18 --resume-from-model ./pt/nn-75980ca503c6.pt

This run is thus started from a previous master net.

all.binpack equaled 4 parts Wrong_NNUE_2.binpack https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq/view?usp=sharing plus two parts of Training_Data.binpack https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing
Each set was concatenated together - making one large Wrong_NNUE 2 binpack and one large Training so the were approximately equal in size. They were then interleaved together. The idea was to give Wrong_NNUE.binpack closer to equal weighting with the Training_Data binpack

passed STC:
https://tests.stockfishchess.org/tests/view/60d0c0a7a8ec07dc34c072b2
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 18440 W: 1693 L: 1531 D: 15216
Ptnml(0-2): 67, 1225, 6464, 1407, 57

passed LTC:
https://tests.stockfishchess.org/tests/view/60d762793beab81350ac9d72
LLR: 2.98 (-2.94,2.94) <0.50,3.50>
Total: 93120 W: 3152 L: 2933 D: 87035
Ptnml(0-2): 48, 2581, 41076, 2814, 41

passed LTC (rebased branch to current master):
https://tests.stockfishchess.org/tests/view/60d85eeb3beab81350ac9e2b
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 42688 W: 1347 L: 1206 D: 40135
Ptnml(0-2): 14, 1097, 18981, 1238, 14.

closes https://github.com/official-stockfish/Stockfish/pull/3592

Bench: 4906727
2021-06-28 21:20:05 +02:00
Joost VandeVondele dc4983327d Update WDL model for NNUE
This updates the WDL model based on the LTC statistics in June this year (10M games),
so from pre-NNUE to NNUE based results.

(for old results see, https://github.com/official-stockfish/Stockfish/pull/2778)

As before the fit by the model to the data is quite good.

closes https://github.com/official-stockfish/Stockfish/pull/3582

No functional change
2021-06-28 21:13:30 +02:00
bmc4 e47b74457e Simplify Reductions Initialization
passed

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 45032 W: 3600 L: 3518 D: 37914
Ptnml(0-2): 111, 2893, 16435, 2957, 120
https://tests.stockfishchess.org/tests/view/60d2655d40925195e7a6c527

LTC:
LLR: 3.00 (-2.94,2.94) <-2.50,0.50>
Total: 25728 W: 786 L: 722 D: 24220
Ptnml(0-2): 5, 650, 11494, 706, 9
https://tests.stockfishchess.org/tests/view/60d2b14240925195e7a6c577

closes https://github.com/official-stockfish/Stockfish/pull/3584

bench: 4602977
2021-06-28 21:12:04 +02:00
Stéphane Nicolet 0470bcef0e Detect fortresses a little bit quicker
In the so-called "hybrid" method of evaluation of current master, we use the
classical eval (because of its speed) instead of the NNUE eval when the classical
material balance approximation hints that the position is "winning enough" to
rely on the classical eval.

This trade-off idea between speed and accuracy works well in general, but in
some fortress positions the classical eval is just bad. So in shuffling branches
of the search tree, we (slowly) increase the thresehold so that eventually we
don't trust classical anymore and switch to NNUE evaluation.

This patch increases that threshold faster, so that we switch to NNUE quicker
in shuffling branches. Idea is to incite Stockfish to spend less time in fortresses
lines in the search tree, and spend more time searching the critical lines.

passed STC:
LLR: 2.96 (-2.94,2.94) <-0.50,2.50>
Total: 47872 W: 3908 L: 3720 D: 40244
Ptnml(0-2): 122, 3053, 17419, 3199, 143
https://tests.stockfishchess.org/tests/view/60cef34b457376eb8bcab79d

passed LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 73616 W: 2326 L: 2143 D: 69147
Ptnml(0-2): 21, 1940, 32705, 2119, 23
https://tests.stockfishchess.org/tests/view/60cf6d842114332881e73528

Retested at LTC against lastest master:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 18264 W: 642 L: 532 D: 17090
Ptnml(0-2): 6, 479, 8055, 583, 9
https://tests.stockfishchess.org/tests/view/60d18cd540925195e7a6c351

closes https://github.com/official-stockfish/Stockfish/pull/3578

Bench: 5139233
2021-06-22 11:51:03 +02:00
MichaelB7 9b82414b67 Make net nn-190f102a22c3.nnue the default net.
Trained with the pytorch trainer: https://github.com/glinscott/nnue-pytorch

python train.py i:/bin/all.binpack i:/bin/all.binpack --gpus 1 --threads 4 --num-workers 30 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^ --lambda=1.0 --max_epochs=440 --seed %random%%random% --default_root_dir exp/run_17 --resume-from-model ./pt/nn-75980ca503c6.pt

This run is thus started from the previous master net.

all.binpack equaled 4 parts Wrong_NNUE_2.binpack https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq/view?usp=sharing plus two parts of Training_Data.binpack https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing
Each set was concatenated together - making one large Wrong_NNUE 2 binpack and one large Training so the were approximately equal in size. They were then interleaved together. The idea was to give Wrong_NNUE.binpack closer to equal weighting with the Training_Data binpack

passed LTC
https://tests.stockfishchess.org/tests/view/60d09f52b4c17000d679517f
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 32184 W: 1100 L: 970 D: 30114
Ptnml(0-2): 10, 878, 14193, 994, 17

passed STC
https://tests.stockfishchess.org/tests/view/60d086c02114332881e7368e
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 11360 W: 1056 L: 906 D: 9398
Ptnml(0-2): 25, 735, 4026, 853, 41

closes https://github.com/official-stockfish/Stockfish/pull/3576

Bench: 4631244
2021-06-21 23:16:55 +02:00
Joost VandeVondele 2e2865d34b Fix build error on OSX
directly use integer version for cp calculation.

fixes https://github.com/official-stockfish/Stockfish/issues/3573

closes https://github.com/official-stockfish/Stockfish/pull/3574

No functional change
2021-06-21 23:14:58 +02:00
Stéphane Nicolet ed436a36ba Remove the Contempt UCI option
This patch removes the UCI option for setting Contempt in classical evaluation.

It is exactly equivalent to using Contempt=0 for the UCI contempt value and keeping
the dynamic part in the algo (renaming this dynamic part `trend` to better describe
what it does). We have tried quite hard to implement a working Contempt feature for
NNUE but nothing really worked, so it is probably time to give up.

Interested chess fans wishing to keep playing with the UCI option for Contempt and
use it with the classical eval are urged to download the version tagged "SF_Classical"
of Stockfish (dated 31 July 2020), as it was the last version where our search
algorithm was tuned for the classical eval and is probably our strongest classical
player ever: https://github.com/official-stockfish/Stockfish/tags

Passed STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 72904 W: 6228 L: 6175 D: 60501
Ptnml(0-2): 221, 5006, 25971, 5007, 247
https://tests.stockfishchess.org/tests/view/60c98bf9457376eb8bcab18d

Passed LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 45168 W: 1601 L: 1547 D: 42020
Ptnml(0-2): 38, 1331, 19786, 1397, 32
https://tests.stockfishchess.org/tests/view/60c9c7fa457376eb8bcab1bb

closes https://github.com/official-stockfish/Stockfish/pull/3575

Bench: 4947716
2021-06-21 22:58:56 +02:00
Stéphane Nicolet 70ac5ecbb6 Keep more pawns and pieces when attacking
This patch increase the weight of pawns and pieces from 28 to 32
in the scaling formula we apply to the output of the NNUE pure eval.

Increasing this gradient for pawns and pieces means that Stockfish
will try a little harder to keep material when she has the advantage,
and try a little bit harder to escape into an endgame when she is
under pressure.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 53168 W: 4371 L: 4177 D: 44620
Ptnml(0-2): 160, 3389, 19283, 3601, 151
https://tests.stockfishchess.org/tests/view/60cefd1d457376eb8bcab7ab

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 10888 W: 386 L: 288 D: 10214
Ptnml(0-2): 3, 260, 4821, 356, 4
https://tests.stockfishchess.org/tests/view/60cf709d2114332881e7352b

closes https://github.com/official-stockfish/Stockfish/pull/3571

Bench: 4965430
2021-06-20 23:17:07 +02:00
MichaelB7 ba01f4b954 Make net nn-75980ca503c6.nnue the default.
trained with the Python command

c:\nnue>python train.py i:/bin/all.binpack i:/bin/all.binpack --gpus 1 --threads 4 --num-workers 30 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^ --lambda=1.0 --max_epochs=440 --seed %random%%random% --default_root_dir exp/run_10 --resume-from-model ./pt/nn-3b20abec10c1.pt
`
all.binpack equaled 4 parts Wrong_NNUE_2.binpack https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq/view?usp=sharing plus two parts of Training_Data.binpack https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing
Each set was concatenated together - making one large Wrong_NNUE 2 binpack and one large Training so the were approximately equal in size. They were then interleaved together. The idea was to give Wrong_NNUE.binpack closer to equal weighting with the Training_Data binpack .

Net nn-3b20abec10c1.nnue was chosen as the --resume-from-model with the idea that through learning, the manually hex edited values will be learned and will not need to be manually adjusted going forward. They would also be fine tuned by the learning process.

passed STC:
https://tests.stockfishchess.org/tests/view/60cdf91e457376eb8bcab66f
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 18256 W: 1639 L: 1479 D: 15138
Ptnml(0-2): 59, 1179, 6505, 1313, 72

passed LTC:
https://tests.stockfishchess.org/tests/view/60ce2166457376eb8bcab6e1
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 18792 W: 654 L: 542 D: 17596
Ptnml(0-2): 9, 490, 8291, 592, 14

closes https://github.com/official-stockfish/Stockfish/pull/3570

Bench: 5020972
2021-06-19 23:24:35 +02:00
Tomasz Sobczyk 2e745956c0 Change trace with NNUE eval support
This patch adds some more output to the `eval` command. It adds a board display
with estimated piece values (method is remove-piece, evaluate, put-piece), and
splits the NNUE evaluation with (psqt,layers) for each bucket for the NNUE net.

Example:

```

./stockfish
position fen 3Qb1k1/1r2ppb1/pN1n2q1/Pp1Pp1Pr/4P2p/4BP2/4B1R1/1R5K b - - 11 40
eval

 Contributing terms for the classical eval:
+------------+-------------+-------------+-------------+
|    Term    |    White    |    Black    |    Total    |
|            |   MG    EG  |   MG    EG  |   MG    EG  |
+------------+-------------+-------------+-------------+
|   Material |  ----  ---- |  ----  ---- | -0.73 -1.55 |
|  Imbalance |  ----  ---- |  ----  ---- | -0.21 -0.17 |
|      Pawns |  0.35 -0.00 |  0.19 -0.26 |  0.16  0.25 |
|    Knights |  0.04 -0.08 |  0.12 -0.01 | -0.08 -0.07 |
|    Bishops | -0.34 -0.87 | -0.17 -0.61 | -0.17 -0.26 |
|      Rooks |  0.12  0.00 |  0.08  0.00 |  0.04  0.00 |
|     Queens |  0.00  0.00 | -0.27 -0.07 |  0.27  0.07 |
|   Mobility |  0.84  1.76 |  0.01  0.66 |  0.83  1.10 |
|King safety | -0.99 -0.17 | -0.72 -0.10 | -0.27 -0.07 |
|    Threats |  0.27  0.27 |  0.73  0.86 | -0.46 -0.59 |
|     Passed |  0.00  0.00 |  0.79  0.82 | -0.79 -0.82 |
|      Space |  0.61  0.00 |  0.24  0.00 |  0.37  0.00 |
|   Winnable |  ----  ---- |  ----  ---- |  0.00 -0.03 |
+------------+-------------+-------------+-------------+
|      Total |  ----  ---- |  ----  ---- | -1.03 -2.14 |
+------------+-------------+-------------+-------------+

 NNUE derived piece values:
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |       |       |   Q   |   b   |       |   k   |       |
|       |       |       | +12.4 | -1.62 |       |       |       |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |   r   |       |       |   p   |   p   |   b   |       |
|       | -3.89 |       |       | -0.84 | -1.19 | -3.32 |       |
+-------+-------+-------+-------+-------+-------+-------+-------+
|   p   |   N   |       |   n   |       |       |   q   |       |
| -1.81 | +3.71 |       | -4.82 |       |       | -5.04 |       |
+-------+-------+-------+-------+-------+-------+-------+-------+
|   P   |   p   |       |   P   |   p   |       |   P   |   r   |
| +1.16 | -0.91 |       | +0.55 | +0.12 |       | +0.50 | -4.02 |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |       |       |       |   P   |       |       |   p   |
|       |       |       |       | +2.33 |       |       | +1.17 |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |       |       |       |   B   |   P   |       |       |
|       |       |       |       | +4.79 | +1.54 |       |       |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |       |       |       |   B   |       |   R   |       |
|       |       |       |       | +4.54 |       | +6.03 |       |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |   R   |       |       |       |       |       |   K   |
|       | +4.81 |       |       |       |       |       |       |
+-------+-------+-------+-------+-------+-------+-------+-------+

 NNUE network contributions (Black to move)
+------------+------------+------------+------------+
|   Bucket   |  Material  | Positional |   Total    |
|            |   (PSQT)   |  (Layers)  |            |
+------------+------------+------------+------------+
|  0         |  +  0.32   |  -  1.46   |  -  1.13   |
|  1         |  +  0.25   |  -  0.68   |  -  0.43   |
|  2         |  +  0.46   |  -  1.72   |  -  1.25   |
|  3         |  +  0.55   |  -  1.80   |  -  1.25   |
|  4         |  +  0.48   |  -  1.77   |  -  1.29   |
|  5         |  +  0.40   |  -  2.00   |  -  1.60   |
|  6         |  +  0.57   |  -  2.12   |  -  1.54   | <-- this bucket is used
|  7         |  +  3.38   |  -  2.00   |  +  1.37   |
+------------+------------+------------+------------+

Classical evaluation   -1.00 (white side)
NNUE evaluation        +1.54 (white side)
Final evaluation       +2.38 (white side) [with scaled NNUE, hybrid, ...]

```

Also renames the export_net() function to save_eval() while there.

closes https://github.com/official-stockfish/Stockfish/pull/3562

No functional change
2021-06-19 11:57:01 +02:00
proukornew 0171b506ec Fix for Cygwin's environment build-profile (fixed)
The Cygwin environment has two g++ compilers, each with a different problem
for compiling  Stockfish at the moment:

(a) g++.exe : full posix build compiler, linked to cygwin dll.

    => This one has a problem embedding the net.

(b) x86_64-w64-mingw32-g++.exe : native Windows build compiler.

    => This one manages to embed the net, but has a problem related to libgcov
       when we use the profile-build target of Stockfish.

This patch solves the problem for compiler (b), so that our recommended command line
if you want to build an optimized version of Stockfish on Cygwin becomes something
like the following (you can change the ARCH value to whatever you want, but note
the COMP and CXX variables pointing at the right compiler):

```
   make -j profile-build ARCH=x86-64-modern COMP=mingw CXX=x86_64-w64-mingw32-c++.exe
```

closes https://github.com/official-stockfish/Stockfish/pull/3569

No functional change
2021-06-19 11:22:30 +02:00
Joost VandeVondele adfb23c029 Make net nn-50144f835024.nnue the default
trained with the Python command

c:\nnue>python train.py i:/bin/all.binpack i:/bin/all.binpack --gpus 1 --threads 4 --num-workers 30 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^ --lambda=1.0 --max_epochs=440 --seed %random%%random% --default_root_dir exp/run_8 --resume-from-model ./pt/nn-6ad41a9207d0.pt
`
all.binpack equaled 4 parts Wrong_NNUE_2.binpack https://drive.google.com/file/d/1seGNOqcVdvK_vPNq98j-zV3XPE5zWAeq/view?usp=sharing plus two parts of Training_Data.binpack https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing
Each set was concatenated together - make one large Wrong_NNUE 2 binpack and one large Training_Data of approximate size. They were then interleaved together. The idea was to give Wrong_NNUE.binpack closer to equal weighting with the Training _Data binpack .

nn-6ad41a9207d0.pt was derived from a net vondele ran which passed STC quickly,
but faltered in LTC. https://tests.stockfishchess.org/tests/view/60cba666457376eb8bcab443

STC:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 18792 W: 2068 L: 1889 D: 14835
Ptnml(0-2): 82, 1480, 6117, 1611, 106
https://tests.stockfishchess.org/tests/view/60ccda8b457376eb8bcab568

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 11376 W: 574 L: 454 D: 10348
Ptnml(0-2): 4, 412, 4747, 510, 15
https://tests.stockfishchess.org/tests/view/60ccf952457376eb8bcab58d

closes https://github.com/official-stockfish/Stockfish/pull/3568

Bench: 4900906
2021-06-18 23:50:26 +02:00
Tomasz Sobczyk 07e6ceacd6 Add basic github workflow
move to github actions to replace travis CI.

First version, testing on linux using gcc and clang.
gcc build with sanitizers and valgrind.

No functional change
2021-06-18 22:05:56 +02:00
SFisGOD 86afb6a7cf Update default net to nn-aa9d7eeb397e.nnue
Optimization of vondele's nn-33c9d39e5eb6.nnue using SPSA
https://tests.stockfishchess.org/tests/view/60ca68be457376eb8bcab28b
Setting: ck values are default based on how large the parameters are
The new values for this net are the raw values at the end of the tuning (80k games)

The significant changes are in buckets 1 and 2 (5-12 pieces) so the main difference is in playing endgames if we compare it to nn-33c9. There is also change in bucket 7 (29-32 pieces) but not as substantial as the changes in buckets 1 and 2. If we interpret the changes based on an experiment a few months ago, this new net plays more optimistically during endgames and less optimistically during openings.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 49504 W: 4246 L: 4053 D: 41205
Ptnml(0-2): 140, 3282, 17749, 3407, 174
https://tests.stockfishchess.org/tests/view/60cbd752457376eb8bcab478

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 88720 W: 4926 L: 4651 D: 79143
Ptnml(0-2): 105, 4048, 35793, 4295, 119
https://tests.stockfishchess.org/tests/view/60cc7828457376eb8bcab4fa

closes https://github.com/official-stockfish/Stockfish/pull/3566

Bench: 4758885
2021-06-18 21:29:14 +02:00
ap 14b673d90f New default net nn-3b20abec10c1.nnue
This net was created by @pleomati, who manually edited with an hex editor
10 values randomly chosen in the LCSFNet10 net (nn-6ad41a9207d0.nnue) to
create this one. The LCSFNet10 net was trained by Joost VandeVondele from
a dataset combining Stockfish games and Leela games (16x10^9 positions from
SF self-play at depth 9, and 6.3x10^9 positions from Leela games, so overall
72% of Stockfish positions and 28% of Leela positions).

passed STC 10+0.1:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 50888 W: 5881 L: 5654 D: 39353
Ptnml(0-2): 281, 4290, 16085, 4497, 291
https://tests.stockfishchess.org/tests/view/60cbfa68457376eb8bcab49a

passed LTC 60+0.6:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 25480 W: 1498 L: 1338 D: 22644
Ptnml(0-2): 36, 1155, 10193, 1325, 31
https://tests.stockfishchess.org/tests/view/60cc4af8457376eb8bcab4d4

closes https://github.com/official-stockfish/Stockfish/pull/3564

Bench: 4904930
2021-06-18 20:00:13 +02:00
Stéphane Nicolet 07c8448034 Revert "Fix for Cygwin's environment build-profile"
This reverts commit "Fix for Cygwin's environment build-profile", as it was
giving errors for "make clean" on some Windows environments. See comments in
https://github.com/official-stockfish/Stockfish/commit/68bf362ea2385a641be9f5ed9ce2acdf55a1ecf1

Possibly somebody can propose a solution that would fix Cygwin builds and
not break on other system too, stay tuned! :-)

No functional change
2021-06-17 18:10:01 +02:00
bmc4 55e69dc88d Simplify reduction when best move doesn't change frequently.
STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 40400 W: 3468 L: 3377 D: 33555
Ptnml(0-2): 134, 2734, 14388, 2795, 149
https://tests.stockfishchess.org/tests/view/60c93e5a457376eb8bcab15f

LTC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 34200 W: 1190 L: 1128 D: 31882
Ptnml(0-2): 22, 998, 15001, 1054, 25
https://tests.stockfishchess.org/tests/view/60c96a1a457376eb8bcab180

closes https://github.com/official-stockfish/Stockfish/pull/3559

bench: 5629669
2021-06-17 02:08:33 +02:00
proukornew 68bf362ea2 Fix for Cygwin's environment build-profile
The Cygwin environment has two g++ compilers, each with a different problem
for compiling  Stockfish at the moment:

(a) g++.exe : full posix build compiler, linked to cygwin dll.

    => This one has a problem embedding the net.

(b) x86_64-w64-mingw32-g++.exe : native Windows build compiler.

    => This one manages to embed the net, but has a problem related to libgcov
       when we use the profile-build target of Stockfish.

This patch solves the problem for compiler (b), so that our recommended command line
if you want to build an optimized version of Stockfish on Cygwin becomes something
like the following (you can change the ARCH value to whatever you want, but note
the COMP and CXX variables pointing at the right compiler):

```
   make -j profile-build ARCH=x86-64-modern COMP=mingw CXX=x86_64-w64-mingw32-c++.exe
```

closes https://github.com/official-stockfish/Stockfish/pull/3463

No functional change
2021-06-17 01:14:20 +02:00
Joost VandeVondele 8ec9e10866 New default net nn-33c9d39e5eb6.nnue
As the previous net, this net is trained on Leela games as provided by borg.
See also https://lczero.org/blog/2021/06/the-importance-of-open-data/

The particular data set, which is a mix of T60 and T74 data, is now available as a single binpack:
https://drive.google.com/file/d/1RFkQES3DpsiJqsOtUshENtzPfFgUmEff/view?usp=sharing

The training command was:
python train.py ../../training_data_pylon.binpack ../../training_data_pylon.binpack --gpus 1 --threads 2 --num-workers 2 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 10 --features=HalfKAv2^   --lambda=1.0  --max_epochs=440 --seed $RANDOM --default_root_dir exp/run_2

passed STC:
https://tests.stockfishchess.org/tests/view/60c887cb457376eb8bcab054
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 12792 W: 1483 L: 1311 D: 9998
Ptnml(0-2): 62, 989, 4131, 1143, 71

passed LTC:
https://tests.stockfishchess.org/tests/view/60c8e5c4457376eb8bcab0f0
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 11272 W: 601 L: 477 D: 10194
Ptnml(0-2): 9, 421, 4657, 535, 14

also had strong LTC performance against another strong net of the series:
https://tests.stockfishchess.org/tests/view/60c8c40d457376eb8bcab0c6

closes https://github.com/official-stockfish/Stockfish/pull/3557

Bench: 5032320
2021-06-15 22:08:40 +02:00
J. Oster 4c4e104cad Fix a rare case of wrong TB ranking
of a root move leading to a 3-fold repetition.
With this small fix a draw ranking and thus a draw score is being applied.
This works for both, ranking by dtz or wdl tables.

Fixes https://github.com/official-stockfish/Stockfish/issues/3542

(No functional change without TBs.)
Bench: 4877339
2021-06-14 17:28:30 +02:00
Tomasz Sobczyk 900f249f59 Reduce the number of accumulator states
Reduce from 3 to 2. Make the intent of the states clearer.

STC: https://tests.stockfishchess.org/tests/view/60c50111457376eb8bcaad03
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 61888 W: 5007 L: 4944 D: 51937
Ptnml(0-2): 164, 3947, 22649, 4030, 154

LTC: https://tests.stockfishchess.org/tests/view/60c52b1c457376eb8bcaad2c
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 20248 W: 688 L: 618 D: 18942
Ptnml(0-2): 7, 551, 8946, 605, 15

closes https://github.com/official-stockfish/Stockfish/pull/3548

No functional change.
2021-06-14 11:22:08 +02:00
JWmer f8c779dbe5 Update default net to nn-8e47cf062333.nnue
This net is the result of training on data used by the Leela project. More precisely,
we shuffled T60 and T74 data kindly provided by borg (for different Tnn, the data is
a result of Leela selfplay with differently sized Leela nets).

The data is available at vondele's google drive:
https://drive.google.com/drive/folders/1mftuzYdl9o6tBaceR3d_VBQIrgKJsFpl.

The Leela data comes in small chunks of .binpack files. To shuffle them, we simply
used a small python script to randomly rename the files, and then concatenated them
using `cat`. As validation data we picked a file of T60 data. We will further investigate
T74 data.

The training for the NNUE architecture used 200 epochs with the Python trainer from
the Stockfish project. Unlike the previous run we tried with this data, this run does
not have adjusted scaling — not because we didn't want to, but because we forgot.
However, this training randomly skips 40% more positions than previous run. The loss
was very spiky and decreased slower than it does usually.

Training loss: https://github.com/official-stockfish/images/blob/main/training-loss-8e47cf062333.png
Validation loss: https://github.com/official-stockfish/images/blob/main/validation-loss-8e47cf062333.png

This is the exact training command:
python train.py --smart-fen-skipping --random-fen-skipping 14 --batch-size 16384 --threads 4 --num-workers 4 --gpus 1 trainingdata\training_data.binpack validationdata\val.binpack

---

10k STC result:
ELO: 3.61 +-3.3 (95%) LOS: 98.4%
Total: 10000 W: 1241 L: 1137 D: 7622
Ptnml(0-2): 68, 841, 3086, 929, 76
https://tests.stockfishchess.org/tests/view/60c67e50457376eb8bcaae70

10k LTC result:
ELO: 2.71 +-2.4 (95%) LOS: 98.8%
Total: 10000 W: 659 L: 581 D: 8760
Ptnml(0-2): 22, 485, 3900, 579, 14
https://tests.stockfishchess.org/tests/view/60c69deb457376eb8bcaae98

Passed LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 9648 W: 685 L: 545 D: 8418
Ptnml(0-2): 22, 448, 3740, 596, 18
https://tests.stockfishchess.org/tests/view/60c6d41c457376eb8bcaaecf

---

closes https://github.com/official-stockfish/Stockfish/pull/3550

Bench: 4877339
2021-06-14 09:24:07 +02:00
Tomasz Sobczyk ce4c523ad3 Register count for feature transformer
Compute optimal register count for feature transformer accumulation dynamically.
This also introduces a change where AVX512 would only use 8 registers instead of 16
(now possible due to a 2x increase in feature transformer size).

closes https://github.com/official-stockfish/Stockfish/pull/3543

No functional change
2021-06-13 13:10:56 +02:00
Vizvezdenec e1f181ee64 Do less LMR extensions
This patch restricts LMR extensions (of non-transposition table moves) from being
used when the transposition table move was extended by two plies via singular
extension. This may serve to limit search explosions in certain positions.

This makes a lot of sense because the precondition for the tt-move to have been
singular extended by two plies is that the result of the alternate search (with
excluded the tt-move) has been a hard fail low: it is natural to later search less
for non tt-moves in this situation.

The current state of depth/extensions/reductions management is getting quite tricky
in our search algo, see https://github.com/official-stockfish/Stockfish/pull/3546#issuecomment-860174549
for some discussion. Suggestions welcome!

Passed STC
https://tests.stockfishchess.org/tests/view/60c3f293457376eb8bcaac8d
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 117984 W: 9698 L: 9430 D: 98856
Ptnml(0-2): 315, 7708, 42703, 7926, 340

passed LTC
https://tests.stockfishchess.org/tests/view/60c46ea5457376eb8bcaacc7
LLR: 2.97 (-2.94,2.94) <0.50,3.50>
Total: 11280 W: 401 L: 302 D: 10577
Ptnml(0-2): 2, 271, 4998, 364, 5

closes https://github.com/official-stockfish/Stockfish/pull/3546

Bench: 4709974
2021-06-13 12:00:20 +02:00
Stéphane Nicolet 7819412002 Clarify use of UCI options
Update README.md to clarify use of UCI options

closes https://github.com/official-stockfish/Stockfish/pull/3540

No functional change
2021-06-13 10:02:43 +02:00
Tomasz Sobczyk b84fa04db6 Read NNUE net faster
Load feature transformer weights in bulk on little-endian machines.
This is in particular useful to test new nets with c-chess-cli,
see https://github.com/lucasart/c-chess-cli/issues/44

```
$ time ./stockfish.exe uci

Before : 0m0.914s
After  : 0m0.483s
```

No functional change
2021-06-13 09:39:03 +02:00
Joost VandeVondele 559942d64d Limit double extensions
Double extensions can lead to search explosions, for specific positions.
Currently, however, these double extensions are worth about 10Elo and cannot
be removed. This patch instead limits the number of double extensions given
to a maximum of 3.

This fixes https://github.com/official-stockfish/Stockfish/issues/3532
where the following testcase was shown to be problematic:

```
uci
setoption name Hash value 4
setoption name Contempt value 0
ucinewgame
position fen 8/Pk6/8/1p6/8/P1K5/8/6B1 w - - 37 130
go depth 20
```

passed STC:
https://tests.stockfishchess.org/tests/view/60c13161457376eb8bcaaa0f
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 73256 W: 6114 L: 6062 D: 61080
Ptnml(0-2): 222, 4912, 26306, 4968, 220

passed LTC:
https://tests.stockfishchess.org/tests/view/60c196fb457376eb8bcaaa6b
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 166440 W: 5559 L: 5594 D: 155287
Ptnml(0-2): 106, 4921, 73197, 4894, 102

closes https://github.com/official-stockfish/Stockfish/pull/3544

Bench: 5067605
2021-06-11 20:33:24 +02:00
bmc4 785b708097 Simplify promotion move generator
This patch removes Knight promotion checks from Captures. As a consequence,
it also removes this underpromotion from qsearch.

STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 37776 W: 3113 L: 3023 D: 31640
Ptnml(0-2): 103, 2419, 13755, 2507, 104
https://tests.stockfishchess.org/tests/view/60be6a06457376eb8bcaa775

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 39760 W: 1257 L: 1203 D: 37300
Ptnml(0-2): 11, 1079, 17646, 1133, 11
https://tests.stockfishchess.org/tests/view/60beb972457376eb8bcaa7c5

closes https://github.com/official-stockfish/Stockfish/pull/3536

Bench: 5530620
2021-06-08 20:16:20 +02:00
bmc4 999e142c54 Reduce in LMR reduction on PvNode
reduce reduction in LMR by 1 on PvNode.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 266080 W: 22438 L: 21996 D: 221646
Ptnml(0-2): 774, 17874, 95376, 18168, 848
https://tests.stockfishchess.org/tests/view/60bc0661457376eb8bcaa4bb

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 20144 W: 698 L: 587 D: 18859
Ptnml(0-2): 2, 529, 8906, 626, 9
https://tests.stockfishchess.org/tests/view/60bcc3f2457376eb8bcaa58d

closes https://github.com/official-stockfish/Stockfish/pull/3534

bench: 5173012
2021-06-06 21:22:39 +02:00
Guy Vreuls 3802cdf9b6 Makefile: Extend sanitize support
Enable compiling with multiple sanitizers at once.

Syntax:
make build ARCH=x86-64-avx512 debug=on sanitize="address undefined"

closes https://github.com/official-stockfish/Stockfish/pull/3524

No functional change.
2021-06-05 11:38:28 +02:00
Joost VandeVondele 98cbaa6c6b Enhance CI to error on leaks
Add flags to valgrind in our Continuous Integration scripts,
to error on memory leaks.

closes https://github.com/official-stockfish/Stockfish/pull/3525

No functional change.
2021-06-05 10:55:57 +02:00
Guy Vreuls 58307562b6 Revert "Simplify En Passant"
This reverts commit 9f8058bd26.

Fixes the memory leak discussed in pull request #3523
https://github.com/official-stockfish/Stockfish/pull/3523

Passed non-regression STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 76184 W: 6330 L: 6282 D: 63572
Ptnml(0-2): 202, 5047, 27564, 5059, 220
https://tests.stockfishchess.org/tests/view/60ba146c457376eb8bcaa2e2

closes https://github.com/official-stockfish/Stockfish/pull/3527

Benched to verify there is no functional change.

Bench: 4364128
2021-06-05 10:47:46 +02:00
Stéphane Nicolet 8f081c86f7 Clean SIMD code a bit
Cleaner vector code structure in feature transformer. This patch just
regroups the parts of the inner loop for each SIMD instruction set.

Tested for non-regression:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 115760 W: 9835 L: 9831 D: 96094
Ptnml(0-2): 326, 7776, 41715, 7694, 369
https://tests.stockfishchess.org/tests/view/60b96b39457376eb8bcaa26e

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).

closes https://github.com/official-stockfish/Stockfish/pull/3506

No functional change
2021-06-04 14:07:46 +02:00
Stéphane Nicolet 4445965f97 Makefile: better "make clean" for Windows
Make clean should be really clean on Windows.

Fixes issue https://github.com/official-stockfish/Stockfish/issues/3291
Closes https://github.com/official-stockfish/Stockfish/pull/3517

No functional change
2021-06-04 01:32:11 +02:00
bmc4 0b7cc8bd2f Introducing NodeType Root
We transform rootNode into constexpr by adding a new NodeType `Root`,
which causes a speed up.

Local test:
```
Build Tester: 1.4.7.0
Windows 10 (Version 10.0, Build 0, 64-bit Edition)
Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
SafeMode: No
Running In VM: No
HyperThreading Enabled: Yes
CPU Warmup: Yes
Command Line: bench
Tests per Build: 25
ANOVA: n/a

                Engine# (NPS)                     Speedup     Sp     Conf. 95%    S.S.
patch  (920.179,4) ---> master  (906.329,2)  --->  1,528%  20.336,5     Yes        No
```

---------

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 98216 W: 8348 L: 8102 D: 81766
Ptnml(0-2): 295, 6357, 35549, 6621, 286
https://tests.stockfishchess.org/tests/view/60b797e2457376eb8bcaa0ab

Yellow LTC:
LLR: -2.95 (-2.94,2.94) <0.50,3.50>
Total: 76936 W: 2651 L: 2626 D: 71659
Ptnml(0-2): 29, 2233, 33916, 2264, 26
https://tests.stockfishchess.org/tests/view/60b80d6d457376eb8bcaa145

closes https://github.com/official-stockfish/Stockfish/pull/3522

No functional change
2021-06-04 01:23:49 +02:00
xoto10 9353e72103 Make extra time for bestMoveInstability dependent on rootdepth.
This change allocates more base time to moves and makes the additional time added for best move instability dependent on rootdepth.

STC 10+0.1 :
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 19432 W: 1711 L: 1553 D: 16168
Ptnml(0-2): 47, 1250, 6989, 1358, 72
https://tests.stockfishchess.org/tests/view/60b8cd41457376eb8bcaa1ad

LTC 60+0.6 :
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 22480 W: 810 L: 693 D: 20977
Ptnml(0-2): 9, 603, 9902, 714, 12
https://tests.stockfishchess.org/tests/view/60b8e5bf457376eb8bcaa1e6

closes https://github.com/official-stockfish/Stockfish/pull/3526

Bench 4364128
2021-06-03 21:22:56 +02:00
Joost VandeVondele d53071eff4 Update default net to nn-7e66505906a6.nnue
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

-------

Data generation command:

generate_training_data depth 9 count 31250000 random_multi_pv 2 random_multi_pv_diff 100 random_move_max_ply 8 random_move_count 3 set_recommended_uci_options eval_limit 32000 output_file_name output.binpack book wrongNNUE.epd seed ${RANDOM}${RANDOM}

Training command:

python train.py ../../all_d9_fishd9_d8_d10_wrong_shuffle.binpack ../../all_d9_fishd9_d8_d10_wrong_shuffle.binpack  --gpus 1 --threads 2 --num-workers 2 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^   --lambda=1.0  --max_epochs=400 --seed $RANDOM --default_root_dir exp/run_5

-------

passed STC:
https://tests.stockfishchess.org/tests/view/60b7c79a457376eb8bcaa104
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 64592 W: 6254 L: 6028 D: 52310
Ptnml(0-2): 255, 4785, 22020, 4951, 285

passed LTC:
https://tests.stockfishchess.org/tests/view/60b85307457376eb8bcaa182
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 45560 W: 1998 L: 1826 D: 41736
Ptnml(0-2): 36, 1604, 19335, 1762, 43

closes https://github.com/official-stockfish/Stockfish/pull/3521

Bench: 4364128
2021-06-03 16:25:44 +02:00
Stéphane Nicolet 4ada291429 Typography change for bench 2021-06-02 08:37:00 +02:00
Stefan Geschwentner 95f73ff393 Remove formerPV variable.
STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 75672 W: 6546 L: 6496 D: 62630
Ptnml(0-2): 238, 5274, 26761, 5326, 237
https://tests.stockfishchess.org/tests/view/60b349c0ec0c03148cbed055

LTC:
LLR: 2.98 (-2.94,2.94) <-2.50,0.50>
Total: 137816 W: 4676 L: 4689 D: 128451
Ptnml(0-2): 52, 4237, 60354, 4202, 63
https://tests.stockfishchess.org/tests/view/60b38970ec0c03148cbed075

closes https://github.com/official-stockfish/Stockfish/pull/3515

Bench: 4892288
2021-06-01 23:21:00 +02:00
J. Oster 9fd5b44d60 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.

Tested for no regression:

STC
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 25784 W: 2205 L: 2101 D: 21478
Ptnml(0-2): 62, 1660, 9368, 1716, 86
https://tests.stockfishchess.org/tests/view/60b516c6457376eb8bca9dfa

LTC
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 26200 W: 944 L: 878 D: 24378
Ptnml(0-2): 12, 732, 11545, 800, 11
https://tests.stockfishchess.org/tests/view/60b53652457376eb8bca9e0e

closes https://github.com/official-stockfish/Stockfish/pull/3516

No functional change.
2021-06-01 21:25:28 +02:00
candirufish e8418bb1b9 Check Extension with Static Evaluation
extension for checking moves, at higher depth and more decisive positions.

stc:
LLR: 2.97 (-2.94,2.94) <-0.50,2.50>
Total: 87008 W: 7337 L: 7100 D: 72571
Ptnml(0-2): 264, 5737, 31270, 5964, 269
https://tests.stockfishchess.org/tests/view/60b1034787a1a67ae56c47b6

ltc:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 79320 W: 2629 L: 2432 D: 74259
Ptnml(0-2): 29, 2205, 35000, 2392, 34
https://tests.stockfishchess.org/tests/view/60b1ae0b87a1a67ae56c487c

closes https://github.com/official-stockfish/Stockfish/pull/3514

Bench: 4447112
2021-05-31 18:31:32 +02:00
Tomasz Sobczyk 5448cad29e Fix export of the feature transformer.
PSQT export was missing.

fixes #3507

closes https://github.com/official-stockfish/Stockfish/pull/3508

No functional change
2021-05-30 21:31:58 +02:00
Joost VandeVondele 4c02998325 Simplify NNUE / classical evaluation selection
for the new network architecture these rules can be simplified,
closer to the original PSQT difference based again.

passed STC
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 22656 W: 1979 L: 1868 D: 18809
Ptnml(0-2): 70, 1496, 8087, 1603, 72
https://tests.stockfishchess.org/tests/view/60b24579db3c4776cb89d122

passed LTC
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 30224 W: 1015 L: 953 D: 28256
Ptnml(0-2): 4, 860, 13330, 906, 12
https://tests.stockfishchess.org/tests/view/60b27613db3c4776cb89d145

closes https://github.com/official-stockfish/Stockfish/pull/3511

Bench: 3937626
2021-05-30 21:30:15 +02:00
VoyagerOne 6174a37a37 Remove Stat Reset at beta cutoff
STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 63936 W: 5350 L: 5288 D: 53298
Ptnml(0-2): 184, 4295, 22954, 4345, 190
https://tests.stockfishchess.org/tests/view/60affb4c12066fd299795c64

LTC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 35856 W: 1201 L: 1142 D: 33513
Ptnml(0-2): 7, 1031, 15795, 1086, 9
https://tests.stockfishchess.org/tests/view/60b0537812066fd299795cc6

closes https://github.com/official-stockfish/Stockfish/pull/3505

bench: 3831936
2021-05-28 20:16:11 +02:00
Stéphane Nicolet f193778446 Do not use lazy evaluation inside NNUE
This simplification patch implements two changes:

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.

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 26280 W: 2244 L: 2137 D: 21899
Ptnml(0-2): 72, 1755, 9405, 1810, 98
https://tests.stockfishchess.org/tests/view/60ae73f112066fd299795a51

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 20592 W: 750 L: 677 D: 19165
Ptnml(0-2): 9, 614, 8980, 681, 12
https://tests.stockfishchess.org/tests/view/60ae88e812066fd299795a82

closes https://github.com/official-stockfish/Stockfish/pull/3503

Bench: 3817907
2021-05-27 01:21:56 +02:00
Stefan Geschwentner 1b325bf86d Less reduction for capture/promotions.
Exclude captures/promotions at expected cut nodes (which also not a
former PV node) from LMR if a response to the first previous
opponent move.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 288656 W: 24886 L: 24413 D: 239357
Ptnml(0-2): 900, 19738, 102578, 20213, 899
https://tests.stockfishchess.org/tests/view/60ad505112066fd29979595b

LTC:
LLR: 2.97 (-2.94,2.94) <0.50,3.50>
Total: 31344 W: 1107 L: 975 D: 29262
Ptnml(0-2): 12, 879, 13757, 1013, 11
https://tests.stockfishchess.org/tests/view/60adffce12066fd2997959d2

closes https://github.com/official-stockfish/Stockfish/pull/3500

Bench: 3827710
2021-05-26 17:32:54 +02:00
IIvec 83e0af288a Simplify the thread term for reduction formula
Dependance on Threads.size() was removed Search::init() for the Reductions[] initialization.

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 17376 W: 1024 L: 929 D: 15423
Ptnml(0-2): 24, 781, 6989, 864, 30
https://tests.stockfishchess.org/tests/view/60ac110812066fd2997957dc

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 145552 W: 3656 L: 3673 D: 138223
Ptnml(0-2): 37, 3351, 66014, 3340, 34
https://tests.stockfishchess.org/tests/view/60ac267412066fd299795825

closes https://github.com/official-stockfish/Stockfish/pull/3502

Bench 3864295
2021-05-26 17:25:05 +02:00
Tomasz Sobczyk 9d53129075 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.

closes https://github.com/official-stockfish/Stockfish/pull/3499

No functional change
2021-05-25 21:40:51 +02:00
bmc4 e044068b43 Increased reduction for captures in LMR
It now does, in LMR, an increased on reduction by 1 for captures in cut nodes.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 30656 W: 2565 L: 2397 D: 25694
Ptnml(0-2): 63, 2012, 11029, 2142, 82
https://tests.stockfishchess.org/tests/view/60a96733ce8ea25a3ef04178

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 124840 W: 4139 L: 3878 D: 116823
Ptnml(0-2): 48, 3480, 55100, 3747, 45
https://tests.stockfishchess.org/tests/view/60a995f5ce8ea25a3ef041b7

closes https://github.com/official-stockfish/Stockfish/pull/3494

bench: 3864295
2021-05-24 15:52:22 +02:00
Stéphane Nicolet a2f01c07eb 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.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 15936 W: 1421 L: 1266 D: 13249
Ptnml(0-2): 37, 1037, 5694, 1134, 66
https://tests.stockfishchess.org/tests/view/60a82df9ce8ea25a3ef0408f

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 13904 W: 516 L: 410 D: 12978
Ptnml(0-2): 4, 374, 6088, 484, 2
https://tests.stockfishchess.org/tests/view/60a8bbf9ce8ea25a3ef04101

closes https://github.com/official-stockfish/Stockfish/pull/3492

Bench: 3856635
2021-05-22 21:09:22 +02:00
bmc4 ff4c22238a Tuning Search
This patch tunes constant in search.cpp

STC:
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 30648 W: 2580 L: 2410 D: 25658
Ptnml(0-2): 80, 1969, 11093, 2065, 117
https://tests.stockfishchess.org/tests/view/60a71d3cce8ea25a3ef03fae

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.50>
Total: 52896 W: 1776 L: 1617 D: 49503
Ptnml(0-2): 13, 1462, 23347, 1605, 21
https://tests.stockfishchess.org/tests/view/60a794ddce8ea25a3ef0400a

closes https://github.com/official-stockfish/Stockfish/pull/3491

Bench: 4004731
2021-05-22 19:23:15 +02:00
bmc4 49c79aa15c Simplify reduction for consecutive fails
Revert the heuristic introduced in #3184, by which we reduced more
the late sons of the root position after consecutive fail highs.

---
Before new net architecture:

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 226336 W: 20373 L: 20500 D: 185463
Ptnml(0-2): 755, 16087, 79595, 15992, 739
https://tests.stockfishchess.org/tests/view/609dec205085663412d08e9d

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 67432 W: 2411 L: 2375 D: 62646
Ptnml(0-2): 33, 1944, 29714, 2004, 21
https://tests.stockfishchess.org/tests/view/609ee30f5085663412d08fc3

---
After new net architecture:

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 141752 W: 11591 L: 11617 D: 118544
Ptnml(0-2): 387, 9231, 51674, 9189, 395
https://tests.stockfishchess.org/tests/view/60a4320ace8ea25a3ef03cfd

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 294072 W: 9825 L: 9950 D: 274297
Ptnml(0-2): 121, 8610, 129681, 8521, 103
https://tests.stockfishchess.org/tests/view/60a51b5ece8ea25a3ef03dcd
---

closes https://github.com/official-stockfish/Stockfish/pull/3490

Bench: 3752892
2021-05-22 19:02:36 +02:00
Joost VandeVondele fb2d175f97 Update default net to nn-7756374aaed3.nnue
trained with pytorch using the master branch and recommended settings,
same data set as previously used:

python train.py ../../all_d9_fishd9_d8_d10_shuffle.binpack ../../all_d9_fishd9_d8_d10_shuffle.binpack \
        --gpus 1 --threads 2 --num-workers 2 --batch-size 16384 --progress_bar_refresh_rate 300 \
        --smart-fen-skipping --random-fen-skipping 3 --features=HalfKAv2^   --lambda=1.0 \
        --max_epochs=400 --seed $RANDOM --default_root_dir exp/run_8

passed STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 21424 W: 2078 L: 1907 D: 17439
Ptnml(0-2): 80, 1512, 7385, 1627, 108
https://tests.stockfishchess.org/tests/view/60a6c749ce8ea25a3ef03f4d

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 67912 W: 2851 L: 2648 D: 62413
Ptnml(0-2): 40, 2348, 28984, 2537, 47
https://tests.stockfishchess.org/tests/view/60a722ecce8ea25a3ef03fb9

closes https://github.com/official-stockfish/Stockfish/pull/3489

Bench: 3779522
2021-05-22 07:35:39 +02:00
Guy Vreuls f233ca1af4 Compact position structures
Reorder the structures data members in position.h to reduce padding.

Passed STC:
https://tests.stockfishchess.org/tests/view/60a8011fce8ea25a3ef04069
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 14120 W: 1214 L: 1067 D: 11839
Ptnml(0-2): 26, 857, 5161, 976, 40

---

Also tested for speed locally by Joost:

Result of  50 runs
==================
base (./stockfish.master       ) =    2254919  +/- 4439
test (./stockfish.patch        ) =    2274003  +/- 5278
diff                             =     +19084  +/- 6386
==================
speedup        = +0.0085
P(speedup > 0) =  1.0000

---

closes https://github.com/official-stockfish/Stockfish/pull/3488

No functional change.
2021-05-22 00:26:00 +02:00
Stéphane Nicolet 754fc8a8b5 Remove Tempo
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.

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 33512 W: 2805 L: 2709 D: 27998
Ptnml(0-2): 80, 2209, 12095, 2279, 93
https://tests.stockfishchess.org/tests/view/60a44ceace8ea25a3ef03d30

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 53920 W: 1807 L: 1760 D: 50353
Ptnml(0-2): 16, 1617, 23650, 1658, 19
https://tests.stockfishchess.org/tests/view/60a477f0ce8ea25a3ef03d49

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.

closes https://github.com/official-stockfish/Stockfish/pull/3481

Bench: 4015864
2021-05-19 20:34:37 +02:00
Vizvezdenec 2c3f7619f9 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.

passed STC
https://tests.stockfishchess.org/tests/view/60a40117ce8ea25a3ef03ca7
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 58976 W: 4875 L: 4807 D: 49294
Ptnml(0-2): 176, 3897, 21270, 3973, 172

passed LTC
https://tests.stockfishchess.org/tests/view/60a43ff8ce8ea25a3ef03d18
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 65272 W: 2203 L: 2165 D: 60904
Ptnml(0-2): 28, 1936, 28668, 1978, 26

closes https://github.com/official-stockfish/Stockfish/pull/3480

bench 4110764
2021-05-19 20:08:51 +02:00
Prokop Randáček 6b9a70ace8 Use if instead of goto
This PR inverts the if and removes goto in the generate_all function.

closes https://github.com/official-stockfish/Stockfish/pull/3461

No functional change
2021-05-19 19:38:44 +02:00
Fanael Linithien 038487f954 Use packed 32-bit MMX operations for updating the PSQT accumulator
This improves the speed of NNUE by a bit on old hardware that code path
is intended for, like a Pentium III 1.13 GHz:

10 repeats of "./stockfish bench 16 1 13 default depth NNUE":

Before:
54 642 504 897 cycles (± 0.12%)
62 301 937 829 instructions (± 0.03%)

After:
54 320 821 928 cycles (± 0.13%)
62 084 742 699 instructions (± 0.02%)

Speed of go depth 20 from startpos:

Before: 53103 nps
After: 53856 nps

closes https://github.com/official-stockfish/Stockfish/pull/3476

No functional change.
2021-05-19 19:34:44 +02:00
Yohaan Seth Nathan 0faf81d1f6 Use Markdown syntax in the readme
provide direct links to the mentioned files.

closes https://github.com/official-stockfish/Stockfish/pull/3477

No Functional Change
2021-05-19 19:34:44 +02:00
Vizvezdenec d37de3cb1d 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.

reduces strenght on STC
https://tests.stockfishchess.org/tests/view/60a3a8bbce8ea25a3ef03c74
ELO: -2.57 +-2.0 (95%) LOS: 0.6%
Total: 20000 W: 1820 L: 1968 D: 16212
Ptnml(0-2): 68, 1582, 6836, 1458, 56

Passed LTC with STC bounds
https://tests.stockfishchess.org/tests/view/60a027395085663412d090ce
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 175256 W: 6774 L: 6548 D: 161934
Ptnml(0-2): 91, 5808, 75604, 6034, 91

Passed VLTC with LTC bounds
https://tests.stockfishchess.org/tests/view/60a2bccce229097940a037a7
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 65736 W: 1224 L: 1092 D: 63420
Ptnml(0-2): 5, 1012, 30706, 1136, 9

closes https://github.com/official-stockfish/Stockfish/pull/3473

bench 3689330
2021-05-19 19:34:37 +02:00
Tomasz Sobczyk e8d64af123 New NNUE architecture and net
Introduces a new NNUE network architecture and associated network parameters,
as obtained by a new pytorch trainer.

The network is already very strong at short TC, without regression at longer TC,
and has potential for further improvements.

https://tests.stockfishchess.org/tests/view/60a159c65085663412d0921d
TC: 10s+0.1s, 1 thread
ELO: 21.74 +-3.4 (95%) LOS: 100.0%
Total: 10000 W: 1559 L: 934 D: 7507
Ptnml(0-2): 38, 701, 2972, 1176, 113

https://tests.stockfishchess.org/tests/view/60a187005085663412d0925b
TC: 60s+0.6s, 1 thread
ELO: 5.85 +-1.7 (95%) LOS: 100.0%
Total: 20000 W: 1381 L: 1044 D: 17575
Ptnml(0-2): 27, 885, 7864, 1172, 52

https://tests.stockfishchess.org/tests/view/60a2beede229097940a03806
TC: 20s+0.2s, 8 threads
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 34272 W: 1610 L: 1452 D: 31210
Ptnml(0-2): 30, 1285, 14350, 1439, 32

https://tests.stockfishchess.org/tests/view/60a2d687e229097940a03c72
TC: 60s+0.6s, 8 threads
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 45544 W: 1262 L: 1214 D: 43068
Ptnml(0-2): 12, 1129, 20442, 1177, 12

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

closes https://github.com/official-stockfish/Stockfish/pull/3474

Bench: 3806488
2021-05-18 18:06:23 +02:00
Stéphane Nicolet f90274d8ce Small clean-ups
- 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

closes https://github.com/official-stockfish/Stockfish/pull/3416

No functional change
2021-05-17 10:47:14 +02:00
Vizvezdenec 61e1c66b7c 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.

passed STC
https://tests.stockfishchess.org/tests/view/609e81f35085663412d08f31
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 28488 W: 2487 L: 2382 D: 23619
Ptnml(0-2): 87, 1919, 10123, 2032, 83

passed LTC
https://tests.stockfishchess.org/tests/view/609e9c085085663412d08f59
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 33176 W: 1219 L: 1155 D: 30802
Ptnml(0-2): 13, 1036, 14423, 1106, 10

closes https://github.com/official-stockfish/Stockfish/pull/3468

Bench: 4749514
2021-05-15 10:29:39 +02:00
bmc4 c82f6f56a6 Simplify LMR rules for statScore
We simplify two parts of LMR which seem not to bring strength anymore.

---

Individual Tests:
https://tests.stockfishchess.org/tests/view/609d1cc15085663412d0856a
https://tests.stockfishchess.org/tests/view/609cb0cc7746e3dc74ffae8d
https://tests.stockfishchess.org/tests/view/609d1c9f5085663412d08568

---

LTC:
LLR: 2.97 (-2.94,2.94) <-2.50,0.50>
Total: 84184 W: 3093 L: 3066 D: 78025
Ptnml(0-2): 47, 2755, 36458, 2788, 44
https://tests.stockfishchess.org/tests/view/609d84615085663412d08e2f

---

While at it, we also update the Elo estimate of the previous rule in LMR, see:
https://tests.stockfishchess.org/tests/view/609a933c3a33eb67a844f7ca
https://tests.stockfishchess.org/tests/view/609a959c3a33eb67a844f7d5
https://tests.stockfishchess.org/tests/view/609afff73a33eb67a844f870

---

closes https://github.com/official-stockfish/Stockfish/pull/3464

Bench: 4156523
2021-05-15 10:16:01 +02:00
bmc4 24b8b3098b Remove early return in Probcut code
We simplify away early return in ProbCut, as it seems not to bring any strength anymore.

STC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 42632 W: 3705 L: 3617 D: 35310
Ptnml(0-2): 123, 2947, 15110, 2991, 145
https://tests.stockfishchess.org/tests/view/609c49da7746e3dc74ffae02

LTC:
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 35384 W: 1314 L: 1251 D: 32819
Ptnml(0-2): 11, 1130, 15355, 1177, 19
https://tests.stockfishchess.org/tests/view/609c71467746e3dc74ffae47

---

While at it, we also update the Elo estimate of ProbCut
(see https://tests.stockfishchess.org/tests/view/609bfb597746e3dc74ffabe3).

closes https://github.com/official-stockfish/Stockfish/pull/3462

bench: 3764662
2021-05-15 10:07:40 +02:00
Unai Corzo bd756ee45c Remove BoolConditions from tuning code
Remove BoolConditions from tuning code, as the feature does not work
and the code has not be touched in years.

No functional change
2021-05-15 09:40:40 +02:00
bmc4 594e2ac999 Simplify LMR rule for non-checking captures
We simplify away the complicated rule in LMR for "non-checking captures
likely to be bad", as it seems not to bring any strength anymore.

STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 55256 W: 4972 L: 4897 D: 45387
Ptnml(0-2): 177, 3976, 19234, 4077, 164
https://tests.stockfishchess.org/tests/view/609adf3b3a33eb67a844f842

LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 10344 W: 437 L: 353 D: 9554
Ptnml(0-2): 1, 322, 4449, 392, 8
https://tests.stockfishchess.org/tests/view/609b3dfa3a33eb67a844f88e

--

While at it, we also update the Elo estimate of the previous rule in LMR
(see https://tests.stockfishchess.org/tests/view/609af2a63a33eb67a844f867).

closes https://github.com/official-stockfish/Stockfish/pull/3460

Bench: 3840688
2021-05-12 17:13:52 +02:00
EntityFX b62af7ac1e 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.

https://en.wikipedia.org/wiki/Elbrus_2000

closes https://github.com/official-stockfish/Stockfish/pull/3425

No functional change
2021-05-11 19:45:14 +02:00
bmc4 a0e2debe3f Remove coordination between searching threads
In summary, this revert #2204, as it seems not to bring any strength anymore, so it's no long needed.

STC (5+0.05 @ 8 threads):
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 105728 W: 6406 L: 6393 D: 92929
Ptnml(0-2): 154, 5479, 41599, 5464, 168
https://tests.stockfishchess.org/tests/view/6096994095e7f1852abd3154

LTC (20+0.2 @ 8 threads):
LLR: 2.96 (-2.94,2.94) <-2.50,0.50>
Total: 26336 W: 774 L: 712 D: 24850
Ptnml(0-2): 9, 641, 11810, 695, 13
https://tests.stockfishchess.org/tests/view/6097c62995e7f1852abd31e8

closes https://github.com/official-stockfish/Stockfish/pull/3459

No functional change.
2021-05-11 19:41:44 +02:00
bmc4 602687801b Simplify LMR
as it seems not to bring any strength and thus is no longer needed.

Tests for updating elo estimates:
https://tests.stockfishchess.org/tests/view/6099ff123a33eb67a844f789
https://tests.stockfishchess.org/tests/view/60953e6695e7f1852abd305b

Individual simplification tests:
https://tests.stockfishchess.org/tests/view/6098cfc73a33eb67a844f6a1
https://tests.stockfishchess.org/tests/view/6095539495e7f1852abd308b

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 96984 W: 3624 L: 3608 D: 89752
Ptnml(0-2): 45, 3222, 41939, 3244, 42
https://tests.stockfishchess.org/tests/view/6099921a3a33eb67a844f74f

closes https://github.com/official-stockfish/Stockfish/pull/3458

bench: 3836428
2021-05-11 19:37:39 +02:00
Tomasz Sobczyk 58054fd0fa 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.

closes https://github.com/official-stockfish/Stockfish/pull/3456

No functional change
2021-05-11 19:36:11 +02:00
Vizvezdenec d777ea79ff 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.

Passed simplification STC
https://tests.stockfishchess.org/tests/view/609148bf95e7f1852abd2e82
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 20128 W: 1865 L: 1751 D: 16512
Ptnml(0-2): 63, 1334, 7165, 1430, 72

Passed simplification LTC
https://tests.stockfishchess.org/tests/view/6091691295e7f1852abd2e8b
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 95128 W: 3498 L: 3481 D: 88149
Ptnml(0-2): 41, 2956, 41549, 2981, 37

closes https://github.com/official-stockfish/Stockfish/pull/3455

Bench: 3933037
2021-05-07 09:47:17 +02:00
Tomasz Sobczyk ca250e969c Add an UCI level command "export_net".
This command writes the embedded net to the file `EvalFileDefaultName`.
If there is no embedded net the command does nothing.

fixes #3453

closes https://github.com/official-stockfish/Stockfish/pull/3454

No functional change
2021-05-07 09:45:08 +02:00
Unai Corzo b1c8840f10 Simplify check extension
Simplify check extension, as it seems not to bring any strength and thus is no longer needed.

STC https://tests.stockfishchess.org/tests/view/608c18e995e7f1852abd2b81
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 54544 W: 4891 L: 4815 D: 44838
Ptnml(0-2): 186, 3889, 19081, 3895, 221

LTC https://tests.stockfishchess.org/tests/view/608c6ab195e7f1852abd2bc6
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 51008 W: 1845 L: 1794 D: 47369
Ptnml(0-2): 31, 1591, 22206, 1648, 28

closes https://github.com/official-stockfish/Stockfish/pull/3452

bench: 3993071
2021-05-02 17:48:57 +02:00
Joost VandeVondele 33fadb5118 Add some more information on the UCI protocol
Improve README.md: provide a link to the protocol,
and document some non-standard options.

fixes https://github.com/official-stockfish/Stockfish/issues/3446

closes https://github.com/official-stockfish/Stockfish/pull/3450

No functional change
2021-05-02 17:43:02 +02:00
xoto10 6ad4f485d3 Change tempo with time and threads
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.

STC 10+0.1:
LLR: 2.94 (-2.94,2.94) {-0.20,1.10}
Total: 120816 W: 11155 L: 10861 D: 98800
Ptnml(0-2): 406, 8728, 41933, 8848, 493
https://tests.stockfishchess.org/tests/view/60735b3a8141753378960534

LTC 60+0.6:
LLR: 2.94 (-2.94,2.94) {0.20,0.90}
Total: 35688 W: 1392 L: 1234 D: 33062
Ptnml(0-2): 23, 1079, 15473, 1255, 14
https://tests.stockfishchess.org/tests/view/6073ffbc814175337896057f

Passed non-regression SMP test at LTC 20+0.2 (8 threads):
LLR: 2.95 (-2.94,2.94) {-0.70,0.20}
Total: 11008 W: 317 L: 267 D: 10424
Ptnml(0-2): 2, 245, 4962, 291, 4
https://tests.stockfishchess.org/tests/view/60749ea881417533789605a4

closes https://github.com/official-stockfish/Stockfish/pull/3426

Bench 4075325
2021-04-28 13:58:46 +02:00
bmc4 84b42b3ab3 Simplify pawn moves generator
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.

STC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 112648 W: 9952 L: 9945 D: 92751
Ptnml(0-2): 369, 7682, 40195, 7729, 349
https://tests.stockfishchess.org/tests/view/6088226895e7f1852abd2978

LTC:
LLR: 2.93 (-2.94,2.94) <-2.50,0.50>
Total: 74656 W: 2797 L: 2765 D: 69094
Ptnml(0-2): 38, 2328, 32554, 2380, 28
https://tests.stockfishchess.org/tests/view/60884e5095e7f1852abd2994

closes https://github.com/official-stockfish/Stockfish/pull/3447

No functional change
2021-04-28 13:38:28 +02:00
lonfom169 33a858eaa1 More extensions if SE search is very low.
More extensions for non-PV nodes if value from singular extension search is significantly below singularBeta.

Passed STC:
LLR: 2.97 (-2.94,2.94) <-0.50,2.50>
Total: 25064 W: 2334 L: 2162 D: 20568
Ptnml(0-2): 82, 1720, 8768, 1868, 94
https://tests.stockfishchess.org/tests/view/6084ba7995e7f1852abd27e3

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.50>
Total: 67136 W: 2644 L: 2450 D: 62042
Ptnml(0-2): 46, 2134, 28990, 2376, 22
https://tests.stockfishchess.org/tests/view/6084d79195e7f1852abd27ee

closes https://github.com/official-stockfish/Stockfish/pull/3445

Bench: 4075325
2021-04-25 13:26:22 +02:00
Stefan Geschwentner c0ff241464 Thread based reduction tweak.
For PV nodes at the first two plies no reductions are done for each fourth thread.

STC (8 threads):
LLR: 2.94 (-2.94,2.94) <-0.50,2.50>
Total: 53992 W: 3334 L: 3167 D: 47491
Ptnml(0-2): 64, 2713, 21285, 2860, 74
https://tests.stockfishchess.org/tests/view/6083b2d695e7f1852abd277a

LTC (8 threads):
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 64888 W: 1888 L: 1725 D: 61275
Ptnml(0-2): 14, 1556, 29146, 1709, 19
https://tests.stockfishchess.org/tests/view/6084249595e7f1852abd2795

closes https://github.com/official-stockfish/Stockfish/pull/3443

No functional change (for one thread)
2021-04-25 13:21:57 +02:00
Tomasz Sobczyk b748b46714 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

Passed STC non-regression:
https://tests.stockfishchess.org/tests/view/608421dd95e7f1852abd2790
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 180008 W: 16186 L: 16258 D: 147564
Ptnml(0-2): 587, 12593, 63725, 12503, 596

closes https://github.com/official-stockfish/Stockfish/pull/3441

No functional change
2021-04-25 13:16:30 +02:00
bmc4 32d781769d Merge all move generators
Merging `generate<EVASIONS>` and `generate<QUIET_CHECKS>` into `generate_all()`.

verified to yield correct perft results, even though bench changes due to different order of generated moves.

No regresion playing games:

passed STC:
LLR: 2.94 (-2.94,2.94) {-1.00,0.20}
Total: 161800 W: 14585 L: 14624 D: 132591
Ptnml(0-2): 577, 11681, 56451, 11586, 605
https://tests.stockfishchess.org/tests/view/606532732b2df919fd5f026d

passed LTC:
LLR: 2.98 (-2.94,2.94) {-0.70,0.20}
Total: 188504 W: 6906 L: 6961 D: 174637
Ptnml(0-2): 87, 6272, 81610, 6175, 108
https://tests.stockfishchess.org/tests/view/6065b0772b2df919fd5f02ae

closes https://github.com/official-stockfish/Stockfish/pull/3418

Bench: 4536129
2021-04-24 12:55:33 +02:00
Tomasz Sobczyk fbbd4adc3c Unify naming convention of the NNUE code
matches the rest of the stockfish code base

closes https://github.com/official-stockfish/Stockfish/pull/3437

No functional change
2021-04-24 12:49:29 +02:00
dsmsgms a7ab92ec25 Use classical eval for Bishop vs Pawns
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).

STC:
LLR: 2.93 (-2.94,2.94) {-0.20,1.10}
Total: 33232 W: 6655 L: 6497 D: 20080
Ptnml(0-2): 4, 2342, 11769, 2494, 7
https://tests.stockfishchess.org/tests/view/6074a52981417533789605b8

LTC:
LLR: 2.93 (-2.94,2.94) {0.20,0.90}
Total: 159056 W: 29799 L: 29378 D: 99879
Ptnml(0-2): 7, 9004, 61085, 9425, 7
https://tests.stockfishchess.org/tests/view/6074c39a81417533789605ca

Closes https://github.com/official-stockfish/Stockfish/pull/3427

Bench: 4503918

blah
2021-04-15 12:45:39 +02:00
Tomasz Sobczyk 255514fb29 Documentation patch: AppendChangedIndices
Clarify the assumptions on the position passed to the AppendChangedIndices().

Closes https://github.com/official-stockfish/Stockfish/pull/3428

No functional change
2021-04-15 12:21:30 +02:00
Vizvezdenec 14d162d9f4 Simplification: last capture extension
The code for last capture extension can be removed in current master.

Passed STC
LLR: 2.95 (-2.94,2.94) {-1.00,0.20}
Total: 85024 W: 7754 L: 7707 D: 69563
Ptnml(0-2): 293, 5991, 29914, 6004, 310
https://tests.stockfishchess.org/tests/view/607690f1814175337896068f

Passed LTC
LLR: 2.96 (-2.94,2.94) {-0.70,0.20}
Total: 39880 W: 1503 L: 1453 D: 36924
Ptnml(0-2): 17, 1281, 17293, 1333, 16
https://tests.stockfishchess.org/tests/view/6076ccbe814175337896069e

Closes https://github.com/official-stockfish/Stockfish/pull/3430

Bench: 4202264
2021-04-15 11:41:30 +02:00
Stéphane Nicolet 4889cf22bb Revert previous patch
Revert the previous patch about move generation, as it unexpectedly
changed the bench. Better to take the time to understand the issue.

Bench: 4191632
2021-04-15 11:19:44 +02:00
bmc4 79bb28281c Merge all move generators
Merging `generate<EVASIONS>` and `generate<QUIET_CHECKS>` into `generate_all()`.

STC:
LLR: 2.94 (-2.94,2.94) {-1.00,0.20}
Total: 161800 W: 14585 L: 14624 D: 132591
Ptnml(0-2): 577, 11681, 56451, 11586, 605
https://tests.stockfishchess.org/tests/view/606532732b2df919fd5f026d

LTC:
LLR: 2.98 (-2.94,2.94) {-0.70,0.20}
Total: 188504 W: 6906 L: 6961 D: 174637
Ptnml(0-2): 87, 6272, 81610, 6175, 108
https://tests.stockfishchess.org/tests/view/6065b0772b2df919fd5f02ae

------------

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

```
./stockfish b3nch 16 1 6 fischer.txt perft
Nodes searched  : 506736009395
```

------------

Closes https://github.com/official-stockfish/Stockfish/pull/3418

No functional change
2021-04-15 10:53:51 +02:00
Vizvezdenec 3dfda1b28e Replace distanceFromPv with a better logic
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.

passed STC:
LLR: 2.95 (-2.94,2.94) {-0.20,1.10}
Total: 153008 W: 13913 L: 13579 D: 125516
Ptnml(0-2): 547, 10811, 53470, 11113, 563
https://tests.stockfishchess.org/tests/view/6069c9d02b2df919fd5f04d2

passed LTC:
LLR: 2.94 (-2.94,2.94) {0.20,0.90}
Total: 101920 W: 3964 L: 3699 D: 94257
Ptnml(0-2): 55, 3279, 44019, 3560, 47
https://tests.stockfishchess.org/tests/view/606a99fd2b2df919fd5f0532

Closes https://github.com/official-stockfish/Stockfish/pull/3421

Bench: 4191632
2021-04-06 18:23:35 +02:00
Stéphane Nicolet f40913f7f6 Keep more pawns
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.

STC:
LLR: 2.93 (-2.94,2.94) {-0.20,1.10}
Total: 42552 W: 3858 L: 3668 D: 35026
Ptnml(0-2): 152, 2956, 14876, 3134, 158
https://tests.stockfishchess.org/tests/view/606a06dd2b2df919fd5f0504

LTC:
LLR: 2.95 (-2.94,2.94) {0.20,0.90}
Total: 44328 W: 1703 L: 1531 D: 41094
Ptnml(0-2): 20, 1373, 19207, 1543, 21
https://tests.stockfishchess.org/tests/view/606aa4ec2b2df919fd5f053e

Closes https://github.com/official-stockfish/Stockfish/pull/3420

Bench: 4310076
2021-04-06 09:07:20 +02:00
Stéphane Nicolet b862c8d4be Small clean-up
Bench: 4321677
2021-03-31 08:12:25 +02:00
bmc4 c489df6f5b 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:

```
./stockfish
bench 16 1 6 default perft
Nodes searched: 71608931810

./stockfish
position fen 4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21
go perft 6
Nodes searched: 6136386434
```

Passed STC:
LLR: 2.94 (-2.94,2.94) {-1.00,0.20}
Total: 16072 W: 1473 L: 1349 D: 13250
Ptnml(0-2): 57, 1047, 5710, 1159, 63
https://tests.stockfishchess.org/tests/view/60629e7ef183b42957b423b1

Passed LTC:
LLR: 2.94 (-2.94,2.94) {-0.70,0.20}
Total: 59064 W: 2214 L: 2177 D: 54673
Ptnml(0-2): 26, 1944, 25556, 1979, 27
https://tests.stockfishchess.org/tests/view/6062dce4f183b42957b423de

closes https://github.com/official-stockfish/Stockfish/pull/3415

No functional change
2021-03-31 07:47:15 +02:00
mstembera 62a0b65ff8 Simplify and unify FRC cornered bishop.
tested locally as fishtest doesn't support FRC:

STC NNUE
9646 - 9647 - 20707 [0.500] 40000 -0.0 +/- 2.4, LOS: 49.7 %, DrawRatio: 51.8 %

STC classical
9678 - 9609 - 20713 [0.501] 40000 0.6 +/- 2.4, LOS: 69.0 %, DrawRatio: 51.8 %

and verified independently:

Score of master vs patch: 6463 - 6580 - 34957 [0.499] 48000

closes https://github.com/official-stockfish/Stockfish/pull/3413

bench: 4321677
2021-03-27 17:03:10 +01:00
Tomasz Sobczyk f28303d214 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

closes https://github.com/official-stockfish/Stockfish/pull/3373

No functional change.
2021-03-27 16:56:05 +01:00
Stéphane Nicolet 83eac08e75 Small cleanups (march 2021)
With help of @BM123499, @mstembera, @gvreuls, @noobpwnftw and @Fanael
Thanks!

Closes https://github.com/official-stockfish/Stockfish/pull/3405

No functional change
2021-03-24 17:11:06 +01:00
Guy Vreuls ec42154ef2 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.

Passed a non-regression STC test:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 21280 W: 1928 L: 1847 D: 17505
Ptnml(0-2): 71, 1427, 7558, 1518, 66
https://tests.stockfishchess.org/tests/view/6053a1e22433018de7a38e2f

We have verified that the generated binary is identical on gcc-10.

Closes https://github.com/official-stockfish/Stockfish/pull/3404

No functional change.
2021-03-19 20:28:57 +01:00
Vizvezdenec ace9632c67 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).

passed STC:
https://tests.stockfishchess.org/tests/view/604fa2532433018de7a38b67
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 30560 W: 2701 L: 2636 D: 25223
Ptnml(0-2): 88, 2056, 10921, 2133, 82

passed STC also in an earlier version:
https://tests.stockfishchess.org/tests/view/604f61282433018de7a38b4d

closes https://github.com/official-stockfish/Stockfish/pull/3398

No functional change
2021-03-19 11:58:17 +01:00
bmc4 5089061659 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).

Passed STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 18736 W: 1746 L: 1607 D: 15383
Ptnml(0-2): 61, 1226, 6644, 1387, 50
https://tests.stockfishchess.org/tests/view/60428c84ddcba5f0627bb6e4

Yellow LTC:
LTC:
LLR: -3.00 (-2.94,2.94) {0.25,1.25}
Total: 39144 W: 1431 L: 1413 D: 36300
Ptnml(0-2): 13, 1176, 17184, 1178, 21
https://tests.stockfishchess.org/tests/view/605128702433018de7a38ca1

Closes https://github.com/official-stockfish/Stockfish/pull/3397

---------

Verified for correctness by running perft on the following position:

./stockfish
position fen 4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21
go perft 6

Nodes searched: 6136386434

--------

No functional change
2021-03-18 00:21:41 +01:00
Vizvezdenec d58e83695f 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.

Passed STC
https://tests.stockfishchess.org/tests/view/6048c5842433018de7a387e6
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 34424 W: 3081 L: 3015 D: 28328
Ptnml(0-2): 110, 2442, 12052, 2488, 120

Passed LTC
https://tests.stockfishchess.org/tests/view/6048f7d22433018de7a387f0
LLR: 2.94 (-2.94,2.94) {-0.75,0.25}
Total: 142024 W: 5170 L: 5202 D: 131652
Ptnml(0-2): 50, 4678, 61613, 4596, 75

Closes https://github.com/official-stockfish/Stockfish/pull/3390

Bench: 4339126
2021-03-17 10:34:02 +01:00
bmc4 830f597134 Simplify move generation (2/2)
STC:
LLR: 2.97 (-2.94,2.94) {-1.25,0.25}
Total: 39352 W: 3551 L: 3493 D: 32308
Ptnml(0-2): 143, 2695, 13928, 2781, 129
https://tests.stockfishchess.org/tests/view/6050007a2433018de7a38bbb

LTC:
LLR: 2.96 (-2.94,2.94) {-0.75,0.25}
Total: 44944 W: 1629 L: 1596 D: 41719
Ptnml(0-2): 22, 1319, 19762, 1342, 27
https://tests.stockfishchess.org/tests/view/60500e892433018de7a38bc4

Closes https://github.com/official-stockfish/Stockfish/pull/3399

No functional change
2021-03-16 22:34:23 +01:00
bmc4 4b509559fb Simplify move generation (1/2)
STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 29792 W: 2611 L: 2545 D: 24636
Ptnml(0-2): 94, 1982, 10659, 2086, 75
https://tests.stockfishchess.org/tests/view/604fe5b62433018de7a38ba8

LTC:
LLR: 2.92 (-2.94,2.94) {-0.75,0.25}
Total: 22040 W: 826 L: 777 D: 20437
Ptnml(0-2): 8, 646, 9664, 693, 9
https://tests.stockfishchess.org/tests/view/604fec892433018de7a38bac

Closes https://github.com/official-stockfish/Stockfish/pull/3399

No functional change
2021-03-16 22:32:53 +01:00
bmc4 939395729c 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.

Passed STC:
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 213200 W: 19171 L: 18753 D: 175276
Ptnml(0-2): 680, 14513, 75831, 14861, 715
https://tests.stockfishchess.org/tests/view/604bc7632433018de7a38982

Closes https://github.com/official-stockfish/Stockfish/pull/3391

No functional change
2021-03-16 20:54:52 +01:00
Topologist f3b296c2e2 Change advanced pawn push threshold
A pawn push is now considered to be "advanced" if the relative destination
rank is > 6 (previously it was > 5). This affects the search heuristic.

Also remove an assert concerning en passant moves in qsearch().

STC:
LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 46744 W: 4224 L: 4040 D: 38480
Ptnml(0-2): 165, 3206, 16451, 3380, 170
https://tests.stockfishchess.org/tests/view/604746082433018de7a3872e

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 107840 W: 4198 L: 3892 D: 99750
Ptnml(0-2): 58, 3472, 46557, 3772, 61
https://tests.stockfishchess.org/tests/view/60475eae2433018de7a38737

Closes https://github.com/official-stockfish/Stockfish/pull/3389

Bench: 4796780
2021-03-10 12:32:53 +01:00
bmc4 b74274628c 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.

Passed STC:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 28176 W: 2506 L: 2437 D: 23233
Ptnml(0-2): 80, 1904, 10063, 1949, 92
https://tests.stockfishchess.org/tests/view/60421d18ddcba5f0627bb6a9

Passed LTC:
LLR: 2.93 (-2.94,2.94) {-0.75,0.25}
Total: 9704 W: 402 L: 341 D: 8961
Ptnml(0-2): 3, 279, 4230, 334, 6
https://tests.stockfishchess.org/tests/view/60422823ddcba5f0627bb6ae

closes https://github.com/official-stockfish/Stockfish/pull/3383

No functional change
2021-03-07 21:16:38 +01:00
mattginsberg 5346f1c6c7 Deal with commented lines in UCI input
commands starting with '#' as the first character will be ignored

closes https://github.com/official-stockfish/Stockfish/pull/3378

No functional change
2021-03-07 21:10:04 +01:00
noobpwnftw d4b864ff12 Do not try to use large pages on 32 bit Windows.
verified to work on windows XP.

fixes  #3379

closes https://github.com/official-stockfish/Stockfish/pull/3380

No functional change.
2021-03-07 20:02:11 +01:00
Dieter Dobbelaere 7ffae17f85 Add Stockfish namespace.
fixes #3350 and is a small cleanup that might make it easier to use SF
in separate projects, like a NNUE trainer or similar.

closes https://github.com/official-stockfish/Stockfish/pull/3370

No functional change.
2021-03-07 14:26:54 +01:00
Antoine Champion 9b1274aba3 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.

closes https://github.com/official-stockfish/Stockfish/pull/3328

No functional change
2021-03-07 14:05:01 +01:00
Stéphane Nicolet 0f3f5d85fb Introduce DistanceFromPV
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.

STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 54936 W: 5047 L: 4850 D: 45039
Ptnml(0-2): 183, 3907, 19075, 4136, 167
https://tests.stockfishchess.org/tests/view/6037b88e7f517a561bc4a392

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 49608 W: 1880 L: 1703 D: 46025
Ptnml(0-2): 22, 1514, 21555, 1691, 22
https://tests.stockfishchess.org/tests/view/6038271b7f517a561bc4a3cb

Closes https://github.com/official-stockfish/Stockfish/pull/3369

Bench: 5037279
2021-02-26 19:45:29 +01:00
Vizvezdenec 7c30091a92 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.

Passed STC
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 33440 W: 3056 L: 2891 D: 27493
Ptnml(0-2): 110, 2338, 11672, 2477, 123
https://tests.stockfishchess.org/tests/view/602cd1087f517a561bc49bda

Passed LTC
LLR: 2.98 (-2.94,2.94) {0.25,1.25}
Total: 10072 W: 401 L: 309 D: 9362
Ptnml(0-2): 2, 288, 4365, 378, 3
https://tests.stockfishchess.org/tests/view/602ceea57f517a561bc49bf0

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:

STC:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 26240 W: 2354 L: 2280 D: 21606
Ptnml(0-2): 85, 1763, 9372, 1793, 107
https://tests.stockfishchess.org/tests/view/602d86a87f517a561bc49c7a

LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 35304 W: 1299 L: 1256 D: 32749
Ptnml(0-2): 14, 1095, 15395, 1130, 18
https://tests.stockfishchess.org/tests/view/602d98d17f517a561bc49c83

Closes https://github.com/official-stockfish/Stockfish/pull/3362

Bench: 3830215
2021-02-20 22:49:39 +01:00
Vizvezdenec 6294db7514 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 :-)

STC:
https://tests.stockfishchess.org/tests/view/602f03d07f517a561bc49d40
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 67664 W: 6252 L: 6035 D: 55377
Ptnml(0-2): 256, 4799, 23527, 4972, 278

LTC:
https://tests.stockfishchess.org/tests/view/602f41697f517a561bc49d5a
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 26256 W: 1034 L: 906 D: 24316
Ptnml(0-2): 10, 804, 11377, 922, 15

Closes https://github.com/official-stockfish/Stockfish/pull/3363

Bench: 3957653
2021-02-20 22:22:07 +01:00
Stéphane Nicolet a31007c9e7 Restore development version
No functional change
2021-02-20 22:19:14 +01:00
74 changed files with 4926 additions and 2994 deletions
+65
View File
@@ -0,0 +1,65 @@
name: Report issue
description: Create a report to help us fix issues with the engine
body:
- type: textarea
attributes:
label: Describe the issue
description: A clear and concise description of what you're experiencing.
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
Steps to reproduce the behavior.
You can also use this section to paste the command line output.
placeholder: |
```
position startpos moves g2g4 e7e5 f2f3
go mate 1
info string NNUE evaluation using nn-6877cd24400e.nnue enabled
info depth 1 seldepth 1 multipv 1 score mate 1 nodes 33 nps 11000 tbhits 0 time 3 pv d8h4
bestmove d8h4
```
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Anything that will give us more context about the issue you are encountering.
You can also use this section to propose ideas on how to solve the issue.
validations:
required: false
- type: dropdown
attributes:
label: Operating system
options:
- All
- Windows
- Linux
- MacOS
- Android
- Other or N/A
validations:
required: true
- type: input
attributes:
label: Stockfish version
description: |
This can be found by running the engine.
You can also use the commit ID.
placeholder: Stockfish 15 / e6e324e
validations:
required: true
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Discord server
url: https://discord.gg/GWDRS3kU6R
about: Feel free to ask for support or have a chat with us in our Discord server!
- name: Discussions, Q&A, ideas, show us something...
url: https://github.com/official-stockfish/Stockfish/discussions/new
about: Do you have an idea for Stockfish? Do you want to show something that you made? Please open a discussion about it!
+21
View File
@@ -0,0 +1,21 @@
name: Stockfish
on:
push:
branches:
- master
- tools
- github_ci
pull_request:
branches:
- master
- tools
jobs:
Sanitizers:
uses: ./.github/workflows/stockfish_sanitizers.yml
Tests:
uses: ./.github/workflows/stockfish_test.yml
Compiles:
uses: ./.github/workflows/stockfish_compile_test.yml
Binaries:
if: github.ref == 'refs/heads/master'
uses: ./.github/workflows/stockfish_binaries.yml
+110
View File
@@ -0,0 +1,110 @@
name: Stockfish
on:
workflow_call:
jobs:
Stockfish:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EXT: ${{ matrix.config.ext }}
OS: ${{ matrix.config.os }}
BINARY: ${{ matrix.binaries }}
strategy:
matrix:
config:
- {
name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04,
compiler: g++,
comp: gcc,
shell: 'bash {0}'
}
- {
name: "MacOS 12 Apple Clang",
os: macos-12,
compiler: clang++,
comp: clang,
shell: 'bash {0}'
}
- {
name: "Windows 2022 Mingw-w64 GCC x86_64",
os: windows-2022,
compiler: g++,
comp: mingw,
msys_sys: 'mingw64',
msys_env: 'x86_64-gcc',
shell: 'msys2 {0}',
ext: .exe
}
binaries:
- x86-64
- x86-64-modern
- x86-64-avx2
exclude:
- binaries: x86-64-avx2
config: {os: macos-12}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download required linux packages
if: runner.os == 'Linux'
run: |
sudo apt update
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.config.msys_sys}}
install: mingw-w64-${{matrix.config.msys_env}} make git expect
- name: Download the used network from the fishtest framework
run: |
make net
- name: Check compiler
run: |
export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
$COMPILER -v
- name: Test help target
run: |
make help
# Compile profile guided builds
- name: Compile ${{ matrix.binaries }} build
run: |
make clean
make -j2 profile-build ARCH=$BINARY COMP=$COMP
strip ./stockfish$EXT
mv ./stockfish$EXT ../stockfish-$OS-$BINARY$EXT
- name: Remove non src files
run: rm -f *.o .depend *.nnue
- name: Create tar archive.
run: |
cd ..
mkdir stockfish
cp -r src stockfish/
cp stockfish-$OS-$BINARY$EXT stockfish/
cp "Top CPU Contributors.txt" stockfish/
cp Copying.txt stockfish/
cp AUTHORS stockfish/
tar -cvf stockfish-$OS-$BINARY.tar stockfish
- name: Upload binaries
uses: actions/upload-artifact@v3
with:
name: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }}
path: |
stockfish-${{ matrix.config.os }}-${{ matrix.binaries }}.tar
@@ -0,0 +1,115 @@
name: Stockfish
on:
workflow_call:
jobs:
Stockfish:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
strategy:
matrix:
config:
- {
name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04,
compiler: g++,
comp: gcc,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 Clang",
os: ubuntu-20.04,
compiler: clang++,
comp: clang,
shell: 'bash {0}'
}
- {
name: "MacOS 12 Apple Clang",
os: macos-12,
compiler: clang++,
comp: clang,
shell: 'bash {0}'
}
- {
name: "MacOS 12 GCC 11",
os: macos-12,
compiler: g++-11,
comp: gcc,
shell: 'bash {0}'
}
- {
name: "Windows 2022 Mingw-w64 GCC x86_64",
os: windows-2022,
compiler: g++,
comp: mingw,
msys_sys: 'mingw64',
msys_env: 'x86_64-gcc',
shell: 'msys2 {0}'
}
- {
name: "Windows 2022 Mingw-w64 Clang x86_64",
os: windows-2022,
compiler: clang++,
comp: clang,
msys_sys: 'clang64',
msys_env: 'clang-x86_64-clang',
shell: 'msys2 {0}'
}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.config.msys_sys}}
install: mingw-w64-${{matrix.config.msys_env}} make git expect
- name: Download the used network from the fishtest framework
run: |
make net
- name: Check compiler
run: |
export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
$COMPILER -v
- name: Test help target
run: |
make help
# x86-64 with newer extensions tests
- name: Compile x86-64-avx2 build
run: |
make clean
make -j2 ARCH=x86-64-avx2 build
- name: Compile x86-64-bmi2 build
run: |
make clean
make -j2 ARCH=x86-64-bmi2 build
- name: Compile x86-64-avx512 build
run: |
make clean
make -j2 ARCH=x86-64-avx512 build
- name: Compile x86-64-vnni512 build
run: |
make clean
make -j2 ARCH=x86-64-vnni512 build
- name: Compile x86-64-vnni256 build
run: |
make clean
make -j2 ARCH=x86-64-vnni256 build
@@ -0,0 +1,77 @@
name: Stockfish
on:
workflow_call:
jobs:
Stockfish:
name: ${{ matrix.sanitizers.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
matrix:
config:
- {
name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04,
compiler: g++,
comp: gcc,
shell: 'bash {0}'
}
sanitizers:
- {
name: Run with thread sanitizer,
make_option: sanitize=thread,
instrumented_option: sanitizer-thread
}
- {
name: Run with UB sanitizer,
make_option: sanitize=undefined,
instrumented_option: sanitizer-undefined
}
- {
name: Run under valgrind,
make_option: "",
instrumented_option: valgrind
}
- {
name: Run under valgrind-thread,
make_option: "",
instrumented_option: valgrind-thread
}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download required linux packages
run: |
sudo apt update
sudo apt install expect valgrind g++-multilib qemu-user
- name: Download the used network from the fishtest framework
run: |
make net
- name: Check compiler
run: |
export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
$COMPILER -v
- name: Test help target
run: |
make help
# Sanitizers
- name: ${{ matrix.sanitizers.name }}
run: |
export CXXFLAGS="-O1 -fno-inline"
make clean
make -j2 ARCH=x86-64-modern ${{ matrix.sanitizers.make_option }} debug=yes optimize=no build > /dev/null
../tests/instrumented.sh --${{ matrix.sanitizers.instrumented_option }}
+284
View File
@@ -0,0 +1,284 @@
name: Stockfish
on:
workflow_call:
jobs:
Stockfish:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
matrix:
config:
- {
name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04,
compiler: g++,
comp: gcc,
run_32bit_tests: true,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 Clang",
os: ubuntu-20.04,
compiler: clang++,
comp: clang,
run_32bit_tests: true,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 NDK armv8",
os: ubuntu-20.04,
compiler: aarch64-linux-android21-clang++,
comp: ndk,
run_armv8_tests: false,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 NDK armv7",
os: ubuntu-20.04,
compiler: armv7a-linux-androideabi21-clang++,
comp: ndk,
run_armv7_tests: false,
shell: 'bash {0}'
}
- {
name: "MacOS 12 Apple Clang",
os: macos-12,
compiler: clang++,
comp: clang,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "MacOS 12 GCC 11",
os: macos-12,
compiler: g++-11,
comp: gcc,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "Windows 2022 Mingw-w64 GCC x86_64",
os: windows-2022,
compiler: g++,
comp: mingw,
run_64bit_tests: true,
msys_sys: 'mingw64',
msys_env: 'x86_64-gcc',
shell: 'msys2 {0}'
}
- {
name: "Windows 2022 Mingw-w64 GCC i686",
os: windows-2022,
compiler: g++,
comp: mingw,
run_32bit_tests: true,
msys_sys: 'mingw32',
msys_env: 'i686-gcc',
shell: 'msys2 {0}'
}
- {
name: "Windows 2022 Mingw-w64 Clang x86_64",
os: windows-2022,
compiler: clang++,
comp: clang,
run_64bit_tests: true,
msys_sys: 'clang64',
msys_env: 'clang-x86_64-clang',
shell: 'msys2 {0}'
}
exclude:
- config:
{
name: "Ubuntu 20.04 NDK armv7"
}
- config:
{
name: "Ubuntu 20.04 NDK armv8"
}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download required linux packages
if: runner.os == 'Linux'
run: |
sudo apt update
sudo apt install expect valgrind g++-multilib qemu-user
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.config.msys_sys}}
install: mingw-w64-${{matrix.config.msys_env}} make git expect
- name: Download the used network from the fishtest framework
run: |
make net
- name: Extract the bench number from the commit history
run: |
git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
[ -s git_sig ] && echo "benchref=$(cat git_sig)" >> $GITHUB_ENV && echo "Reference bench:" $(cat git_sig) || echo "No bench found"
- name: Check compiler
run: |
export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
$COMPILER -v
- name: Test help target
run: |
make help
# x86-32 tests
- name: Test debug x86-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j2 ARCH=x86-32 optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32 build
../tests/signature.sh $benchref
- name: Test x86-32-sse41-popcnt build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32-sse41-popcnt build
../tests/signature.sh $benchref
- name: Test x86-32-sse2 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32-sse2 build
../tests/signature.sh $benchref
- name: Test general-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=general-32 build
../tests/signature.sh $benchref
# x86-64 tests
- name: Test debug x86-64-modern build
if: ${{ matrix.config.run_64bit_tests }}
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j2 ARCH=x86-64-modern optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-64-modern build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-modern build
../tests/signature.sh $benchref
- name: Test x86-64-ssse3 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-ssse3 build
../tests/signature.sh $benchref
- name: Test x86-64-sse3-popcnt build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-sse3-popcnt build
../tests/signature.sh $benchref
- name: Test x86-64 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64 build
../tests/signature.sh $benchref
- name: Test general-64 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j2 ARCH=general-64 build
../tests/signature.sh $benchref
# armv8 tests
- name: Test armv8 build
if: ${{ matrix.config.run_armv8_tests }}
run: |
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT
export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j2 ARCH=armv8 build
../tests/signature.sh $benchref
# armv7 tests
- name: Test armv7 build
if: ${{ matrix.config.run_armv7_tests }}
run: |
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT
export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j2 ARCH=armv7 build
../tests/signature.sh $benchref
- name: Test armv7-neon build
if: ${{ matrix.config.run_armv7_tests }}
run: |
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT
export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j2 ARCH=armv7-neon build
../tests/signature.sh $benchref
# Other tests
- name: Check perft and search reproducibility
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-modern build
../tests/perft.sh
../tests/reprosearch.sh
-101
View File
@@ -1,101 +0,0 @@
language: cpp
dist: bionic
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
packages: ['g++-8', 'g++-8-multilib', 'g++-multilib', 'valgrind', 'expect', 'curl']
env:
- COMPILER=g++-8
- COMP=gcc
- os: linux
compiler: clang
addons:
apt:
packages: ['clang-10', 'llvm-10-dev', 'g++-multilib', 'valgrind', 'expect', 'curl']
env:
- COMPILER=clang++-10
- COMP=clang
- os: osx
osx_image: xcode12
compiler: gcc
env:
- COMPILER=g++
- COMP=gcc
- os: osx
osx_image: xcode12
compiler: clang
env:
- COMPILER=clang++
- COMP=clang
branches:
only:
- master
before_script:
- cd src
script:
# Download net
- make net
# Obtain bench reference from git log
- git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
- export benchref=$(cat git_sig)
- echo "Reference bench:" $benchref
# Compiler version string
- $COMPILER -v
# test help target
- make help
# Verify bench number against various builds
- export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
- make clean && make -j2 ARCH=x86-64-modern optimize=no debug=yes build && ../tests/signature.sh $benchref
- export CXXFLAGS="-Werror"
- make clean && make -j2 ARCH=x86-64-modern build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64-ssse3 build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64-sse3-popcnt build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=general-64 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32-sse41-popcnt build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32-sse2 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=general-32 build && ../tests/signature.sh $benchref; fi
# workaround: exclude a custom version of llvm+clang, which doesn't find llvm-profdata on ubuntu
- if [[ "$TRAVIS_OS_NAME" != "linux" || "$COMP" == "gcc" ]]; then make clean && make -j2 ARCH=x86-64-modern profile-build && ../tests/signature.sh $benchref; fi
# compile only for some more advanced architectures (might not run in travis)
- make clean && make -j2 ARCH=x86-64-avx2 build
- make clean && make -j2 ARCH=x86-64-bmi2 build
- make clean && make -j2 ARCH=x86-64-avx512 build
- make clean && make -j2 ARCH=x86-64-vnni512 build
- make clean && make -j2 ARCH=x86-64-vnni256 build
#
# Check perft and reproducible search
- make clean && make -j2 ARCH=x86-64-modern build
- ../tests/perft.sh
- ../tests/reprosearch.sh
#
# Valgrind
#
- export CXXFLAGS="-O1 -fno-inline"
- if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64-modern debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
- if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi
#
# Sanitizer
#
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-64-modern sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-64-modern sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
+29 -5
View File
@@ -1,4 +1,4 @@
# List of authors for Stockfish, as of August 4, 2020 # List of authors for Stockfish
# Founders of the Stockfish project and fishtest infrastructure # Founders of the Stockfish project and fishtest infrastructure
Tord Romstad (romstad) Tord Romstad (romstad)
@@ -21,35 +21,45 @@ Alexander Kure
Alexander Pagel (Lolligerhans) Alexander Pagel (Lolligerhans)
Alfredo Menezes (lonfom169) Alfredo Menezes (lonfom169)
Ali AlZhrani (Cooffe) Ali AlZhrani (Cooffe)
Andrei Vetrov (proukornew)
Andrew Grant (AndyGrant) Andrew Grant (AndyGrant)
Andrey Neporada (nepal) Andrey Neporada (nepal)
Andy Duplain Andy Duplain
Antoine Champion (antoinechampion)
Aram Tumanian (atumanian) Aram Tumanian (atumanian)
Arjun Temurnikar Arjun Temurnikar
Artem Solopiy (EntityFX)
Auguste Pop Auguste Pop
Balint Pfliegel Balint Pfliegel
Ben Chaney (Chaneybenjamini)
Ben Koshy (BKSpurgeon) Ben Koshy (BKSpurgeon)
Bill Henry (VoyagerOne) Bill Henry (VoyagerOne)
Bojun Guo (noobpwnftw, Nooby) Bojun Guo (noobpwnftw, Nooby)
Boštjan Mejak (PedanticHacker)
braich braich
Brian Sheppard (SapphireBrand, briansheppard-toast) Brian Sheppard (SapphireBrand, briansheppard-toast)
Bruno de Melo Costa (BM123499) Bruno de Melo Costa (BM123499)
Bruno Pellanda (pellanda)
Bryan Cross (crossbr) Bryan Cross (crossbr)
candirufish candirufish
Chess13234 Chess13234
Chris Cain (ceebo) Chris Cain (ceebo)
clefrks
Dale Weiler (graphitemaster) Dale Weiler (graphitemaster)
Dan Schmidt (dfannius) Dan Schmidt (dfannius)
Daniel Axtens (daxtens) Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic) Daniel Dugovic (ddugovic)
Dariusz Orzechowski (dorzechowski) Dariusz Orzechowski (dorzechowski)
David Zar David Zar
David (dav1312)
Daylen Yang (daylen) Daylen Yang (daylen)
Deshawn Mohan-Smith (GoldenRare) Deshawn Mohan-Smith (GoldenRare)
Dieter Dobbelaere (ddobbelaere) Dieter Dobbelaere (ddobbelaere)
DiscanX DiscanX
Dominik Schlösser (domschl) Dominik Schlösser (domschl)
double-beep double-beep
Douglas Matos Gomes (dsmsgms)
Dubslow
Eduardo Cáceres (eduherminio) Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender) Eelco de Groot (KingDefender)
Elvin Liu (solarlight2) Elvin Liu (solarlight2)
@@ -66,6 +76,7 @@ gamander
Gary Heckman (gheckman) Gary Heckman (gheckman)
George Sobala (gsobala) George Sobala (gsobala)
gguliash gguliash
Giacomo Lorenzetti (G-Lorenz)
Gian-Carlo Pascutto (gcp) Gian-Carlo Pascutto (gcp)
Gontran Lemaire (gonlem) Gontran Lemaire (gonlem)
Goodkov Vasiliy Aleksandrovich (goodkov) Goodkov Vasiliy Aleksandrovich (goodkov)
@@ -80,7 +91,7 @@ Hongzhi Cheng
Ivan Ivec (IIvec) Ivan Ivec (IIvec)
Jacques B. (Timshel) Jacques B. (Timshel)
Jan Ondruš (hxim) Jan Ondruš (hxim)
Jared Kish (Kurtbusch) Jared Kish (Kurtbusch, kurt22i)
Jarrod Torriero (DU-jdto) Jarrod Torriero (DU-jdto)
Jean Gauthier (OuaisBla) Jean Gauthier (OuaisBla)
Jean-Francois Romang (jromang) Jean-Francois Romang (jromang)
@@ -93,16 +104,19 @@ Joost VandeVondele (vondele)
Jörg Oster (joergoster) Jörg Oster (joergoster)
Joseph Ellis (jhellis3) Joseph Ellis (jhellis3)
Joseph R. Prostko Joseph R. Prostko
Julian Willemer (NightlyKing)
jundery jundery
Justin Blanchard (UncombedCoconut) Justin Blanchard (UncombedCoconut)
Kelly Wilson Kelly Wilson
Ken Takusagawa Ken Takusagawa
Kian E (KJE-98)
kinderchocolate kinderchocolate
Kiran Panditrao (Krgp) Kiran Panditrao (Krgp)
Kojirion Kojirion
Krystian Kuzniarek (kuzkry) Krystian Kuzniarek (kuzkry)
Leonardo Ljubičić (ICCF World Champion) Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--) Leonid Pechenik (lp--)
Liam Keegan (lkeegan)
Linus Arver (listx) Linus Arver (listx)
loco-loco loco-loco
Lub van den Berg (ElbertoOne) Lub van den Berg (ElbertoOne)
@@ -116,6 +130,7 @@ marotear
Matt Ginsberg (mattginsberg) Matt Ginsberg (mattginsberg)
Matthew Lai (matthewlai) Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916) Matthew Sullivan (Matt14916)
Max A. (Disservin)
Maxim Molchanov (Maxim) Maxim Molchanov (Maxim)
Michael An (man) Michael An (man)
Michael Byrne (MichaelB7) Michael Byrne (MichaelB7)
@@ -125,6 +140,7 @@ Michael Whiteley (protonspring)
Michel Van den Bergh (vdbergh) Michel Van den Bergh (vdbergh)
Miguel Lahoz (miguel-l) Miguel Lahoz (miguel-l)
Mikael Bäckman (mbootsector) Mikael Bäckman (mbootsector)
Mike Babigian (Farseer)
Mira Mira
Miroslav Fontán (Hexik) Miroslav Fontán (Hexik)
Moez Jellouli (MJZ1977) Moez Jellouli (MJZ1977)
@@ -137,6 +153,7 @@ Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham) Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather) Norman Schmidt (FireFather)
notruck notruck
Ofek Shochat (OfekShochat, ghostway)
Ondrej Mosnáček (WOnder93) Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin Oskar Werkelin Ahlin
Pablo Vazquez Pablo Vazquez
@@ -144,19 +161,21 @@ Panthee
Pascal Romaret Pascal Romaret
Pasquale Pigazzini (ppigazzini) Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere) Patrick Jansen (mibere)
pellanda Peter Schneider (pschneider1968)
Peter Zsifkovits (CoffeeOne) Peter Zsifkovits (CoffeeOne)
Praveen Kumar Tummala (praveentml) Praveen Kumar Tummala (praveentml)
Rahul Dsilva (silversolver1) Rahul Dsilva (silversolver1)
Ralph Stößer (Ralph Stoesser) Ralph Stößer (Ralph Stoesser)
Raminder Singh Raminder Singh
renouve renouve
Reuven Peleg Reuven Peleg (R-Peleg)
Richard Lloyd Richard Lloyd (Richard-Lloyd)
Rodrigo Exterckötter Tjäder Rodrigo Exterckötter Tjäder
Rodrigo Roim (roim)
Ron Britvich (Britvich) Ron Britvich (Britvich)
Ronald de Man (syzygy1, syzygy) Ronald de Man (syzygy1, syzygy)
rqs rqs
Rui Coelho (ruicoelhopedro)
Ryan Schmitt Ryan Schmitt
Ryan Takker Ryan Takker
Sami Kiminki (skiminki) Sami Kiminki (skiminki)
@@ -167,10 +186,13 @@ Sergio Vieri (sergiovieri)
sf-x sf-x
Shane Booth (shane31) Shane Booth (shane31)
Shawn Varghese (xXH4CKST3RXx) Shawn Varghese (xXH4CKST3RXx)
Siad Daboul (Topologist)
Stefan Geschwentner (locutus2) Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80) Stefano Cardanobile (Stefano80)
Steinar Gunderson (sesse) Steinar Gunderson (sesse)
Stéphane Nicolet (snicolet) Stéphane Nicolet (snicolet)
Syine Mineta (MinetaS)
Prokop Randáček (ProkopRandacek)
Thanar2 Thanar2
thaspel thaspel
theo77186 theo77186
@@ -178,11 +200,13 @@ Tom Truscott
Tom Vijlbrief (tomtor) Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97) Tomasz Sobczyk (Sopel97)
Torsten Franz (torfranz, tfranzer) Torsten Franz (torfranz, tfranzer)
Torsten Hellwig (Torom)
Tracey Emery (basepr1me) Tracey Emery (basepr1me)
tttak tttak
Unai Corzo (unaiic) Unai Corzo (unaiic)
Uri Blass (uriblass) Uri Blass (uriblass)
Vince Negri (cuddlestmonkey) Vince Negri (cuddlestmonkey)
xefoci7612
zz4032 zz4032
+147 -69
View File
@@ -1,41 +1,62 @@
<div align="center">
[![Stockfish][stockfish128-logo]][website-link]
[![Build][build-badge]][build-link]
[![License][license-badge]][license-link]
<br>
[![Release][release-badge]][release-link]
[![Commits][commits-badge]][commits-link]
<br>
[![Website][website-badge]][website-link]
[![Fishtest][fishtest-badge]][fishtest-link]
[![Discord][discord-badge]][discord-link]
</div>
## Overview ## Overview
[![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish) [Stockfish][website-link] is a free, powerful UCI chess engine derived from
[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master) Glaurung 2.1. Stockfish is not a complete chess program and requires a UCI-compatible
graphical user interface (GUI) (e.g. XBoard with PolyGlot, Scid, Cute Chess, eboard,
[Stockfish](https://stockfishchess.org) is a free, powerful UCI chess engine Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in order to be used comfortably.
derived from Glaurung 2.1. Stockfish is not a complete chess program and requires a Read the documentation for your GUI of choice for information about how to use
UCI-compatible graphical user interface (GUI) (e.g. XBoard with PolyGlot, Scid, Stockfish with it.
Cute Chess, eboard, Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in order
to be used comfortably. Read the documentation for your GUI of choice for information
about how to use Stockfish with it.
The Stockfish engine features two evaluation functions for chess, the classical
evaluation based on handcrafted terms, and the NNUE evaluation based on efficiently
updatable neural networks. The classical evaluation runs efficiently on almost all
CPU architectures, while the NNUE evaluation benefits from the vector
intrinsics available on most CPUs (sse2, avx2, neon, or similar).
The Stockfish engine features two evaluation functions for chess. The efficiently
updatable neural network (NNUE) based evaluation is the default and by far the strongest.
The classical evaluation based on handcrafted terms remains available. The strongest
network is integrated in the binary and downloaded automatically during the build process.
The NNUE evaluation benefits from the vector intrinsics available on most CPUs (sse2,
avx2, neon, or similar).
## Files ## Files
This distribution of Stockfish consists of the following files: This distribution of Stockfish consists of the following files:
* Readme.md, the file you are currently reading. * [README.md][readme-link], the file you are currently reading.
* Copying.txt, a text file containing the GNU General Public License version 3. * [Copying.txt][license-link], a text file containing the GNU General Public License
version 3.
* AUTHORS, a text file with the list of authors for the project
* src, a subdirectory containing the full source code, including a Makefile * [AUTHORS][authors-link], a text file with the list of authors for the project.
* [src][src-link], a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems. that can be used to compile Stockfish on Unix-like systems.
* a file with the .nnue extension, storing the neural network for the NNUE * a file with the .nnue extension, storing the neural network for the NNUE evaluation.
evaluation. Binary distributions will have this file embedded. Binary distributions will have this file embedded.
## UCI options ## The UCI protocol and available options
Currently, Stockfish has the following UCI options: The Universal Chess Interface (UCI) is a standard protocol used to communicate with
a chess engine, and is the recommended way to do so for typical graphical user interfaces
(GUI) or chess tools. Stockfish implements the majority of its options as described
in [the UCI protocol][uci-link].
Developers can see the default values for UCI options available in Stockfish by typing
`./stockfish uci` in a terminal, but the majority of users will typically see them and
change them via a chess GUI. This is a list of available UCI options in Stockfish:
* #### Threads * #### Threads
The number of CPU threads used for searching a position. For best performance, set The number of CPU threads used for searching a position. For best performance, set
@@ -61,9 +82,9 @@ Currently, Stockfish has the following UCI options:
* #### EvalFile * #### EvalFile
The name of the file of the NNUE evaluation parameters. Depending on the GUI the The name of the file of the NNUE evaluation parameters. Depending on the GUI the
filename might have to include the full path to the folder/directory that contains the file. filename might have to include the full path to the folder/directory that contains
Other locations, such as the directory that contains the binary and the working directory, the file. Other locations, such as the directory that contains the binary and the
are also searched. working directory, are also searched.
* #### UCI_AnalyseMode * #### UCI_AnalyseMode
An option handled by your GUI. An option handled by your GUI.
@@ -96,7 +117,7 @@ Currently, Stockfish has the following UCI options:
Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6` Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6`
It is recommended to store .rtbw files on an SSD. There is no loss in storing It is recommended to store .rtbw files on an SSD. There is no loss in storing
the .rtbz files on a regular HD. It is recommended to verify all md5 checksums the .rtbz files on a regular HDD. It is recommended to verify all md5 checksums
of the downloaded tablebase files (`md5sum -c checksum.md5`) as corruption will of the downloaded tablebase files (`md5sum -c checksum.md5`) as corruption will
lead to engine crashes. lead to engine crashes.
@@ -113,14 +134,6 @@ Currently, Stockfish has the following UCI options:
Limit Syzygy tablebase probing to positions with at most this many pieces left Limit Syzygy tablebase probing to positions with at most this many pieces left
(including kings and pawns). (including kings and pawns).
* #### Contempt
A positive value for contempt favors middle game positions and avoids draws,
effective for the classical evaluation only.
* #### Analysis Contempt
By default, contempt is set to prefer the side to move. Set this option to "White"
or "Black" to analyse with contempt for that side, or "Off" to disable contempt.
* #### Move Overhead * #### Move Overhead
Assume a time delay of x ms due to network and GUI overheads. This is useful to Assume a time delay of x ms due to network and GUI overheads. This is useful to
avoid losses on time in those cases. avoid losses on time in those cases.
@@ -136,6 +149,35 @@ Currently, Stockfish has the following UCI options:
* #### Debug Log File * #### Debug Log File
Write all communication to and from the engine into a text file. Write all communication to and from the engine into a text file.
For developers the following non-standard commands might be of interest, mainly useful for debugging:
* #### bench *ttSize threads limit fenFile limitType evalType*
Performs a standard benchmark using various options. The signature of a version
(standard node count) is obtained using all defaults. `bench` is currently
`bench 16 1 13 default depth mixed`.
* #### compiler
Give information about the compiler and environment used for building a binary.
* #### d
Display the current position, with ascii art and fen.
* #### eval
Return the evaluation of the current position.
* #### export_net [filename]
Exports the currently loaded network to a file.
If the currently loaded network is the embedded network and the filename
is not specified then the network is saved to the file matching the name
of the embedded network, as defined in evaluate.h.
If the currently loaded network is not the embedded network (some net set
through the UCI setoption) then the filename parameter is required and the
network is saved into that file.
* #### flip
Flips the side to move.
## A note on classical evaluation versus NNUE evaluation ## A note on classical evaluation versus NNUE evaluation
Both approaches assign a value to a position that is used in alpha-beta (PVS) search Both approaches assign a value to a position that is used in alpha-beta (PVS) search
@@ -148,22 +190,25 @@ on the evaluations of millions of positions at moderate search depth.
The NNUE evaluation was first introduced in shogi, and ported to Stockfish afterward. The NNUE evaluation was first introduced in shogi, and ported to Stockfish afterward.
It can be evaluated efficiently on CPUs, and exploits the fact that only parts It can be evaluated efficiently on CPUs, and exploits the fact that only parts
of the neural network need to be updated after a typical chess move. of the neural network need to be updated after a typical chess move.
[The nodchip repository](https://github.com/nodchip/Stockfish) provides additional [The nodchip repository][nodchip-link] provided the first version of the needed tools
tools to train and develop the NNUE networks. On CPUs supporting modern vector instructions to train and develop the NNUE networks. Today, more advanced training tools are
(avx2 and similar), the NNUE evaluation results in much stronger playing strength, even available in [the nnue-pytorch repository][pytorch-link], while data generation tools
if the nodes per second computed by the engine is somewhat lower (roughly 80% of nps are available in [a dedicated branch][tools-link].
is typical).
On CPUs supporting modern vector instructions (avx2 and similar), the NNUE evaluation
results in much stronger playing strength, even if the nodes per second computed by
the engine is somewhat lower (roughly 80% of nps is typical).
Notes: Notes:
1) the NNUE evaluation depends on the Stockfish binary and the network parameter 1) the NNUE evaluation depends on the Stockfish binary and the network parameter file
file (see the EvalFile UCI option). Not every parameter file is compatible with a given (see the EvalFile UCI option). Not every parameter file is compatible with a given
Stockfish binary, but the default value of the EvalFile UCI option is the name of a network Stockfish binary, but the default value of the EvalFile UCI option is the name of a
that is guaranteed to be compatible with that binary. network that is guaranteed to be compatible with that binary.
2) to use the NNUE evaluation, the additional data file with neural network parameters 2) to use the NNUE evaluation, the additional data file with neural network parameters
needs to be available. Normally, this file is already embedded in the binary or it needs to be available. Normally, this file is already embedded in the binary or it can
can be downloaded. The filename for the default (recommended) net can be found as the default be downloaded. The filename for the default (recommended) net can be found as the default
value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue` value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue`
(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from (for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from
``` ```
@@ -175,7 +220,7 @@ replacing `[filename]` as needed.
If the engine is searching a position that is not in the tablebases (e.g. If the engine is searching a position that is not in the tablebases (e.g.
a position with 8 pieces), it will access the tablebases during the search. a position with 8 pieces), it will access the tablebases during the search.
If the engine reports a very large score (typically 153.xx), this means If the engine reports a very large score (typically 153.xx), this means
it has found a winning line into a tablebase position. it has found a winning line into a tablebase position.
If the engine is given a position to search that is in the tablebases, it If the engine is given a position to search that is in the tablebases, it
@@ -214,8 +259,8 @@ are already enabled, and no configuration is needed.
### Support on Windows ### Support on Windows
The use of large pages requires "Lock Pages in Memory" privilege. See The use of large pages requires "Lock Pages in Memory" privilege. See
[Enable the Lock Pages in Memory Option (Windows)](https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows) [Enable the Lock Pages in Memory Option (Windows)][lockpages-link]
on how to enable this privilege, then run [RAMMap](https://docs.microsoft.com/en-us/sysinternals/downloads/rammap) on how to enable this privilege, then run [RAMMap][rammap-link]
to double-check that large pages are used. We suggest that you reboot to double-check that large pages are used. We suggest that you reboot
your computer after you have enabled large pages, because long Windows your computer after you have enabled large pages, because long Windows
sessions suffer from memory fragmentation, which may prevent Stockfish sessions suffer from memory fragmentation, which may prevent Stockfish
@@ -242,9 +287,9 @@ When not using the Makefile to compile (for instance, with Microsoft MSVC) you
need to manually set/unset some switches in the compiler command line; see need to manually set/unset some switches in the compiler command line; see
file *types.h* for a quick reference. file *types.h* for a quick reference.
When reporting an issue or a bug, please tell us which version and When reporting an issue or a bug, please tell us which Stockfish version
compiler you used to create your executable. These informations can and which compiler you used to create your executable. This information
be found by typing the following commands in a console: can be found by typing the following command in a console:
``` ```
./stockfish compiler ./stockfish compiler
@@ -252,32 +297,32 @@ be found by typing the following commands in a console:
## Understanding the code base and participating in the project ## Understanding the code base and participating in the project
Stockfish's improvement over the last couple of years has been a great Stockfish's improvement over the last decade has been a great community
community effort. There are a few ways to help contribute to its growth. effort. There are a few ways to help contribute to its growth.
### Donating hardware ### Donating hardware
Improving Stockfish requires a massive amount of testing. You can donate Improving Stockfish requires a massive amount of testing. You can donate
your hardware resources by installing the [Fishtest Worker](https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview) your hardware resources by installing the [Fishtest Worker][worker-link]
and view the current tests on [Fishtest](https://tests.stockfishchess.org/tests). and view the current tests on [Fishtest][fishtest-link].
### Improving the code ### Improving the code
If you want to help improve the code, there are several valuable resources: If you want to help improve the code, there are several valuable resources:
* [In this wiki,](https://www.chessprogramming.org) many techniques used in * [In this wiki,][programming-link] many techniques used in
Stockfish are explained with a lot of background information. Stockfish are explained with a lot of background information.
* [The section on Stockfish](https://www.chessprogramming.org/Stockfish) * [The section on Stockfish][programmingsf-link]
describes many features and techniques used by Stockfish. However, it is describes many features and techniques used by Stockfish. However, it is
generic rather than being focused on Stockfish's precise implementation. generic rather than being focused on Stockfish's precise implementation.
Nevertheless, a helpful resource. Nevertheless, a helpful resource.
* The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish). * The latest source can always be found on [GitHub][github-link].
Discussions about Stockfish take place these days mainly in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking) Discussions about Stockfish take place these days mainly in the [FishCooking][fishcooking-link]
group and on the [Stockfish Discord channel](https://discord.gg/nv8gDtt). group and on the [Stockfish Discord channel][discord-link].
The engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests). The engine testing is done on [Fishtest][fishtest-link].
If you want to help improve Stockfish, please read this [guideline](https://github.com/glinscott/fishtest/wiki/Creating-my-first-test) If you want to help improve Stockfish, please read this [guideline][guideline-link]
first, where the basics of Stockfish development are explained. first, where the basics of Stockfish development are explained.
@@ -291,10 +336,43 @@ it (either by itself or as part of some bigger software package), or
using it as the starting point for a software project of your own. using it as the starting point for a software project of your own.
The only real limitation is that whenever you distribute Stockfish in The only real limitation is that whenever you distribute Stockfish in
some way, you MUST always include the full source code, or a pointer some way, you MUST always include the license and the full source code
to where the source code can be found, to generate the exact binary (or a pointer to where the source code can be found) to generate the
you are distributing. If you make any changes to the source code, exact binary you are distributing. If you make any changes to the
these changes must also be made available under the GPL. source code, these changes must also be made available under the GPL v3.
For full details, read the copy of the GPL v3 found in the file named For full details, read the copy of the GPL v3 found in the file named
*Copying.txt*. [*Copying.txt*][license-link].
[authors-link]: https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS
[build-link]: https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml
[commits-link]: https://github.com/official-stockfish/Stockfish/commits/master
[discord-link]: https://discord.gg/GWDRS3kU6R
[fishcooking-link]: https://groups.google.com/g/fishcooking
[fishtest-link]: https://tests.stockfishchess.org/tests
[github-link]: https://github.com/official-stockfish/Stockfish
[guideline-link]: https://github.com/glinscott/fishtest/wiki/Creating-my-first-test
[license-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt
[lockpages-link]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows
[nodchip-link]: https://github.com/nodchip/Stockfish
[programming-link]: https://www.chessprogramming.org/Main_Page
[programmingsf-link]: https://www.chessprogramming.org/Stockfish
[pytorch-link]: https://github.com/glinscott/nnue-pytorch
[rammap-link]: https://docs.microsoft.com/en-us/sysinternals/downloads/rammap
[readme-link]: https://github.com/official-stockfish/Stockfish/blob/master/README.md
[release-link]: https://github.com/official-stockfish/Stockfish/releases/latest
[src-link]: https://github.com/official-stockfish/Stockfish/tree/master/src
[stockfish128-logo]: https://stockfishchess.org/images/logo/icon_128x128.png
[tools-link]: https://github.com/official-stockfish/Stockfish/tree/tools
[uci-link]: https://www.shredderchess.com/download/div/uci.zip
[website-link]: https://stockfishchess.org
[worker-link]: https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview
[build-badge]: https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github
[commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge
[discord-badge]: https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord
[fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests%2Ffinished
[license-badge]: https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success
[release-badge]: https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release
[website-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org
+258 -187
View File
@@ -1,189 +1,260 @@
Contributors to Fishtest with >10,000 CPU hours, as of Feb 15, 2021. Contributors to Fishtest with >10,000 CPU hours, as of 2022-11-19.
Thank you! Thank you!
Username CPU Hours Games played Username CPU Hours Games played
---------------------------------------------------- ------------------------------------------------------------------
noobpwnftw 23930906 1560559941 noobpwnftw 36475307 2748033975
dew 1169948 70333008 technologov 14570711 760073590
mlang 957168 61657446 mlang 3026000 200065824
mibere 703840 46867607 dew 1689222 100034318
tvijlbrief 517888 33379462 grandphish2 1442171 86798057
JojoM 515404 30334272 okrout 1439985 133471766
cw 443276 29385549 pemo 1405374 44189811
crunchy 427035 27344275 linrock 1299003 28382783
grandphish2 425794 26347253 TueRens 1163420 71159522
fastgm 414133 24519696 JojoM 897158 55177114
gvreuls 377843 24708884 tvijlbrief 796125 51897690
CSU_Dynasty 338718 23030006 mibere 703840 46867607
Fisherman 326795 21820747 gvreuls 635982 40652394
TueRens 313730 19490246 oz 590763 41201352
ctoks 298442 20052551 sebastronomy 581517 23307132
velislav 270519 17355456 cw 517915 34865769
bcross 241064 17196165 fastgm 504266 30264740
glinscott 217799 13780820 CSU_Dynasty 479901 31846710
nordlandia 211692 13484886 ctoks 433503 28180725
bking_US 198894 11876016 crunchy 427035 27344275
drabel 191096 13129722 leszek 416883 27493447
leszek 189170 11446821 bcross 409982 28062127
mgrabiak 187153 12013300 velislav 345954 22232274
robal 181389 11539242 Fisherman 327231 21829379
Thanar 179852 12365359 Dantist 296386 18031762
vdv 175274 9889046 mgrabiak 288928 18869896
spams 157128 10319326 rpngn 259965 16281463
marrco 150292 9401741 robal 237653 15148350
sqrt2 147963 9724586 ncfish1 231764 15275003
CoffeeOne 137086 5022516 nordlandia 226923 14624832
vdbergh 137041 8926915 glinscott 208125 13277240
malala 136182 8002293 drabel 204167 13930674
mhoram 132780 8398229 mhoram 202894 12601997
xoto 124729 8652088 bking_US 198894 11876016
davar 122092 7960001 thirdlife 198844 5453268
dsmith 122059 7570238 Thanar 179852 12365359
Data 113305 8220352 vdv 175544 9904472
BrunoBanani 112960 7436849 armo9494 168201 11136452
pemo 109598 5036441 spams 157128 10319326
Dantist 106768 6431396 marrco 151599 9551115
MaZePallas 102741 6630419 sqrt2 147963 9724586
ElbertoOne 99028 7023771 vdbergh 137690 8971569
brabos 92118 6186135 CoffeeOne 137100 5024116
linrock 90903 6708639 malala 136182 8002293
psk 89957 5984901 DesolatedDodo 135276 8657464
sunu 88614 6020673 xoto 133759 9159372
sterni1971 86948 5613788 davar 129023 8376525
Vizvezdenec 83761 5344740 dsmith 122059 7570238
BRAVONE 81239 5054681 amicic 119661 7938029
nssy 76497 5259388 Data 113305 8220352
cuistot 76366 4370584 BrunoBanani 112960 7436849
racerschmacer 75753 5442626 CypressChess 108331 7759788
teddybaer 75125 5407666 skiminki 106518 7062598
Pking_cda 73776 5293873 MaZePallas 102823 6633619
0x3C33 73133 4670293 sterni1971 100532 5880772
jromang 72117 5054915 sunu 100167 7040199
solarlight 70517 5028306 zeryl 99331 6221261
dv8silencer 70287 3883992 ElbertoOne 99028 7023771
Bobo1239 68515 4652287 DMBK 97572 6950312
manap 66273 4121774 Calis007 96779 5611552
tinker 64321 4268390 cuistot 93111 5536500
robnjr 57262 4053117 brabos 92118 6186135
Freja 56938 3733019 Wolfgang 91769 5720158
ttruscott 56010 3680085 psk 89957 5984901
rkl 54986 4150767 racerschmacer 85805 6122790
renouve 53811 3501516 jcAEie 85527 5630616
finfish 51360 3370515 Vizvezdenec 83761 5344740
eva42 51272 3599691 sschnee 83557 4853690
rap 49985 3219146 0x3C33 82614 5271253
pb00067 49727 3298270 BRAVONE 81239 5054681
amicic 49691 3042481 Dubslow 78461 5042980
ronaldjerum 47654 3240695 nssy 76497 5259388
bigpen0r 47278 3291647 jromang 76106 5236025
biffhero 46564 3111352 teddybaer 75125 5407666
VoyagerOne 45476 3452465 yurikvelo 73933 5031096
eastorwest 45033 3071805 tolkki963 73885 4721430
speedycpu 43842 3003273 Pking_cda 73776 5293873
jbwiebe 43305 2805433 Bobo1239 71675 4860987
Antihistamine 41788 2761312 solarlight 70517 5028306
mhunt 41735 2691355 dv8silencer 70287 3883992
homyur 39893 2850481 Gelma 69304 3980932
gri 39871 2515779 manap 66273 4121774
oryx 38282 2944400 megaman7de 65419 4120200
Spprtr 38157 2470529 markkulix 65331 4114860
SC 37290 2731014 bigpen0r 64932 4683883
csnodgrass 36207 2688994 tinker 64333 4268790
jmdana 36157 2210661 qurashee 61208 3429862
strelock 34716 2074055 AGI 58325 4258646
Garf 33800 2747562 robnjr 57262 4053117
skiminki 33515 2055584 Freja 56938 3733019
EthanOConnor 33370 2090311 MaxKlaxxMiner 56879 3423958
slakovv 32915 2021889 ttruscott 56010 3680085
yurikvelo 32600 2255966 rkl 55132 4164467
Prcuvu 30377 2170122 renouve 53811 3501516
manapbk 30326 1770143 Spprtr 52736 3410019
anst 30301 2190091 finfish 51360 3370515
jkiiski 30136 1904470 eva42 51272 3599691
hyperbolic.tom 29840 2017394 eastorwest 51117 3454811
Pyafue 29650 1902349 rap 49985 3219146
qurashee 27758 1509620 unixwizard 49734 2536230
OuaisBla 27636 1578800 pb00067 49727 3298270
chriswk 26902 1868317 ronaldjerum 47654 3240695
achambord 26582 1767323 biffhero 46564 3111352
Fifis 26376 1776853 GPUex 45861 2926502
Patrick_G 26276 1801617 Fifis 45843 3088497
yorkman 26193 1992080 oryx 45578 3493978
SFTUser 25182 1675689 VoyagerOne 45476 3452465
nabildanial 24942 1519409 Wencey 44943 2654490
Sharaf_DG 24765 1786697 speedycpu 43842 3003273
ncfish1 24411 1520927 jbwiebe 43305 2805433
agg177 23890 1395014 Antihistamine 41788 2761312
JanErik 23408 1703875 mhunt 41735 2691355
Isidor 23388 1680691 olafm 41277 3284344
Norabor 23164 1591830 homyur 39893 2850481
cisco2015 22895 1762069 gri 39871 2515779
Zirie 22542 1472937 MarcusTullius 38303 2251097
team-oh 22272 1636708 Garf 37741 2999686
MazeOfGalious 21978 1629593 kdave 37424 2557406
sg4032 21945 1643065 SC 37299 2731694
ianh2105 21725 1632562 csnodgrass 36207 2688994
xor12 21628 1680365 jmdana 36157 2210661
dex 21612 1467203 strelock 34716 2074055
nesoneg 21494 1463031 EthanOConnor 33370 2090311
jjoshua2 20997 1422689 slakovv 32915 2021889
horst.prack 20878 1465656 gopeto 31669 2060958
0xB00B1ES 20590 1208666 manapbk 30987 1810399
sphinx 20515 1352368 Prcuvu 30377 2170122
j3corre 20405 941444 anst 30301 2190091
Adrian.Schmidt123 20316 1281436 jkiiski 30136 1904470
Ente 20017 1432602 spcc 30135 1903728
wei 19973 1745989 hyperbolic.tom 29840 2017394
rstoesser 19569 1293588 xwziegtm 29763 2347412
eudhan 19274 1283717 chuckstablers 29659 2093438
jundery 18445 1115855 Pyafue 29650 1902349
iisiraider 18247 1101015 belzedar94 28846 1811530
ville 17883 1384026 OuaisBla 27636 1578800
chris 17698 1487385 chriswk 26902 1868317
purplefishies 17595 1092533 achambord 26582 1767323
DMBK 17357 1279152 Patrick_G 26276 1801617
DragonLord 17014 1162790 yorkman 26193 1992080
dju 16515 929427 Ulysses 25289 1674274
IgorLeMasson 16064 1147232 SFTUser 25182 1675689
ako027ako 15671 1173203 nabildanial 24942 1519409
Nikolay.IT 15154 1068349 Sharaf_DG 24765 1786697
Andrew Grant 15114 895539 rodneyc 24376 1416402
OssumOpossum 14857 1007129 agg177 23890 1395014
enedene 14476 905279 Ente 23747 1674582
bpfliegel 14298 884523 Karpovbot 23629 1313186
jpulman 13982 870599 JanErik 23408 1703875
joster 13794 950160 Isidor 23388 1680691
Nesa92 13786 1114691 Norabor 23371 1603244
crocogoat 13753 1114622 cisco2015 22934 1763773
Hjax 13535 915487 Zirie 22542 1472937
Dark_wizzie 13422 1007152 team-oh 22272 1636708
mpx86 12941 693640 Roady 22220 1465606
mabichito 12903 749391 MazeOfGalious 21978 1629593
thijsk 12886 722107 sg4032 21947 1643353
AdrianSA 12860 804972 ianh2105 21725 1632562
Flopzee 12698 894821 xor12 21628 1680365
fatmurphy 12547 853210 dex 21612 1467203
scuzzi 12511 845761 nesoneg 21494 1463031
Karby 12429 735880 user213718 21454 1404128
SapphireBrand 12416 969604 AndreasKrug 21227 1577833
modolief 12386 896470 sphinx 21211 1384728
pgontarz 12151 848794 jjoshua2 21001 1423089
stocky 11954 699440 horst.prack 20878 1465656
mschmidt 11941 803401 jsys14 20729 1221010
infinity 11470 727027 0xB00B1ES 20590 1208666
torbjo 11395 729145 j3corre 20405 941444
Thomas A. Anderson 11372 732094 Adrian.Schmidt123 20316 1281436
d64 11263 789184 bonsi 20022 1300682
Maxim 11129 804704 wei 19973 1745989
snicolet 11106 869170 dapper 19754 1167758
MooTheCow 11008 694942 Zake9298 19745 1458416
savage84 10965 641068 fishtester 19617 1257388
Rudolphous 10915 741268 rstoesser 19569 1293588
Wolfgang 10809 580032 eudhan 19274 1283717
rpngn 10712 688203 vulcan 18871 1729392
basepi 10637 744851 Jopo12321 18803 1036284
michaelrpg 10409 735127 jundery 18445 1115855
dzjp 10343 732529 ville 17883 1384026
ali-al-zhrani 10324 726502 5t0ckf15hTr4in3r 17809 1105858
ols 10259 570669 chris 17698 1487385
lbraesch 10252 647825 dju 17697 994333
purplefishies 17595 1092533
iisiraider 17275 1049015
DragonLord 17014 1162790
Karby 16457 1010138
Goatminola 16278 1145026
IgorLeMasson 16064 1147232
Gaster319 16056 1109070
redstone59 15953 1161664
scuzzi 15757 968735
ako027ako 15671 1173203
Nikolay.IT 15154 1068349
Andrew Grant 15114 895539
Naven94 15054 834762
OssumOpossum 14857 1007129
qoo_charly_cai 14490 847865
enedene 14476 905279
szupaw 14252 929130
bpfliegel 14233 882523
mpx86 14019 759568
jpulman 13982 870599
crocogoat 13803 1117422
Nesa92 13786 1114691
joster 13710 946160
mbeier 13650 1044928
Hjax 13535 915487
Dark_wizzie 13422 1007152
Rudolphous 13244 883140
Machariel 13010 863104
infinigon 12991 943216
pirt 12925 985437
Skiff84 12923 649994
mabichito 12903 749391
thijsk 12886 722107
AdrianSA 12860 804972
Flopzee 12698 894821
fatmurphy 12547 853210
woutboat 12419 836696
SapphireBrand 12416 969604
Oakwen 12406 840961
deflectooor 12386 579392
modolief 12386 896470
Farseer 12249 694108
pgontarz 12151 848794
stocky 11954 699440
mschmidt 11941 803401
MooTheCow 11871 773654
Jackfish 11867 773550
dbernier 11705 821780
whelanh 11557 245188
Maxim 11543 836024
Nullvalue 11534 731410
icewulf 11528 650470
FormazChar 11523 861599
infinity 11470 727027
aga 11412 695127
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
ali-al-zhrani 11272 781310
d64 11263 789184
Bourbaki 11108 709144
snicolet 11106 869170
Alb11747 10855 696920
basepi 10637 744851
Cubox 10621 826448
Karmatron 10616 674818
michaelrpg 10509 739239
OIVAS7572 10420 995586
Garruk 10348 704905
dzjp 10343 732529
ols 10259 570669
-88
View File
@@ -1,88 +0,0 @@
version: 1.0.{build}
clone_depth: 50
branches:
only:
- master
# Operating system (build VM template)
os: Visual Studio 2019
# Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
platform:
- x86
- x64
# build Configuration, i.e. Debug, Release, etc.
configuration:
- Debug
- Release
matrix:
# The build fail immediately once one of the job fails
fast_finish: true
# Scripts that are called at very beginning, before repo cloning
init:
- cmake --version
- msbuild /version
before_build:
- ps: |
# Get sources
$src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName
$src = $src -join ' '
$src = $src.Replace("\", "/")
# Build CMakeLists.txt
$t = 'cmake_minimum_required(VERSION 3.17)',
'project(Stockfish)',
'set(CMAKE_CXX_STANDARD 17)',
'set(CMAKE_CXX_STANDARD_REQUIRED ON)',
'set (CMAKE_CXX_EXTENSIONS OFF)',
'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
'set(source_files', $src, ')',
'add_executable(stockfish ${source_files})'
# Write CMakeLists.txt withouth BOM
$MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
# Obtain bench reference from git log
$b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
$bench = $b -match '\D+(\d+)' | % { $matches[1] }
Write-Host "Reference bench:" $bench
$g = "Visual Studio 16 2019"
If (${env:PLATFORM} -eq 'x64') { $a = "x64" }
If (${env:PLATFORM} -eq 'x86') { $a = "Win32" }
cmake -G "${g}" -A ${a} .
Write-Host "Generated files for: " $g $a
build_script:
- cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
- ps: |
# Download default NNUE net from fishtest
$nnuenet = Get-Content -Path src\evaluate.h | Select-String -CaseSensitive -Pattern "EvalFileDefaultName" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
$dummy = $nnuenet -match "(?<nnuenet>nn-[a-z0-9]{12}.nnue)"
$nnuenet = $Matches.nnuenet
Write-Host "Default net:" $nnuenet
$nnuedownloadurl = "https://tests.stockfishchess.org/api/nn/$nnuenet"
$nnuefilepath = "src\${env:CONFIGURATION}\$nnuenet"
if (Test-Path -Path $nnuefilepath) {
Write-Host "Already available."
} else {
Write-Host "Downloading $nnuedownloadurl to $nnuefilepath"
Invoke-WebRequest -Uri $nnuedownloadurl -OutFile $nnuefilepath
}
before_test:
- cd src/%CONFIGURATION%
- stockfish bench 2> out.txt >NUL
- ps: |
# Verify bench number
$s = (gc "./out.txt" | out-string)
$r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
Write-Host "Engine bench:" $r
Write-Host "Reference bench:" $bench
If ($r -ne $bench) { exit 1 }
+224 -103
View File
@@ -1,5 +1,5 @@
# Stockfish, a UCI chess playing engine derived from Glaurung 2.1 # Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) # Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
# #
# Stockfish is free software: you can redistribute it and/or modify # Stockfish is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -19,11 +19,29 @@
### Section 1. General Configuration ### Section 1. General Configuration
### ========================================================================== ### ==========================================================================
### Establish the operating system name
KERNEL = $(shell uname -s)
ifeq ($(KERNEL),Linux)
OS = $(shell uname -o)
endif
### Target Windows OS
ifeq ($(OS),Windows_NT)
ifneq ($(COMP),ndk)
target_windows = yes
endif
else ifeq ($(COMP),mingw)
target_windows = yes
ifeq ($(WINE_PATH),)
WINE_PATH = $(shell which wine)
endif
endif
### Executable name ### Executable name
ifeq ($(COMP),mingw) ifeq ($(target_windows),yes)
EXE = stockfish.exe EXE = stockfish.exe
else else
EXE = stockfish EXE = stockfish
endif endif
### Installation dir definitions ### Installation dir definitions
@@ -31,24 +49,22 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds ### Built-in benchmark for pgo-builds
PGOBENCH = ./$(EXE) bench ifeq ($(SDE_PATH),)
PGOBENCH = $(WINE_PATH) ./$(EXE) bench
else
PGOBENCH = $(SDE_PATH) -- $(WINE_PATH) ./$(EXE) bench
endif
### Source and object files ### Source and object files
SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \ SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \ material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
nnue/evaluate_nnue.cpp nnue/features/half_kp.cpp nnue/evaluate_nnue.cpp nnue/features/half_ka_v2_hm.cpp
OBJS = $(notdir $(SRCS:.cpp=.o)) OBJS = $(notdir $(SRCS:.cpp=.o))
VPATH = syzygy:nnue:nnue/features VPATH = syzygy:nnue:nnue/features
### Establish the operating system name
KERNEL = $(shell uname -s)
ifeq ($(KERNEL),Linux)
OS = $(shell uname -o)
endif
### ========================================================================== ### ==========================================================================
### Section 2. High-level Configuration ### Section 2. High-level Configuration
### ========================================================================== ### ==========================================================================
@@ -57,9 +73,11 @@ endif
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# #
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode # debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
# sanitize = undefined/thread/no (-fsanitize ) # sanitize = none/<sanitizer> ... (-fsanitize )
# --- ( undefined ) --- enable undefined behavior checks # --- ( undefined ) --- enable undefined behavior checks
# --- ( thread ) --- enable threading error checks # --- ( thread ) --- enable threading error checks
# --- ( address ) --- enable memory access checks
# --- ...etc... --- see compiler documentation for supported sanitizers
# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations # optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
# arch = (name) --- (-arch) --- Target architecture # arch = (name) --- (-arch) --- Target architecture
# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system # bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
@@ -72,6 +90,7 @@ endif
# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3 # ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1 # sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2 # avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
# avxvnni = yes/no --- -mavxvnni --- Use Intel Vector Neural Network Instructions AVX
# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512 # avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256 # vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512 # vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
@@ -80,6 +99,10 @@ endif
# Note that Makefile is space sensitive, so when adding new architectures # Note that Makefile is space sensitive, so when adding new architectures
# or modifying existing flags, you have to make sure there are no extra spaces # or modifying existing flags, you have to make sure there are no extra spaces
# at the end of the line for flag values. # at the end of the line for flag values.
#
# Example of use for these flags:
# make build ARCH=x86-64-avx512 debug=yes sanitize="address undefined"
### 2.1. General and architecture defaults ### 2.1. General and architecture defaults
@@ -90,10 +113,10 @@ endif
# explicitly check for the list of supported architectures (as listed with make help), # explicitly check for the list of supported architectures (as listed with make help),
# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true` # the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
ifeq ($(ARCH), $(filter $(ARCH), \ ifeq ($(ARCH), $(filter $(ARCH), \
x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \ x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-avxvnni x86-64-bmi2 \
x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \ x86-64-avx2 x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 \ x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 e2k \
armv7 armv7-neon armv8 apple-silicon general-64 general-32)) armv7 armv7-neon armv8 apple-silicon general-64 general-32 riscv64))
SUPPORTED_ARCH=true SUPPORTED_ARCH=true
else else
SUPPORTED_ARCH=false SUPPORTED_ARCH=false
@@ -101,7 +124,7 @@ endif
optimize = yes optimize = yes
debug = no debug = no
sanitize = no sanitize = none
bits = 64 bits = 64
prefetch = no prefetch = no
popcnt = no popcnt = no
@@ -112,10 +135,12 @@ sse2 = no
ssse3 = no ssse3 = no
sse41 = no sse41 = no
avx2 = no avx2 = no
avxvnni = no
avx512 = no avx512 = no
vnni256 = no vnni256 = no
vnni512 = no vnni512 = no
neon = no neon = no
arm_version = 0
STRIP = strip STRIP = strip
### 2.2 Architecture specific ### 2.2 Architecture specific
@@ -127,7 +152,7 @@ ifeq ($(findstring x86,$(ARCH)),x86)
ifeq ($(findstring x86-32,$(ARCH)),x86-32) ifeq ($(findstring x86-32,$(ARCH)),x86-32)
arch = i386 arch = i386
bits = 32 bits = 32
sse = yes sse = no
mmx = yes mmx = yes
else else
arch = x86_64 arch = x86_64
@@ -182,6 +207,17 @@ ifeq ($(findstring -avx2,$(ARCH)),-avx2)
avx2 = yes avx2 = yes
endif endif
ifeq ($(findstring -avxvnni,$(ARCH)),-avxvnni)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
avxvnni = yes
pext = yes
endif
ifeq ($(findstring -bmi2,$(ARCH)),-bmi2) ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
popcnt = yes popcnt = yes
sse = yes sse = yes
@@ -252,6 +288,7 @@ ifeq ($(ARCH),armv7)
arch = armv7 arch = armv7
prefetch = yes prefetch = yes
bits = 32 bits = 32
arm_version = 7
endif endif
ifeq ($(ARCH),armv7-neon) ifeq ($(ARCH),armv7-neon)
@@ -260,6 +297,7 @@ ifeq ($(ARCH),armv7-neon)
popcnt = yes popcnt = yes
neon = yes neon = yes
bits = 32 bits = 32
arm_version = 7
endif endif
ifeq ($(ARCH),armv8) ifeq ($(ARCH),armv8)
@@ -267,6 +305,7 @@ ifeq ($(ARCH),armv8)
prefetch = yes prefetch = yes
popcnt = yes popcnt = yes
neon = yes neon = yes
arm_version = 8
endif endif
ifeq ($(ARCH),apple-silicon) ifeq ($(ARCH),apple-silicon)
@@ -274,6 +313,7 @@ ifeq ($(ARCH),apple-silicon)
prefetch = yes prefetch = yes
popcnt = yes popcnt = yes
neon = yes neon = yes
arm_version = 8
endif endif
ifeq ($(ARCH),ppc-32) ifeq ($(ARCH),ppc-32)
@@ -287,16 +327,37 @@ ifeq ($(ARCH),ppc-64)
prefetch = yes prefetch = yes
endif endif
ifeq ($(findstring e2k,$(ARCH)),e2k)
arch = e2k
mmx = yes
bits = 64
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
popcnt = yes
endif endif
ifeq ($(ARCH),riscv64)
arch = riscv64
endif
endif
### ========================================================================== ### ==========================================================================
### Section 3. Low-level Configuration ### Section 3. Low-level Configuration
### ========================================================================== ### ==========================================================================
### 3.1 Selecting compiler (default = gcc) ### 3.1 Selecting compiler (default = gcc)
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS) ifeq ($(MAKELEVEL),0)
DEPENDFLAGS += -std=c++17 export ENV_CXXFLAGS := $(CXXFLAGS)
LDFLAGS += $(EXTRALDFLAGS) export ENV_DEPENDFLAGS := $(DEPENDFLAGS)
export ENV_LDFLAGS := $(LDFLAGS)
endif
CXXFLAGS = $(ENV_CXXFLAGS) -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
DEPENDFLAGS = $(ENV_DEPENDFLAGS) -std=c++17
LDFLAGS = $(ENV_LDFLAGS) $(EXTRALDFLAGS)
ifeq ($(COMP),) ifeq ($(COMP),)
COMP=gcc COMP=gcc
@@ -307,11 +368,14 @@ ifeq ($(COMP),gcc)
CXX=g++ CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(arch),$(filter $(arch),armv7 armv8)) ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64))
ifeq ($(OS),Android) ifeq ($(OS),Android)
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
endif endif
ifeq ($(ARCH),riscv64)
CXXFLAGS += -latomic
endif
else else
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
@@ -326,29 +390,27 @@ ifeq ($(COMP),gcc)
endif endif
endif endif
ifeq ($(target_windows),yes)
LDFLAGS += -static
endif
ifeq ($(COMP),mingw) ifeq ($(COMP),mingw)
comp=mingw comp=mingw
ifeq ($(KERNEL),Linux) ifeq ($(bits),64)
ifeq ($(bits),64) ifeq ($(shell which x86_64-w64-mingw32-c++-posix 2> /dev/null),)
ifeq ($(shell which x86_64-w64-mingw32-c++-posix),) CXX=x86_64-w64-mingw32-c++
CXX=x86_64-w64-mingw32-c++
else
CXX=x86_64-w64-mingw32-c++-posix
endif
else else
ifeq ($(shell which i686-w64-mingw32-c++-posix),) CXX=x86_64-w64-mingw32-c++-posix
CXX=i686-w64-mingw32-c++
else
CXX=i686-w64-mingw32-c++-posix
endif
endif endif
else else
CXX=g++ ifeq ($(shell which i686-w64-mingw32-c++-posix 2> /dev/null),)
CXX=i686-w64-mingw32-c++
else
CXX=i686-w64-mingw32-c++-posix
endif
endif endif
CXXFLAGS += -pedantic -Wextra -Wshadow
CXXFLAGS += -Wextra -Wshadow
LDFLAGS += -static
endif endif
ifeq ($(COMP),icc) ifeq ($(COMP),icc)
@@ -360,21 +422,28 @@ endif
ifeq ($(COMP),clang) ifeq ($(COMP),clang)
comp=clang comp=clang
CXX=clang++ CXX=clang++
ifeq ($(target_windows),yes)
CXX=x86_64-w64-mingw32-clang++
endif
CXXFLAGS += -pedantic -Wextra -Wshadow CXXFLAGS += -pedantic -Wextra -Wshadow
ifneq ($(KERNEL),Darwin) ifeq ($(filter $(KERNEL),Darwin OpenBSD FreeBSD),)
ifneq ($(KERNEL),OpenBSD) ifeq ($(target_windows),)
ifneq ($(KERNEL),FreeBSD) ifneq ($(RTLIB),compiler-rt)
LDFLAGS += -latomic LDFLAGS += -latomic
endif endif
endif endif
endif endif
ifeq ($(arch),$(filter $(arch),armv7 armv8)) ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64))
ifeq ($(OS),Android) ifeq ($(OS),Android)
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
endif endif
ifeq ($(ARCH),riscv64)
CXXFLAGS += -latomic
endif
else else
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
@@ -382,8 +451,12 @@ ifeq ($(COMP),clang)
endif endif
ifeq ($(KERNEL),Darwin) ifeq ($(KERNEL),Darwin)
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14 CXXFLAGS += -mmacosx-version-min=10.14
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14 LDFLAGS += -mmacosx-version-min=10.14
ifneq ($(arch),any)
CXXFLAGS += -arch $(arch)
LDFLAGS += -arch $(arch)
endif
XCRUN = xcrun XCRUN = xcrun
endif endif
@@ -396,11 +469,19 @@ ifeq ($(COMP),ndk)
ifeq ($(arch),armv7) ifeq ($(arch),armv7)
CXX=armv7a-linux-androideabi16-clang++ CXX=armv7a-linux-androideabi16-clang++
CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
STRIP=arm-linux-androideabi-strip ifneq ($(shell which arm-linux-androideabi-strip 2>/dev/null),)
STRIP=arm-linux-androideabi-strip
else
STRIP=llvm-strip
endif
endif endif
ifeq ($(arch),armv8) ifeq ($(arch),armv8)
CXX=aarch64-linux-android21-clang++ CXX=aarch64-linux-android21-clang++
STRIP=aarch64-linux-android-strip ifneq ($(shell which aarch64-linux-android-strip 2>/dev/null),)
STRIP=aarch64-linux-android-strip
else
STRIP=llvm-strip
endif
endif endif
LDFLAGS += -static-libstdc++ -pie -lm -latomic LDFLAGS += -static-libstdc++ -pie -lm -latomic
endif endif
@@ -414,6 +495,9 @@ else ifeq ($(comp),clang)
else else
profile_make = gcc-profile-make profile_make = gcc-profile-make
profile_use = gcc-profile-use profile_use = gcc-profile-use
ifeq ($(KERNEL),Darwin)
EXTRAPROFILEFLAGS = -fvisibility=hidden
endif
endif endif
### Travis CI script uses COMPILER to overwrite CXX ### Travis CI script uses COMPILER to overwrite CXX
@@ -458,9 +542,9 @@ else
endif endif
### 3.2.2 Debugging with undefined behavior sanitizers ### 3.2.2 Debugging with undefined behavior sanitizers
ifneq ($(sanitize),no) ifneq ($(sanitize),none)
CXXFLAGS += -g3 -fsanitize=$(sanitize) CXXFLAGS += -g3 $(addprefix -fsanitize=,$(sanitize))
LDFLAGS += -fsanitize=$(sanitize) LDFLAGS += $(addprefix -fsanitize=,$(sanitize))
endif endif
### 3.3 Optimization ### 3.3 Optimization
@@ -474,10 +558,16 @@ ifeq ($(optimize),yes)
endif endif
endif endif
ifeq ($(comp),$(filter $(comp),gcc clang icc)) ifeq ($(KERNEL),Darwin)
ifeq ($(KERNEL),Darwin) ifeq ($(comp),$(filter $(comp),clang icc))
CXXFLAGS += -mdynamic-no-pic CXXFLAGS += -mdynamic-no-pic
endif endif
ifeq ($(comp),gcc)
ifneq ($(arch),arm64)
CXXFLAGS += -mdynamic-no-pic
endif
endif
endif endif
ifeq ($(comp),clang) ifeq ($(comp),clang)
@@ -490,7 +580,7 @@ ifeq ($(bits),64)
CXXFLAGS += -DIS_64BIT CXXFLAGS += -DIS_64BIT
endif endif
### 3.5 prefetch ### 3.5 prefetch and popcount
ifeq ($(prefetch),yes) ifeq ($(prefetch),yes)
ifeq ($(sse),yes) ifeq ($(sse),yes)
CXXFLAGS += -msse CXXFLAGS += -msse
@@ -499,7 +589,6 @@ else
CXXFLAGS += -DNO_PREFETCH CXXFLAGS += -DNO_PREFETCH
endif endif
### 3.6 popcnt
ifeq ($(popcnt),yes) ifeq ($(popcnt),yes)
ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64)) ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
CXXFLAGS += -DUSE_POPCNT CXXFLAGS += -DUSE_POPCNT
@@ -510,11 +599,18 @@ ifeq ($(popcnt),yes)
endif endif
endif endif
### 3.6 SIMD architectures
ifeq ($(avx2),yes) ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2 CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw)) ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx2 CXXFLAGS += -mavx2 -mbmi
endif
endif
ifeq ($(avxvnni),yes)
CXXFLAGS += -DUSE_VNNI -DUSE_AVXVNNI
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavxvnni
endif endif
endif endif
@@ -568,7 +664,7 @@ ifeq ($(mmx),yes)
endif endif
ifeq ($(neon),yes) ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON CXXFLAGS += -DUSE_NEON=$(arm_version)
ifeq ($(KERNEL),Linux) ifeq ($(KERNEL),Linux)
ifneq ($(COMP),ndk) ifneq ($(COMP),ndk)
ifneq ($(arch),armv8) ifneq ($(arch),armv8)
@@ -586,16 +682,26 @@ ifeq ($(pext),yes)
endif endif
endif endif
### 3.7.1 Try to include git commit sha for versioning
GIT_SHA = $(shell git rev-parse --short HEAD 2>/dev/null)
ifneq ($(GIT_SHA), )
CXXFLAGS += -DGIT_SHA=\"$(GIT_SHA)\"
endif
### 3.7.2 Try to include git commit date for versioning
GIT_DATE = $(shell git show -s --date=format:'%Y%m%d' --format=%cd HEAD 2>/dev/null)
ifneq ($(GIT_DATE), )
CXXFLAGS += -DGIT_DATE=\"$(GIT_DATE)\"
endif
### 3.8 Link Time Optimization ### 3.8 Link Time Optimization
### This is a mix of compile and link time options because the lto link phase ### This is a mix of compile and link time options because the lto link phase
### needs access to the optimization flags. ### needs access to the optimization flags.
ifeq ($(optimize),yes) ifeq ($(optimize),yes)
ifeq ($(debug), no) ifeq ($(debug), no)
ifeq ($(comp),clang) ifeq ($(comp),clang)
CXXFLAGS += -flto CXXFLAGS += -flto=full
ifneq ($(findstring MINGW,$(KERNEL)),) ifeq ($(target_windows),yes)
CXXFLAGS += -fuse-ld=lld
else ifneq ($(findstring MSYS,$(KERNEL)),)
CXXFLAGS += -fuse-ld=lld CXXFLAGS += -fuse-ld=lld
endif endif
LDFLAGS += $(CXXFLAGS) LDFLAGS += $(CXXFLAGS)
@@ -604,28 +710,18 @@ ifeq ($(debug), no)
# GCC on some systems. # GCC on some systems.
else ifeq ($(comp),gcc) else ifeq ($(comp),gcc)
ifeq ($(gccisclang),) ifeq ($(gccisclang),)
CXXFLAGS += -flto CXXFLAGS += -flto -flto-partition=one
LDFLAGS += $(CXXFLAGS) -flto=jobserver LDFLAGS += $(CXXFLAGS) -flto=jobserver
ifneq ($(findstring MINGW,$(KERNEL)),)
LDFLAGS += -save-temps
else ifneq ($(findstring MSYS,$(KERNEL)),)
LDFLAGS += -save-temps
endif
else else
CXXFLAGS += -flto CXXFLAGS += -flto=full
LDFLAGS += $(CXXFLAGS) LDFLAGS += $(CXXFLAGS)
endif endif
# To use LTO and static linking on windows, the tool chain requires a recent gcc: # To use LTO and static linking on Windows,
# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not. # the tool chain requires gcc version 10.1 or later.
# So, only enable it for a cross from Linux by default.
else ifeq ($(comp),mingw) else ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux) CXXFLAGS += -flto -flto-partition=one
ifneq ($(arch),i386) LDFLAGS += $(CXXFLAGS) -save-temps
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS) -flto=jobserver
endif
endif
endif endif
endif endif
endif endif
@@ -663,6 +759,7 @@ help:
@echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide" @echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
@echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide" @echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
@echo "x86-64-avx512 > x86 64-bit with avx512 support" @echo "x86-64-avx512 > x86 64-bit with avx512 support"
@echo "x86-64-avxvnni > x86 64-bit with avxvnni support"
@echo "x86-64-bmi2 > x86 64-bit with bmi2 support" @echo "x86-64-bmi2 > x86 64-bit with bmi2 support"
@echo "x86-64-avx2 > x86 64-bit with avx2 support" @echo "x86-64-avx2 > x86 64-bit with avx2 support"
@echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support" @echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support"
@@ -678,9 +775,11 @@ help:
@echo "armv7 > ARMv7 32-bit" @echo "armv7 > ARMv7 32-bit"
@echo "armv7-neon > ARMv7 32-bit with popcnt and neon" @echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
@echo "armv8 > ARMv8 64-bit with popcnt and neon" @echo "armv8 > ARMv8 64-bit with popcnt and neon"
@echo "e2k > Elbrus 2000"
@echo "apple-silicon > Apple silicon ARM64" @echo "apple-silicon > Apple silicon ARM64"
@echo "general-64 > unspecified 64-bit" @echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit" @echo "general-32 > unspecified 32-bit"
@echo "riscv64 > RISC-V 64-bit"
@echo "" @echo ""
@echo "Supported compilers:" @echo "Supported compilers:"
@echo "" @echo ""
@@ -713,7 +812,7 @@ endif
.PHONY: help build profile-build strip install clean net objclean profileclean \ .PHONY: help build profile-build strip install clean net objclean profileclean \
config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \ config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
clang-profile-use clang-profile-make clang-profile-use clang-profile-make FORCE
build: net config-sanity build: net config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
@@ -724,7 +823,7 @@ profile-build: net config-sanity objclean profileclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make) $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
@echo "" @echo ""
@echo "Step 2/4. Running benchmark for pgo-build ..." @echo "Step 2/4. Running benchmark for pgo-build ..."
$(PGOBENCH) > /dev/null $(PGOBENCH) 2>&1 | tail -n 4
@echo "" @echo ""
@echo "Step 3/4. Building optimized executable ..." @echo "Step 3/4. Building optimized executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
@@ -739,7 +838,7 @@ strip:
install: install:
-mkdir -p -m 755 $(BINDIR) -mkdir -p -m 755 $(BINDIR)
-cp $(EXE) $(BINDIR) -cp $(EXE) $(BINDIR)
-strip $(BINDIR)/$(EXE) $(STRIP) $(BINDIR)/$(EXE)
# clean all # clean all
clean: objclean profileclean clean: objclean profileclean
@@ -749,35 +848,49 @@ clean: objclean profileclean
net: net:
$(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/')) $(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
@echo "Default net: $(nnuenet)" @echo "Default net: $(nnuenet)"
$(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet)) $(eval nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet))
$(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet))
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi)) $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
@if test -f "$(nnuenet)"; then \ @if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Already available."; \ echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
else \ fi
if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
else \
echo "Downloading $(nnuedownloadurl)"; $(curl_or_wget) $(nnuedownloadurl) > $(nnuenet);\
fi; \
fi;
$(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi)) $(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
@if [ "x$(shasum_command)" != "x" ]; then \ @if [ "x$(shasum_command)" = "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Failed download or $(nnuenet) corrupted, please delete!"; exit 1; \
fi \
else \
echo "shasum / sha256sum not found, skipping net validation"; \ echo "shasum / sha256sum not found, skipping net validation"; \
fi fi
@for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \
if test -f "$(nnuenet)"; then \
echo "$(nnuenet) available."; \
else \
if [ "x$(curl_or_wget)" != "x" ]; then \
echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\
fi; \
fi; \
if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Removing failed download"; rm -f $(nnuenet); \
else \
echo "Network validated"; break; \
fi; \
fi; \
done
@if ! test -f "$(nnuenet)"; then \
echo "Failed to download $(nnuenet)."; \
fi
# clean binaries and objects # clean binaries and objects
objclean: objclean:
@rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o @rm -f stockfish stockfish.exe *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
# clean auxiliary profiling files # clean auxiliary profiling files
profileclean: profileclean:
@rm -rf profdir @rm -rf profdir
@rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s @rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s
@rm -f stockfish.profdata *.profraw @rm -f stockfish.profdata *.profraw
@rm -f stockfish.*args*
@rm -f stockfish.*lt*
@rm -f stockfish.res
@rm -f ./-lstdc++.res
default: default:
help help
@@ -807,10 +920,12 @@ config-sanity: net
@echo "ssse3: '$(ssse3)'" @echo "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'" @echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'" @echo "avx2: '$(avx2)'"
@echo "avxvnni: '$(avxvnni)'"
@echo "avx512: '$(avx512)'" @echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'" @echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'" @echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'" @echo "neon: '$(neon)'"
@echo "arm_version: '$(arm_version)'"
@echo "" @echo ""
@echo "Flags:" @echo "Flags:"
@echo "CXX: $(CXX)" @echo "CXX: $(CXX)"
@@ -820,12 +935,11 @@ config-sanity: net
@echo "Testing config sanity. If this fails, try 'make help' ..." @echo "Testing config sanity. If this fails, try 'make help' ..."
@echo "" @echo ""
@test "$(debug)" = "yes" || test "$(debug)" = "no" @test "$(debug)" = "yes" || test "$(debug)" = "no"
@test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || test "$(sanitize)" = "address" || test "$(sanitize)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no" @test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(SUPPORTED_ARCH)" = "true" @test "$(SUPPORTED_ARCH)" = "true"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \ @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || \ test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || test "$(arch)" = "riscv64"
@test "$(bits)" = "32" || test "$(bits)" = "64" @test "$(bits)" = "32" || test "$(bits)" = "64"
@test "$(prefetch)" = "yes" || test "$(prefetch)" = "no" @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
@test "$(popcnt)" = "yes" || test "$(popcnt)" = "no" @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
@@ -846,6 +960,10 @@ config-sanity: net
$(EXE): $(OBJS) $(EXE): $(OBJS)
+$(CXX) -o $@ $(OBJS) $(LDFLAGS) +$(CXX) -o $@ $(OBJS) $(LDFLAGS)
# Force recompilation to ensure version info is up-to-date
misc.o: FORCE
FORCE:
clang-profile-make: clang-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-instr-generate ' \ EXTRACXXFLAGS='-fprofile-instr-generate ' \
@@ -860,14 +978,17 @@ clang-profile-use:
all all
gcc-profile-make: gcc-profile-make:
@mkdir -p profdir
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-generate' \ EXTRACXXFLAGS='-fprofile-generate=profdir' \
EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
EXTRALDFLAGS='-lgcov' \ EXTRALDFLAGS='-lgcov' \
all all
gcc-profile-use: gcc-profile-use:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-use -fno-peel-loops -fno-tracer' \ EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
EXTRALDFLAGS='-lgcov' \ EXTRALDFLAGS='-lgcov' \
all all
@@ -882,7 +1003,7 @@ icc-profile-use:
EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \ EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
all all
.depend: .depend: $(SRCS)
-@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
-include .depend -include .depend
+6 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -87,11 +87,14 @@ const vector<string> Defaults = {
// Chess 960 // Chess 960
"setoption name UCI_Chess960 value true", "setoption name UCI_Chess960 value true",
"bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6", "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
"nqbnrkrb/pppppppp/8/8/8/8/PPPPPPPP/NQBNRKRB w KQkq - 0 1",
"setoption name UCI_Chess960 value false" "setoption name UCI_Chess960 value false"
}; };
} // namespace } // namespace
namespace Stockfish {
/// setup_bench() builds a list of UCI commands to be run by bench. There /// setup_bench() builds a list of UCI commands to be run by bench. There
/// are five parameters: TT size in MB, number of search threads that /// are five parameters: TT size in MB, number of search threads that
/// should be used, the limit value spent for each position, a file name /// should be used, the limit value spent for each position, a file name
@@ -168,3 +171,5 @@ vector<string> setup_bench(const Position& current, istream& is) {
return list; return list;
} }
} // namespace Stockfish
+7 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
#include "bitboard.h" #include "bitboard.h"
#include "types.h" #include "types.h"
namespace Stockfish {
namespace { namespace {
// There are 24 possible pawn squares: files A to D and ranks from 2 to 7. // There are 24 possible pawn squares: files A to D and ranks from 2 to 7.
@@ -66,7 +68,6 @@ namespace {
} // namespace } // namespace
bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) { bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
assert(file_of(wpsq) <= FILE_D); assert(file_of(wpsq) <= FILE_D);
@@ -96,7 +97,6 @@ void Bitbases::init() {
KPKBitbase.set(idx); KPKBitbase.set(idx);
} }
namespace { namespace {
KPKPosition::KPKPosition(unsigned idx) { KPKPosition::KPKPosition(unsigned idx) {
@@ -150,8 +150,8 @@ namespace {
Bitboard b = attacks_bb<KING>(ksq[stm]); Bitboard b = attacks_bb<KING>(ksq[stm]);
while (b) while (b)
r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(&b), psq)] r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
: db[index(WHITE, pop_lsb(&b), ksq[WHITE], psq)]; : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
if (stm == WHITE) if (stm == WHITE)
{ {
@@ -168,3 +168,5 @@ namespace {
} }
} // namespace } // namespace
} // namespace Stockfish
+15 -6
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,11 +22,14 @@
#include "bitboard.h" #include "bitboard.h"
#include "misc.h" #include "misc.h"
namespace Stockfish {
uint8_t PopCnt16[1 << 16]; uint8_t PopCnt16[1 << 16];
uint8_t SquareDistance[SQUARE_NB][SQUARE_NB]; uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
Bitboard SquareBB[SQUARE_NB]; Bitboard SquareBB[SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB]; Bitboard LineBB[SQUARE_NB][SQUARE_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB]; Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
@@ -42,7 +45,6 @@ namespace {
} }
/// safe_destination() returns the bitboard of target square for the given step /// safe_destination() returns the bitboard of target square for the given step
/// from the given square. If the step is off the board, returns empty bitboard. /// from the given square. If the step is off the board, returns empty bitboard.
@@ -55,7 +57,7 @@ inline Bitboard safe_destination(Square s, int step) {
/// Bitboards::pretty() returns an ASCII representation of a bitboard suitable /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
/// to be printed to standard output. Useful for debugging. /// to be printed to standard output. Useful for debugging.
const std::string Bitboards::pretty(Bitboard b) { std::string Bitboards::pretty(Bitboard b) {
std::string s = "+---+---+---+---+---+---+---+---+\n"; std::string s = "+---+---+---+---+---+---+---+---+\n";
@@ -106,12 +108,17 @@ void Bitboards::init() {
for (PieceType pt : { BISHOP, ROOK }) for (PieceType pt : { BISHOP, ROOK })
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
{
if (PseudoAttacks[pt][s1] & s2) if (PseudoAttacks[pt][s1] & s2)
LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2; {
LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
BetweenBB[s1][s2] = (attacks_bb(pt, s1, square_bb(s2)) & attacks_bb(pt, s2, square_bb(s1)));
}
BetweenBB[s1][s2] |= s2;
}
} }
} }
namespace { namespace {
Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) { Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
@@ -123,7 +130,7 @@ namespace {
for (Direction d : (pt == ROOK ? RookDirections : BishopDirections)) for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
{ {
Square s = sq; Square s = sq;
while(safe_destination(s, d) && !(occupied & s)) while (safe_destination(s, d) && !(occupied & s))
attacks |= (s += d); attacks |= (s += d);
} }
@@ -211,3 +218,5 @@ namespace {
} }
} }
} }
} // namespace Stockfish
+34 -16
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,19 +23,21 @@
#include "types.h" #include "types.h"
namespace Stockfish {
namespace Bitbases { namespace Bitbases {
void init(); void init();
bool probe(Square wksq, Square wpsq, Square bksq, Color us); bool probe(Square wksq, Square wpsq, Square bksq, Color us);
} } // namespace Stockfish::Bitbases
namespace Bitboards { namespace Bitboards {
void init(); void init();
const std::string pretty(Bitboard b); std::string pretty(Bitboard b);
} } // namespace Stockfish::Bitboards
constexpr Bitboard AllSquares = ~Bitboard(0); constexpr Bitboard AllSquares = ~Bitboard(0);
constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL; constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
@@ -73,6 +75,7 @@ extern uint8_t PopCnt16[1 << 16];
extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB]; extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
extern Bitboard SquareBB[SQUARE_NB]; extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB]; extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB]; extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
@@ -209,23 +212,29 @@ constexpr Bitboard adjacent_files_bb(Square s) {
inline Bitboard line_bb(Square s1, Square s2) { inline Bitboard line_bb(Square s1, Square s2) {
assert(is_ok(s1) && is_ok(s2)); assert(is_ok(s1) && is_ok(s2));
return LineBB[s1][s2]; return LineBB[s1][s2];
} }
/// between_bb() returns a bitboard representing squares that are linearly /// between_bb(s1, s2) returns a bitboard representing the squares in the semi-open
/// between the two given squares (excluding the given squares). If the given /// segment between the squares s1 and s2 (excluding s1 but including s2). If the
/// squares are not on a same file/rank/diagonal, we return 0. For instance, /// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6. /// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
/// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
/// allows to generate non-king evasion moves faster: the defending piece must either
/// interpose itself to cover the check or capture the checking piece.
inline Bitboard between_bb(Square s1, Square s2) { inline Bitboard between_bb(Square s1, Square s2) {
Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2));
return b & (b - 1); //exclude lsb assert(is_ok(s1) && is_ok(s2));
return BetweenBB[s1][s2];
} }
/// forward_ranks_bb() returns a bitboard representing the squares on the ranks /// forward_ranks_bb() returns a bitboard representing the squares on the ranks in
/// in front of the given one, from the point of view of the given color. For instance, /// front of the given one, from the point of view of the given color. For instance,
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2. /// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
constexpr Bitboard forward_ranks_bb(Color c, Square s) { constexpr Bitboard forward_ranks_bb(Color c, Square s) {
@@ -412,13 +421,20 @@ inline Square msb(Bitboard b) {
#endif #endif
/// least_significant_square_bb() returns the bitboard of the least significant
/// square of a non-zero bitboard. It is equivalent to square_bb(lsb(bb)).
inline Bitboard least_significant_square_bb(Bitboard b) {
assert(b);
return b & -b;
}
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
inline Square pop_lsb(Bitboard* b) { inline Square pop_lsb(Bitboard& b) {
assert(*b); assert(b);
const Square s = lsb(*b); const Square s = lsb(b);
*b &= *b - 1; b &= b - 1;
return s; return s;
} }
@@ -430,4 +446,6 @@ inline Square frontmost_sq(Color c, Bitboard b) {
return c == WHITE ? msb(b) : lsb(b); return c == WHITE ? msb(b) : lsb(b);
} }
} // namespace Stockfish
#endif // #ifndef BITBOARD_H_INCLUDED #endif // #ifndef BITBOARD_H_INCLUDED
+5 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
#include "endgame.h" #include "endgame.h"
#include "movegen.h" #include "movegen.h"
namespace Stockfish {
namespace { namespace {
// Used to drive the king towards the edge of the board // Used to drive the king towards the edge of the board
@@ -741,3 +743,5 @@ ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
// it's probably at least a draw even with the pawn. // it's probably at least a draw even with the pawn.
return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW; return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
} }
} // namespace Stockfish
+4 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "position.h" #include "position.h"
#include "types.h" #include "types.h"
namespace Stockfish {
/// EndgameCode lists all supported endgame functions by corresponding codes /// EndgameCode lists all supported endgame functions by corresponding codes
@@ -120,4 +121,6 @@ namespace Endgames {
} }
} }
} // namespace Stockfish
#endif // #ifndef ENDGAME_H_INCLUDED #endif // #ifndef ENDGAME_H_INCLUDED
+126 -103
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@
#include "misc.h" #include "misc.h"
#include "pawns.h" #include "pawns.h"
#include "thread.h" #include "thread.h"
#include "timeman.h"
#include "uci.h" #include "uci.h"
#include "incbin/incbin.h" #include "incbin/incbin.h"
@@ -54,12 +55,13 @@
using namespace std; using namespace std;
using namespace Eval::NNUE;
namespace Stockfish {
namespace Eval { namespace Eval {
bool useNNUE; bool useNNUE;
string eval_file_loaded = "None"; string currentEvalFileName = "None";
/// NNUE::init() tries to load a NNUE network at startup time, or when the engine /// NNUE::init() tries to load a NNUE network at startup time, or when the engine
/// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue" /// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue"
@@ -76,6 +78,8 @@ namespace Eval {
return; return;
string eval_file = string(Options["EvalFile"]); string eval_file = string(Options["EvalFile"]);
if (eval_file.empty())
eval_file = EvalFileDefaultName;
#if defined(DEFAULT_NNUE_DIRECTORY) #if defined(DEFAULT_NNUE_DIRECTORY)
#define stringify2(x) #x #define stringify2(x) #x
@@ -86,13 +90,13 @@ namespace Eval {
#endif #endif
for (string directory : dirs) for (string directory : dirs)
if (eval_file_loaded != eval_file) if (currentEvalFileName != eval_file)
{ {
if (directory != "<internal>") if (directory != "<internal>")
{ {
ifstream stream(directory + eval_file, ios::binary); ifstream stream(directory + eval_file, ios::binary);
if (load_eval(eval_file, stream)) if (load_eval(eval_file, stream))
eval_file_loaded = eval_file; currentEvalFileName = eval_file;
} }
if (directory == "<internal>" && eval_file == EvalFileDefaultName) if (directory == "<internal>" && eval_file == EvalFileDefaultName)
@@ -104,10 +108,11 @@ namespace Eval {
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)), MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
size_t(gEmbeddedNNUESize)); size_t(gEmbeddedNNUESize));
(void) gEmbeddedNNUEEnd; // Silence warning on unused variable
istream stream(&buffer); istream stream(&buffer);
if (load_eval(eval_file, stream)) if (load_eval(eval_file, stream))
eval_file_loaded = eval_file; currentEvalFileName = eval_file;
} }
} }
} }
@@ -116,16 +121,16 @@ namespace Eval {
void NNUE::verify() { void NNUE::verify() {
string eval_file = string(Options["EvalFile"]); string eval_file = string(Options["EvalFile"]);
if (eval_file.empty())
eval_file = EvalFileDefaultName;
if (useNNUE && eval_file_loaded != eval_file) if (useNNUE && currentEvalFileName != eval_file)
{ {
UCI::OptionsMap defaults;
UCI::init(defaults);
string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available."; string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available.";
string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully."; string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully.";
string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file."; string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file.";
string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + string(defaults["EvalFile"]); string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + std::string(EvalFileDefaultName);
string msg5 = "The engine will be terminated now."; string msg5 = "The engine will be terminated now.";
sync_cout << "info string ERROR: " << msg1 << sync_endl; sync_cout << "info string ERROR: " << msg1 << sync_endl;
@@ -154,7 +159,7 @@ namespace Trace {
Score scores[TERM_NB][COLOR_NB]; Score scores[TERM_NB][COLOR_NB];
double to_cp(Value v) { return double(v) / PawnValueEg; } double to_cp(Value v) { return double(v) / UCI::NormalizeToPawnValue; }
void add(int idx, Color c, Score s) { void add(int idx, Color c, Score s) {
scores[idx][c] = s; scores[idx][c] = s;
@@ -178,7 +183,7 @@ namespace Trace {
else else
os << scores[t][WHITE] << " | " << scores[t][BLACK]; os << scores[t][WHITE] << " | " << scores[t][BLACK];
os << " | " << scores[t][WHITE] - scores[t][BLACK] << "\n"; os << " | " << scores[t][WHITE] - scores[t][BLACK] << " |\n";
return os; return os;
} }
} }
@@ -188,19 +193,17 @@ using namespace Trace;
namespace { namespace {
// Threshold for lazy and space evaluation // Threshold for lazy and space evaluation
constexpr Value LazyThreshold1 = Value(1565); constexpr Value LazyThreshold1 = Value(3631);
constexpr Value LazyThreshold2 = Value(1102); constexpr Value LazyThreshold2 = Value(2084);
constexpr Value SpaceThreshold = Value(11551); constexpr Value SpaceThreshold = Value(11551);
constexpr Value NNUEThreshold1 = Value(682);
constexpr Value NNUEThreshold2 = Value(176);
// KingAttackWeights[PieceType] contains king attack weights by piece type // KingAttackWeights[PieceType] contains king attack weights by piece type
constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 }; constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 76, 46, 45, 14 };
// SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type, // SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
// higher if multiple safe checks are possible for that piece type. // higher if multiple safe checks are possible for that piece type.
constexpr int SafeCheck[][2] = { constexpr int SafeCheck[][2] = {
{}, {}, {803, 1292}, {639, 974}, {1087, 1878}, {759, 1132} {}, {}, {805, 1292}, {650, 984}, {1071, 1886}, {730, 1128}
}; };
#define S(mg, eg) make_score(mg, eg) #define S(mg, eg) make_score(mg, eg)
@@ -226,57 +229,58 @@ namespace {
// BishopPawns[distance from edge] contains a file-dependent penalty for pawns on // BishopPawns[distance from edge] contains a file-dependent penalty for pawns on
// squares of the same color as our bishop. // squares of the same color as our bishop.
constexpr Score BishopPawns[int(FILE_NB) / 2] = { constexpr Score BishopPawns[int(FILE_NB) / 2] = {
S(3, 8), S(3, 9), S(2, 8), S(3, 8) S(3, 8), S(3, 9), S(2, 7), S(3, 7)
}; };
// KingProtector[knight/bishop] contains penalty for each distance unit to own king // KingProtector[knight/bishop] contains penalty for each distance unit to own king
constexpr Score KingProtector[] = { S(8, 9), S(6, 9) }; constexpr Score KingProtector[] = { S(9, 9), S(7, 9) };
// Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a // Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
// pawn protected square on rank 4 to 6 which is also safe from a pawn attack. // pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
constexpr Score Outpost[] = { S(57, 38), S(31, 24) }; constexpr Score Outpost[] = { S(54, 34), S(31, 25) };
// PassedRank[Rank] contains a bonus according to the rank of a passed pawn // PassedRank[Rank] contains a bonus according to the rank of a passed pawn
constexpr Score PassedRank[RANK_NB] = { constexpr Score PassedRank[RANK_NB] = {
S(0, 0), S(7, 27), S(16, 32), S(17, 40), S(64, 71), S(170, 174), S(278, 262) S(0, 0), S(2, 38), S(15, 36), S(22, 50), S(64, 81), S(166, 184), S(284, 269)
}; };
constexpr Score RookOnClosedFile = S(10, 5); constexpr Score RookOnClosedFile = S(10, 5);
constexpr Score RookOnOpenFile[] = { S(19, 6), S(47, 26) }; constexpr Score RookOnOpenFile[] = { S(18, 8), S(49, 26) };
// ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
// which piece type attacks which one. Attacks on lesser pieces which are // which piece type attacks which one. Attacks on lesser pieces which are
// pawn-defended are not considered. // pawn-defended are not considered.
constexpr Score ThreatByMinor[PIECE_TYPE_NB] = { constexpr Score ThreatByMinor[PIECE_TYPE_NB] = {
S(0, 0), S(5, 32), S(55, 41), S(77, 56), S(89, 119), S(79, 162) S(0, 0), S(6, 37), S(64, 50), S(82, 57), S(103, 130), S(81, 163)
}; };
constexpr Score ThreatByRook[PIECE_TYPE_NB] = { constexpr Score ThreatByRook[PIECE_TYPE_NB] = {
S(0, 0), S(3, 44), S(37, 68), S(42, 60), S(0, 39), S(58, 43) S(0, 0), S(3, 44), S(36, 71), S(44, 59), S(0, 39), S(60, 39)
}; };
constexpr Value CorneredBishop = Value(50);
// Assorted bonuses and penalties // Assorted bonuses and penalties
constexpr Score UncontestedOutpost = S( 1, 10); constexpr Score UncontestedOutpost = S( 0, 10);
constexpr Score BishopOnKingRing = S( 24, 0); constexpr Score BishopOnKingRing = S( 24, 0);
constexpr Score BishopXRayPawns = S( 4, 5); constexpr Score BishopXRayPawns = S( 4, 5);
constexpr Score CorneredBishop = S( 50, 50);
constexpr Score FlankAttacks = S( 8, 0); constexpr Score FlankAttacks = S( 8, 0);
constexpr Score Hanging = S( 69, 36); constexpr Score Hanging = S( 72, 40);
constexpr Score KnightOnQueen = S( 16, 11); constexpr Score KnightOnQueen = S( 16, 11);
constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3); constexpr Score MinorBehindPawn = S( 18, 3);
constexpr Score PassedFile = S( 11, 8); constexpr Score PassedFile = S( 13, 8);
constexpr Score PawnlessFlank = S( 17, 95); constexpr Score PawnlessFlank = S( 19, 97);
constexpr Score ReachableOutpost = S( 31, 22); constexpr Score ReachableOutpost = S( 33, 19);
constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RestrictedPiece = S( 6, 7);
constexpr Score RookOnKingRing = S( 16, 0); constexpr Score RookOnKingRing = S( 16, 0);
constexpr Score SliderOnQueen = S( 60, 18); constexpr Score SliderOnQueen = S( 62, 21);
constexpr Score ThreatByKing = S( 24, 89); constexpr Score ThreatByKing = S( 24, 87);
constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score ThreatBySafePawn = S(167, 99);
constexpr Score TrappedRook = S( 55, 13); constexpr Score TrappedRook = S( 55, 13);
constexpr Score WeakQueenProtection = S( 14, 0); constexpr Score WeakQueenProtection = S( 14, 0);
constexpr Score WeakQueen = S( 56, 15); constexpr Score WeakQueen = S( 57, 19);
#undef S #undef S
@@ -394,8 +398,9 @@ namespace {
attackedBy[Us][Pt] = 0; attackedBy[Us][Pt] = 0;
while (b1) { while (b1)
Square s = pop_lsb(&b1); {
Square s = pop_lsb(b1);
// Find attacked squares, including x-ray attacks for bishops and rooks // Find attacked squares, including x-ray attacks for bishops and rooks
b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN)) b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN))
@@ -475,9 +480,8 @@ namespace {
{ {
Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
if (pos.piece_on(s + d) == make_piece(Us, PAWN)) if (pos.piece_on(s + d) == make_piece(Us, PAWN))
score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4 score -= !pos.empty(s + d + pawn_push(Us)) ? 4 * make_score(CorneredBishop, CorneredBishop)
: pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2 : 3 * make_score(CorneredBishop, CorneredBishop);
: CorneredBishop;
} }
} }
} }
@@ -656,11 +660,11 @@ namespace {
{ {
b = (defended | weak) & (attackedBy[Us][KNIGHT] | attackedBy[Us][BISHOP]); b = (defended | weak) & (attackedBy[Us][KNIGHT] | attackedBy[Us][BISHOP]);
while (b) while (b)
score += ThreatByMinor[type_of(pos.piece_on(pop_lsb(&b)))]; score += ThreatByMinor[type_of(pos.piece_on(pop_lsb(b)))];
b = weak & attackedBy[Us][ROOK]; b = weak & attackedBy[Us][ROOK];
while (b) while (b)
score += ThreatByRook[type_of(pos.piece_on(pop_lsb(&b)))]; score += ThreatByRook[type_of(pos.piece_on(pop_lsb(b)))];
if (weak & attackedBy[Us][KING]) if (weak & attackedBy[Us][KING])
score += ThreatByKing; score += ThreatByKing;
@@ -758,7 +762,7 @@ namespace {
while (b) while (b)
{ {
Square s = pop_lsb(&b); Square s = pop_lsb(b);
assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
@@ -904,7 +908,7 @@ namespace {
Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK; Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
int sf = me->scale_factor(pos, strongSide); int sf = me->scale_factor(pos, strongSide);
// If scale factor is not already specific, scale down via general heuristics // If scale factor is not already specific, scale up/down via general heuristics
if (sf == SCALE_FACTOR_NORMAL) if (sf == SCALE_FACTOR_NORMAL)
{ {
if (pos.opposite_bishops()) if (pos.opposite_bishops())
@@ -977,7 +981,7 @@ namespace {
// Initialize score by reading the incrementally updated scores included in // Initialize score by reading the incrementally updated scores included in
// the position object (material + piece square tables) and the material // the position object (material + piece square tables) and the material
// imbalance. Score is computed internally from the white point of view. // imbalance. Score is computed internally from the white point of view.
Score score = pos.psq_score() + me->imbalance() + pos.this_thread()->contempt; Score score = pos.psq_score() + me->imbalance();
// Probe the pawn hash table // Probe the pawn hash table
pe = Pawns::probe(pos); pe = Pawns::probe(pos);
@@ -985,7 +989,9 @@ namespace {
// Early exit if score is high // Early exit if score is high
auto lazy_skip = [&](Value lazyThreshold) { auto lazy_skip = [&](Value lazyThreshold) {
return abs(mg_value(score) + eg_value(score)) / 2 > lazyThreshold + pos.non_pawn_material() / 64; return abs(mg_value(score) + eg_value(score)) > lazyThreshold
+ std::abs(pos.this_thread()->bestValue) * 5 / 4
+ pos.non_pawn_material() / 32;
}; };
if (lazy_skip(LazyThreshold1)) if (lazy_skip(LazyThreshold1))
@@ -1031,60 +1037,63 @@ make_v:
v = (v / 16) * 16; v = (v / 16) * 16;
// Side to move point of view // Side to move point of view
v = (pos.side_to_move() == WHITE ? v : -v) + Tempo; v = (pos.side_to_move() == WHITE ? v : -v);
return v; return v;
} }
} // namespace } // namespace Eval
/// evaluate() is the evaluator for the outer world. It returns a static /// evaluate() is the evaluator for the outer world. It returns a static
/// evaluation of the position from the point of view of the side to move. /// evaluation of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos) { Value Eval::evaluate(const Position& pos, int* complexity) {
Value v; Value v;
Value psq = pos.psq_eg_stm();
if (!Eval::useNNUE) // We use the much less accurate but faster Classical eval when the NNUE
// option is set to false. Otherwise we use the NNUE eval unless the
// PSQ advantage is decisive and several pieces remain. (~3 Elo)
bool useClassical = !useNNUE || (pos.count<ALL_PIECES>() > 7 && abs(psq) > 1760);
if (useClassical)
v = Evaluation<NO_TRACE>(pos).value(); v = Evaluation<NO_TRACE>(pos).value();
else else
{ {
// Scale and shift NNUE for compatibility with search and classical evaluation int nnueComplexity;
auto adjusted_NNUE = [&](){ int scale = 1064 + 106 * pos.non_pawn_material() / 5120;
int mat = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>();
return NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo;
};
// If there is PSQ imbalance use classical eval, with small probability if it is small Color stm = pos.side_to_move();
Value psq = Value(abs(eg_value(pos.psq_score()))); Value optimism = pos.this_thread()->optimism[stm];
int r50 = 16 + pos.rule50_count();
bool largePsq = psq * 16 > (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50;
bool classical = largePsq || (psq > PawnValueMg / 4 && !(pos.this_thread()->nodes & 0xB));
// Use classical evaluation for really low piece endgames. Value nnue = NNUE::evaluate(pos, true, &nnueComplexity);
// The most critical case is a bishop + A/H file pawn vs naked king draw.
bool strongClassical = pos.non_pawn_material() < 2 * RookValueMg && pos.count<PAWN>() < 2;
v = classical || strongClassical ? Evaluation<NO_TRACE>(pos).value() : adjusted_NNUE(); // Blend nnue complexity with (semi)classical complexity
nnueComplexity = ( 416 * nnueComplexity
+ 424 * abs(psq - nnue)
+ (optimism > 0 ? int(optimism) * int(psq - nnue) : 0)
) / 1024;
// If the classical eval is small and imbalance large, use NNUE nevertheless. // Return hybrid NNUE complexity to caller
// For the case of opposite colored bishops, switch to NNUE eval with if (complexity)
// small probability if the classical eval is less than the threshold. *complexity = nnueComplexity;
if ( largePsq && !strongClassical
&& ( abs(v) * 16 < NNUEThreshold2 * r50 optimism = optimism * (269 + nnueComplexity) / 256;
|| ( pos.opposite_bishops() v = (nnue * scale + optimism * (scale - 754)) / 1024;
&& abs(v) * 16 < (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50
&& !(pos.this_thread()->nodes & 0xB))))
v = adjusted_NNUE();
} }
// Damp down the evaluation linearly when shuffling // Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100; v = v * (195 - pos.rule50_count()) / 211;
// Guarantee evaluation does not hit the tablebase range // Guarantee evaluation does not hit the tablebase range
v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
// When not using NNUE, return classical complexity to caller
if (complexity && (!useNNUE || useClassical))
*complexity = abs(v - psq);
return v; return v;
} }
@@ -1093,7 +1102,7 @@ Value Eval::evaluate(const Position& pos) {
/// descriptions and values of each evaluation term. Useful for debugging. /// descriptions and values of each evaluation term. Useful for debugging.
/// Trace scores are from white's point of view /// Trace scores are from white's point of view
std::string Eval::trace(const Position& pos) { std::string Eval::trace(Position& pos) {
if (pos.checkers()) if (pos.checkers())
return "Final evaluation: none (in check)"; return "Final evaluation: none (in check)";
@@ -1105,44 +1114,58 @@ std::string Eval::trace(const Position& pos) {
std::memset(scores, 0, sizeof(scores)); std::memset(scores, 0, sizeof(scores));
pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt // Reset any global variable used in eval
pos.this_thread()->bestValue = VALUE_ZERO;
pos.this_thread()->optimism[WHITE] = VALUE_ZERO;
pos.this_thread()->optimism[BLACK] = VALUE_ZERO;
v = Evaluation<TRACE>(pos).value(); v = Evaluation<TRACE>(pos).value();
ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2) ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2)
<< " Term | White | Black | Total \n" << " Contributing terms for the classical eval:\n"
<< " | MG EG | MG EG | MG EG \n" << "+------------+-------------+-------------+-------------+\n"
<< " ------------+-------------+-------------+------------\n" << "| Term | White | Black | Total |\n"
<< " Material | " << Term(MATERIAL) << "| | MG EG | MG EG | MG EG |\n"
<< " Imbalance | " << Term(IMBALANCE) << "+------------+-------------+-------------+-------------+\n"
<< " Pawns | " << Term(PAWN) << "| Material | " << Term(MATERIAL)
<< " Knights | " << Term(KNIGHT) << "| Imbalance | " << Term(IMBALANCE)
<< " Bishops | " << Term(BISHOP) << "| Pawns | " << Term(PAWN)
<< " Rooks | " << Term(ROOK) << "| Knights | " << Term(KNIGHT)
<< " Queens | " << Term(QUEEN) << "| Bishops | " << Term(BISHOP)
<< " Mobility | " << Term(MOBILITY) << "| Rooks | " << Term(ROOK)
<< " King safety | " << Term(KING) << "| Queens | " << Term(QUEEN)
<< " Threats | " << Term(THREAT) << "| Mobility | " << Term(MOBILITY)
<< " Passed | " << Term(PASSED) << "|King safety | " << Term(KING)
<< " Space | " << Term(SPACE) << "| Threats | " << Term(THREAT)
<< " Winnable | " << Term(WINNABLE) << "| Passed | " << Term(PASSED)
<< " ------------+-------------+-------------+------------\n" << "| Space | " << Term(SPACE)
<< " Total | " << Term(TOTAL); << "| Winnable | " << Term(WINNABLE)
<< "+------------+-------------+-------------+-------------+\n"
v = pos.side_to_move() == WHITE ? v : -v; << "| Total | " << Term(TOTAL)
<< "+------------+-------------+-------------+-------------+\n";
ss << "\nClassical evaluation: " << to_cp(v) << " (white side)\n";
if (Eval::useNNUE)
ss << '\n' << NNUE::trace(pos) << '\n';
ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15);
v = pos.side_to_move() == WHITE ? v : -v;
ss << "\nClassical evaluation " << to_cp(v) << " (white side)\n";
if (Eval::useNNUE) if (Eval::useNNUE)
{ {
v = NNUE::evaluate(pos); v = NNUE::evaluate(pos, false);
v = pos.side_to_move() == WHITE ? v : -v; v = pos.side_to_move() == WHITE ? v : -v;
ss << "\nNNUE evaluation: " << to_cp(v) << " (white side)\n"; ss << "NNUE evaluation " << to_cp(v) << " (white side)\n";
} }
v = evaluate(pos); v = evaluate(pos);
v = pos.side_to_move() == WHITE ? v : -v; v = pos.side_to_move() == WHITE ? v : -v;
ss << "\nFinal evaluation: " << to_cp(v) << " (white side)\n"; ss << "Final evaluation " << to_cp(v) << " (white side)";
if (Eval::useNNUE)
ss << " [with scaled NNUE, hybrid, ...]";
ss << "\n";
return ss.str(); return ss.str();
} }
} // namespace Stockfish
+17 -7
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -20,33 +20,43 @@
#define EVALUATE_H_INCLUDED #define EVALUATE_H_INCLUDED
#include <string> #include <string>
#include <optional>
#include "types.h" #include "types.h"
namespace Stockfish {
class Position; class Position;
namespace Eval { namespace Eval {
std::string trace(const Position& pos); std::string trace(Position& pos);
Value evaluate(const Position& pos); Value evaluate(const Position& pos, int* complexity = nullptr);
extern bool useNNUE; extern bool useNNUE;
extern std::string eval_file_loaded; extern std::string currentEvalFileName;
// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
// for the build process (profile-build and fishtest) to work. Do not change the // for the build process (profile-build and fishtest) to work. Do not change the
// name of the macro, as it is used in the Makefile. // name of the macro, as it is used in the Makefile.
#define EvalFileDefaultName "nn-62ef826d1a6d.nnue" #define EvalFileDefaultName "nn-ad9b42354671.nnue"
namespace NNUE { namespace NNUE {
Value evaluate(const Position& pos); std::string trace(Position& pos);
bool load_eval(std::string name, std::istream& stream); Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr);
void init(); void init();
void verify(); void verify();
bool load_eval(std::string name, std::istream& stream);
bool save_eval(std::ostream& stream);
bool save_eval(const std::optional<std::string>& filename);
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
} // namespace Stockfish
#endif // #ifndef EVALUATE_H_INCLUDED #endif // #ifndef EVALUATE_H_INCLUDED
+3 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,6 +28,8 @@
#include "tt.h" #include "tt.h"
#include "uci.h" #include "uci.h"
using namespace Stockfish;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
std::cout << engine_info() << std::endl; std::cout << engine_info() << std::endl;
+6 -2
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
using namespace std; using namespace std;
namespace Stockfish {
namespace { namespace {
#define S(mg, eg) make_score(mg, eg) #define S(mg, eg) make_score(mg, eg)
@@ -72,7 +74,7 @@ namespace {
bool is_KBPsK(const Position& pos, Color us) { bool is_KBPsK(const Position& pos, Color us) {
return pos.non_pawn_material(us) == BishopValueMg return pos.non_pawn_material(us) == BishopValueMg
&& pos.count<PAWN >(us) >= 1; && pos.count<PAWN>(us) >= 1;
} }
bool is_KQKRPs(const Position& pos, Color us) { bool is_KQKRPs(const Position& pos, Color us) {
@@ -223,3 +225,5 @@ Entry* probe(const Position& pos) {
} }
} // namespace Material } // namespace Material
} // namespace Stockfish
+3 -3
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
#include "position.h" #include "position.h"
#include "types.h" #include "types.h"
namespace Material { namespace Stockfish::Material {
/// Material::Entry contains various information about a material configuration. /// Material::Entry contains various information about a material configuration.
/// It contains a material imbalance evaluation, a function pointer to a special /// It contains a material imbalance evaluation, a function pointer to a special
@@ -66,6 +66,6 @@ typedef HashTable<Entry, 8192> Table;
Entry* probe(const Position& pos); Entry* probe(const Position& pos);
} // namespace Material } // namespace Stockfish::Material
#endif // #ifndef MATERIAL_H_INCLUDED #endif // #ifndef MATERIAL_H_INCLUDED
+101 -42
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -36,6 +36,8 @@ typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP,
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY); typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY);
typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY); typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
typedef bool(*fun4_t)(USHORT, PGROUP_AFFINITY, USHORT, PUSHORT);
typedef WORD(*fun5_t)();
} }
#endif #endif
@@ -51,7 +53,7 @@ typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) || (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) #if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) || (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) || defined(__e2k__)
#define POSIXALIGNEDALLOC #define POSIXALIGNEDALLOC
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@@ -61,11 +63,12 @@ typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
using namespace std; using namespace std;
namespace Stockfish {
namespace { namespace {
/// Version number. If Version is left empty, then compile date in the format /// Version number or dev.
/// DD-MM-YY and show in engine_info. const string version = "15.1";
const string Version = "13";
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
/// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
@@ -108,7 +111,14 @@ public:
static Logger l; static Logger l;
if (!fname.empty() && !l.file.is_open()) if (l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
if (!fname.empty())
{ {
l.file.open(fname, ifstream::out); l.file.open(fname, ifstream::out);
@@ -121,35 +131,47 @@ public:
cin.rdbuf(&l.in); cin.rdbuf(&l.in);
cout.rdbuf(&l.out); cout.rdbuf(&l.out);
} }
else if (fname.empty() && l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
} }
}; };
} // namespace } // namespace
/// engine_info() returns the full name of the current Stockfish version. This /// engine_info() returns the full name of the current Stockfish version.
/// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when /// For local dev compiles we try to append the commit sha and commit date
/// the program was compiled) or "Stockfish <Version>", depending on whether /// from git if that fails only the local compilation date is set and "nogit" is specified:
/// Version is empty. /// Stockfish dev-YYYYMMDD-SHA
/// or
/// Stockfish dev-YYYYMMDD-nogit
///
/// For releases (non dev builds) we only include the version number:
/// Stockfish version
const string engine_info(bool to_uci) { string engine_info(bool to_uci) {
stringstream ss;
ss << "Stockfish " << version << setfill('0');
const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); if (version == "dev")
string month, day, year;
stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
ss << "Stockfish " << Version << setfill('0');
if (Version.empty())
{ {
ss << "-";
#ifdef GIT_DATE
ss << GIT_DATE;
#else
const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
string month, day, year;
stringstream date(__DATE__); // From compiler, format is "Sep 21 2008"
date >> month >> day >> year; date >> month >> day >> year;
ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2); ss << year << setw(2) << setfill('0') << (1 + months.find(month) / 4) << setw(2) << setfill('0') << day;
#endif
ss << "-";
#ifdef GIT_SHA
ss << GIT_SHA;
#else
ss << "nogit";
#endif
} }
ss << (to_uci ? "\nid author ": " by ") ss << (to_uci ? "\nid author ": " by ")
@@ -161,7 +183,7 @@ const string engine_info(bool to_uci) {
/// compiler_info() returns a string trying to describe the compiler we use /// compiler_info() returns a string trying to describe the compiler we use
const std::string compiler_info() { std::string compiler_info() {
#define stringify2(x) #x #define stringify2(x) #x
#define stringify(x) stringify2(x) #define stringify(x) stringify2(x)
@@ -190,6 +212,18 @@ const std::string compiler_info() {
compiler += "(version "; compiler += "(version ";
compiler += stringify(_MSC_FULL_VER) "." stringify(_MSC_BUILD); compiler += stringify(_MSC_FULL_VER) "." stringify(_MSC_BUILD);
compiler += ")"; compiler += ")";
#elif defined(__e2k__) && defined(__LCC__)
#define dot_ver2(n) \
compiler += (char)'.'; \
compiler += (char)('0' + (n) / 10); \
compiler += (char)('0' + (n) % 10);
compiler += "MCST LCC ";
compiler += "(version ";
compiler += std::to_string(__LCC__ / 100);
dot_ver2(__LCC__ % 100)
dot_ver2(__LCC_MINOR__)
compiler += ")";
#elif __GNUC__ #elif __GNUC__
compiler += "g++ (GNUC) "; compiler += "g++ (GNUC) ";
compiler += make_version_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); compiler += make_version_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
@@ -361,7 +395,11 @@ void std_aligned_free(void* ptr) {
#if defined(_WIN32) #if defined(_WIN32)
static void* aligned_large_pages_alloc_win(size_t allocSize) { static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) {
#if !defined(_WIN64)
return nullptr;
#else
HANDLE hProcessToken { }; HANDLE hProcessToken { };
LUID luid { }; LUID luid { };
@@ -404,12 +442,14 @@ static void* aligned_large_pages_alloc_win(size_t allocSize) {
CloseHandle(hProcessToken); CloseHandle(hProcessToken);
return mem; return mem;
#endif
} }
void* aligned_large_pages_alloc(size_t allocSize) { void* aligned_large_pages_alloc(size_t allocSize) {
// Try to allocate large pages // Try to allocate large pages
void* mem = aligned_large_pages_alloc_win(allocSize); void* mem = aligned_large_pages_alloc_windows(allocSize);
// Fall back to regular, page aligned, allocation if necessary // Fall back to regular, page aligned, allocation if necessary
if (!mem) if (!mem)
@@ -449,8 +489,9 @@ void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE)) if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{ {
DWORD err = GetLastError(); DWORD err = GetLastError();
std::cerr << "Failed to free transposition table. Error code: 0x" << std::cerr << "Failed to free large page memory. Error code: 0x"
std::hex << err << std::dec << std::endl; << std::hex << err
<< std::dec << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@@ -472,11 +513,11 @@ void bindThisThread(size_t) {}
#else #else
/// best_group() retrieves logical processor information using Windows specific /// best_node() retrieves logical processor information using Windows specific
/// API and returns the best group id for the thread with index idx. Original /// API and returns the best node id for the thread with index idx. Original
/// code from Texel by Peter Österlund. /// code from Texel by Peter Österlund.
int best_group(size_t idx) { int best_node(size_t idx) {
int threads = 0; int threads = 0;
int nodes = 0; int nodes = 0;
@@ -490,7 +531,8 @@ int best_group(size_t idx) {
if (!fun1) if (!fun1)
return -1; return -1;
// First call to get returnLength. We expect it to fail due to null buffer // First call to GetLogicalProcessorInformationEx() to get returnLength.
// We expect the call to fail due to null buffer.
if (fun1(RelationAll, nullptr, &returnLength)) if (fun1(RelationAll, nullptr, &returnLength))
return -1; return -1;
@@ -498,7 +540,7 @@ int best_group(size_t idx) {
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr; SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr;
ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength); ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength);
// Second call, now we expect to succeed // Second call to GetLogicalProcessorInformationEx(), now we expect to succeed
if (!fun1(RelationAll, buffer, &returnLength)) if (!fun1(RelationAll, buffer, &returnLength))
{ {
free(buffer); free(buffer);
@@ -548,22 +590,38 @@ int best_group(size_t idx) {
void bindThisThread(size_t idx) { void bindThisThread(size_t idx) {
// Use only local variables to be thread-safe // Use only local variables to be thread-safe
int group = best_group(idx); int node = best_node(idx);
if (group == -1) if (node == -1)
return; return;
// Early exit if the needed API are not available at runtime // Early exit if the needed API are not available at runtime
HMODULE k32 = GetModuleHandle("Kernel32.dll"); HMODULE k32 = GetModuleHandle("Kernel32.dll");
auto fun2 = (fun2_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMaskEx"); auto fun2 = (fun2_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMaskEx");
auto fun3 = (fun3_t)(void(*)())GetProcAddress(k32, "SetThreadGroupAffinity"); auto fun3 = (fun3_t)(void(*)())GetProcAddress(k32, "SetThreadGroupAffinity");
auto fun4 = (fun4_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMask2");
auto fun5 = (fun5_t)(void(*)())GetProcAddress(k32, "GetMaximumProcessorGroupCount");
if (!fun2 || !fun3) if (!fun2 || !fun3)
return; return;
GROUP_AFFINITY affinity; if (!fun4 || !fun5)
if (fun2(group, &affinity)) {
fun3(GetCurrentThread(), &affinity, nullptr); GROUP_AFFINITY affinity;
if (fun2(node, &affinity)) // GetNumaNodeProcessorMaskEx
fun3(GetCurrentThread(), &affinity, nullptr); // SetThreadGroupAffinity
}
else
{
// If a numa node has more than one processor group, we assume they are
// sized equal and we spread threads evenly across the groups.
USHORT elements, returnedElements;
elements = fun5(); // GetMaximumProcessorGroupCount
GROUP_AFFINITY *affinity = (GROUP_AFFINITY*)malloc(elements * sizeof(GROUP_AFFINITY));
if (fun4(node, affinity, elements, &returnedElements)) // GetNumaNodeProcessorMask2
fun3(GetCurrentThread(), &affinity[idx % returnedElements], nullptr); // SetThreadGroupAffinity
free(affinity);
}
} }
#endif #endif
@@ -584,8 +642,7 @@ string argv0; // path+name of the executable binary, as given by argv
string binaryDirectory; // path of the executable directory string binaryDirectory; // path of the executable directory
string workingDirectory; // path of the working directory string workingDirectory; // path of the working directory
void init(int argc, char* argv[]) { void init([[maybe_unused]] int argc, char* argv[]) {
(void)argc;
string pathSeparator; string pathSeparator;
// extract the path+name of the executable binary // extract the path+name of the executable binary
@@ -626,3 +683,5 @@ void init(int argc, char* argv[]) {
} // namespace CommandLine } // namespace CommandLine
} // namespace Stockfish
+58 -6
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,8 +28,10 @@
#include "types.h" #include "types.h"
const std::string engine_info(bool to_uci = false); namespace Stockfish {
const std::string compiler_info();
std::string engine_info(bool to_uci = false);
std::string compiler_info();
void prefetch(void* addr); void prefetch(void* addr);
void start_logger(const std::string& fname); void start_logger(const std::string& fname);
void* std_aligned_alloc(size_t alignment, size_t size); void* std_aligned_alloc(size_t alignment, size_t size);
@@ -64,9 +66,10 @@ std::ostream& operator<<(std::ostream&, SyncCout);
#define sync_cout std::cout << IO_LOCK #define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK #define sync_endl std::endl << IO_UNLOCK
// `ptr` must point to an array of size at least
// `sizeof(T) * N + alignment` bytes, where `N` is the // align_ptr_up() : get the first aligned element of an array.
// number of elements in the array. // ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes,
// where N is the number of elements in the array.
template <uintptr_t Alignment, typename T> template <uintptr_t Alignment, typename T>
T* align_ptr_up(T* ptr) T* align_ptr_up(T* ptr)
{ {
@@ -76,6 +79,53 @@ T* align_ptr_up(T* ptr)
return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment)); return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
} }
// IsLittleEndian : true if and only if the binary is compiled on a little endian machine
static inline const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
static inline const bool IsLittleEndian = (Le.c[0] == 4);
// RunningAverage : a class to calculate a running average of a series of values.
// For efficiency, all computations are done with integers.
class RunningAverage {
public:
// Reset the running average to rational value p / q
void set(int64_t p, int64_t q)
{ average = p * PERIOD * RESOLUTION / q; }
// Update average with value v
void update(int64_t v)
{ average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; }
// Test if average is strictly greater than rational a / b
bool is_greater(int64_t a, int64_t b) const
{ return b * average > a * (PERIOD * RESOLUTION); }
int64_t value() const
{ return average / (PERIOD * RESOLUTION); }
private :
static constexpr int64_t PERIOD = 4096;
static constexpr int64_t RESOLUTION = 1024;
int64_t average;
};
template <typename T, std::size_t MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
void push_back(const T& value) { values_[size_++] = value; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
private:
T values_[MaxSize];
std::size_t size_ = 0;
};
/// xorshift64star Pseudo-Random Number Generator /// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated /// This class is based on original code written and dedicated
/// to the public domain by Sebastiano Vigna (2014). /// to the public domain by Sebastiano Vigna (2014).
@@ -143,4 +193,6 @@ namespace CommandLine {
extern std::string workingDirectory; // path of the working directory extern std::string workingDirectory; // path of the working directory
} }
} // namespace Stockfish
#endif // #ifndef MISC_H_INCLUDED #endif // #ifndef MISC_H_INCLUDED
+70 -158
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,24 +21,21 @@
#include "movegen.h" #include "movegen.h"
#include "position.h" #include "position.h"
namespace Stockfish {
namespace { namespace {
template<GenType Type, Direction D> template<GenType Type, Direction D>
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) { ExtMove* make_promotions(ExtMove* moveList, Square to) {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
{
*moveList++ = make<PROMOTION>(to - D, to, QUEEN); *moveList++ = make<PROMOTION>(to - D, to, QUEEN);
if (attacks_bb<KNIGHT>(to) & ksq)
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
}
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS) if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
{ {
*moveList++ = make<PROMOTION>(to - D, to, ROOK); *moveList++ = make<PROMOTION>(to - D, to, ROOK);
*moveList++ = make<PROMOTION>(to - D, to, BISHOP); *moveList++ = make<PROMOTION>(to - D, to, BISHOP);
if (!(attacks_bb<KNIGHT>(to) & ksq)) *moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
} }
return moveList; return moveList;
@@ -55,20 +52,16 @@ namespace {
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
const Square ksq = pos.square<KING>(Them); const Bitboard emptySquares = ~pos.pieces();
Bitboard emptySquares; const Bitboard enemies = Type == EVASIONS ? pos.checkers()
: pos.pieces(Them);
Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB; Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB; Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
Bitboard enemies = (Type == EVASIONS ? pos.pieces(Them) & target:
Type == CAPTURES ? target : pos.pieces(Them));
// Single and double pawn pushes, no promotions // Single and double pawn pushes, no promotions
if (Type != CAPTURES) if (Type != CAPTURES)
{ {
emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces());
Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares; Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares;
Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares; Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares;
@@ -80,33 +73,24 @@ namespace {
if (Type == QUIET_CHECKS) if (Type == QUIET_CHECKS)
{ {
b1 &= pawn_attacks_bb(Them, ksq); // To make a quiet check, you either make a direct check by pushing a pawn
b2 &= pawn_attacks_bb(Them, ksq); // or push a blocker pawn that is not on the same file as the enemy king.
// Discovered check promotion has been already generated amongst the captures.
// Add pawn pushes which give discovered check. This is possible only Square ksq = pos.square<KING>(Them);
// if the pawn is not on the same file as the enemy king, because we Bitboard dcCandidatePawns = pos.blockers_for_king(Them) & ~file_bb(ksq);
// don't generate captures. Note that a possible discovered check b1 &= pawn_attacks_bb(Them, ksq) | shift< Up>(dcCandidatePawns);
// promotion has been already generated amongst the captures. b2 &= pawn_attacks_bb(Them, ksq) | shift<Up+Up>(dcCandidatePawns);
Bitboard dcCandidateQuiets = pos.blockers_for_king(Them) & pawnsNotOn7;
if (dcCandidateQuiets)
{
Bitboard dc1 = shift<Up>(dcCandidateQuiets) & emptySquares & ~file_bb(ksq);
Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;
b1 |= dc1;
b2 |= dc2;
}
} }
while (b1) while (b1)
{ {
Square to = pop_lsb(&b1); Square to = pop_lsb(b1);
*moveList++ = make_move(to - Up, to); *moveList++ = make_move(to - Up, to);
} }
while (b2) while (b2)
{ {
Square to = pop_lsb(&b2); Square to = pop_lsb(b2);
*moveList++ = make_move(to - Up - Up, to); *moveList++ = make_move(to - Up - Up, to);
} }
} }
@@ -114,24 +98,21 @@ namespace {
// Promotions and underpromotions // Promotions and underpromotions
if (pawnsOn7) if (pawnsOn7)
{ {
if (Type == CAPTURES)
emptySquares = ~pos.pieces();
if (Type == EVASIONS)
emptySquares &= target;
Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies; Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies;
Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies; Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies;
Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares; Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;
if (Type == EVASIONS)
b3 &= target;
while (b1) while (b1)
moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(&b1), ksq); moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(b1));
while (b2) while (b2)
moveList = make_promotions<Type, UpLeft >(moveList, pop_lsb(&b2), ksq); moveList = make_promotions<Type, UpLeft >(moveList, pop_lsb(b2));
while (b3) while (b3)
moveList = make_promotions<Type, Up >(moveList, pop_lsb(&b3), ksq); moveList = make_promotions<Type, Up >(moveList, pop_lsb(b3));
} }
// Standard and en passant captures // Standard and en passant captures
@@ -142,13 +123,13 @@ namespace {
while (b1) while (b1)
{ {
Square to = pop_lsb(&b1); Square to = pop_lsb(b1);
*moveList++ = make_move(to - UpRight, to); *moveList++ = make_move(to - UpRight, to);
} }
while (b2) while (b2)
{ {
Square to = pop_lsb(&b2); Square to = pop_lsb(b2);
*moveList++ = make_move(to - UpLeft, to); *moveList++ = make_move(to - UpLeft, to);
} }
@@ -156,7 +137,7 @@ namespace {
{ {
assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6)); assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));
// An en passant capture cannot resolve a discovered check. // An en passant capture cannot resolve a discovered check
if (Type == EVASIONS && (target & (pos.ep_square() + Up))) if (Type == EVASIONS && (target & (pos.ep_square() + Up)))
return moveList; return moveList;
@@ -165,7 +146,7 @@ namespace {
assert(b1); assert(b1);
while (b1) while (b1)
*moveList++ = make<EN_PASSANT>(pop_lsb(&b1), pos.ep_square()); *moveList++ = make<EN_PASSANT>(pop_lsb(b1), pos.ep_square());
} }
} }
@@ -173,27 +154,24 @@ namespace {
} }
template<PieceType Pt, bool Checks> template<Color Us, PieceType Pt, bool Checks>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard piecesToMove, Bitboard target) { ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()"); static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
Bitboard bb = piecesToMove & pos.pieces(Pt); Bitboard bb = pos.pieces(Us, Pt);
if (!bb)
return moveList;
[[maybe_unused]] const Bitboard checkSquares = pos.check_squares(Pt);
while (bb) {
Square from = pop_lsb(&bb);
while (bb)
{
Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target; Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
if constexpr (Checks)
b &= checkSquares; // To check, you either move freely a blocker or make a direct check.
if (Checks && (Pt == QUEEN || !(pos.blockers_for_king(~Us) & from)))
b &= pos.check_squares(Pt);
while (b) while (b)
*moveList++ = make_move(from, pop_lsb(&b)); *moveList++ = make_move(from, pop_lsb(b));
} }
return moveList; return moveList;
@@ -206,45 +184,34 @@ namespace {
static_assert(Type != LEGAL, "Unsupported type in generate_all()"); static_assert(Type != LEGAL, "Unsupported type in generate_all()");
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
Bitboard target, piecesToMove = pos.pieces(Us); const Square ksq = pos.square<KING>(Us);
Bitboard target;
if(Type == QUIET_CHECKS) // Skip generating non-king moves when in double check
piecesToMove &= ~pos.blockers_for_king(~Us); if (Type != EVASIONS || !more_than_one(pos.checkers()))
switch (Type)
{ {
case CAPTURES: target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers()))
target = pos.pieces(~Us); : Type == NON_EVASIONS ? ~pos.pieces( Us)
break; : Type == CAPTURES ? pos.pieces(~Us)
case QUIETS: : ~pos.pieces( ); // QUIETS || QUIET_CHECKS
case QUIET_CHECKS:
target = ~pos.pieces(); moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
break; moveList = generate_moves<Us, KNIGHT, Checks>(pos, moveList, target);
case EVASIONS: moveList = generate_moves<Us, BISHOP, Checks>(pos, moveList, target);
{ moveList = generate_moves<Us, ROOK, Checks>(pos, moveList, target);
Square checksq = lsb(pos.checkers()); moveList = generate_moves<Us, QUEEN, Checks>(pos, moveList, target);
target = between_bb(pos.square<KING>(Us), checksq) | checksq;
break;
}
case NON_EVASIONS:
target = ~pos.pieces(Us);
break;
} }
moveList = generate_pawn_moves<Us, Type>(pos, moveList, target); if (!Checks || pos.blockers_for_king(~Us) & ksq)
moveList = generate_moves<KNIGHT, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves<BISHOP, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves< ROOK, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves< QUEEN, Checks>(pos, moveList, piecesToMove, target);
if (Type != QUIET_CHECKS && Type != EVASIONS)
{ {
Square ksq = pos.square<KING>(Us); Bitboard b = attacks_bb<KING>(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
Bitboard b = attacks_bb<KING>(ksq) & target; if (Checks)
while (b) b &= ~attacks_bb<QUEEN>(pos.square<KING>(~Us));
*moveList++ = make_move(ksq, pop_lsb(&b));
if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING)) while (b)
*moveList++ = make_move(ksq, pop_lsb(b));
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } ) for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
if (!pos.castling_impeded(cr) && pos.can_castle(cr)) if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr)); *moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
@@ -256,8 +223,10 @@ namespace {
} // namespace } // namespace
/// <CAPTURES> Generates all pseudo-legal captures plus queen and checking knight promotions /// <CAPTURES> Generates all pseudo-legal captures plus queen promotions
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions (except checking knight) /// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
/// <EVASIONS> Generates all pseudo-legal check evasions when the side to move is in check
/// <QUIET_CHECKS> Generates all pseudo-legal non-captures giving check, except castling and promotions
/// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures /// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
/// ///
/// Returns a pointer to the end of the move list. /// Returns a pointer to the end of the move list.
@@ -265,8 +234,8 @@ namespace {
template<GenType Type> template<GenType Type>
ExtMove* generate(const Position& pos, ExtMove* moveList) { ExtMove* generate(const Position& pos, ExtMove* moveList) {
static_assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS, "Unsupported type in generate()"); static_assert(Type != LEGAL, "Unsupported type in generate()");
assert(!pos.checkers()); assert((Type == EVASIONS) == (bool)pos.checkers());
Color us = pos.side_to_move(); Color us = pos.side_to_move();
@@ -277,70 +246,11 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) {
// Explicit template instantiations // Explicit template instantiations
template ExtMove* generate<CAPTURES>(const Position&, ExtMove*); template ExtMove* generate<CAPTURES>(const Position&, ExtMove*);
template ExtMove* generate<QUIETS>(const Position&, ExtMove*); template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
template ExtMove* generate<EVASIONS>(const Position&, ExtMove*);
template ExtMove* generate<QUIET_CHECKS>(const Position&, ExtMove*);
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*); template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures giving check,
/// except castling. Returns a pointer to the end of the move list.
template<>
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
assert(!pos.checkers());
Color us = pos.side_to_move();
Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us) & ~pos.pieces(PAWN);
while (dc)
{
Square from = pop_lsb(&dc);
PieceType pt = type_of(pos.piece_on(from));
Bitboard b = attacks_bb(pt, from, pos.pieces()) & ~pos.pieces();
if (pt == KING)
b &= ~attacks_bb<QUEEN>(pos.square<KING>(~us));
while (b)
*moveList++ = make_move(from, pop_lsb(&b));
}
return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList)
: generate_all<BLACK, QUIET_CHECKS>(pos, moveList);
}
/// generate<EVASIONS> generates all pseudo-legal check evasions when the side
/// to move is in check. Returns a pointer to the end of the move list.
template<>
ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
assert(pos.checkers());
Color us = pos.side_to_move();
Square ksq = pos.square<KING>(us);
Bitboard sliderAttacks = 0;
Bitboard sliders = pos.checkers() & ~pos.pieces(KNIGHT, PAWN);
// Find all the squares attacked by slider checkers. We will remove them from
// the king evasions in order to skip known illegal moves, which avoids any
// useless legality checks later on.
while (sliders)
sliderAttacks |= line_bb(ksq, pop_lsb(&sliders)) & ~pos.checkers();
// Generate evasions for king, capture and non capture moves
Bitboard b = attacks_bb<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks;
while (b)
*moveList++ = make_move(ksq, pop_lsb(&b));
if (more_than_one(pos.checkers()))
return moveList; // Double check, only a king move can save the day
// Generate blocking evasions or captures of the checking piece
return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList)
: generate_all<BLACK, EVASIONS>(pos, moveList);
}
/// generate<LEGAL> generates all the legal moves in the given position /// generate<LEGAL> generates all the legal moves in the given position
template<> template<>
@@ -362,3 +272,5 @@ ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
return moveList; return moveList;
} }
} // namespace Stockfish
+5 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
#include "types.h" #include "types.h"
namespace Stockfish {
class Position; class Position;
enum GenType { enum GenType {
@@ -70,4 +72,6 @@ private:
ExtMove moveList[MAX_MOVES], *last; ExtMove moveList[MAX_MOVES], *last;
}; };
} // namespace Stockfish
#endif // #ifndef MOVEGEN_H_INCLUDED #endif // #ifndef MOVEGEN_H_INCLUDED
+55 -24
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,8 +18,11 @@
#include <cassert> #include <cassert>
#include "bitboard.h"
#include "movepick.h" #include "movepick.h"
namespace Stockfish {
namespace { namespace {
enum Stages { enum Stages {
@@ -54,35 +57,40 @@ namespace {
/// ordering is at the current node. /// ordering is at the current node.
/// MovePicker constructor for the main search /// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const LowPlyHistory* lp, MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, const Move* killers, int pl) const CapturePieceToHistory* cph,
: pos(p), mainHistory(mh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch), const PieceToHistory** ch,
ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d), ply(pl) { Move cm,
const Move* killers)
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch),
ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d)
{
assert(d > 0); assert(d > 0);
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) + stage = (pos.checkers() ? EVASION_TT : MAIN_TT) +
!(ttm && pos.pseudo_legal(ttm)); !(ttm && pos.pseudo_legal(ttm));
threatenedPieces = 0;
} }
/// MovePicker constructor for quiescence search /// MovePicker constructor for quiescence search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs) const CapturePieceToHistory* cph,
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) { const PieceToHistory** ch,
Square rs)
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d)
{
assert(d <= 0); assert(d <= 0);
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) + stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) +
!( ttm !( ttm
&& (pos.checkers() || depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
&& pos.pseudo_legal(ttm)); && pos.pseudo_legal(ttm));
} }
/// MovePicker constructor for ProbCut: we generate captures with SEE greater /// MovePicker constructor for ProbCut: we generate captures with SEE greater
/// than or equal to the given threshold. /// than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph) MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph)
: pos(p), captureHistory(cph), ttMove(ttm), threshold(th) { : pos(p), captureHistory(cph), ttMove(ttm), threshold(th)
{
assert(!pos.checkers()); assert(!pos.checkers());
stage = PROBCUT_TT + !(ttm && pos.capture(ttm) stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
@@ -98,28 +106,48 @@ void MovePicker::score() {
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
[[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook;
if constexpr (Type == QUIETS)
{
Color us = pos.side_to_move();
threatenedByPawn = pos.attacks_by<PAWN>(~us);
threatenedByMinor = pos.attacks_by<KNIGHT>(~us) | pos.attacks_by<BISHOP>(~us) | threatenedByPawn;
threatenedByRook = pos.attacks_by<ROOK>(~us) | threatenedByMinor;
// Pieces threatened by pieces of lesser material value
threatenedPieces = (pos.pieces(us, QUEEN) & threatenedByRook)
| (pos.pieces(us, ROOK) & threatenedByMinor)
| (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn);
}
for (auto& m : *this) for (auto& m : *this)
if constexpr (Type == CAPTURES) if constexpr (Type == CAPTURES)
m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6 m.value = 6 * int(PieceValue[MG][pos.piece_on(to_sq(m))])
+ (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]; + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];
else if constexpr (Type == QUIETS) else if constexpr (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)]
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
+ (ply < MAX_LPH ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0); + (threatenedPieces & from_sq(m) ?
(type_of(pos.moved_piece(m)) == QUEEN && !(to_sq(m) & threatenedByRook) ? 50000
: type_of(pos.moved_piece(m)) == ROOK && !(to_sq(m) & threatenedByMinor) ? 25000
: !(to_sq(m) & threatenedByPawn) ? 15000
: 0)
: 0)
+ bool(pos.check_squares(type_of(pos.moved_piece(m))) & to_sq(m)) * 16384;
else // Type == EVASIONS else // Type == EVASIONS
{ {
if (pos.capture(m)) if (pos.capture(m))
m.value = PieceValue[MG][pos.piece_on(to_sq(m))] m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m))); - Value(type_of(pos.moved_piece(m)))
+ (1 << 28);
else else
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)];
- (1 << 28);
} }
} }
@@ -163,11 +191,12 @@ top:
endMoves = generate<CAPTURES>(pos, cur); endMoves = generate<CAPTURES>(pos, cur);
score<CAPTURES>(); score<CAPTURES>();
partial_insertion_sort(cur, endMoves, std::numeric_limits<int>::min());
++stage; ++stage;
goto top; goto top;
case GOOD_CAPTURE: case GOOD_CAPTURE:
if (select<Best>([&](){ if (select<Next>([&](){
return pos.see_ge(*cur, Value(-69 * cur->value / 1024)) ? return pos.see_ge(*cur, Value(-69 * cur->value / 1024)) ?
// Move losing capture to endBadCaptures to be tried later // Move losing capture to endBadCaptures to be tried later
true : (*endBadCaptures++ = *cur, false); })) true : (*endBadCaptures++ = *cur, false); }))
@@ -235,10 +264,10 @@ top:
return select<Best>([](){ return true; }); return select<Best>([](){ return true; });
case PROBCUT: case PROBCUT:
return select<Best>([&](){ return pos.see_ge(*cur, threshold); }); return select<Next>([&](){ return pos.see_ge(*cur, threshold); });
case QCAPTURE: case QCAPTURE:
if (select<Best>([&](){ return depth > DEPTH_QS_RECAPTURES if (select<Next>([&](){ return depth > DEPTH_QS_RECAPTURES
|| to_sq(*cur) == recaptureSquare; })) || to_sq(*cur) == recaptureSquare; }))
return *(cur - 1); return *(cur - 1);
@@ -263,3 +292,5 @@ top:
assert(false); assert(false);
return MOVE_NONE; // Silence warning return MOVE_NONE; // Silence warning
} }
} // namespace Stockfish
+16 -18
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -27,6 +27,8 @@
#include "position.h" #include "position.h"
#include "types.h" #include "types.h"
namespace Stockfish {
/// StatsEntry stores the stat table value. It is usually a number but could /// StatsEntry stores the stat table value. It is usually a number but could
/// be a move or even a nested history. We use a class instead of naked value /// be a move or even a nested history. We use a class instead of naked value
/// to directly call history update operator<<() on the entry so to use stats /// to directly call history update operator<<() on the entry so to use stats
@@ -84,13 +86,8 @@ enum StatsType { NoCaptures, Captures };
/// unsuccessful during the current search, and is used for reduction and move /// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by /// ordering decisions. It uses 2 tables (one for each color) indexed by
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory; /// (~11 elo)
typedef Stats<int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
/// At higher depths LowPlyHistory records successful quiet moves near the root
/// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
/// search and filled during iterative deepening.
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see www.chessprogramming.org/Countermove_Heuristic /// move, see www.chessprogramming.org/Countermove_Heuristic
@@ -105,6 +102,7 @@ typedef Stats<int16_t, 29952, PIECE_NB, SQUARE_NB> PieceToHistory;
/// ContinuationHistory is the combined history of a given pair of moves, usually /// ContinuationHistory is the combined history of a given pair of moves, usually
/// the current one given a previous one. The nested history table is based on /// the current one given a previous one. The nested history table is based on
/// PieceToHistory instead of ButterflyBoards. /// PieceToHistory instead of ButterflyBoards.
/// (~63 elo)
typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory; typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
@@ -121,20 +119,20 @@ class MovePicker {
public: public:
MovePicker(const MovePicker&) = delete; MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete; MovePicker& operator=(const MovePicker&) = delete;
MovePicker(const Position&, Move, Value, const CapturePieceToHistory*); MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Move,
const Move*);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*, MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const CapturePieceToHistory*, const CapturePieceToHistory*,
const PieceToHistory**, const PieceToHistory**,
Square); Square);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*, MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Move,
const Move*,
int);
Move next_move(bool skipQuiets = false); Move next_move(bool skipQuiets = false);
Bitboard threatenedPieces;
private: private:
template<PickType T, typename Pred> Move select(Pred); template<PickType T, typename Pred> Move select(Pred);
template<GenType> void score(); template<GenType> void score();
@@ -143,7 +141,6 @@ private:
const Position& pos; const Position& pos;
const ButterflyHistory* mainHistory; const ButterflyHistory* mainHistory;
const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory; const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory; const PieceToHistory** continuationHistory;
Move ttMove; Move ttMove;
@@ -152,8 +149,9 @@ private:
Square recaptureSquare; Square recaptureSquare;
Value threshold; Value threshold;
Depth depth; Depth depth;
int ply;
ExtMove moves[MAX_MOVES]; ExtMove moves[MAX_MOVES];
}; };
} // namespace Stockfish
#endif // #ifndef MOVEPICK_H_INCLUDED #endif // #ifndef MOVEPICK_H_INCLUDED
@@ -1,54 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Definition of input features and network structure used in NNUE evaluation function
#ifndef NNUE_HALFKP_256X2_32_32_H_INCLUDED
#define NNUE_HALFKP_256X2_32_32_H_INCLUDED
#include "../features/feature_set.h"
#include "../features/half_kp.h"
#include "../layers/input_slice.h"
#include "../layers/affine_transform.h"
#include "../layers/clipped_relu.h"
namespace Eval::NNUE {
// Input features used in evaluation function
using RawFeatures = Features::FeatureSet<
Features::HalfKP<Features::Side::kFriend>>;
// Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers {
// Define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
using OutputLayer = AffineTransform<HiddenLayer2, 1>;
} // namespace Layers
using Network = Layers::OutputLayer;
} // namespace Eval::NNUE
#endif // #ifndef NNUE_HALFKP_256X2_32_32_H_INCLUDED
+303 -41
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -20,6 +20,9 @@
#include <iostream> #include <iostream>
#include <set> #include <set>
#include <sstream>
#include <iomanip>
#include <fstream>
#include "../evaluate.h" #include "../evaluate.h"
#include "../position.h" #include "../position.h"
@@ -29,29 +32,30 @@
#include "evaluate_nnue.h" #include "evaluate_nnue.h"
namespace Eval::NNUE { namespace Stockfish::Eval::NNUE {
// Input feature converter // Input feature converter
LargePagePtr<FeatureTransformer> feature_transformer; LargePagePtr<FeatureTransformer> featureTransformer;
// Evaluation function // Evaluation function
AlignedPtr<Network> network; AlignedPtr<Network> network[LayerStacks];
// Evaluation function file name // Evaluation function file name
std::string fileName; std::string fileName;
std::string netDescription;
namespace Detail { namespace Detail {
// Initialize the evaluation function parameters // Initialize the evaluation function parameters
template <typename T> template <typename T>
void Initialize(AlignedPtr<T>& pointer) { void initialize(AlignedPtr<T>& pointer) {
pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T)))); pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T))));
std::memset(pointer.get(), 0, sizeof(T)); std::memset(pointer.get(), 0, sizeof(T));
} }
template <typename T> template <typename T>
void Initialize(LargePagePtr<T>& pointer) { void initialize(LargePagePtr<T>& pointer) {
static_assert(alignof(T) <= 4096, "aligned_large_pages_alloc() may fail for such a big alignment requirement of T"); static_assert(alignof(T) <= 4096, "aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T)))); pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T))));
@@ -60,85 +64,343 @@ namespace Eval::NNUE {
// Read evaluation function parameters // Read evaluation function parameters
template <typename T> template <typename T>
bool ReadParameters(std::istream& stream, T& reference) { bool read_parameters(std::istream& stream, T& reference) {
std::uint32_t header; std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream); header = read_little_endian<std::uint32_t>(stream);
if (!stream || header != T::GetHashValue()) return false; if (!stream || header != T::get_hash_value()) return false;
return reference.ReadParameters(stream); return reference.read_parameters(stream);
}
// Write evaluation function parameters
template <typename T>
bool write_parameters(std::ostream& stream, const T& reference) {
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
return reference.write_parameters(stream);
} }
} // namespace Detail } // namespace Detail
// Initialize the evaluation function parameters // Initialize the evaluation function parameters
void Initialize() { void initialize() {
Detail::Initialize(feature_transformer); Detail::initialize(featureTransformer);
Detail::Initialize(network); for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(network[i]);
} }
// Read network header // Read network header
bool ReadHeader(std::istream& stream, std::uint32_t* hash_value, std::string* architecture) bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc)
{ {
std::uint32_t version, size; std::uint32_t version, size;
version = read_little_endian<std::uint32_t>(stream); version = read_little_endian<std::uint32_t>(stream);
*hash_value = read_little_endian<std::uint32_t>(stream); *hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream); size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != kVersion) return false; if (!stream || version != Version) return false;
architecture->resize(size); desc->resize(size);
stream.read(&(*architecture)[0], size); stream.read(&(*desc)[0], size);
return !stream.fail();
}
// Write network header
bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc)
{
write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, (std::uint32_t)desc.size());
stream.write(&desc[0], desc.size());
return !stream.fail(); return !stream.fail();
} }
// Read network parameters // Read network parameters
bool ReadParameters(std::istream& stream) { bool read_parameters(std::istream& stream) {
std::uint32_t hash_value; std::uint32_t hashValue;
std::string architecture; if (!read_header(stream, &hashValue, &netDescription)) return false;
if (!ReadHeader(stream, &hash_value, &architecture)) return false; if (hashValue != HashValue) return false;
if (hash_value != kHashValue) return false; if (!Detail::read_parameters(stream, *featureTransformer)) return false;
if (!Detail::ReadParameters(stream, *feature_transformer)) return false; for (std::size_t i = 0; i < LayerStacks; ++i)
if (!Detail::ReadParameters(stream, *network)) return false; if (!Detail::read_parameters(stream, *(network[i]))) return false;
return stream && stream.peek() == std::ios::traits_type::eof(); return stream && stream.peek() == std::ios::traits_type::eof();
} }
// Write network parameters
bool write_parameters(std::ostream& stream) {
if (!write_header(stream, HashValue, netDescription)) return false;
if (!Detail::write_parameters(stream, *featureTransformer)) return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
if (!Detail::write_parameters(stream, *(network[i]))) return false;
return (bool)stream;
}
// Evaluation function. Perform differential calculation. // Evaluation function. Perform differential calculation.
Value evaluate(const Position& pos) { Value evaluate(const Position& pos, bool adjusted, int* complexity) {
// We manually align the arrays on the stack because with gcc < 9.3 // We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly. // overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = kCacheLineSize; constexpr uint64_t alignment = CacheLineSize;
int delta = 24 - pos.non_pawn_material() / 9560;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformed_features_unaligned[ TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::kBufferSize + alignment / sizeof(TransformedFeatureType)]; FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
char buffer_unaligned[Network::kBufferSize + alignment];
auto* transformed_features = align_ptr_up<alignment>(&transformed_features_unaligned[0]); auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
auto* buffer = align_ptr_up<alignment>(&buffer_unaligned[0]);
#else #else
alignas(alignment) alignas(alignment)
TransformedFeatureType transformed_features[FeatureTransformer::kBufferSize]; TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
alignas(alignment) char buffer[Network::kBufferSize];
#endif #endif
ASSERT_ALIGNED(transformed_features, alignment); ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
feature_transformer->Transform(pos, transformed_features); const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto output = network->Propagate(transformed_features, buffer); const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto positional = network[bucket]->propagate(transformedFeatures);
return static_cast<Value>(output[0] / FV_SCALE); if (complexity)
*complexity = abs(psqt - positional) / OutputScale;
// Give more value to positional evaluation when adjusted flag is set
if (adjusted)
return static_cast<Value>(((1024 - delta) * psqt + (1024 + delta) * positional) / (1024 * OutputScale));
else
return static_cast<Value>((psqt + positional) / OutputScale);
} }
struct NnueEvalTrace {
static_assert(LayerStacks == PSQTBuckets);
Value psqt[LayerStacks];
Value positional[LayerStacks];
std::size_t correctBucket;
};
static NnueEvalTrace trace_evaluate(const Position& pos) {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
#else
alignas(alignment)
TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
NnueEvalTrace t{};
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket) {
const auto materialist = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto positional = network[bucket]->propagate(transformedFeatures);
t.psqt[bucket] = static_cast<Value>( materialist / OutputScale );
t.positional[bucket] = static_cast<Value>( positional / OutputScale );
}
return t;
}
static const std::string PieceToChar(" PNBRQK pnbrqk");
// format_cp_compact() converts a Value into (centi)pawns and writes it in a buffer.
// The buffer must have capacity for at least 5 chars.
static void format_cp_compact(Value v, char* buffer) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
int cp = std::abs(100 * v / UCI::NormalizeToPawnValue);
if (cp >= 10000)
{
buffer[1] = '0' + cp / 10000; cp %= 10000;
buffer[2] = '0' + cp / 1000; cp %= 1000;
buffer[3] = '0' + cp / 100;
buffer[4] = ' ';
}
else if (cp >= 1000)
{
buffer[1] = '0' + cp / 1000; cp %= 1000;
buffer[2] = '0' + cp / 100; cp %= 100;
buffer[3] = '.';
buffer[4] = '0' + cp / 10;
}
else
{
buffer[1] = '0' + cp / 100; cp %= 100;
buffer[2] = '.';
buffer[3] = '0' + cp / 10; cp %= 10;
buffer[4] = '0' + cp / 1;
}
}
// format_cp_aligned_dot() converts a Value into (centi)pawns and writes it in a buffer,
// always keeping two decimals. The buffer must have capacity for at least 7 chars.
static void format_cp_aligned_dot(Value v, char* buffer) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
double cp = 1.0 * std::abs(int(v)) / UCI::NormalizeToPawnValue;
sprintf(&buffer[1], "%6.2f", cp);
}
// trace() returns a string with the value of each piece on a board,
// and a table for (PSQT, Layers) values bucket by bucket.
std::string trace(Position& pos) {
std::stringstream ss;
char board[3*8+1][8*8+2];
std::memset(board, ' ', sizeof(board));
for (int row = 0; row < 3*8+1; ++row)
board[row][8*8+1] = '\0';
// A lambda to output one box of the board
auto writeSquare = [&board](File file, Rank rank, Piece pc, Value value) {
const int x = ((int)file) * 8;
const int y = (7 - (int)rank) * 3;
for (int i = 1; i < 8; ++i)
board[y][x+i] = board[y+3][x+i] = '-';
for (int i = 1; i < 3; ++i)
board[y+i][x] = board[y+i][x+8] = '|';
board[y][x] = board[y][x+8] = board[y+3][x+8] = board[y+3][x] = '+';
if (pc != NO_PIECE)
board[y+1][x+4] = PieceToChar[pc];
if (value != VALUE_NONE)
format_cp_compact(value, &board[y+2][x+2]);
};
// We estimate the value of each piece by doing a differential evaluation from
// the current base eval, simulating the removal of the piece from its square.
Value base = evaluate(pos);
base = pos.side_to_move() == WHITE ? base : -base;
for (File f = FILE_A; f <= FILE_H; ++f)
for (Rank r = RANK_1; r <= RANK_8; ++r)
{
Square sq = make_square(f, r);
Piece pc = pos.piece_on(sq);
Value v = VALUE_NONE;
if (pc != NO_PIECE && type_of(pc) != KING)
{
auto st = pos.state();
pos.remove_piece(sq);
st->accumulator.computed[WHITE] = false;
st->accumulator.computed[BLACK] = false;
Value eval = evaluate(pos);
eval = pos.side_to_move() == WHITE ? eval : -eval;
v = base - eval;
pos.put_piece(pc, sq);
st->accumulator.computed[WHITE] = false;
st->accumulator.computed[BLACK] = false;
}
writeSquare(f, r, pc, v);
}
ss << " NNUE derived piece values:\n";
for (int row = 0; row < 3*8+1; ++row)
ss << board[row] << '\n';
ss << '\n';
auto t = trace_evaluate(pos);
ss << " NNUE network contributions "
<< (pos.side_to_move() == WHITE ? "(White to move)" : "(Black to move)") << std::endl
<< "+------------+------------+------------+------------+\n"
<< "| Bucket | Material | Positional | Total |\n"
<< "| | (PSQT) | (Layers) | |\n"
<< "+------------+------------+------------+------------+\n";
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
{
char buffer[3][8];
std::memset(buffer, '\0', sizeof(buffer));
format_cp_aligned_dot(t.psqt[bucket], buffer[0]);
format_cp_aligned_dot(t.positional[bucket], buffer[1]);
format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], buffer[2]);
ss << "| " << bucket << " "
<< " | " << buffer[0] << " "
<< " | " << buffer[1] << " "
<< " | " << buffer[2] << " "
<< " |";
if (bucket == t.correctBucket)
ss << " <-- this bucket is used";
ss << '\n';
}
ss << "+------------+------------+------------+------------+\n";
return ss.str();
}
// Load eval, from a file stream or a memory stream // Load eval, from a file stream or a memory stream
bool load_eval(std::string name, std::istream& stream) { bool load_eval(std::string name, std::istream& stream) {
Initialize(); initialize();
fileName = name; fileName = name;
return ReadParameters(stream); return read_parameters(stream);
} }
} // namespace Eval::NNUE // Save eval, to a file stream or a memory stream
bool save_eval(std::ostream& stream) {
if (fileName.empty())
return false;
return write_parameters(stream);
}
/// Save eval, to a file given by its name
bool save_eval(const std::optional<std::string>& filename) {
std::string actualFilename;
std::string msg;
if (filename.has_value())
actualFilename = filename.value();
else
{
if (currentEvalFileName != EvalFileDefaultName)
{
msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified";
sync_cout << msg << sync_endl;
return false;
}
actualFilename = EvalFileDefaultName;
}
std::ofstream stream(actualFilename, std::ios_base::binary);
bool saved = save_eval(stream);
msg = saved ? "Network saved successfully to " + actualFilename
: "Failed to export a net";
sync_cout << msg << sync_endl;
return saved;
}
} // namespace Stockfish::Eval::NNUE
+5 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -25,11 +25,11 @@
#include <memory> #include <memory>
namespace Eval::NNUE { namespace Stockfish::Eval::NNUE {
// Hash value of evaluation function structure // Hash value of evaluation function structure
constexpr std::uint32_t kHashValue = constexpr std::uint32_t HashValue =
FeatureTransformer::GetHashValue() ^ Network::GetHashValue(); FeatureTransformer::get_hash_value() ^ Network::get_hash_value();
// Deleter for automating release of memory area // Deleter for automating release of memory area
template <typename T> template <typename T>
@@ -54,6 +54,6 @@ namespace Eval::NNUE {
template <typename T> template <typename T>
using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>; using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
} // namespace Eval::NNUE } // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED #endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
-69
View File
@@ -1,69 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// A class template that represents the input feature set of the NNUE evaluation function
#ifndef NNUE_FEATURE_SET_H_INCLUDED
#define NNUE_FEATURE_SET_H_INCLUDED
#include "features_common.h"
#include <array>
namespace Eval::NNUE::Features {
// Class template that represents a list of values
template <typename T, T... Values>
struct CompileTimeList;
template <typename T, T First, T... Remaining>
struct CompileTimeList<T, First, Remaining...> {
static constexpr bool Contains(T value) {
return value == First || CompileTimeList<T, Remaining...>::Contains(value);
}
static constexpr std::array<T, sizeof...(Remaining) + 1>
kValues = {{First, Remaining...}};
};
// Base class of feature set
template <typename Derived>
class FeatureSetBase {
};
// Class template that represents the feature set
template <typename FeatureType>
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
public:
// Hash value embedded in the evaluation file
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
// Number of feature dimensions
static constexpr IndexType kDimensions = FeatureType::kDimensions;
// Maximum number of simultaneously active features
static constexpr IndexType kMaxActiveDimensions =
FeatureType::kMaxActiveDimensions;
// Trigger for full calculation instead of difference calculation
using SortedTriggerSet =
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURE_SET_H_INCLUDED
-45
View File
@@ -1,45 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Common header of input features of NNUE evaluation function
#ifndef NNUE_FEATURES_COMMON_H_INCLUDED
#define NNUE_FEATURES_COMMON_H_INCLUDED
#include "../../evaluate.h"
#include "../nnue_common.h"
namespace Eval::NNUE::Features {
class IndexList;
template <typename... FeatureTypes>
class FeatureSet;
// Trigger to perform full calculations instead of difference only
enum class TriggerEvent {
kFriendKingMoved // calculate full evaluation when own king moves
};
enum class Side {
kFriend // side to move
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_COMMON_H_INCLUDED
+84
View File
@@ -0,0 +1,84 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Definition of input features HalfKAv2_hm of NNUE evaluation function
#include "half_ka_v2_hm.h"
#include "../../position.h"
namespace Stockfish::Eval::NNUE::Features {
// Index of a feature for a given king position and another piece on some square
template<Color Perspective>
inline IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) {
return IndexType((int(s) ^ OrientTBL[Perspective][ksq]) + PieceSquareIndex[Perspective][pc] + KingBuckets[Perspective][ksq]);
}
// Get a list of indices for active features
template<Color Perspective>
void HalfKAv2_hm::append_active_indices(
const Position& pos,
IndexList& active
) {
Square ksq = pos.square<KING>(Perspective);
Bitboard bb = pos.pieces();
while (bb)
{
Square s = pop_lsb(bb);
active.push_back(make_index<Perspective>(s, pos.piece_on(s), ksq));
}
}
// Explicit template instantiations
template void HalfKAv2_hm::append_active_indices<WHITE>(const Position& pos, IndexList& active);
template void HalfKAv2_hm::append_active_indices<BLACK>(const Position& pos, IndexList& active);
// append_changed_indices() : get a list of indices for recently changed features
template<Color Perspective>
void HalfKAv2_hm::append_changed_indices(
Square ksq,
const DirtyPiece& dp,
IndexList& removed,
IndexList& added
) {
for (int i = 0; i < dp.dirty_num; ++i) {
if (dp.from[i] != SQ_NONE)
removed.push_back(make_index<Perspective>(dp.from[i], dp.piece[i], ksq));
if (dp.to[i] != SQ_NONE)
added.push_back(make_index<Perspective>(dp.to[i], dp.piece[i], ksq));
}
}
// Explicit template instantiations
template void HalfKAv2_hm::append_changed_indices<WHITE>(Square ksq, const DirtyPiece& dp, IndexList& removed, IndexList& added);
template void HalfKAv2_hm::append_changed_indices<BLACK>(Square ksq, const DirtyPiece& dp, IndexList& removed, IndexList& added);
int HalfKAv2_hm::update_cost(const StateInfo* st) {
return st->dirtyPiece.dirty_num;
}
int HalfKAv2_hm::refresh_cost(const Position& pos) {
return pos.count<ALL_PIECES>();
}
bool HalfKAv2_hm::requires_refresh(const StateInfo* st, Color perspective) {
return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
}
} // namespace Stockfish::Eval::NNUE::Features
+152
View File
@@ -0,0 +1,152 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Definition of input features HalfKP of NNUE evaluation function
#ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#define NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#include "../nnue_common.h"
#include "../../evaluate.h"
#include "../../misc.h"
namespace Stockfish {
struct StateInfo;
}
namespace Stockfish::Eval::NNUE::Features {
// Feature HalfKAv2_hm: Combination of the position of own king
// and the position of pieces. Position mirrored such that king always on e..h files.
class HalfKAv2_hm {
// unique number for each piece type on each square
enum {
PS_NONE = 0,
PS_W_PAWN = 0,
PS_B_PAWN = 1 * SQUARE_NB,
PS_W_KNIGHT = 2 * SQUARE_NB,
PS_B_KNIGHT = 3 * SQUARE_NB,
PS_W_BISHOP = 4 * SQUARE_NB,
PS_B_BISHOP = 5 * SQUARE_NB,
PS_W_ROOK = 6 * SQUARE_NB,
PS_B_ROOK = 7 * SQUARE_NB,
PS_W_QUEEN = 8 * SQUARE_NB,
PS_B_QUEEN = 9 * SQUARE_NB,
PS_KING = 10 * SQUARE_NB,
PS_NB = 11 * SQUARE_NB
};
static constexpr IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = {
// convention: W - us, B - them
// viewed from other side, W and B are reversed
{ PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE },
{ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE }
};
// Index of a feature for a given king position and another piece on some square
template<Color Perspective>
static IndexType make_index(Square s, Piece pc, Square ksq);
public:
// Feature name
static constexpr const char* Name = "HalfKAv2_hm(Friend)";
// Hash value embedded in the evaluation file
static constexpr std::uint32_t HashValue = 0x7f234cb8u;
// Number of feature dimensions
static constexpr IndexType Dimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_NB) / 2;
#define B(v) (v * PS_NB)
static constexpr int KingBuckets[COLOR_NB][SQUARE_NB] = {
{ B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28),
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0) },
{ B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0),
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28) }
};
#undef B
// Orient a square according to perspective (rotates by 180 for black)
static constexpr int OrientTBL[COLOR_NB][SQUARE_NB] = {
{ SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1 },
{ SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8 }
};
// Maximum number of simultaneously active features.
static constexpr IndexType MaxActiveDimensions = 32;
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
// Get a list of indices for active features
template<Color Perspective>
static void append_active_indices(
const Position& pos,
IndexList& active);
// Get a list of indices for recently changed features
template<Color Perspective>
static void append_changed_indices(
Square ksq,
const DirtyPiece& dp,
IndexList& removed,
IndexList& added
);
// Returns the cost of updating one perspective, the most costly one.
// Assumes no refresh needed.
static int update_cost(const StateInfo* st);
static int refresh_cost(const Position& pos);
// Returns whether the change stored in this StateInfo means that
// a full accumulator refresh is required.
static bool requires_refresh(const StateInfo* st, Color perspective);
};
} // namespace Stockfish::Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
-68
View File
@@ -1,68 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Definition of input features HalfKP of NNUE evaluation function
#include "half_kp.h"
#include "index_list.h"
namespace Eval::NNUE::Features {
// Orient a square according to perspective (rotates by 180 for black)
inline Square orient(Color perspective, Square s) {
return Square(int(s) ^ (bool(perspective) * 63));
}
// Index of a feature for a given king position and another piece on some square
inline IndexType make_index(Color perspective, Square s, Piece pc, Square ksq) {
return IndexType(orient(perspective, s) + kpp_board_index[perspective][pc] + PS_END * ksq);
}
// Get a list of indices for active features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
Square ksq = orient(perspective, pos.square<KING>(perspective));
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb) {
Square s = pop_lsb(&bb);
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
}
}
// Get a list of indices for recently changed features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendChangedIndices(
const Position& pos, const DirtyPiece& dp, Color perspective,
IndexList* removed, IndexList* added) {
Square ksq = orient(perspective, pos.square<KING>(perspective));
for (int i = 0; i < dp.dirty_num; ++i) {
Piece pc = dp.piece[i];
if (type_of(pc) == KING) continue;
if (dp.from[i] != SQ_NONE)
removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
if (dp.to[i] != SQ_NONE)
added->push_back(make_index(perspective, dp.to[i], pc, ksq));
}
}
template class HalfKP<Side::kFriend>;
} // namespace Eval::NNUE::Features
-59
View File
@@ -1,59 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Definition of input features HalfKP of NNUE evaluation function
#ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
#define NNUE_FEATURES_HALF_KP_H_INCLUDED
#include "../../evaluate.h"
#include "features_common.h"
namespace Eval::NNUE::Features {
// Feature HalfKP: Combination of the position of own king
// and the position of pieces other than kings
template <Side AssociatedKing>
class HalfKP {
public:
// Feature name
static constexpr const char* kName = "HalfKP(Friend)";
// Hash value embedded in the evaluation file
static constexpr std::uint32_t kHashValue =
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// Number of feature dimensions
static constexpr IndexType kDimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_END);
// Maximum number of simultaneously active features
static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count
// Trigger for full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kFriendKingMoved;
// Get a list of indices for active features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices for recently changed features
static void AppendChangedIndices(const Position& pos, const DirtyPiece& dp, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
-64
View File
@@ -1,64 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Definition of index list of input features
#ifndef NNUE_FEATURES_INDEX_LIST_H_INCLUDED
#define NNUE_FEATURES_INDEX_LIST_H_INCLUDED
#include "../../position.h"
#include "../nnue_architecture.h"
namespace Eval::NNUE::Features {
// Class template used for feature index list
template <typename T, std::size_t MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
void resize(std::size_t size) { size_ = size; }
void push_back(const T& value) { values_[size_++] = value; }
T& operator[](std::size_t index) { return values_[index]; }
T* begin() { return values_; }
T* end() { return values_ + size_; }
const T& operator[](std::size_t index) const { return values_[index]; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
void swap(ValueList& other) {
const std::size_t max_size = std::max(size_, other.size_);
for (std::size_t i = 0; i < max_size; ++i) {
std::swap(values_[i], other.values_[i]);
}
std::swap(size_, other.size_);
}
private:
T values_[MaxSize];
std::size_t size_ = 0;
};
//Type of feature index list
class IndexList
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
};
} // namespace Eval::NNUE::Features
#endif // NNUE_FEATURES_INDEX_LIST_H_INCLUDED
+474 -393
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,410 +22,344 @@
#define NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED #define NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#include <iostream> #include <iostream>
#include <algorithm>
#include <type_traits>
#include "../nnue_common.h" #include "../nnue_common.h"
#include "simd.h"
namespace Eval::NNUE::Layers { /*
This file contains the definition for a fully connected layer (aka affine transform).
Two approaches are employed, depending on the sizes of the transform.
// Affine transformation layer Approach 1:
template <typename PreviousLayer, IndexType OutputDimensions> - used when the PaddedInputDimensions >= 128
class AffineTransform { - uses AVX512 if possible
public: - processes inputs in batches of 2*InputSimdWidth
// Input/output type - so in batches of 128 for AVX512
using InputType = typename PreviousLayer::OutputType; - the weight blocks of size InputSimdWidth are transposed such that
using OutputType = std::int32_t; access is sequential
static_assert(std::is_same<InputType, std::uint8_t>::value, ""); - N columns of the weight matrix are processed a time, where N
depends on the architecture (the amount of registers)
- accumulate + hadd is used
// Number of input/output dimensions Approach 2:
static constexpr IndexType kInputDimensions = - used when the PaddedInputDimensions < 128
PreviousLayer::kOutputDimensions; - does not use AVX512
static constexpr IndexType kOutputDimensions = OutputDimensions; - expected use-case is for when PaddedInputDimensions == 32 and InputDimensions <= 32.
static constexpr IndexType kPaddedInputDimensions = - that's why AVX512 is hard to implement
CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth); - expected use-case is small layers
#if defined (USE_AVX512) - not optimized as well as the approach 1
static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 2; - inputs are processed in chunks of 4, weights are respectively transposed
#elif defined (USE_SSSE3) - accumulation happens directly to int32s
static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 4; */
#endif
// Size of forward propagation buffer used in this layer namespace Stockfish::Eval::NNUE::Layers {
static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer // Fallback implementation for older/other architectures.
static constexpr std::size_t kBufferSize = // Identical for both approaches. Requires the input to be padded to at least 16 values.
PreviousLayer::kBufferSize + kSelfBufferSize; #if !defined(USE_SSSE3)
template <IndexType InputDimensions, IndexType PaddedInputDimensions, IndexType OutputDimensions>
static void affine_transform_non_ssse3(std::int32_t* output, const std::int8_t* weights, const std::int32_t* biases, const std::uint8_t* input)
{
# if defined(USE_SSE2)
// At least a multiple of 16, with SSE2.
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const __m128i Zeros = _mm_setzero_si128();
const auto inputVector = reinterpret_cast<const __m128i*>(input);
// Hash value embedded in the evaluation file # elif defined(USE_MMX)
static constexpr std::uint32_t GetHashValue() { constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / 8;
std::uint32_t hash_value = 0xCC03DAE4u; const __m64 Zeros = _mm_setzero_si64();
hash_value += kOutputDimensions; const auto inputVector = reinterpret_cast<const __m64*>(input);
hash_value ^= PreviousLayer::GetHashValue() >> 1;
hash_value ^= PreviousLayer::GetHashValue() << 31; # elif defined(USE_NEON)
return hash_value; constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
# endif
for (IndexType i = 0; i < OutputDimensions; ++i) {
const IndexType offset = i * PaddedInputDimensions;
# if defined(USE_SSE2)
__m128i sumLo = _mm_cvtsi32_si128(biases[i]);
__m128i sumHi = Zeros;
const auto row = reinterpret_cast<const __m128i*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
__m128i row_j = _mm_load_si128(&row[j]);
__m128i input_j = _mm_load_si128(&inputVector[j]);
__m128i extendedRowLo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
__m128i extendedRowHi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
__m128i extendedInputLo = _mm_unpacklo_epi8(input_j, Zeros);
__m128i extendedInputHi = _mm_unpackhi_epi8(input_j, Zeros);
__m128i productLo = _mm_madd_epi16(extendedRowLo, extendedInputLo);
__m128i productHi = _mm_madd_epi16(extendedRowHi, extendedInputHi);
sumLo = _mm_add_epi32(sumLo, productLo);
sumHi = _mm_add_epi32(sumHi, productHi);
}
__m128i sum = _mm_add_epi32(sumLo, sumHi);
__m128i sumHigh_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sumHigh_64);
__m128i sum_second_32 = _mm_shufflelo_epi16(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_second_32);
output[i] = _mm_cvtsi128_si32(sum);
# elif defined(USE_MMX)
__m64 sumLo = _mm_cvtsi32_si64(biases[i]);
__m64 sumHi = Zeros;
const auto row = reinterpret_cast<const __m64*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
__m64 row_j = row[j];
__m64 input_j = inputVector[j];
__m64 extendedRowLo = _mm_srai_pi16(_mm_unpacklo_pi8(row_j, row_j), 8);
__m64 extendedRowHi = _mm_srai_pi16(_mm_unpackhi_pi8(row_j, row_j), 8);
__m64 extendedInputLo = _mm_unpacklo_pi8(input_j, Zeros);
__m64 extendedInputHi = _mm_unpackhi_pi8(input_j, Zeros);
__m64 productLo = _mm_madd_pi16(extendedRowLo, extendedInputLo);
__m64 productHi = _mm_madd_pi16(extendedRowHi, extendedInputHi);
sumLo = _mm_add_pi32(sumLo, productLo);
sumHi = _mm_add_pi32(sumHi, productHi);
}
__m64 sum = _mm_add_pi32(sumLo, sumHi);
sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum));
output[i] = _mm_cvtsi64_si32(sum);
# elif defined(USE_NEON)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x8_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
int16x8_t product = vmull_s8(inputVector[j * 2], row[j * 2]);
product = vmlal_s8(product, inputVector[j * 2 + 1], row[j * 2 + 1]);
sum = vpadalq_s16(sum, product);
}
output[i] = sum[0] + sum[1] + sum[2] + sum[3];
# else
std::int32_t sum = biases[i];
for (IndexType j = 0; j < InputDimensions; ++j) {
sum += weights[offset + j] * input[j];
}
output[i] = sum;
# endif
} }
// Read network parameters # if defined(USE_MMX)
bool ReadParameters(std::istream& stream) { _mm_empty();
if (!previous_layer_.ReadParameters(stream)) return false; # endif
for (std::size_t i = 0; i < kOutputDimensions; ++i) }
biases_[i] = read_little_endian<BiasType>(stream); #endif
for (std::size_t i = 0; i < kOutputDimensions * kPaddedInputDimensions; ++i)
#if !defined (USE_SSSE3) template <IndexType InDims, IndexType OutDims, typename Enabled = void>
weights_[i] = read_little_endian<WeightType>(stream); class AffineTransform;
#if defined (USE_AVX512)
constexpr IndexType LargeInputSize = 2 * 64;
#else #else
weights_[ constexpr IndexType LargeInputSize = std::numeric_limits<IndexType>::max();
(i / 4) % (kPaddedInputDimensions / 4) * kOutputDimensions * 4 +
i / kPaddedInputDimensions * 4 +
i % 4
] = read_little_endian<WeightType>(stream);
// Determine if eights of weight and input products can be summed using 16bits
// without saturation. We assume worst case combinations of 0 and 127 for all inputs.
if (kOutputDimensions > 1 && !stream.fail())
{
canSaturate16.count = 0;
#if !defined(USE_VNNI)
for (IndexType i = 0; i < kPaddedInputDimensions; i += 16)
for (IndexType j = 0; j < kOutputDimensions; ++j)
for (int x = 0; x < 2; ++x)
{
WeightType* w = &weights_[i * kOutputDimensions + j * 4 + x * 2];
int sum[2] = {0, 0};
for (int k = 0; k < 8; ++k)
{
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
sum[w[idx] < 0] += w[idx];
}
for (int sign : {-1, 1})
while (sign * sum[sign == -1] > 258)
{
int maxK = 0, maxW = 0;
for (int k = 0; k < 8; ++k)
{
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
if (maxW < sign * w[idx])
maxK = k, maxW = sign * w[idx];
}
IndexType idx = maxK / 2 * kOutputDimensions * 4 + maxK % 2;
sum[sign == -1] -= w[idx];
canSaturate16.add(j, i + maxK / 2 * 4 + maxK % 2 + x * 2, w[idx]);
w[idx] = 0;
}
}
// Non functional optimization for faster more linear access
std::sort(canSaturate16.ids, canSaturate16.ids + canSaturate16.count,
[](const typename CanSaturate::Entry& e1, const typename CanSaturate::Entry& e2)
{ return e1.in == e2.in ? e1.out < e2.out : e1.in < e2.in; });
#endif #endif
}
// A specialization for large inputs.
template <IndexType InDims, IndexType OutDims>
class AffineTransform<InDims, OutDims, std::enable_if_t<(ceil_to_multiple<IndexType>(InDims, MaxSimdWidth) >= LargeInputSize)>> {
public:
// Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
using OutputBuffer = OutputType[PaddedOutputDimensions];
static_assert(PaddedInputDimensions >= LargeInputSize, "Something went wrong. This specialization should not have been chosen.");
#if defined (USE_AVX512)
static constexpr const IndexType InputSimdWidth = 64;
static constexpr const IndexType MaxNumOutputRegs = 16;
#elif defined (USE_AVX2)
static constexpr const IndexType InputSimdWidth = 32;
static constexpr const IndexType MaxNumOutputRegs = 8;
#elif defined (USE_SSSE3)
static constexpr const IndexType InputSimdWidth = 16;
static constexpr const IndexType MaxNumOutputRegs = 8;
#elif defined (USE_NEON)
static constexpr const IndexType InputSimdWidth = 8;
static constexpr const IndexType MaxNumOutputRegs = 8;
#else
// The fallback implementation will not have permuted weights.
// We define these to avoid a lot of ifdefs later.
static constexpr const IndexType InputSimdWidth = 1;
static constexpr const IndexType MaxNumOutputRegs = 1;
#endif #endif
// A big block is a region in the weight matrix of the size [PaddedInputDimensions, NumOutputRegs].
// A small block is a region of size [InputSimdWidth, 1]
static constexpr const IndexType NumOutputRegs = std::min(MaxNumOutputRegs, OutputDimensions);
static constexpr const IndexType SmallBlockSize = InputSimdWidth;
static constexpr const IndexType BigBlockSize = NumOutputRegs * PaddedInputDimensions;
static constexpr const IndexType NumSmallBlocksInBigBlock = BigBlockSize / SmallBlockSize;
static constexpr const IndexType NumSmallBlocksPerOutput = PaddedInputDimensions / SmallBlockSize;
static constexpr const IndexType NumBigBlocks = OutputDimensions / NumOutputRegs;
static_assert(OutputDimensions % NumOutputRegs == 0);
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
return hashValue;
}
/*
Transposes the small blocks within a block.
Effectively means that weights can be traversed sequentially during inference.
*/
static IndexType get_weight_index(IndexType i)
{
const IndexType smallBlock = (i / SmallBlockSize) % NumSmallBlocksInBigBlock;
const IndexType smallBlockCol = smallBlock / NumSmallBlocksPerOutput;
const IndexType smallBlockRow = smallBlock % NumSmallBlocksPerOutput;
const IndexType bigBlock = i / BigBlockSize;
const IndexType rest = i % SmallBlockSize;
const IndexType idx =
bigBlock * BigBlockSize
+ smallBlockRow * SmallBlockSize * NumOutputRegs
+ smallBlockCol * SmallBlockSize
+ rest;
return idx;
}
// Read network parameters
bool read_parameters(std::istream& stream) {
for (IndexType i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
for (IndexType i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail(); return !stream.fail();
} }
// Forward propagation // Forward propagation
const OutputType* Propagate( const OutputType* propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const InputType* input, OutputType* output) const {
const auto input = previous_layer_.Propagate(
transformed_features, buffer + kSelfBufferSize);
#if defined (USE_AVX512) #if defined (USE_AVX512)
using acc_vec_t = __m512i;
[[maybe_unused]] const __m512i kOnes512 = _mm512_set1_epi16(1); using bias_vec_t = __m128i;
using weight_vec_t = __m512i;
[[maybe_unused]] auto m512_hadd = [](__m512i sum, int bias) -> int { using in_vec_t = __m512i;
return _mm512_reduce_add_epi32(sum) + bias; #define vec_zero _mm512_setzero_si512()
}; #define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2
#define vec_hadd Simd::m512_hadd
[[maybe_unused]] auto m512_add_dpbusd_epi32 = [=](__m512i& acc, __m512i a, __m512i b) { #define vec_haddx4 Simd::m512_haddx4
#if defined (USE_VNNI)
acc = _mm512_dpbusd_epi32(acc, a, b);
#else
__m512i product0 = _mm512_maddubs_epi16(a, b);
product0 = _mm512_madd_epi16(product0, kOnes512);
acc = _mm512_add_epi32(acc, product0);
#endif
};
[[maybe_unused]] auto m512_add_dpbusd_epi32x4 = [=](__m512i& acc, __m512i a0, __m512i b0, __m512i a1, __m512i b1,
__m512i a2, __m512i b2, __m512i a3, __m512i b3) {
#if defined (USE_VNNI)
acc = _mm512_dpbusd_epi32(acc, a0, b0);
acc = _mm512_dpbusd_epi32(acc, a1, b1);
acc = _mm512_dpbusd_epi32(acc, a2, b2);
acc = _mm512_dpbusd_epi32(acc, a3, b3);
#else
__m512i product0 = _mm512_maddubs_epi16(a0, b0);
__m512i product1 = _mm512_maddubs_epi16(a1, b1);
__m512i product2 = _mm512_maddubs_epi16(a2, b2);
__m512i product3 = _mm512_maddubs_epi16(a3, b3);
product0 = _mm512_add_epi16(product0, product1);
product2 = _mm512_add_epi16(product2, product3);
product0 = _mm512_add_epi16(product0, product2);
product0 = _mm512_madd_epi16(product0, kOnes512);
acc = _mm512_add_epi32(acc, product0);
#endif
};
#endif
#if defined (USE_AVX2)
[[maybe_unused]] const __m256i kOnes256 = _mm256_set1_epi16(1);
[[maybe_unused]] auto m256_hadd = [](__m256i sum, int bias) -> int {
__m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
return _mm_cvtsi128_si32(sum128) + bias;
};
[[maybe_unused]] auto m256_add_dpbusd_epi32 = [=](__m256i& acc, __m256i a, __m256i b) {
#if defined (USE_VNNI)
acc = _mm256_dpbusd_epi32(acc, a, b);
#else
__m256i product0 = _mm256_maddubs_epi16(a, b);
product0 = _mm256_madd_epi16(product0, kOnes256);
acc = _mm256_add_epi32(acc, product0);
#endif
};
[[maybe_unused]] auto m256_add_dpbusd_epi32x4 = [=](__m256i& acc, __m256i a0, __m256i b0, __m256i a1, __m256i b1,
__m256i a2, __m256i b2, __m256i a3, __m256i b3) {
#if defined (USE_VNNI)
acc = _mm256_dpbusd_epi32(acc, a0, b0);
acc = _mm256_dpbusd_epi32(acc, a1, b1);
acc = _mm256_dpbusd_epi32(acc, a2, b2);
acc = _mm256_dpbusd_epi32(acc, a3, b3);
#else
__m256i product0 = _mm256_maddubs_epi16(a0, b0);
__m256i product1 = _mm256_maddubs_epi16(a1, b1);
__m256i product2 = _mm256_maddubs_epi16(a2, b2);
__m256i product3 = _mm256_maddubs_epi16(a3, b3);
product0 = _mm256_add_epi16(product0, product1);
product2 = _mm256_add_epi16(product2, product3);
product0 = _mm256_add_epi16(product0, product2);
product0 = _mm256_madd_epi16(product0, kOnes256);
acc = _mm256_add_epi32(acc, product0);
#endif
};
#endif
#if defined (USE_SSSE3)
[[maybe_unused]] const __m128i kOnes128 = _mm_set1_epi16(1);
[[maybe_unused]] auto m128_hadd = [](__m128i sum, int bias) -> int {
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
return _mm_cvtsi128_si32(sum) + bias;
};
[[maybe_unused]] auto m128_add_dpbusd_epi32 = [=](__m128i& acc, __m128i a, __m128i b) {
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};
[[maybe_unused]] auto m128_add_dpbusd_epi32x4 = [=](__m128i& acc, __m128i a0, __m128i b0, __m128i a1, __m128i b1,
__m128i a2, __m128i b2, __m128i a3, __m128i b3) {
__m128i product0 = _mm_maddubs_epi16(a0, b0);
__m128i product1 = _mm_maddubs_epi16(a1, b1);
__m128i product2 = _mm_maddubs_epi16(a2, b2);
__m128i product3 = _mm_maddubs_epi16(a3, b3);
product0 = _mm_adds_epi16(product0, product1);
product2 = _mm_adds_epi16(product2, product3);
product0 = _mm_adds_epi16(product0, product2);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};
#endif
#if defined (USE_AVX512)
using vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512
#define vec_set_32 _mm512_set1_epi32
auto& vec_add_dpbusd_32 = m512_add_dpbusd_epi32;
auto& vec_add_dpbusd_32x4 = m512_add_dpbusd_epi32x4;
auto& vec_hadd = m512_hadd;
#elif defined (USE_AVX2) #elif defined (USE_AVX2)
using vec_t = __m256i; using acc_vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256 using bias_vec_t = __m128i;
#define vec_set_32 _mm256_set1_epi32 using weight_vec_t = __m256i;
auto& vec_add_dpbusd_32 = m256_add_dpbusd_epi32; using in_vec_t = __m256i;
auto& vec_add_dpbusd_32x4 = m256_add_dpbusd_epi32x4; #define vec_zero _mm256_setzero_si256()
auto& vec_hadd = m256_hadd; #define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4
#elif defined (USE_SSSE3) #elif defined (USE_SSSE3)
using vec_t = __m128i; using acc_vec_t = __m128i;
#define vec_setzero _mm_setzero_si128 using bias_vec_t = __m128i;
#define vec_set_32 _mm_set1_epi32 using weight_vec_t = __m128i;
auto& vec_add_dpbusd_32 = m128_add_dpbusd_epi32; using in_vec_t = __m128i;
auto& vec_add_dpbusd_32x4 = m128_add_dpbusd_epi32x4; #define vec_zero _mm_setzero_si128()
auto& vec_hadd = m128_hadd; #define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4
#elif defined (USE_NEON)
using acc_vec_t = int32x4_t;
using bias_vec_t = int32x4_t;
using weight_vec_t = int8x8_t;
using in_vec_t = int8x8_t;
#define vec_zero {0}
#define vec_add_dpbusd_32x2 Simd::neon_m128_add_dpbusd_epi32x2
#define vec_hadd Simd::neon_m128_hadd
#define vec_haddx4 Simd::neon_m128_haddx4
#endif #endif
#if defined (USE_SSSE3) #if defined (USE_SSSE3) || defined (USE_NEON)
const in_vec_t* invec = reinterpret_cast<const in_vec_t*>(input);
const auto output = reinterpret_cast<OutputType*>(buffer); // Perform accumulation to registers for each big block
const auto input_vector = reinterpret_cast<const vec_t*>(input); for (IndexType bigBlock = 0; bigBlock < NumBigBlocks; ++bigBlock)
static_assert(kOutputDimensions % kOutputSimdWidth == 0 || kOutputDimensions == 1);
// kOutputDimensions is either 1 or a multiple of kSimdWidth
// because then it is also an input dimension.
if constexpr (kOutputDimensions % kOutputSimdWidth == 0)
{ {
constexpr IndexType kNumChunks = kPaddedInputDimensions / 4; acc_vec_t acc[NumOutputRegs] = { vec_zero };
const auto input32 = reinterpret_cast<const std::int32_t*>(input); // Each big block has NumOutputRegs small blocks in each "row", one per register.
vec_t* outptr = reinterpret_cast<vec_t*>(output); // We process two small blocks at a time to save on one addition without VNNI.
std::memcpy(output, biases_, kOutputDimensions * sizeof(OutputType)); for (IndexType smallBlock = 0; smallBlock < NumSmallBlocksPerOutput; smallBlock += 2)
{
const weight_vec_t* weightvec =
reinterpret_cast<const weight_vec_t*>(
weights
+ bigBlock * BigBlockSize
+ smallBlock * SmallBlockSize * NumOutputRegs);
for (int i = 0; i < (int)kNumChunks - 3; i += 4) const in_vec_t in0 = invec[smallBlock + 0];
const in_vec_t in1 = invec[smallBlock + 1];
for (IndexType k = 0; k < NumOutputRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, weightvec[k], in1, weightvec[k + NumOutputRegs]);
}
// Horizontally add all accumulators.
if constexpr (NumOutputRegs % 4 == 0)
{
bias_vec_t* outputvec = reinterpret_cast<bias_vec_t*>(output);
const bias_vec_t* biasvec = reinterpret_cast<const bias_vec_t*>(biases);
for (IndexType k = 0; k < NumOutputRegs; k += 4)
{ {
const vec_t in0 = vec_set_32(input32[i + 0]); const IndexType idx = (bigBlock * NumOutputRegs + k) / 4;
const vec_t in1 = vec_set_32(input32[i + 1]); outputvec[idx] = vec_haddx4(acc[k+0], acc[k+1], acc[k+2], acc[k+3], biasvec[idx]);
const vec_t in2 = vec_set_32(input32[i + 2]);
const vec_t in3 = vec_set_32(input32[i + 3]);
const auto col0 = reinterpret_cast<const vec_t*>(&weights_[(i + 0) * kOutputDimensions * 4]);
const auto col1 = reinterpret_cast<const vec_t*>(&weights_[(i + 1) * kOutputDimensions * 4]);
const auto col2 = reinterpret_cast<const vec_t*>(&weights_[(i + 2) * kOutputDimensions * 4]);
const auto col3 = reinterpret_cast<const vec_t*>(&weights_[(i + 3) * kOutputDimensions * 4]);
for (int j = 0; j * kOutputSimdWidth < kOutputDimensions; ++j)
vec_add_dpbusd_32x4(outptr[j], in0, col0[j], in1, col1[j], in2, col2[j], in3, col3[j]);
} }
for (int i = 0; i < canSaturate16.count; ++i) }
output[canSaturate16.ids[i].out] += input[canSaturate16.ids[i].in] * canSaturate16.ids[i].w; else
} {
else if constexpr (kOutputDimensions == 1) for (IndexType k = 0; k < NumOutputRegs; ++k)
{
#if defined (USE_AVX512)
if constexpr (kPaddedInputDimensions % (kSimdWidth * 2) != 0)
{ {
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth; const IndexType idx = (bigBlock * NumOutputRegs + k);
const auto input_vector256 = reinterpret_cast<const __m256i*>(input); output[idx] = vec_hadd(acc[k], biases[idx]);
__m256i sum0 = _mm256_setzero_si256();
const auto row0 = reinterpret_cast<const __m256i*>(&weights_[0]);
for (int j = 0; j < (int)kNumChunks; ++j)
{
const __m256i in = input_vector256[j];
m256_add_dpbusd_epi32(sum0, in, row0[j]);
}
output[0] = m256_hadd(sum0, biases_[0]);
}
else
#endif
{
#if defined (USE_AVX512)
constexpr IndexType kNumChunks = kPaddedInputDimensions / (kSimdWidth * 2);
#else
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
#endif
vec_t sum0 = vec_setzero();
const auto row0 = reinterpret_cast<const vec_t*>(&weights_[0]);
for (int j = 0; j < (int)kNumChunks; ++j)
{
const vec_t in = input_vector[j];
vec_add_dpbusd_32(sum0, in, row0[j]);
}
output[0] = vec_hadd(sum0, biases_[0]);
} }
}
} }
# undef vec_zero
# undef vec_add_dpbusd_32x2
# undef vec_hadd
# undef vec_haddx4
#else #else
// Use old implementation for the other architectures.
// Use old implementation for the other architectures. affine_transform_non_ssse3<
InputDimensions,
auto output = reinterpret_cast<OutputType*>(buffer); PaddedInputDimensions,
OutputDimensions>(output, weights, biases, input);
#if defined(USE_SSE2)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const __m128i kZeros = _mm_setzero_si128();
const auto input_vector = reinterpret_cast<const __m128i*>(input);
#elif defined(USE_MMX)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const __m64 kZeros = _mm_setzero_si64();
const auto input_vector = reinterpret_cast<const __m64*>(input);
#elif defined(USE_NEON)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const auto input_vector = reinterpret_cast<const int8x8_t*>(input);
#endif
for (IndexType i = 0; i < kOutputDimensions; ++i) {
const IndexType offset = i * kPaddedInputDimensions;
#if defined(USE_SSE2)
__m128i sum_lo = _mm_cvtsi32_si128(biases_[i]);
__m128i sum_hi = kZeros;
const auto row = reinterpret_cast<const __m128i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m128i row_j = _mm_load_si128(&row[j]);
__m128i input_j = _mm_load_si128(&input_vector[j]);
__m128i extended_row_lo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
__m128i extended_row_hi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
__m128i extended_input_lo = _mm_unpacklo_epi8(input_j, kZeros);
__m128i extended_input_hi = _mm_unpackhi_epi8(input_j, kZeros);
__m128i product_lo = _mm_madd_epi16(extended_row_lo, extended_input_lo);
__m128i product_hi = _mm_madd_epi16(extended_row_hi, extended_input_hi);
sum_lo = _mm_add_epi32(sum_lo, product_lo);
sum_hi = _mm_add_epi32(sum_hi, product_hi);
}
__m128i sum = _mm_add_epi32(sum_lo, sum_hi);
__m128i sum_high_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_high_64);
__m128i sum_second_32 = _mm_shufflelo_epi16(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_second_32);
output[i] = _mm_cvtsi128_si32(sum);
#elif defined(USE_MMX)
__m64 sum_lo = _mm_cvtsi32_si64(biases_[i]);
__m64 sum_hi = kZeros;
const auto row = reinterpret_cast<const __m64*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m64 row_j = row[j];
__m64 input_j = input_vector[j];
__m64 extended_row_lo = _mm_srai_pi16(_mm_unpacklo_pi8(row_j, row_j), 8);
__m64 extended_row_hi = _mm_srai_pi16(_mm_unpackhi_pi8(row_j, row_j), 8);
__m64 extended_input_lo = _mm_unpacklo_pi8(input_j, kZeros);
__m64 extended_input_hi = _mm_unpackhi_pi8(input_j, kZeros);
__m64 product_lo = _mm_madd_pi16(extended_row_lo, extended_input_lo);
__m64 product_hi = _mm_madd_pi16(extended_row_hi, extended_input_hi);
sum_lo = _mm_add_pi32(sum_lo, product_lo);
sum_hi = _mm_add_pi32(sum_hi, product_hi);
}
__m64 sum = _mm_add_pi32(sum_lo, sum_hi);
sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum));
output[i] = _mm_cvtsi64_si32(sum);
#elif defined(USE_NEON)
int32x4_t sum = {biases_[i]};
const auto row = reinterpret_cast<const int8x8_t*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
int16x8_t product = vmull_s8(input_vector[j * 2], row[j * 2]);
product = vmlal_s8(product, input_vector[j * 2 + 1], row[j * 2 + 1]);
sum = vpadalq_s16(sum, product);
}
output[i] = sum[0] + sum[1] + sum[2] + sum[3];
#else
OutputType sum = biases_[i];
for (IndexType j = 0; j < kInputDimensions; ++j) {
sum += weights_[offset + j] * input[j];
}
output[i] = sum;
#endif
}
#if defined(USE_MMX)
_mm_empty();
#endif
#endif #endif
@@ -436,29 +370,176 @@ namespace Eval::NNUE::Layers {
using BiasType = OutputType; using BiasType = OutputType;
using WeightType = std::int8_t; using WeightType = std::int8_t;
PreviousLayer previous_layer_; alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
alignas(kCacheLineSize) BiasType biases_[kOutputDimensions];
alignas(kCacheLineSize) WeightType weights_[kOutputDimensions * kPaddedInputDimensions];
#if defined (USE_SSSE3)
struct CanSaturate {
int count;
struct Entry {
uint16_t out;
uint16_t in;
int8_t w;
} ids[kPaddedInputDimensions * kOutputDimensions * 3 / 4];
void add(int i, int j, int8_t w) {
ids[count].out = i;
ids[count].in = j;
ids[count].w = w;
++count;
}
} canSaturate16;
#endif
}; };
} // namespace Eval::NNUE::Layers template <IndexType InDims, IndexType OutDims>
class AffineTransform<InDims, OutDims, std::enable_if_t<(ceil_to_multiple<IndexType>(InDims, MaxSimdWidth) < LargeInputSize)>> {
public:
// Input/output type
// Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
using OutputBuffer = OutputType[PaddedOutputDimensions];
static_assert(PaddedInputDimensions < LargeInputSize, "Something went wrong. This specialization should not have been chosen.");
#if defined (USE_SSSE3)
static constexpr const IndexType OutputSimdWidth = SimdWidth / 4;
static constexpr const IndexType InputSimdWidth = SimdWidth;
#endif
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
return hashValue;
}
static IndexType get_weight_index_scrambled(IndexType i)
{
return
(i / 4) % (PaddedInputDimensions / 4) * OutputDimensions * 4 +
i / PaddedInputDimensions * 4 +
i % 4;
}
static IndexType get_weight_index(IndexType i)
{
#if defined (USE_SSSE3)
return get_weight_index_scrambled(i);
#else
return i;
#endif
}
// Read network parameters
bool read_parameters(std::istream& stream) {
for (IndexType i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
for (IndexType i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail();
}
// Forward propagation
const OutputType* propagate(
const InputType* input, OutputType* output) const {
#if defined (USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_add_dpbusd_32x4 Simd::m256_add_dpbusd_epi32x4
#define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4
#elif defined (USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_add_dpbusd_32x4 Simd::m128_add_dpbusd_epi32x4
#define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4
#endif
#if defined (USE_SSSE3)
const auto inputVector = reinterpret_cast<const vec_t*>(input);
static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1);
if constexpr (OutputDimensions % OutputSimdWidth == 0)
{
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / 4;
constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth;
const auto input32 = reinterpret_cast<const std::int32_t*>(input);
const vec_t* biasvec = reinterpret_cast<const vec_t*>(biases);
vec_t acc[NumRegs];
for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = biasvec[k];
for (IndexType i = 0; i < NumChunks; i += 2)
{
const vec_t in0 = vec_set_32(input32[i + 0]);
const vec_t in1 = vec_set_32(input32[i + 1]);
const auto col0 = reinterpret_cast<const vec_t*>(&weights[(i + 0) * OutputDimensions * 4]);
const auto col1 = reinterpret_cast<const vec_t*>(&weights[(i + 1) * OutputDimensions * 4]);
for (IndexType k = 0; k < NumRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, col0[k], in1, col1[k]);
}
vec_t* outptr = reinterpret_cast<vec_t*>(output);
for (IndexType k = 0; k < NumRegs; ++k)
outptr[k] = acc[k];
}
else if constexpr (OutputDimensions == 1)
{
constexpr IndexType NumChunks = PaddedInputDimensions / SimdWidth;
vec_t sum0 = vec_setzero();
const auto row0 = reinterpret_cast<const vec_t*>(&weights[0]);
for (int j = 0; j < (int)NumChunks; ++j)
{
const vec_t in = inputVector[j];
vec_add_dpbusd_32(sum0, in, row0[j]);
}
output[0] = vec_hadd(sum0, biases[0]);
}
# undef vec_setzero
# undef vec_set_32
# undef vec_add_dpbusd_32
# undef vec_add_dpbusd_32x2
# undef vec_add_dpbusd_32x4
# undef vec_hadd
# undef vec_haddx4
#else
// Use old implementation for the other architectures.
affine_transform_non_ssse3<
InputDimensions,
PaddedInputDimensions,
OutputDimensions>(output, weights, biases, input);
#endif
return output;
}
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED #endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
+81 -67
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,144 +23,158 @@
#include "../nnue_common.h" #include "../nnue_common.h"
namespace Eval::NNUE::Layers { namespace Stockfish::Eval::NNUE::Layers {
// Clipped ReLU // Clipped ReLU
template <typename PreviousLayer> template <IndexType InDims>
class ClippedReLU { class ClippedReLU {
public: public:
// Input/output type // Input/output type
using InputType = typename PreviousLayer::OutputType; using InputType = std::int32_t;
using OutputType = std::uint8_t; using OutputType = std::uint8_t;
static_assert(std::is_same<InputType, std::int32_t>::value, "");
// Number of input/output dimensions // Number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType InputDimensions = InDims;
PreviousLayer::kOutputDimensions; static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType kOutputDimensions = kInputDimensions; static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
// Size of forward propagation buffer used in this layer using OutputBuffer = OutputType[PaddedOutputDimensions];
static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize =
PreviousLayer::kBufferSize + kSelfBufferSize;
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hash_value = 0x538D24C7u; std::uint32_t hashValue = 0x538D24C7u;
hash_value += PreviousLayer::GetHashValue(); hashValue += prevHash;
return hash_value; return hashValue;
} }
// Read network parameters // Read network parameters
bool ReadParameters(std::istream& stream) { bool read_parameters(std::istream&) {
return previous_layer_.ReadParameters(stream); return true;
}
// Write network parameters
bool write_parameters(std::ostream&) const {
return true;
} }
// Forward propagation // Forward propagation
const OutputType* Propagate( const OutputType* propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const InputType* input, OutputType* output) const {
const auto input = previous_layer_.Propagate(
transformed_features, buffer + kSelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
#if defined(USE_AVX2) #if defined(USE_AVX2)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth; if constexpr (InputDimensions % SimdWidth == 0) {
const __m256i kZero = _mm256_setzero_si256(); constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m256i kOffsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0); const __m256i Zero = _mm256_setzero_si256();
const auto in = reinterpret_cast<const __m256i*>(input); const __m256i Offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
const auto out = reinterpret_cast<__m256i*>(output); const auto in = reinterpret_cast<const __m256i*>(input);
for (IndexType i = 0; i < kNumChunks; ++i) { const auto out = reinterpret_cast<__m256i*>(output);
const __m256i words0 = _mm256_srai_epi16(_mm256_packs_epi32( for (IndexType i = 0; i < NumChunks; ++i) {
_mm256_load_si256(&in[i * 4 + 0]), const __m256i words0 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 1])), kWeightScaleBits); _mm256_load_si256(&in[i * 4 + 0]),
const __m256i words1 = _mm256_srai_epi16(_mm256_packs_epi32( _mm256_load_si256(&in[i * 4 + 1])), WeightScaleBits);
_mm256_load_si256(&in[i * 4 + 2]), const __m256i words1 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 3])), kWeightScaleBits); _mm256_load_si256(&in[i * 4 + 2]),
_mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(_mm256_max_epi8( _mm256_load_si256(&in[i * 4 + 3])), WeightScaleBits);
_mm256_packs_epi16(words0, words1), kZero), kOffsets)); _mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(_mm256_max_epi8(
_mm256_packs_epi16(words0, words1), Zero), Offsets));
}
} else {
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const __m128i Zero = _mm_setzero_si128();
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i], _mm_max_epi8(packedbytes, Zero));
}
} }
constexpr IndexType kStart = kNumChunks * kSimdWidth; constexpr IndexType Start =
InputDimensions % SimdWidth == 0
? InputDimensions / SimdWidth * SimdWidth
: InputDimensions / (SimdWidth / 2) * (SimdWidth / 2);
#elif defined(USE_SSE2) #elif defined(USE_SSE2)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth; constexpr IndexType NumChunks = InputDimensions / SimdWidth;
#ifdef USE_SSE41 #ifdef USE_SSE41
const __m128i kZero = _mm_setzero_si128(); const __m128i Zero = _mm_setzero_si128();
#else #else
const __m128i k0x80s = _mm_set1_epi8(-128); const __m128i k0x80s = _mm_set1_epi8(-128);
#endif #endif
const auto in = reinterpret_cast<const __m128i*>(input); const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output); const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < kNumChunks; ++i) { for (IndexType i = 0; i < NumChunks; ++i) {
const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32( const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1])), kWeightScaleBits); _mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32( const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3])), kWeightScaleBits); _mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1); const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i], _mm_store_si128(&out[i],
#ifdef USE_SSE41 #ifdef USE_SSE41
_mm_max_epi8(packedbytes, kZero) _mm_max_epi8(packedbytes, Zero)
#else #else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s) _mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif #endif
); );
} }
constexpr IndexType kStart = kNumChunks * kSimdWidth; constexpr IndexType Start = NumChunks * SimdWidth;
#elif defined(USE_MMX) #elif defined(USE_MMX)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth; constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m64 k0x80s = _mm_set1_pi8(-128); const __m64 k0x80s = _mm_set1_pi8(-128);
const auto in = reinterpret_cast<const __m64*>(input); const auto in = reinterpret_cast<const __m64*>(input);
const auto out = reinterpret_cast<__m64*>(output); const auto out = reinterpret_cast<__m64*>(output);
for (IndexType i = 0; i < kNumChunks; ++i) { for (IndexType i = 0; i < NumChunks; ++i) {
const __m64 words0 = _mm_srai_pi16( const __m64 words0 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 0], in[i * 4 + 1]), _mm_packs_pi32(in[i * 4 + 0], in[i * 4 + 1]),
kWeightScaleBits); WeightScaleBits);
const __m64 words1 = _mm_srai_pi16( const __m64 words1 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 2], in[i * 4 + 3]), _mm_packs_pi32(in[i * 4 + 2], in[i * 4 + 3]),
kWeightScaleBits); WeightScaleBits);
const __m64 packedbytes = _mm_packs_pi16(words0, words1); const __m64 packedbytes = _mm_packs_pi16(words0, words1);
out[i] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s); out[i] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
} }
_mm_empty(); _mm_empty();
constexpr IndexType kStart = kNumChunks * kSimdWidth; constexpr IndexType Start = NumChunks * SimdWidth;
#elif defined(USE_NEON) #elif defined(USE_NEON)
constexpr IndexType kNumChunks = kInputDimensions / (kSimdWidth / 2); constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const int8x8_t kZero = {0}; const int8x8_t Zero = {0};
const auto in = reinterpret_cast<const int32x4_t*>(input); const auto in = reinterpret_cast<const int32x4_t*>(input);
const auto out = reinterpret_cast<int8x8_t*>(output); const auto out = reinterpret_cast<int8x8_t*>(output);
for (IndexType i = 0; i < kNumChunks; ++i) { for (IndexType i = 0; i < NumChunks; ++i) {
int16x8_t shifted; int16x8_t shifted;
const auto pack = reinterpret_cast<int16x4_t*>(&shifted); const auto pack = reinterpret_cast<int16x4_t*>(&shifted);
pack[0] = vqshrn_n_s32(in[i * 2 + 0], kWeightScaleBits); pack[0] = vqshrn_n_s32(in[i * 2 + 0], WeightScaleBits);
pack[1] = vqshrn_n_s32(in[i * 2 + 1], kWeightScaleBits); pack[1] = vqshrn_n_s32(in[i * 2 + 1], WeightScaleBits);
out[i] = vmax_s8(vqmovn_s16(shifted), kZero); out[i] = vmax_s8(vqmovn_s16(shifted), Zero);
} }
constexpr IndexType kStart = kNumChunks * (kSimdWidth / 2); constexpr IndexType Start = NumChunks * (SimdWidth / 2);
#else #else
constexpr IndexType kStart = 0; constexpr IndexType Start = 0;
#endif #endif
for (IndexType i = kStart; i < kInputDimensions; ++i) { for (IndexType i = Start; i < InputDimensions; ++i) {
output[i] = static_cast<OutputType>( output[i] = static_cast<OutputType>(
std::max(0, std::min(127, input[i] >> kWeightScaleBits))); std::max(0, std::min(127, input[i] >> WeightScaleBits)));
} }
return output; return output;
} }
private:
PreviousLayer previous_layer_;
}; };
} // namespace Eval::NNUE::Layers } // namespace Stockfish::Eval::NNUE::Layers
#endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED #endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
-68
View File
@@ -1,68 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// NNUE evaluation function layer InputSlice definition
#ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
#define NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
#include "../nnue_common.h"
namespace Eval::NNUE::Layers {
// Input layer
template <IndexType OutputDimensions, IndexType Offset = 0>
class InputSlice {
public:
// Need to maintain alignment
static_assert(Offset % kMaxSimdWidth == 0, "");
// Output type
using OutputType = TransformedFeatureType;
// Output dimensionality
static constexpr IndexType kOutputDimensions = OutputDimensions;
// Size of forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = 0;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xEC42E90Du;
hash_value ^= kOutputDimensions ^ (Offset << 10);
return hash_value;
}
// Read network parameters
bool ReadParameters(std::istream& /*stream*/) {
return true;
}
// Forward propagation
const OutputType* Propagate(
const TransformedFeatureType* transformed_features,
char* /*buffer*/) const {
return transformed_features + Offset;
}
private:
};
} // namespace Layers
#endif // #ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
+387
View File
@@ -0,0 +1,387 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STOCKFISH_SIMD_H_INCLUDED
#define STOCKFISH_SIMD_H_INCLUDED
#if defined(USE_AVX2)
# include <immintrin.h>
#elif defined(USE_SSE41)
# include <smmintrin.h>
#elif defined(USE_SSSE3)
# include <tmmintrin.h>
#elif defined(USE_SSE2)
# include <emmintrin.h>
#elif defined(USE_MMX)
# include <mmintrin.h>
#elif defined(USE_NEON)
# include <arm_neon.h>
#endif
// The inline asm is only safe for GCC, where it is necessary to get good codegen.
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101693
// Clang does fine without it.
// Play around here: https://godbolt.org/z/7EWqrYq51
#if (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER))
#define USE_INLINE_ASM
#endif
// Use either the AVX512 or AVX-VNNI version of the VNNI instructions.
#if defined(USE_AVXVNNI)
#define VNNI_PREFIX "%{vex%} "
#else
#define VNNI_PREFIX ""
#endif
namespace Stockfish::Simd {
#if defined (USE_AVX512)
[[maybe_unused]] static int m512_hadd(__m512i sum, int bias) {
return _mm512_reduce_add_epi32(sum) + bias;
}
/*
Parameters:
sum0 = [zmm0.i128[0], zmm0.i128[1], zmm0.i128[2], zmm0.i128[3]]
sum1 = [zmm1.i128[0], zmm1.i128[1], zmm1.i128[2], zmm1.i128[3]]
sum2 = [zmm2.i128[0], zmm2.i128[1], zmm2.i128[2], zmm2.i128[3]]
sum3 = [zmm3.i128[0], zmm3.i128[1], zmm3.i128[2], zmm3.i128[3]]
Returns:
ret = [
reduce_add_epi32(zmm0.i128[0]), reduce_add_epi32(zmm1.i128[0]), reduce_add_epi32(zmm2.i128[0]), reduce_add_epi32(zmm3.i128[0]),
reduce_add_epi32(zmm0.i128[1]), reduce_add_epi32(zmm1.i128[1]), reduce_add_epi32(zmm2.i128[1]), reduce_add_epi32(zmm3.i128[1]),
reduce_add_epi32(zmm0.i128[2]), reduce_add_epi32(zmm1.i128[2]), reduce_add_epi32(zmm2.i128[2]), reduce_add_epi32(zmm3.i128[2]),
reduce_add_epi32(zmm0.i128[3]), reduce_add_epi32(zmm1.i128[3]), reduce_add_epi32(zmm2.i128[3]), reduce_add_epi32(zmm3.i128[3])
]
*/
[[maybe_unused]] static __m512i m512_hadd128x16_interleave(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) {
__m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
__m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
__m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
__m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
__m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
__m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
__m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
__m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
return _mm512_add_epi32(sum0123a, sum0123b);
}
[[maybe_unused]] static __m128i m512_haddx4(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3,
__m128i bias) {
__m512i sum = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
__m256i sum256lo = _mm512_castsi512_si256(sum);
__m256i sum256hi = _mm512_extracti64x4_epi64(sum, 1);
sum256lo = _mm256_add_epi32(sum256lo, sum256hi);
__m128i sum128lo = _mm256_castsi256_si128(sum256lo);
__m128i sum128hi = _mm256_extracti128_si256(sum256lo, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m512_add_dpbusd_epi32(
__m512i& acc,
__m512i a,
__m512i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm512_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp = _mm512_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a, b);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m512_add_dpbusd_epi32x2(
__m512i& acc,
__m512i a0, __m512i b0,
__m512i a1, __m512i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b0], %[a0], %[acc]\n\t"
"vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm512_dpbusd_epi32(acc, a0, b0);
acc = _mm512_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp0 = _mm512_maddubs_epi16(a0, b0);
__m512i tmp1 = _mm512_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a0, b0);
__m512i product1 = _mm512_maddubs_epi16(a1, b1);
product0 = _mm512_adds_epi16(product0, product1);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_AVX2)
[[maybe_unused]] static int m256_hadd(__m256i sum, int bias) {
__m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
return _mm_cvtsi128_si32(sum128) + bias;
}
[[maybe_unused]] static __m128i m256_haddx4(
__m256i sum0, __m256i sum1, __m256i sum2, __m256i sum3,
__m128i bias) {
sum0 = _mm256_hadd_epi32(sum0, sum1);
sum2 = _mm256_hadd_epi32(sum2, sum3);
sum0 = _mm256_hadd_epi32(sum0, sum2);
__m128i sum128lo = _mm256_castsi256_si128(sum0);
__m128i sum128hi = _mm256_extracti128_si256(sum0, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m256_add_dpbusd_epi32(
__m256i& acc,
__m256i a,
__m256i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
VNNI_PREFIX "vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm256_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp = _mm256_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a, b);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m256_add_dpbusd_epi32x2(
__m256i& acc,
__m256i a0, __m256i b0,
__m256i a1, __m256i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
VNNI_PREFIX "vpdpbusd %[b0], %[a0], %[acc]\n\t"
VNNI_PREFIX "vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm256_dpbusd_epi32(acc, a0, b0);
acc = _mm256_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp0 = _mm256_maddubs_epi16(a0, b0);
__m256i tmp1 = _mm256_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a0, b0);
__m256i product1 = _mm256_maddubs_epi16(a1, b1);
product0 = _mm256_adds_epi16(product0, product1);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_SSSE3)
[[maybe_unused]] static int m128_hadd(__m128i sum, int bias) {
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
return _mm_cvtsi128_si32(sum) + bias;
}
[[maybe_unused]] static __m128i m128_haddx4(
__m128i sum0, __m128i sum1, __m128i sum2, __m128i sum3,
__m128i bias) {
sum0 = _mm_hadd_epi32(sum0, sum1);
sum2 = _mm_hadd_epi32(sum2, sum3);
sum0 = _mm_hadd_epi32(sum0, sum2);
return _mm_add_epi32(sum0, bias);
}
[[maybe_unused]] static void m128_add_dpbusd_epi32(
__m128i& acc,
__m128i a,
__m128i b) {
# if defined (USE_INLINE_ASM)
__m128i tmp = _mm_maddubs_epi16(a, b);
asm(
"pmaddwd %[ones], %[tmp]\n\t"
"paddd %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
[[maybe_unused]] static void m128_add_dpbusd_epi32x2(
__m128i& acc,
__m128i a0, __m128i b0,
__m128i a1, __m128i b1) {
# if defined (USE_INLINE_ASM)
__m128i tmp0 = _mm_maddubs_epi16(a0, b0);
__m128i tmp1 = _mm_maddubs_epi16(a1, b1);
asm(
"paddsw %[tmp1], %[tmp0]\n\t"
"pmaddwd %[ones], %[tmp0]\n\t"
"paddd %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a0, b0);
__m128i product1 = _mm_maddubs_epi16(a1, b1);
product0 = _mm_adds_epi16(product0, product1);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
#endif
#if defined (USE_NEON)
[[maybe_unused]] static int neon_m128_reduce_add_epi32(int32x4_t s) {
# if USE_NEON >= 8
return vaddvq_s32(s);
# else
return s[0] + s[1] + s[2] + s[3];
# endif
}
[[maybe_unused]] static int neon_m128_hadd(int32x4_t sum, int bias) {
return neon_m128_reduce_add_epi32(sum) + bias;
}
[[maybe_unused]] static int32x4_t neon_m128_haddx4(
int32x4_t sum0, int32x4_t sum1, int32x4_t sum2, int32x4_t sum3,
int32x4_t bias) {
int32x4_t hsums {
neon_m128_reduce_add_epi32(sum0),
neon_m128_reduce_add_epi32(sum1),
neon_m128_reduce_add_epi32(sum2),
neon_m128_reduce_add_epi32(sum3)
};
return vaddq_s32(hsums, bias);
}
[[maybe_unused]] static void neon_m128_add_dpbusd_epi32x2(
int32x4_t& acc,
int8x8_t a0, int8x8_t b0,
int8x8_t a1, int8x8_t b1) {
int16x8_t product = vmull_s8(a0, b0);
product = vmlal_s8(product, a1, b1);
acc = vpadalq_s16(acc, product);
}
#endif
}
#endif // STOCKFISH_SIMD_H_INCLUDED
+120
View File
@@ -0,0 +1,120 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Definition of layer ClippedReLU of NNUE evaluation function
#ifndef NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#define NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Layers {
// Clipped ReLU
template <IndexType InDims>
class SqrClippedReLU {
public:
// Input/output type
using InputType = std::int32_t;
using OutputType = std::uint8_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
hashValue += prevHash;
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream&) {
return true;
}
// Write network parameters
bool write_parameters(std::ostream&) const {
return true;
}
// Forward propagation
const OutputType* propagate(
const InputType* input, OutputType* output) const {
#if defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / 16;
#ifdef USE_SSE41
const __m128i Zero = _mm_setzero_si128();
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
static_assert(WeightScaleBits == 6);
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
__m128i words0 = _mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1]));
__m128i words1 = _mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3]));
// Not sure if
words0 = _mm_srli_epi16(_mm_mulhi_epi16(words0, words0), 3);
words1 = _mm_srli_epi16(_mm_mulhi_epi16(words1, words1), 3);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, Zero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
constexpr IndexType Start = NumChunks * 16;
#else
constexpr IndexType Start = 0;
#endif
for (IndexType i = Start; i < InputDimensions; ++i) {
output[i] = static_cast<OutputType>(
// realy should be /127 but we need to make it fast
// needs to be accounted for in the trainer
std::max(0ll, std::min(127ll, (((long long)input[i] * input[i]) >> (2 * WeightScaleBits)) / 128)));
}
return output;
}
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
+7 -10
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,18 +23,15 @@
#include "nnue_architecture.h" #include "nnue_architecture.h"
namespace Eval::NNUE { namespace Stockfish::Eval::NNUE {
// The accumulator of a StateInfo without parent is set to the INIT state
enum AccumulatorState { EMPTY, COMPUTED, INIT };
// Class that holds the result of affine transformation of input features // Class that holds the result of affine transformation of input features
struct alignas(kCacheLineSize) Accumulator { struct alignas(CacheLineSize) Accumulator {
std::int16_t std::int16_t accumulation[2][TransformedFeatureDimensions];
accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions]; std::int32_t psqtAccumulation[2][PSQTBuckets];
AccumulatorState state[2]; bool computed[2];
}; };
} // namespace Eval::NNUE } // namespace Stockfish::Eval::NNUE
#endif // NNUE_ACCUMULATOR_H_INCLUDED #endif // NNUE_ACCUMULATOR_H_INCLUDED
+110 -10
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,18 +21,118 @@
#ifndef NNUE_ARCHITECTURE_H_INCLUDED #ifndef NNUE_ARCHITECTURE_H_INCLUDED
#define NNUE_ARCHITECTURE_H_INCLUDED #define NNUE_ARCHITECTURE_H_INCLUDED
// Defines the network structure #include <memory>
#include "architectures/halfkp_256x2-32-32.h"
namespace Eval::NNUE { #include "nnue_common.h"
static_assert(kTransformedFeatureDimensions % kMaxSimdWidth == 0, ""); #include "features/half_ka_v2_hm.h"
static_assert(Network::kOutputDimensions == 1, "");
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
// Trigger for full calculation instead of difference calculation #include "layers/affine_transform.h"
constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers; #include "layers/clipped_relu.h"
#include "layers/sqr_clipped_relu.h"
} // namespace Eval::NNUE #include "../misc.h"
namespace Stockfish::Eval::NNUE {
// Input features used in evaluation function
using FeatureSet = Features::HalfKAv2_hm;
// Number of input feature dimensions after conversion
constexpr IndexType TransformedFeatureDimensions = 1024;
constexpr IndexType PSQTBuckets = 8;
constexpr IndexType LayerStacks = 8;
struct Network
{
static constexpr int FC_0_OUTPUTS = 15;
static constexpr int FC_1_OUTPUTS = 32;
Layers::AffineTransform<TransformedFeatureDimensions, FC_0_OUTPUTS + 1> fc_0;
Layers::SqrClippedReLU<FC_0_OUTPUTS + 1> ac_sqr_0;
Layers::ClippedReLU<FC_0_OUTPUTS + 1> ac_0;
Layers::AffineTransform<FC_0_OUTPUTS * 2, FC_1_OUTPUTS> fc_1;
Layers::ClippedReLU<FC_1_OUTPUTS> ac_1;
Layers::AffineTransform<FC_1_OUTPUTS, 1> fc_2;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
// input slice hash
std::uint32_t hashValue = 0xEC42E90Du;
hashValue ^= TransformedFeatureDimensions * 2;
hashValue = decltype(fc_0)::get_hash_value(hashValue);
hashValue = decltype(ac_0)::get_hash_value(hashValue);
hashValue = decltype(fc_1)::get_hash_value(hashValue);
hashValue = decltype(ac_1)::get_hash_value(hashValue);
hashValue = decltype(fc_2)::get_hash_value(hashValue);
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream& stream) {
if (!fc_0.read_parameters(stream)) return false;
if (!ac_0.read_parameters(stream)) return false;
if (!fc_1.read_parameters(stream)) return false;
if (!ac_1.read_parameters(stream)) return false;
if (!fc_2.read_parameters(stream)) return false;
return true;
}
// Read network parameters
bool write_parameters(std::ostream& stream) const {
if (!fc_0.write_parameters(stream)) return false;
if (!ac_0.write_parameters(stream)) return false;
if (!fc_1.write_parameters(stream)) return false;
if (!ac_1.write_parameters(stream)) return false;
if (!fc_2.write_parameters(stream)) return false;
return true;
}
std::int32_t propagate(const TransformedFeatureType* transformedFeatures)
{
struct alignas(CacheLineSize) Buffer
{
alignas(CacheLineSize) decltype(fc_0)::OutputBuffer fc_0_out;
alignas(CacheLineSize) decltype(ac_sqr_0)::OutputType ac_sqr_0_out[ceil_to_multiple<IndexType>(FC_0_OUTPUTS * 2, 32)];
alignas(CacheLineSize) decltype(ac_0)::OutputBuffer ac_0_out;
alignas(CacheLineSize) decltype(fc_1)::OutputBuffer fc_1_out;
alignas(CacheLineSize) decltype(ac_1)::OutputBuffer ac_1_out;
alignas(CacheLineSize) decltype(fc_2)::OutputBuffer fc_2_out;
Buffer()
{
std::memset(this, 0, sizeof(*this));
}
};
#if defined(__clang__) && (__APPLE__)
// workaround for a bug reported with xcode 12
static thread_local auto tlsBuffer = std::make_unique<Buffer>();
// Access TLS only once, cache result.
Buffer& buffer = *tlsBuffer;
#else
alignas(CacheLineSize) static thread_local Buffer buffer;
#endif
fc_0.propagate(transformedFeatures, buffer.fc_0_out);
ac_sqr_0.propagate(buffer.fc_0_out, buffer.ac_sqr_0_out);
ac_0.propagate(buffer.fc_0_out, buffer.ac_0_out);
std::memcpy(buffer.ac_sqr_0_out + FC_0_OUTPUTS, buffer.ac_0_out, FC_0_OUTPUTS * sizeof(decltype(ac_0)::OutputType));
fc_1.propagate(buffer.ac_sqr_0_out, buffer.fc_1_out);
ac_1.propagate(buffer.fc_1_out, buffer.ac_1_out);
fc_2.propagate(buffer.ac_1_out, buffer.fc_2_out);
// buffer.fc_0_out[FC_0_OUTPUTS] is such that 1.0 is equal to 127*(1<<WeightScaleBits) in quantized form
// but we want 1.0 to be equal to 600*OutputScale
std::int32_t fwdOut = int(buffer.fc_0_out[FC_0_OUTPUTS]) * (600*OutputScale) / (127*(1<<WeightScaleBits));
std::int32_t outputValue = buffer.fc_2_out[0] + fwdOut;
return outputValue;
}
};
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED #endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED
+80 -48
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include "../misc.h" // for IsLittleEndian
#if defined(USE_AVX2) #if defined(USE_AVX2)
#include <immintrin.h> #include <immintrin.h>
@@ -43,61 +45,33 @@
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
namespace Eval::NNUE { namespace Stockfish::Eval::NNUE {
// Version of the evaluation file // Version of the evaluation file
constexpr std::uint32_t kVersion = 0x7AF32F16u; constexpr std::uint32_t Version = 0x7AF32F20u;
// Constant used in evaluation value calculation // Constant used in evaluation value calculation
constexpr int FV_SCALE = 16; constexpr int OutputScale = 16;
constexpr int kWeightScaleBits = 6; constexpr int WeightScaleBits = 6;
// Size of cache line (in bytes) // Size of cache line (in bytes)
constexpr std::size_t kCacheLineSize = 64; constexpr std::size_t CacheLineSize = 64;
// SIMD width (in bytes) // SIMD width (in bytes)
#if defined(USE_AVX2) #if defined(USE_AVX2)
constexpr std::size_t kSimdWidth = 32; constexpr std::size_t SimdWidth = 32;
#elif defined(USE_SSE2) #elif defined(USE_SSE2)
constexpr std::size_t kSimdWidth = 16; constexpr std::size_t SimdWidth = 16;
#elif defined(USE_MMX) #elif defined(USE_MMX)
constexpr std::size_t kSimdWidth = 8; constexpr std::size_t SimdWidth = 8;
#elif defined(USE_NEON) #elif defined(USE_NEON)
constexpr std::size_t kSimdWidth = 16; constexpr std::size_t SimdWidth = 16;
#endif #endif
constexpr std::size_t kMaxSimdWidth = 32; constexpr std::size_t MaxSimdWidth = 32;
// unique number for each piece type on each square
enum {
PS_NONE = 0,
PS_W_PAWN = 1,
PS_B_PAWN = 1 * SQUARE_NB + 1,
PS_W_KNIGHT = 2 * SQUARE_NB + 1,
PS_B_KNIGHT = 3 * SQUARE_NB + 1,
PS_W_BISHOP = 4 * SQUARE_NB + 1,
PS_B_BISHOP = 5 * SQUARE_NB + 1,
PS_W_ROOK = 6 * SQUARE_NB + 1,
PS_B_ROOK = 7 * SQUARE_NB + 1,
PS_W_QUEEN = 8 * SQUARE_NB + 1,
PS_B_QUEEN = 9 * SQUARE_NB + 1,
PS_W_KING = 10 * SQUARE_NB + 1,
PS_END = PS_W_KING, // pieces without kings (pawns included)
PS_B_KING = 11 * SQUARE_NB + 1,
PS_END2 = 12 * SQUARE_NB + 1
};
constexpr uint32_t kpp_board_index[COLOR_NB][PIECE_NB] = {
// convention: W - us, B - them
// viewed from other side, W and B are reversed
{ PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE },
{ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_KING, PS_NONE }
};
// Type of input feature after conversion // Type of input feature after conversion
using TransformedFeatureType = std::uint8_t; using TransformedFeatureType = std::uint8_t;
@@ -105,7 +79,7 @@ namespace Eval::NNUE {
// Round n up to be a multiple of base // Round n up to be a multiple of base
template <typename IntType> template <typename IntType>
constexpr IntType CeilToMultiple(IntType n, IntType base) { constexpr IntType ceil_to_multiple(IntType n, IntType base) {
return (n + base - 1) / base * base; return (n + base - 1) / base * base;
} }
@@ -114,19 +88,77 @@ namespace Eval::NNUE {
// necessary to return a result with the byte ordering of the compiling machine. // necessary to return a result with the byte ordering of the compiling machine.
template <typename IntType> template <typename IntType>
inline IntType read_little_endian(std::istream& stream) { inline IntType read_little_endian(std::istream& stream) {
IntType result; IntType result;
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = 0;
stream.read(reinterpret_cast<char*>(u), sizeof(IntType)); if (IsLittleEndian)
for (std::size_t i = 0; i < sizeof(IntType); ++i) stream.read(reinterpret_cast<char*>(&result), sizeof(IntType));
v = (v << 8) | u[sizeof(IntType) - i - 1]; else
{
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = 0;
stream.read(reinterpret_cast<char*>(u), sizeof(IntType));
for (std::size_t i = 0; i < sizeof(IntType); ++i)
v = (v << 8) | u[sizeof(IntType) - i - 1];
std::memcpy(&result, &v, sizeof(IntType));
}
std::memcpy(&result, &v, sizeof(IntType));
return result; return result;
} }
} // namespace Eval::NNUE // write_little_endian() is our utility to write an integer (signed or unsigned, any size)
// to a stream in little-endian order. We swap the byte order before the write if
// necessary to always write in little endian order, independently of the byte
// ordering of the compiling machine.
template <typename IntType>
inline void write_little_endian(std::ostream& stream, IntType value) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(&value), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = value;
std::size_t i = 0;
// if constexpr to silence the warning about shift by 8
if constexpr (sizeof(IntType) > 1)
{
for (; i + 1 < sizeof(IntType); ++i)
{
u[i] = (std::uint8_t)v;
v >>= 8;
}
}
u[i] = (std::uint8_t)v;
stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
}
}
// read_little_endian(s, out, N) : read integers in bulk from a little indian stream.
// This reads N integers from stream s and put them in array out.
template <typename IntType>
inline void read_little_endian(std::istream& stream, IntType* out, std::size_t count) {
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(out), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
out[i] = read_little_endian<IntType>(stream);
}
// write_little_endian(s, values, N) : write integers in bulk to a little indian stream.
// This takes N integers from array values and writes them on stream s.
template <typename IntType>
inline void write_little_endian(std::ostream& stream, const IntType* values, std::size_t count) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(values), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
write_little_endian<IntType>(stream, values[i]);
}
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_COMMON_H_INCLUDED #endif // #ifndef NNUE_COMMON_H_INCLUDED
+369 -197
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,72 +23,213 @@
#include "nnue_common.h" #include "nnue_common.h"
#include "nnue_architecture.h" #include "nnue_architecture.h"
#include "features/index_list.h"
#include <cstring> // std::memset() #include <cstring> // std::memset()
namespace Eval::NNUE { namespace Stockfish::Eval::NNUE {
using BiasType = std::int16_t;
using WeightType = std::int16_t;
using PSQTWeightType = std::int32_t;
// If vector instructions are enabled, we update and refresh the // If vector instructions are enabled, we update and refresh the
// accumulator tile by tile such that each tile fits in the CPU's // accumulator tile by tile such that each tile fits in the CPU's
// vector registers. // vector registers.
#define VECTOR #define VECTOR
static_assert(PSQTBuckets % 8 == 0,
"Per feature PSQT values cannot be processed at granularity lower than 8 at a time.");
#ifdef USE_AVX512 #ifdef USE_AVX512
typedef __m512i vec_t; typedef __m512i vec_t;
typedef __m256i psqt_vec_t;
#define vec_load(a) _mm512_load_si512(a) #define vec_load(a) _mm512_load_si512(a)
#define vec_store(a,b) _mm512_store_si512(a,b) #define vec_store(a,b) _mm512_store_si512(a,b)
#define vec_add_16(a,b) _mm512_add_epi16(a,b) #define vec_add_16(a,b) _mm512_add_epi16(a,b)
#define vec_sub_16(a,b) _mm512_sub_epi16(a,b) #define vec_sub_16(a,b) _mm512_sub_epi16(a,b)
static constexpr IndexType kNumRegs = 8; // only 8 are needed #define vec_mul_16(a,b) _mm512_mullo_epi16(a,b)
#define vec_zero() _mm512_setzero_epi32()
#define vec_set_16(a) _mm512_set1_epi16(a)
#define vec_max_16(a,b) _mm512_max_epi16(a,b)
#define vec_min_16(a,b) _mm512_min_epi16(a,b)
inline vec_t vec_msb_pack_16(vec_t a, vec_t b){
vec_t compacted = _mm512_packs_epi16(_mm512_srli_epi16(a,7),_mm512_srli_epi16(b,7));
return _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7), compacted);
}
#define vec_load_psqt(a) _mm256_load_si256(a)
#define vec_store_psqt(a,b) _mm256_store_si256(a,b)
#define vec_add_psqt_32(a,b) _mm256_add_epi32(a,b)
#define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b)
#define vec_zero_psqt() _mm256_setzero_si256()
#define NumRegistersSIMD 32
#define MaxChunkSize 64
#elif USE_AVX2 #elif USE_AVX2
typedef __m256i vec_t; typedef __m256i vec_t;
typedef __m256i psqt_vec_t;
#define vec_load(a) _mm256_load_si256(a) #define vec_load(a) _mm256_load_si256(a)
#define vec_store(a,b) _mm256_store_si256(a,b) #define vec_store(a,b) _mm256_store_si256(a,b)
#define vec_add_16(a,b) _mm256_add_epi16(a,b) #define vec_add_16(a,b) _mm256_add_epi16(a,b)
#define vec_sub_16(a,b) _mm256_sub_epi16(a,b) #define vec_sub_16(a,b) _mm256_sub_epi16(a,b)
static constexpr IndexType kNumRegs = 16; #define vec_mul_16(a,b) _mm256_mullo_epi16(a,b)
#define vec_zero() _mm256_setzero_si256()
#define vec_set_16(a) _mm256_set1_epi16(a)
#define vec_max_16(a,b) _mm256_max_epi16(a,b)
#define vec_min_16(a,b) _mm256_min_epi16(a,b)
inline vec_t vec_msb_pack_16(vec_t a, vec_t b){
vec_t compacted = _mm256_packs_epi16(_mm256_srli_epi16(a,7), _mm256_srli_epi16(b,7));
return _mm256_permute4x64_epi64(compacted, 0b11011000);
}
#define vec_load_psqt(a) _mm256_load_si256(a)
#define vec_store_psqt(a,b) _mm256_store_si256(a,b)
#define vec_add_psqt_32(a,b) _mm256_add_epi32(a,b)
#define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b)
#define vec_zero_psqt() _mm256_setzero_si256()
#define NumRegistersSIMD 16
#define MaxChunkSize 32
#elif USE_SSE2 #elif USE_SSE2
typedef __m128i vec_t; typedef __m128i vec_t;
typedef __m128i psqt_vec_t;
#define vec_load(a) (*(a)) #define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b) #define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) _mm_add_epi16(a,b) #define vec_add_16(a,b) _mm_add_epi16(a,b)
#define vec_sub_16(a,b) _mm_sub_epi16(a,b) #define vec_sub_16(a,b) _mm_sub_epi16(a,b)
static constexpr IndexType kNumRegs = Is64Bit ? 16 : 8; #define vec_mul_16(a,b) _mm_mullo_epi16(a,b)
#define vec_zero() _mm_setzero_si128()
#define vec_set_16(a) _mm_set1_epi16(a)
#define vec_max_16(a,b) _mm_max_epi16(a,b)
#define vec_min_16(a,b) _mm_min_epi16(a,b)
#define vec_msb_pack_16(a,b) _mm_packs_epi16(_mm_srli_epi16(a,7),_mm_srli_epi16(b,7))
#define vec_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) _mm_add_epi32(a,b)
#define vec_sub_psqt_32(a,b) _mm_sub_epi32(a,b)
#define vec_zero_psqt() _mm_setzero_si128()
#define NumRegistersSIMD (Is64Bit ? 16 : 8)
#define MaxChunkSize 16
#elif USE_MMX #elif USE_MMX
typedef __m64 vec_t; typedef __m64 vec_t;
typedef __m64 psqt_vec_t;
#define vec_load(a) (*(a)) #define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b) #define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) _mm_add_pi16(a,b) #define vec_add_16(a,b) _mm_add_pi16(a,b)
#define vec_sub_16(a,b) _mm_sub_pi16(a,b) #define vec_sub_16(a,b) _mm_sub_pi16(a,b)
static constexpr IndexType kNumRegs = 8; #define vec_mul_16(a,b) _mm_mullo_pi16(a,b)
#define vec_zero() _mm_setzero_si64()
#define vec_set_16(a) _mm_set1_pi16(a)
inline vec_t vec_max_16(vec_t a,vec_t b){
vec_t comparison = _mm_cmpgt_pi16(a,b);
return _mm_or_si64(_mm_and_si64(comparison, a), _mm_andnot_si64(comparison, b));
}
inline vec_t vec_min_16(vec_t a,vec_t b){
vec_t comparison = _mm_cmpgt_pi16(a,b);
return _mm_or_si64(_mm_and_si64(comparison, b), _mm_andnot_si64(comparison, a));
}
#define vec_msb_pack_16(a,b) _mm_packs_pi16(_mm_srli_pi16(a,7),_mm_srli_pi16(b,7))
#define vec_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) _mm_add_pi32(a,b)
#define vec_sub_psqt_32(a,b) _mm_sub_pi32(a,b)
#define vec_zero_psqt() _mm_setzero_si64()
#define vec_cleanup() _mm_empty()
#define NumRegistersSIMD 8
#define MaxChunkSize 8
#elif USE_NEON #elif USE_NEON
typedef int16x8_t vec_t; typedef int16x8_t vec_t;
typedef int32x4_t psqt_vec_t;
#define vec_load(a) (*(a)) #define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b) #define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) vaddq_s16(a,b) #define vec_add_16(a,b) vaddq_s16(a,b)
#define vec_sub_16(a,b) vsubq_s16(a,b) #define vec_sub_16(a,b) vsubq_s16(a,b)
static constexpr IndexType kNumRegs = 16; #define vec_mul_16(a,b) vmulq_s16(a,b)
#define vec_zero() vec_t{0}
#define vec_set_16(a) vdupq_n_s16(a)
#define vec_max_16(a,b) vmaxq_s16(a,b)
#define vec_min_16(a,b) vminq_s16(a,b)
inline vec_t vec_msb_pack_16(vec_t a, vec_t b){
const int8x8_t shifta = vshrn_n_s16(a, 7);
const int8x8_t shiftb = vshrn_n_s16(b, 7);
const int8x16_t compacted = vcombine_s8(shifta,shiftb);
return *reinterpret_cast<const vec_t*> (&compacted);
}
#define vec_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) vaddq_s32(a,b)
#define vec_sub_psqt_32(a,b) vsubq_s32(a,b)
#define vec_zero_psqt() psqt_vec_t{0}
#define NumRegistersSIMD 16
#define MaxChunkSize 16
#else #else
#undef VECTOR #undef VECTOR
#endif #endif
#ifdef VECTOR
// Compute optimal SIMD register count for feature transformer accumulation.
// We use __m* types as template arguments, which causes GCC to emit warnings
// about losing some attribute information. This is irrelevant to us as we
// only take their size, so the following pragma are harmless.
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
template <typename SIMDRegisterType,
typename LaneType,
int NumLanes,
int MaxRegisters>
static constexpr int BestRegisterCount()
{
#define RegisterSize sizeof(SIMDRegisterType)
#define LaneSize sizeof(LaneType)
static_assert(RegisterSize >= LaneSize);
static_assert(MaxRegisters <= NumRegistersSIMD);
static_assert(MaxRegisters > 0);
static_assert(NumRegistersSIMD > 0);
static_assert(RegisterSize % LaneSize == 0);
static_assert((NumLanes * LaneSize) % RegisterSize == 0);
const int ideal = (NumLanes * LaneSize) / RegisterSize;
if (ideal <= MaxRegisters)
return ideal;
// Look for the largest divisor of the ideal register count that is smaller than MaxRegisters
for (int divisor = MaxRegisters; divisor > 1; --divisor)
if (ideal % divisor == 0)
return divisor;
return 1;
}
static constexpr int NumRegs = BestRegisterCount<vec_t, WeightType, TransformedFeatureDimensions, NumRegistersSIMD>();
static constexpr int NumPsqtRegs = BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>();
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif
// Input feature converter // Input feature converter
class FeatureTransformer { class FeatureTransformer {
private: private:
// Number of output dimensions for one side // Number of output dimensions for one side
static constexpr IndexType kHalfDimensions = kTransformedFeatureDimensions; static constexpr IndexType HalfDimensions = TransformedFeatureDimensions;
#ifdef VECTOR #ifdef VECTOR
static constexpr IndexType kTileHeight = kNumRegs * sizeof(vec_t) / 2; static constexpr IndexType TileHeight = NumRegs * sizeof(vec_t) / 2;
static_assert(kHalfDimensions % kTileHeight == 0, "kTileHeight must divide kHalfDimensions"); static constexpr IndexType PsqtTileHeight = NumPsqtRegs * sizeof(psqt_vec_t) / 4;
static_assert(HalfDimensions % TileHeight == 0, "TileHeight must divide HalfDimensions");
static_assert(PSQTBuckets % PsqtTileHeight == 0, "PsqtTileHeight must divide PSQTBuckets");
#endif #endif
public: public:
@@ -96,174 +237,138 @@ namespace Eval::NNUE {
using OutputType = TransformedFeatureType; using OutputType = TransformedFeatureType;
// Number of input/output dimensions // Number of input/output dimensions
static constexpr IndexType kInputDimensions = RawFeatures::kDimensions; static constexpr IndexType InputDimensions = FeatureSet::Dimensions;
static constexpr IndexType kOutputDimensions = kHalfDimensions * 2; static constexpr IndexType OutputDimensions = HalfDimensions;
// Size of forward propagation buffer // Size of forward propagation buffer
static constexpr std::size_t kBufferSize = static constexpr std::size_t BufferSize =
kOutputDimensions * sizeof(OutputType); OutputDimensions * sizeof(OutputType);
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t get_hash_value() {
return FeatureSet::HashValue ^ (OutputDimensions * 2);
return RawFeatures::kHashValue ^ kOutputDimensions;
} }
// Read network parameters // Read network parameters
bool ReadParameters(std::istream& stream) { bool read_parameters(std::istream& stream) {
read_little_endian<BiasType >(stream, biases , HalfDimensions );
read_little_endian<WeightType >(stream, weights , HalfDimensions * InputDimensions);
read_little_endian<PSQTWeightType>(stream, psqtWeights, PSQTBuckets * InputDimensions);
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
write_little_endian<BiasType >(stream, biases , HalfDimensions );
write_little_endian<WeightType >(stream, weights , HalfDimensions * InputDimensions);
write_little_endian<PSQTWeightType>(stream, psqtWeights, PSQTBuckets * InputDimensions);
for (std::size_t i = 0; i < kHalfDimensions; ++i)
biases_[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < kHalfDimensions * kInputDimensions; ++i)
weights_[i] = read_little_endian<WeightType>(stream);
return !stream.fail(); return !stream.fail();
} }
// Convert input features // Convert input features
void Transform(const Position& pos, OutputType* output) const { std::int32_t transform(const Position& pos, OutputType* output, int bucket) const {
update_accumulator<WHITE>(pos);
UpdateAccumulator(pos, WHITE); update_accumulator<BLACK>(pos);
UpdateAccumulator(pos, BLACK);
const auto& accumulation = pos.state()->accumulator.accumulation;
#if defined(USE_AVX512)
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth * 2);
static_assert(kHalfDimensions % (kSimdWidth * 2) == 0);
const __m512i kControl = _mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7);
const __m512i kZero = _mm512_setzero_si512();
#elif defined(USE_AVX2)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
constexpr int kControl = 0b11011000;
const __m256i kZero = _mm256_setzero_si256();
#elif defined(USE_SSE2)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
#ifdef USE_SSE41
const __m128i kZero = _mm_setzero_si128();
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
#elif defined(USE_MMX)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
const __m64 k0x80s = _mm_set1_pi8(-128);
#elif defined(USE_NEON)
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth / 2);
const int8x8_t kZero = {0};
#endif
const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()}; const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()};
for (IndexType p = 0; p < 2; ++p) { const auto& accumulation = pos.state()->accumulator.accumulation;
const IndexType offset = kHalfDimensions * p; const auto& psqtAccumulation = pos.state()->accumulator.psqtAccumulation;
#if defined(USE_AVX512) const auto psqt = (
auto out = reinterpret_cast<__m512i*>(&output[offset]); psqtAccumulation[perspectives[0]][bucket]
for (IndexType j = 0; j < kNumChunks; ++j) { - psqtAccumulation[perspectives[1]][bucket]
__m512i sum0 = _mm512_load_si512( ) / 2;
&reinterpret_cast<const __m512i*>(accumulation[perspectives[p]][0])[j * 2 + 0]);
__m512i sum1 = _mm512_load_si512(
&reinterpret_cast<const __m512i*>(accumulation[perspectives[p]][0])[j * 2 + 1]);
_mm512_store_si512(&out[j], _mm512_permutexvar_epi64(kControl,
_mm512_max_epi8(_mm512_packs_epi16(sum0, sum1), kZero)));
}
#elif defined(USE_AVX2)
auto out = reinterpret_cast<__m256i*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m256i sum0 = _mm256_load_si256(
&reinterpret_cast<const __m256i*>(accumulation[perspectives[p]][0])[j * 2 + 0]);
__m256i sum1 = _mm256_load_si256(
&reinterpret_cast<const __m256i*>(accumulation[perspectives[p]][0])[j * 2 + 1]);
_mm256_store_si256(&out[j], _mm256_permute4x64_epi64(_mm256_max_epi8(
_mm256_packs_epi16(sum0, sum1), kZero), kControl));
}
#elif defined(USE_SSE2) for (IndexType p = 0; p < 2; ++p)
auto out = reinterpret_cast<__m128i*>(&output[offset]); {
for (IndexType j = 0; j < kNumChunks; ++j) { const IndexType offset = (HalfDimensions / 2) * p;
__m128i sum0 = _mm_load_si128(&reinterpret_cast<const __m128i*>(
accumulation[perspectives[p]][0])[j * 2 + 0]);
__m128i sum1 = _mm_load_si128(&reinterpret_cast<const __m128i*>(
accumulation[perspectives[p]][0])[j * 2 + 1]);
const __m128i packedbytes = _mm_packs_epi16(sum0, sum1);
_mm_store_si128(&out[j], #if defined(VECTOR)
#ifdef USE_SSE41 constexpr IndexType OutputChunkSize = MaxChunkSize;
_mm_max_epi8(packedbytes, kZero) static_assert((HalfDimensions / 2) % OutputChunkSize == 0);
#else constexpr IndexType NumOutputChunks = HalfDimensions / 2 / OutputChunkSize;
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
); vec_t Zero = vec_zero();
} vec_t One = vec_set_16(127);
#elif defined(USE_MMX) const vec_t* in0 = reinterpret_cast<const vec_t*>(&(accumulation[perspectives[p]][0]));
auto out = reinterpret_cast<__m64*>(&output[offset]); const vec_t* in1 = reinterpret_cast<const vec_t*>(&(accumulation[perspectives[p]][HalfDimensions / 2]));
for (IndexType j = 0; j < kNumChunks; ++j) { vec_t* out = reinterpret_cast< vec_t*>(output + offset);
__m64 sum0 = *(&reinterpret_cast<const __m64*>(
accumulation[perspectives[p]][0])[j * 2 + 0]);
__m64 sum1 = *(&reinterpret_cast<const __m64*>(
accumulation[perspectives[p]][0])[j * 2 + 1]);
const __m64 packedbytes = _mm_packs_pi16(sum0, sum1);
out[j] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
}
#elif defined(USE_NEON) for (IndexType j = 0; j < NumOutputChunks; j += 1)
const auto out = reinterpret_cast<int8x8_t*>(&output[offset]); {
for (IndexType j = 0; j < kNumChunks; ++j) { const vec_t sum0a = vec_max_16(vec_min_16(in0[j * 2 + 0], One), Zero);
int16x8_t sum = reinterpret_cast<const int16x8_t*>( const vec_t sum0b = vec_max_16(vec_min_16(in0[j * 2 + 1], One), Zero);
accumulation[perspectives[p]][0])[j]; const vec_t sum1a = vec_max_16(vec_min_16(in1[j * 2 + 0], One), Zero);
out[j] = vmax_s8(vqmovn_s16(sum), kZero); const vec_t sum1b = vec_max_16(vec_min_16(in1[j * 2 + 1], One), Zero);
}
#else const vec_t pa = vec_mul_16(sum0a, sum1a);
for (IndexType j = 0; j < kHalfDimensions; ++j) { const vec_t pb = vec_mul_16(sum0b, sum1b);
BiasType sum = accumulation[static_cast<int>(perspectives[p])][0][j];
output[offset + j] = static_cast<OutputType>(
std::max<int>(0, std::min<int>(127, sum)));
}
#endif
out[j] = vec_msb_pack_16(pa, pb);
}
#else
for (IndexType j = 0; j < HalfDimensions / 2; ++j) {
BiasType sum0 = accumulation[static_cast<int>(perspectives[p])][j + 0];
BiasType sum1 = accumulation[static_cast<int>(perspectives[p])][j + HalfDimensions / 2];
sum0 = std::max<int>(0, std::min<int>(127, sum0));
sum1 = std::max<int>(0, std::min<int>(127, sum1));
output[offset + j] = static_cast<OutputType>(sum0 * sum1 / 128);
}
#endif
} }
#if defined(USE_MMX)
_mm_empty(); #if defined(vec_cleanup)
#endif vec_cleanup();
} #endif
return psqt;
} // end of function transform()
private: private:
void UpdateAccumulator(const Position& pos, const Color c) const { template<Color Perspective>
void update_accumulator(const Position& pos) const {
// The size must be enough to contain the largest possible update.
// That might depend on the feature set and generally relies on the
// feature set's update cost calculation to be correct and never
// allow updates with more added/removed features than MaxActiveDimensions.
#ifdef VECTOR #ifdef VECTOR
// Gcc-10.2 unnecessarily spills AVX2 registers if this array // Gcc-10.2 unnecessarily spills AVX2 registers if this array
// is defined in the VECTOR code below, once in each branch // is defined in the VECTOR code below, once in each branch
vec_t acc[kNumRegs]; vec_t acc[NumRegs];
psqt_vec_t psqt[NumPsqtRegs];
#endif #endif
// Look for a usable accumulator of an earlier position. We keep track // Look for a usable accumulator of an earlier position. We keep track
// of the estimated gain in terms of features to be added/subtracted. // of the estimated gain in terms of features to be added/subtracted.
StateInfo *st = pos.state(), *next = nullptr; StateInfo *st = pos.state(), *next = nullptr;
int gain = pos.count<ALL_PIECES>() - 2; int gain = FeatureSet::refresh_cost(pos);
while (st->accumulator.state[c] == EMPTY) while (st->previous && !st->accumulator.computed[Perspective])
{ {
auto& dp = st->dirtyPiece; // This governs when a full feature refresh is needed and how many
// The first condition tests whether an incremental update is // updates are better than just one full refresh.
// possible at all: if this side's king has moved, it is not possible. if ( FeatureSet::requires_refresh(st, Perspective)
static_assert(std::is_same_v<RawFeatures::SortedTriggerSet, || (gain -= FeatureSet::update_cost(st) + 1) < 0)
Features::CompileTimeList<Features::TriggerEvent, Features::TriggerEvent::kFriendKingMoved>>,
"Current code assumes that only kFriendlyKingMoved refresh trigger is being used.");
if ( dp.piece[0] == make_piece(c, KING)
|| (gain -= dp.dirty_num + 1) < 0)
break; break;
next = st; next = st;
st = st->previous; st = st->previous;
} }
if (st->accumulator.state[c] == COMPUTED) if (st->accumulator.computed[Perspective])
{ {
if (next == nullptr) if (next == nullptr)
return; return;
@@ -271,85 +376,129 @@ namespace Eval::NNUE {
// Update incrementally in two steps. First, we update the "next" // Update incrementally in two steps. First, we update the "next"
// accumulator. Then, we update the current accumulator (pos.state()). // accumulator. Then, we update the current accumulator (pos.state()).
// Gather all features to be updated. This code assumes HalfKP features // Gather all features to be updated.
// only and doesn't support refresh triggers. const Square ksq = pos.square<KING>(Perspective);
static_assert(std::is_same_v<Features::FeatureSet<Features::HalfKP<Features::Side::kFriend>>, FeatureSet::IndexList removed[2], added[2];
RawFeatures>); FeatureSet::append_changed_indices<Perspective>(
Features::IndexList removed[2], added[2]; ksq, next->dirtyPiece, removed[0], added[0]);
Features::HalfKP<Features::Side::kFriend>::AppendChangedIndices(pos,
next->dirtyPiece, c, &removed[0], &added[0]);
for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous) for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous)
Features::HalfKP<Features::Side::kFriend>::AppendChangedIndices(pos, FeatureSet::append_changed_indices<Perspective>(
st2->dirtyPiece, c, &removed[1], &added[1]); ksq, st2->dirtyPiece, removed[1], added[1]);
// Mark the accumulators as computed. // Mark the accumulators as computed.
next->accumulator.state[c] = COMPUTED; next->accumulator.computed[Perspective] = true;
pos.state()->accumulator.state[c] = COMPUTED; pos.state()->accumulator.computed[Perspective] = true;
// Now update the accumulators listed in info[], where the last element is a sentinel. // Now update the accumulators listed in states_to_update[], where the last element is a sentinel.
StateInfo *info[3] = StateInfo *states_to_update[3] =
{ next, next == pos.state() ? nullptr : pos.state(), nullptr }; { next, next == pos.state() ? nullptr : pos.state(), nullptr };
#ifdef VECTOR #ifdef VECTOR
for (IndexType j = 0; j < kHalfDimensions / kTileHeight; ++j) for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
{ {
// Load accumulator // Load accumulator
auto accTile = reinterpret_cast<vec_t*>( auto accTile = reinterpret_cast<vec_t*>(
&st->accumulator.accumulation[c][0][j * kTileHeight]); &st->accumulator.accumulation[Perspective][j * TileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k) for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = vec_load(&accTile[k]); acc[k] = vec_load(&accTile[k]);
for (IndexType i = 0; info[i]; ++i) for (IndexType i = 0; states_to_update[i]; ++i)
{ {
// Difference calculation for the deactivated features // Difference calculation for the deactivated features
for (const auto index : removed[i]) for (const auto index : removed[i])
{ {
const IndexType offset = kHalfDimensions * index + j * kTileHeight; const IndexType offset = HalfDimensions * index + j * TileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]); auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < kNumRegs; ++k) for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = vec_sub_16(acc[k], column[k]); acc[k] = vec_sub_16(acc[k], column[k]);
} }
// Difference calculation for the activated features // Difference calculation for the activated features
for (const auto index : added[i]) for (const auto index : added[i])
{ {
const IndexType offset = kHalfDimensions * index + j * kTileHeight; const IndexType offset = HalfDimensions * index + j * TileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]); auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < kNumRegs; ++k) for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]); acc[k] = vec_add_16(acc[k], column[k]);
} }
// Store accumulator // Store accumulator
accTile = reinterpret_cast<vec_t*>( accTile = reinterpret_cast<vec_t*>(
&info[i]->accumulator.accumulation[c][0][j * kTileHeight]); &states_to_update[i]->accumulator.accumulation[Perspective][j * TileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k) for (IndexType k = 0; k < NumRegs; ++k)
vec_store(&accTile[k], acc[k]); vec_store(&accTile[k], acc[k]);
} }
} }
#else for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j)
for (IndexType i = 0; info[i]; ++i)
{ {
std::memcpy(info[i]->accumulator.accumulation[c][0], // Load accumulator
st->accumulator.accumulation[c][0], auto accTilePsqt = reinterpret_cast<psqt_vec_t*>(
kHalfDimensions * sizeof(BiasType)); &st->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]);
st = info[i]; for (std::size_t k = 0; k < NumPsqtRegs; ++k)
psqt[k] = vec_load_psqt(&accTilePsqt[k]);
for (IndexType i = 0; states_to_update[i]; ++i)
{
// Difference calculation for the deactivated features
for (const auto index : removed[i])
{
const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight;
auto columnPsqt = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offset]);
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]);
}
// Difference calculation for the activated features
for (const auto index : added[i])
{
const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight;
auto columnPsqt = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offset]);
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]);
}
// Store accumulator
accTilePsqt = reinterpret_cast<psqt_vec_t*>(
&states_to_update[i]->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]);
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
vec_store_psqt(&accTilePsqt[k], psqt[k]);
}
}
#else
for (IndexType i = 0; states_to_update[i]; ++i)
{
std::memcpy(states_to_update[i]->accumulator.accumulation[Perspective],
st->accumulator.accumulation[Perspective],
HalfDimensions * sizeof(BiasType));
for (std::size_t k = 0; k < PSQTBuckets; ++k)
states_to_update[i]->accumulator.psqtAccumulation[Perspective][k] = st->accumulator.psqtAccumulation[Perspective][k];
st = states_to_update[i];
// Difference calculation for the deactivated features // Difference calculation for the deactivated features
for (const auto index : removed[i]) for (const auto index : removed[i])
{ {
const IndexType offset = kHalfDimensions * index; const IndexType offset = HalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j) for (IndexType j = 0; j < HalfDimensions; ++j)
st->accumulator.accumulation[c][0][j] -= weights_[offset + j]; st->accumulator.accumulation[Perspective][j] -= weights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
st->accumulator.psqtAccumulation[Perspective][k] -= psqtWeights[index * PSQTBuckets + k];
} }
// Difference calculation for the activated features // Difference calculation for the activated features
for (const auto index : added[i]) for (const auto index : added[i])
{ {
const IndexType offset = kHalfDimensions * index; const IndexType offset = HalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j) for (IndexType j = 0; j < HalfDimensions; ++j)
st->accumulator.accumulation[c][0][j] += weights_[offset + j]; st->accumulator.accumulation[Perspective][j] += weights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
st->accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k];
} }
} }
#endif #endif
@@ -358,43 +507,69 @@ namespace Eval::NNUE {
{ {
// Refresh the accumulator // Refresh the accumulator
auto& accumulator = pos.state()->accumulator; auto& accumulator = pos.state()->accumulator;
accumulator.state[c] = COMPUTED; accumulator.computed[Perspective] = true;
Features::IndexList active; FeatureSet::IndexList active;
Features::HalfKP<Features::Side::kFriend>::AppendActiveIndices(pos, c, &active); FeatureSet::append_active_indices<Perspective>(pos, active);
#ifdef VECTOR #ifdef VECTOR
for (IndexType j = 0; j < kHalfDimensions / kTileHeight; ++j) for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
{ {
auto biasesTile = reinterpret_cast<const vec_t*>( auto biasesTile = reinterpret_cast<const vec_t*>(
&biases_[j * kTileHeight]); &biases[j * TileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k) for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = biasesTile[k]; acc[k] = biasesTile[k];
for (const auto index : active) for (const auto index : active)
{ {
const IndexType offset = kHalfDimensions * index + j * kTileHeight; const IndexType offset = HalfDimensions * index + j * TileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]); auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (unsigned k = 0; k < kNumRegs; ++k) for (unsigned k = 0; k < NumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]); acc[k] = vec_add_16(acc[k], column[k]);
} }
auto accTile = reinterpret_cast<vec_t*>( auto accTile = reinterpret_cast<vec_t*>(
&accumulator.accumulation[c][0][j * kTileHeight]); &accumulator.accumulation[Perspective][j * TileHeight]);
for (unsigned k = 0; k < kNumRegs; k++) for (unsigned k = 0; k < NumRegs; k++)
vec_store(&accTile[k], acc[k]); vec_store(&accTile[k], acc[k]);
} }
for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j)
{
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
psqt[k] = vec_zero_psqt();
for (const auto index : active)
{
const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight;
auto columnPsqt = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offset]);
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]);
}
auto accTilePsqt = reinterpret_cast<psqt_vec_t*>(
&accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]);
for (std::size_t k = 0; k < NumPsqtRegs; ++k)
vec_store_psqt(&accTilePsqt[k], psqt[k]);
}
#else #else
std::memcpy(accumulator.accumulation[c][0], biases_, std::memcpy(accumulator.accumulation[Perspective], biases,
kHalfDimensions * sizeof(BiasType)); HalfDimensions * sizeof(BiasType));
for (std::size_t k = 0; k < PSQTBuckets; ++k)
accumulator.psqtAccumulation[Perspective][k] = 0;
for (const auto index : active) for (const auto index : active)
{ {
const IndexType offset = kHalfDimensions * index; const IndexType offset = HalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j) for (IndexType j = 0; j < HalfDimensions; ++j)
accumulator.accumulation[c][0][j] += weights_[offset + j]; accumulator.accumulation[Perspective][j] += weights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k];
} }
#endif #endif
} }
@@ -404,14 +579,11 @@ namespace Eval::NNUE {
#endif #endif
} }
using BiasType = std::int16_t; alignas(CacheLineSize) BiasType biases[HalfDimensions];
using WeightType = std::int16_t; alignas(CacheLineSize) WeightType weights[HalfDimensions * InputDimensions];
alignas(CacheLineSize) PSQTWeightType psqtWeights[InputDimensions * PSQTBuckets];
alignas(kCacheLineSize) BiasType biases_[kHalfDimensions];
alignas(kCacheLineSize)
WeightType weights_[kHalfDimensions * kInputDimensions];
}; };
} // namespace Eval::NNUE } // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_FEATURE_TRANSFORMER_H_INCLUDED #endif // #ifndef NNUE_FEATURE_TRANSFORMER_H_INCLUDED
+28 -23
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,36 +24,38 @@
#include "position.h" #include "position.h"
#include "thread.h" #include "thread.h"
namespace Stockfish {
namespace { namespace {
#define V Value #define V Value
#define S(mg, eg) make_score(mg, eg) #define S(mg, eg) make_score(mg, eg)
// Pawn penalties // Pawn penalties
constexpr Score Backward = S( 9, 22); constexpr Score Backward = S( 6, 19);
constexpr Score Doubled = S(13, 51); constexpr Score Doubled = S(11, 51);
constexpr Score DoubledEarly = S(20, 7); constexpr Score DoubledEarly = S(17, 7);
constexpr Score Isolated = S( 3, 15); constexpr Score Isolated = S( 1, 20);
constexpr Score WeakLever = S( 4, 58); constexpr Score WeakLever = S( 2, 57);
constexpr Score WeakUnopposed = S(13, 24); constexpr Score WeakUnopposed = S(15, 18);
// Bonus for blocked pawns at 5th or 6th rank // Bonus for blocked pawns at 5th or 6th rank
constexpr Score BlockedPawn[2] = { S(-17, -6), S(-9, 2) }; constexpr Score BlockedPawn[2] = { S(-19, -8), S(-7, 3) };
constexpr Score BlockedStorm[RANK_NB] = { constexpr Score BlockedStorm[RANK_NB] = {
S(0, 0), S(0, 0), S(75, 78), S(-8, 16), S(-6, 10), S(-6, 6), S(0, 2) S(0, 0), S(0, 0), S(64, 75), S(-3, 14), S(-12, 19), S(-7, 4), S(-10, 5)
}; };
// Connected pawn bonus // Connected pawn bonus
constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 23, 48, 87 }; constexpr int Connected[RANK_NB] = { 0, 3, 7, 7, 15, 54, 86 };
// Strength of pawn shelter for our king by [distance from edge][rank]. // Strength of pawn shelter for our king by [distance from edge][rank].
// RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king. // RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king.
constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = { constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = {
{ V( -5), V( 82), V( 92), V( 54), V( 36), V( 22), V( 28) }, { V(-2), V(85), V(95), V(53), V(39), V(23), V(25) },
{ V(-44), V( 63), V( 33), V(-50), V(-30), V(-12), V( -62) }, { V(-55), V(64), V(32), V(-55), V(-30), V(-11), V(-61) },
{ V(-11), V( 77), V( 22), V( -6), V( 31), V( 8), V( -45) }, { V(-11), V(75), V(19), V(-6), V(26), V(9), V(-47) },
{ V(-39), V(-12), V(-29), V(-50), V(-43), V(-68), V(-164) } { V(-41), V(-11), V(-27), V(-58), V(-42), V(-66), V(-163) }
}; };
// Danger of enemy pawns moving toward our king by [distance from edge][rank]. // Danger of enemy pawns moving toward our king by [distance from edge][rank].
@@ -61,17 +63,17 @@ namespace {
// is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn // is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn
// on edge, likely blocked by our king. // on edge, likely blocked by our king.
constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = { constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = {
{ V( 87), V(-288), V(-168), V( 96), V( 47), V( 44), V( 46) }, { V(94), V(-280), V(-170), V(90), V(59), V(47), V(53) },
{ V( 42), V( -25), V( 120), V( 45), V( 34), V( -9), V( 24) }, { V(43), V(-17), V(128), V(39), V(26), V(-17), V(15) },
{ V( -8), V( 51), V( 167), V( 35), V( -4), V(-16), V(-12) }, { V(-9), V(62), V(170), V(34), V(-5), V(-20), V(-11) },
{ V(-17), V( -13), V( 100), V( 4), V( 9), V(-16), V(-31) } { V(-27), V(-19), V(106), V(10), V(2), V(-13), V(-24) }
}; };
// KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties // KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties
// for king when the king is on a semi-open or open file. // for king when the king is on a semi-open or open file.
constexpr Score KingOnFile[2][2] = {{ S(-21,10), S(-7, 1) }, constexpr Score KingOnFile[2][2] = {{ S(-18,11), S(-6,-3) },
{ S( 0,-3), S( 9,-4) }}; { S( 0, 0), S( 5,-4) }};
#undef S #undef S
#undef V #undef V
@@ -107,8 +109,9 @@ namespace {
e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem)); e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem));
// Loop through all pawns of the current color and score each pawn // Loop through all pawns of the current color and score each pawn
while (b) { while (b)
s = pop_lsb(&b); {
s = pop_lsb(b);
assert(pos.piece_on(s) == make_piece(Us, PAWN)); assert(pos.piece_on(s) == make_piece(Us, PAWN));
@@ -288,7 +291,7 @@ Score Entry::do_king_safety(const Position& pos) {
if (pawns & attacks_bb<KING>(ksq)) if (pawns & attacks_bb<KING>(ksq))
minPawnDist = 1; minPawnDist = 1;
else while (pawns) else while (pawns)
minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(&pawns))); minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(pawns)));
return shelter - make_score(0, 16 * minPawnDist); return shelter - make_score(0, 16 * minPawnDist);
} }
@@ -298,3 +301,5 @@ template Score Entry::do_king_safety<WHITE>(const Position& pos);
template Score Entry::do_king_safety<BLACK>(const Position& pos); template Score Entry::do_king_safety<BLACK>(const Position& pos);
} // namespace Pawns } // namespace Pawns
} // namespace Stockfish
+3 -3
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
#include "position.h" #include "position.h"
#include "types.h" #include "types.h"
namespace Pawns { namespace Stockfish::Pawns {
/// Pawns::Entry contains various information about a pawn structure. A lookup /// Pawns::Entry contains various information about a pawn structure. A lookup
/// to the pawn hash table (performed by calling the probe function) returns a /// to the pawn hash table (performed by calling the probe function) returns a
@@ -65,6 +65,6 @@ typedef HashTable<Entry, 131072> Table;
Entry* probe(const Position& pos); Entry* probe(const Position& pos);
} // namespace Pawns } // namespace Stockfish::Pawns
#endif // #ifndef PAWNS_H_INCLUDED #endif // #ifndef PAWNS_H_INCLUDED
+72 -59
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -34,6 +34,8 @@
using std::string; using std::string;
namespace Stockfish {
namespace Zobrist { namespace Zobrist {
Key psq[PIECE_NB][SQUARE_NB]; Key psq[PIECE_NB][SQUARE_NB];
@@ -71,13 +73,13 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
<< std::setfill(' ') << std::dec << "\nCheckers: "; << std::setfill(' ') << std::dec << "\nCheckers: ";
for (Bitboard b = pos.checkers(); b; ) for (Bitboard b = pos.checkers(); b; )
os << UCI::square(pop_lsb(&b)) << " "; os << UCI::square(pop_lsb(b)) << " ";
if ( int(Tablebases::MaxCardinality) >= popcount(pos.pieces()) if ( int(Tablebases::MaxCardinality) >= popcount(pos.pieces())
&& !pos.can_castle(ANY_CASTLING)) && !pos.can_castle(ANY_CASTLING))
{ {
StateInfo st; StateInfo st;
ASSERT_ALIGNED(&st, Eval::NNUE::kCacheLineSize); ASSERT_ALIGNED(&st, Eval::NNUE::CacheLineSize);
Position p; Position p;
p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread()); p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread());
@@ -127,7 +129,7 @@ void Position::init() {
// Prepare the cuckoo tables // Prepare the cuckoo tables
std::memset(cuckoo, 0, sizeof(cuckoo)); std::memset(cuckoo, 0, sizeof(cuckoo));
std::memset(cuckooMove, 0, sizeof(cuckooMove)); std::memset(cuckooMove, 0, sizeof(cuckooMove));
int count = 0; [[maybe_unused]] int count = 0;
for (Piece pc : Pieces) for (Piece pc : Pieces)
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2) for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2)
@@ -249,8 +251,6 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
set_castling_right(c, rsq); set_castling_right(c, rsq);
} }
set_state(st);
// 4. En passant square. // 4. En passant square.
// Ignore if square is invalid or not on side to move relative rank 6. // Ignore if square is invalid or not on side to move relative rank 6.
bool enpassant = false; bool enpassant = false;
@@ -264,24 +264,12 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
// a) side to move have a pawn threatening epSquare // a) side to move have a pawn threatening epSquare
// b) there is an enemy pawn in front of epSquare // b) there is an enemy pawn in front of epSquare
// c) there is no piece on epSquare or behind epSquare // c) there is no piece on epSquare or behind epSquare
// d) enemy pawn didn't block a check of its own color by moving forward
enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN) enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
&& (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove))) && (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
&& !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove)))) && !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))));
&& ( file_of(square<KING>(sideToMove)) == file_of(st->epSquare)
|| !(blockers_for_king(sideToMove) & (st->epSquare + pawn_push(~sideToMove))));
} }
// It's necessary for st->previous to be intialized in this way because legality check relies on its existence if (!enpassant)
if (enpassant) {
st->previous = new StateInfo();
remove_piece(st->epSquare - pawn_push(sideToMove));
st->previous->checkersBB = attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove);
st->previous->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), st->previous->pinners[BLACK]);
st->previous->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), st->previous->pinners[WHITE]);
put_piece(make_piece(~sideToMove, PAWN), st->epSquare - pawn_push(sideToMove));
}
else
st->epSquare = SQ_NONE; st->epSquare = SQ_NONE;
// 5-6. Halfmove clock and fullmove number // 5-6. Halfmove clock and fullmove number
@@ -293,8 +281,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
chess960 = isChess960; chess960 = isChess960;
thisThread = th; thisThread = th;
st->accumulator.state[WHITE] = Eval::NNUE::INIT; set_state(st);
st->accumulator.state[BLACK] = Eval::NNUE::INIT;
assert(pos_is_ok()); assert(pos_is_ok());
@@ -318,7 +305,7 @@ void Position::set_castling_right(Color c, Square rfrom) {
Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1); Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1);
Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1); Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto) | rto | kto) castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto))
& ~(kfrom | rfrom); & ~(kfrom | rfrom);
} }
@@ -357,7 +344,7 @@ void Position::set_state(StateInfo* si) const {
for (Bitboard b = pieces(); b; ) for (Bitboard b = pieces(); b; )
{ {
Square s = pop_lsb(&b); Square s = pop_lsb(b);
Piece pc = piece_on(s); Piece pc = piece_on(s);
si->key ^= Zobrist::psq[pc][s]; si->key ^= Zobrist::psq[pc][s];
@@ -408,7 +395,7 @@ Position& Position::set(const string& code, Color c, StateInfo* si) {
/// Position::fen() returns a FEN representation of the position. In case of /// Position::fen() returns a FEN representation of the position. In case of
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function. /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
const string Position::fen() const { string Position::fen() const {
int emptyCnt; int emptyCnt;
std::ostringstream ss; std::ostringstream ss;
@@ -474,7 +461,7 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners
while (snipers) while (snipers)
{ {
Square sniperSq = pop_lsb(&snipers); Square sniperSq = pop_lsb(snipers);
Bitboard b = between_bb(s, sniperSq) & occupancy; Bitboard b = between_bb(s, sniperSq) & occupancy;
if (b && !more_than_one(b)) if (b && !more_than_one(b))
@@ -515,11 +502,23 @@ bool Position::legal(Move m) const {
assert(color_of(moved_piece(m)) == us); assert(color_of(moved_piece(m)) == us);
assert(piece_on(square<KING>(us)) == make_piece(us, KING)); assert(piece_on(square<KING>(us)) == make_piece(us, KING));
// st->previous->blockersForKing consider capsq as empty. // En passant captures are a tricky special case. Because they are rather
// If pinned, it has to move along the king ray. // uncommon, we do it simply by testing whether the king is attacked after
// the move is made.
if (type_of(m) == EN_PASSANT) if (type_of(m) == EN_PASSANT)
return !(st->previous->blockersForKing[sideToMove] & from) {
|| aligned(from, to, square<KING>(us)); Square ksq = square<KING>(us);
Square capsq = to - pawn_push(us);
Bitboard occupied = (pieces() ^ from ^ capsq) | to;
assert(to == ep_square());
assert(moved_piece(m) == make_piece(us, PAWN));
assert(piece_on(capsq) == make_piece(~us, PAWN));
assert(piece_on(to) == NO_PIECE);
return !(attacks_bb< ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK))
&& !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP));
}
// Castling moves generation does not check if the castling path is clear of // Castling moves generation does not check if the castling path is clear of
// enemy attacks, it is delayed at a later time: now! // enemy attacks, it is delayed at a later time: now!
@@ -542,7 +541,7 @@ bool Position::legal(Move m) const {
// If the moving piece is a king, check whether the destination square is // If the moving piece is a king, check whether the destination square is
// attacked by the opponent. // attacked by the opponent.
if (type_of(piece_on(from)) == KING) if (type_of(piece_on(from)) == KING)
return !(attackers_to(to) & pieces(~us)); return !(attackers_to(to, pieces() ^ from) & pieces(~us));
// A non-king move is legal if and only if it is not pinned or it // A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king. // is moving along the ray towards or away from the king.
@@ -611,8 +610,8 @@ bool Position::pseudo_legal(const Move m) const {
if (more_than_one(checkers())) if (more_than_one(checkers()))
return false; return false;
// Our move must be a blocking evasion or a capture of the checking piece // Our move must be a blocking interposition or a capture of the checking piece
if (!((between_bb(lsb(checkers()), square<KING>(us)) | checkers()) & to)) if (!(between_bb(square<KING>(us), lsb(checkers())) & to))
return false; return false;
} }
// In case of king moves under check we have to remove king so as to catch // In case of king moves under check we have to remove king so as to catch
@@ -652,15 +651,18 @@ bool Position::gives_check(Move m) const {
case PROMOTION: case PROMOTION:
return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove); return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
// The double-pushed pawn blocked a check? En Passant will remove the blocker. // En passant capture with check? We have already handled the case
// The only discovery check that wasn't handle is through capsq and fromsq // of direct checks and ordinary discovered check, so the only case we
// So the King must be in the same rank as fromsq to consider this possibility. // need to handle is the unusual case of a discovered check through
// st->previous->blockersForKing consider capsq as empty. // the captured pawn.
case EN_PASSANT: case EN_PASSANT:
return st->previous->checkersBB {
|| ( rank_of(square<KING>(~sideToMove)) == rank_of(from) Square capsq = make_square(file_of(to), rank_of(from));
&& st->previous->blockersForKing[~sideToMove] & from); Bitboard b = (pieces() ^ from ^ capsq) | to;
return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
| (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
}
default: //CASTLING default: //CASTLING
{ {
// Castling is encoded as 'king captures the rook' // Castling is encoded as 'king captures the rook'
@@ -700,8 +702,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
++st->pliesFromNull; ++st->pliesFromNull;
// Used by NNUE // Used by NNUE
st->accumulator.state[WHITE] = Eval::NNUE::EMPTY; st->accumulator.computed[WHITE] = false;
st->accumulator.state[BLACK] = Eval::NNUE::EMPTY; st->accumulator.computed[BLACK] = false;
auto& dp = st->dirtyPiece; auto& dp = st->dirtyPiece;
dp.dirty_num = 1; dp.dirty_num = 1;
@@ -986,7 +988,7 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
} }
/// Position::do(undo)_null_move() is used to do(undo) a "null move": it flips /// Position::do_null_move() is used to do a "null move": it flips
/// the side to move without executing any move on the board. /// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt) { void Position::do_null_move(StateInfo& newSt) {
@@ -1001,8 +1003,8 @@ void Position::do_null_move(StateInfo& newSt) {
st->dirtyPiece.dirty_num = 0; st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator() st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
st->accumulator.state[WHITE] = Eval::NNUE::EMPTY; st->accumulator.computed[WHITE] = false;
st->accumulator.state[BLACK] = Eval::NNUE::EMPTY; st->accumulator.computed[BLACK] = false;
if (st->epSquare != SQ_NONE) if (st->epSquare != SQ_NONE)
{ {
@@ -1011,9 +1013,9 @@ void Position::do_null_move(StateInfo& newSt) {
} }
st->key ^= Zobrist::side; st->key ^= Zobrist::side;
++st->rule50;
prefetch(TT.first_entry(key())); prefetch(TT.first_entry(key()));
++st->rule50;
st->pliesFromNull = 0; st->pliesFromNull = 0;
sideToMove = ~sideToMove; sideToMove = ~sideToMove;
@@ -1025,6 +1027,9 @@ void Position::do_null_move(StateInfo& newSt) {
assert(pos_is_ok()); assert(pos_is_ok());
} }
/// Position::undo_null_move() must be used to undo a "null move"
void Position::undo_null_move() { void Position::undo_null_move() {
assert(!checkers()); assert(!checkers());
@@ -1049,7 +1054,10 @@ Key Position::key_after(Move m) const {
if (captured) if (captured)
k ^= Zobrist::psq[captured][to]; k ^= Zobrist::psq[captured][to];
return k ^ Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from];
return (captured || type_of(pc) == PAWN)
? k : adjust_key50<true>(k);
} }
@@ -1075,8 +1083,9 @@ bool Position::see_ge(Move m, Value threshold) const {
if (swap <= 0) if (swap <= 0)
return true; return true;
assert(color_of(piece_on(from)) == sideToMove);
Bitboard occupied = pieces() ^ from ^ to; Bitboard occupied = pieces() ^ from ^ to;
Color stm = color_of(piece_on(from)); Color stm = sideToMove;
Bitboard attackers = attackers_to(to, occupied); Bitboard attackers = attackers_to(to, occupied);
Bitboard stmAttackers, bb; Bitboard stmAttackers, bb;
int res = 1; int res = 1;
@@ -1090,13 +1099,15 @@ bool Position::see_ge(Move m, Value threshold) const {
if (!(stmAttackers = attackers & pieces(stm))) if (!(stmAttackers = attackers & pieces(stm)))
break; break;
// Don't allow pinned pieces to attack (except the king) as long as // Don't allow pinned pieces to attack as long as there are
// there are pinners on their original square. // pinners on their original square.
if (pinners(~stm) & occupied) if (pinners(~stm) & occupied)
{
stmAttackers &= ~blockers_for_king(stm); stmAttackers &= ~blockers_for_king(stm);
if (!stmAttackers) if (!stmAttackers)
break; break;
}
res ^= 1; res ^= 1;
@@ -1107,7 +1118,7 @@ bool Position::see_ge(Move m, Value threshold) const {
if ((swap = PawnValueMg - swap) < res) if ((swap = PawnValueMg - swap) < res)
break; break;
occupied ^= lsb(bb); occupied ^= least_significant_square_bb(bb);
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN); attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
} }
@@ -1116,7 +1127,7 @@ bool Position::see_ge(Move m, Value threshold) const {
if ((swap = KnightValueMg - swap) < res) if ((swap = KnightValueMg - swap) < res)
break; break;
occupied ^= lsb(bb); occupied ^= least_significant_square_bb(bb);
} }
else if ((bb = stmAttackers & pieces(BISHOP))) else if ((bb = stmAttackers & pieces(BISHOP)))
@@ -1124,7 +1135,7 @@ bool Position::see_ge(Move m, Value threshold) const {
if ((swap = BishopValueMg - swap) < res) if ((swap = BishopValueMg - swap) < res)
break; break;
occupied ^= lsb(bb); occupied ^= least_significant_square_bb(bb);
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN); attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
} }
@@ -1133,7 +1144,7 @@ bool Position::see_ge(Move m, Value threshold) const {
if ((swap = RookValueMg - swap) < res) if ((swap = RookValueMg - swap) < res)
break; break;
occupied ^= lsb(bb); occupied ^= least_significant_square_bb(bb);
attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN); attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
} }
@@ -1142,7 +1153,7 @@ bool Position::see_ge(Move m, Value threshold) const {
if ((swap = QueenValueMg - swap) < res) if ((swap = QueenValueMg - swap) < res)
break; break;
occupied ^= lsb(bb); occupied ^= least_significant_square_bb(bb);
attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN)) attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
| (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN)); | (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
} }
@@ -1216,7 +1227,7 @@ bool Position::has_game_cycle(int ply) const {
Square s1 = from_sq(move); Square s1 = from_sq(move);
Square s2 = to_sq(move); Square s2 = to_sq(move);
if (!(between_bb(s1, s2) & pieces())) if (!((between_bb(s1, s2) ^ s2) & pieces()))
{ {
if (ply > i) if (ply > i)
return true; return true;
@@ -1313,7 +1324,7 @@ bool Position::pos_is_ok() const {
assert(0 && "pos_is_ok: Bitboards"); assert(0 && "pos_is_ok: Bitboards");
StateInfo si = *st; StateInfo si = *st;
ASSERT_ALIGNED(&si, Eval::NNUE::kCacheLineSize); ASSERT_ALIGNED(&si, Eval::NNUE::CacheLineSize);
set_state(&si); set_state(&si);
if (std::memcmp(&si, st, sizeof(StateInfo))) if (std::memcmp(&si, st, sizeof(StateInfo)))
@@ -1338,3 +1349,5 @@ bool Position::pos_is_ok() const {
return true; return true;
} }
} // namespace Stockfish
+44 -27
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
#include "nnue/nnue_accumulator.h" #include "nnue/nnue_accumulator.h"
namespace Stockfish {
/// StateInfo struct stores information needed to restore a Position object to /// StateInfo struct stores information needed to restore a Position object to
/// its previous state when we retract a move. Whenever a move is made on the /// its previous state when we retract a move. Whenever a move is made on the
@@ -50,11 +51,11 @@ struct StateInfo {
// Not copied when making a move (will be recomputed anyhow) // Not copied when making a move (will be recomputed anyhow)
Key key; Key key;
Bitboard checkersBB; Bitboard checkersBB;
Piece capturedPiece;
StateInfo* previous; StateInfo* previous;
Bitboard blockersForKing[COLOR_NB]; Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB]; Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB]; Bitboard checkSquares[PIECE_TYPE_NB];
Piece capturedPiece;
int repetition; int repetition;
// Used by NNUE // Used by NNUE
@@ -87,7 +88,7 @@ public:
// FEN string input/output // FEN string input/output
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th); Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th);
Position& set(const std::string& code, Color c, StateInfo* si); Position& set(const std::string& code, Color c, StateInfo* si);
const std::string fen() const; std::string fen() const;
// Position representation // Position representation
Bitboard pieces(PieceType pt) const; Bitboard pieces(PieceType pt) const;
@@ -114,20 +115,18 @@ public:
Bitboard blockers_for_king(Color c) const; Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const; Bitboard check_squares(PieceType pt) const;
Bitboard pinners(Color c) const; Bitboard pinners(Color c) const;
bool is_discovered_check_on_king(Color c, Move m) const;
// Attacks to/from a given square // Attacks to/from a given square
Bitboard attackers_to(Square s) const; Bitboard attackers_to(Square s) const;
Bitboard attackers_to(Square s, Bitboard occupied) const; Bitboard attackers_to(Square s, Bitboard occupied) const;
Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const; Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
template<PieceType Pt> Bitboard attacks_by(Color c) const;
// Properties of moves // Properties of moves
bool legal(Move m) const; bool legal(Move m) const;
bool pseudo_legal(const Move m) const; bool pseudo_legal(const Move m) const;
bool capture(Move m) const; bool capture(Move m) const;
bool capture_or_promotion(Move m) const;
bool gives_check(Move m) const; bool gives_check(Move m) const;
bool advanced_pawn_push(Move m) const;
Piece moved_piece(Move m) const; Piece moved_piece(Move m) const;
Piece captured_piece() const; Piece captured_piece() const;
@@ -162,6 +161,7 @@ public:
bool has_repeated() const; bool has_repeated() const;
int rule50_count() const; int rule50_count() const;
Score psq_score() const; Score psq_score() const;
Value psq_eg_stm() const;
Value non_pawn_material(Color c) const; Value non_pawn_material(Color c) const;
Value non_pawn_material() const; Value non_pawn_material() const;
@@ -172,6 +172,9 @@ public:
// Used by NNUE // Used by NNUE
StateInfo* state() const; StateInfo* state() const;
void put_piece(Piece pc, Square s);
void remove_piece(Square s);
private: private:
// Initialization helpers (used while setting up a position) // Initialization helpers (used while setting up a position)
void set_castling_right(Color c, Square rfrom); void set_castling_right(Color c, Square rfrom);
@@ -179,11 +182,11 @@ private:
void set_check_info(StateInfo* si) const; void set_check_info(StateInfo* si) const;
// Other helpers // Other helpers
void put_piece(Piece pc, Square s);
void remove_piece(Square s);
void move_piece(Square from, Square to); void move_piece(Square from, Square to);
template<bool Do> template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto); void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
template<bool AfterMove>
Key adjust_key50(Key k) const;
// Data members // Data members
Piece board[SQUARE_NB]; Piece board[SQUARE_NB];
@@ -193,11 +196,11 @@ private:
int castlingRightsMask[SQUARE_NB]; int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB]; Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB]; Bitboard castlingPath[CASTLING_RIGHT_NB];
Thread* thisThread;
StateInfo* st;
int gamePly; int gamePly;
Color sideToMove; Color sideToMove;
Score psq; Score psq;
Thread* thisThread;
StateInfo* st;
bool chess960; bool chess960;
}; };
@@ -285,6 +288,22 @@ inline Bitboard Position::attackers_to(Square s) const {
return attackers_to(s, pieces()); return attackers_to(s, pieces());
} }
template<PieceType Pt>
inline Bitboard Position::attacks_by(Color c) const {
if constexpr (Pt == PAWN)
return c == WHITE ? pawn_attacks_bb<WHITE>(pieces(WHITE, PAWN))
: pawn_attacks_bb<BLACK>(pieces(BLACK, PAWN));
else
{
Bitboard threats = 0;
Bitboard attackers = pieces(c, Pt);
while (attackers)
threats |= attacks_bb<Pt>(pop_lsb(attackers), pieces());
return threats;
}
}
inline Bitboard Position::checkers() const { inline Bitboard Position::checkers() const {
return st->checkersBB; return st->checkersBB;
} }
@@ -301,26 +320,23 @@ inline Bitboard Position::check_squares(PieceType pt) const {
return st->checkSquares[pt]; return st->checkSquares[pt];
} }
inline bool Position::is_discovered_check_on_king(Color c, Move m) const {
return st->blockersForKing[c] & from_sq(m);
}
inline bool Position::pawn_passed(Color c, Square s) const { inline bool Position::pawn_passed(Color c, Square s) const {
return !(pieces(~c, PAWN) & passed_pawn_span(c, s)); return !(pieces(~c, PAWN) & passed_pawn_span(c, s));
} }
inline bool Position::advanced_pawn_push(Move m) const {
return type_of(moved_piece(m)) == PAWN
&& relative_rank(sideToMove, to_sq(m)) > RANK_5;
}
inline int Position::pawns_on_same_color_squares(Color c, Square s) const { inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
return popcount(pieces(c, PAWN) & ((DarkSquares & s) ? DarkSquares : ~DarkSquares)); return popcount(pieces(c, PAWN) & ((DarkSquares & s) ? DarkSquares : ~DarkSquares));
} }
inline Key Position::key() const { inline Key Position::key() const {
return st->rule50 < 14 ? st->key return adjust_key50<false>(st->key);
: st->key ^ make_key((st->rule50 - 14) / 8); }
template<bool AfterMove>
inline Key Position::adjust_key50(Key k) const
{
return st->rule50 < 14 - AfterMove
? k : k ^ make_key((st->rule50 - (14 - AfterMove)) / 8);
} }
inline Key Position::pawn_key() const { inline Key Position::pawn_key() const {
@@ -335,6 +351,10 @@ inline Score Position::psq_score() const {
return psq; return psq;
} }
inline Value Position::psq_eg_stm() const {
return (sideToMove == WHITE ? 1 : -1) * eg_value(psq);
}
inline Value Position::non_pawn_material(Color c) const { inline Value Position::non_pawn_material(Color c) const {
return st->nonPawnMaterial[c]; return st->nonPawnMaterial[c];
} }
@@ -361,11 +381,6 @@ inline bool Position::is_chess960() const {
return chess960; return chess960;
} }
inline bool Position::capture_or_promotion(Move m) const {
assert(is_ok(m));
return type_of(m) != NORMAL ? type_of(m) != CASTLING : !empty(to_sq(m));
}
inline bool Position::capture(Move m) const { inline bool Position::capture(Move m) const {
assert(is_ok(m)); assert(is_ok(m));
// Castling is encoded as "king captures rook" // Castling is encoded as "king captures rook"
@@ -396,7 +411,7 @@ inline void Position::remove_piece(Square s) {
byTypeBB[ALL_PIECES] ^= s; byTypeBB[ALL_PIECES] ^= s;
byTypeBB[type_of(pc)] ^= s; byTypeBB[type_of(pc)] ^= s;
byColorBB[color_of(pc)] ^= s; byColorBB[color_of(pc)] ^= s;
/* board[s] = NO_PIECE; Not needed, overwritten by the capturing one */ board[s] = NO_PIECE;
pieceCount[pc]--; pieceCount[pc]--;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--; pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
psq -= PSQT::psq[pc][s]; psq -= PSQT::psq[pc][s];
@@ -423,4 +438,6 @@ inline StateInfo* Position::state() const {
return st; return st;
} }
} // namespace Stockfish
#endif // #ifndef POSITION_H_INCLUDED #endif // #ifndef POSITION_H_INCLUDED
+4 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
#include "bitboard.h" #include "bitboard.h"
#include "types.h" #include "types.h"
namespace Stockfish {
namespace namespace
{ {
@@ -126,3 +127,5 @@ void init() {
} }
} // namespace PSQT } // namespace PSQT
} // namespace Stockfish
+3 -3
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
#include "types.h" #include "types.h"
namespace PSQT namespace Stockfish::PSQT
{ {
extern Score psq[PIECE_NB][SQUARE_NB]; extern Score psq[PIECE_NB][SQUARE_NB];
@@ -32,7 +32,7 @@ extern Score psq[PIECE_NB][SQUARE_NB];
// Fill psqt array from a set of internally linked parameters // Fill psqt array from a set of internally linked parameters
extern void init(); extern void init();
} // namespace PSQT } // namespace Stockfish::PSQT
#endif // PSQT_H_INCLUDED #endif // PSQT_H_INCLUDED
+456 -510
View File
File diff suppressed because it is too large Load Diff
+10 -4
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -25,13 +25,12 @@
#include "movepick.h" #include "movepick.h"
#include "types.h" #include "types.h"
namespace Stockfish {
class Position; class Position;
namespace Search { namespace Search {
/// Threshold used for countermoves based pruning
constexpr int CounterMovePruneThreshold = 0;
/// Stack struct keeps track of the information we need to remember from nodes /// Stack struct keeps track of the information we need to remember from nodes
/// shallower and deeper in the tree during the search. Each search thread has /// shallower and deeper in the tree during the search. Each search thread has
@@ -50,6 +49,8 @@ struct Stack {
bool inCheck; bool inCheck;
bool ttPv; bool ttPv;
bool ttHit; bool ttHit;
int doubleExtensions;
int cutoffCnt;
}; };
@@ -69,6 +70,9 @@ struct RootMove {
Value score = -VALUE_INFINITE; Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE; Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0; int selDepth = 0;
int tbRank = 0; int tbRank = 0;
Value tbScore; Value tbScore;
@@ -106,4 +110,6 @@ void clear();
} // namespace Search } // namespace Search
} // namespace Stockfish
#endif // #ifndef SEARCH_H_INCLUDED #endif // #ifndef SEARCH_H_INCLUDED
+46 -30
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -50,13 +50,16 @@
#include <windows.h> #include <windows.h>
#endif #endif
using namespace Tablebases; using namespace Stockfish::Tablebases;
int Tablebases::MaxCardinality; int Stockfish::Tablebases::MaxCardinality;
namespace Stockfish {
namespace { namespace {
constexpr int TBPIECES = 7; // Max number of supported pieces constexpr int TBPIECES = 7; // Max number of supported pieces
constexpr int MAX_DTZ = 1 << 18; // Max DTZ supported, large enough to deal with the syzygy TB limit.
enum { BigEndian, LittleEndian }; enum { BigEndian, LittleEndian };
enum TBType { WDL, DTZ }; // Used as template parameter enum TBType { WDL, DTZ }; // Used as template parameter
@@ -103,9 +106,6 @@ template<> inline void swap_endian<uint8_t>(uint8_t&) {}
template<typename T, int LE> T number(void* addr) template<typename T, int LE> T number(void* addr)
{ {
static const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
static const bool IsLittleEndian = (Le.c[0] == 4);
T v; T v;
if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare) if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare)
@@ -190,7 +190,8 @@ public:
std::stringstream ss(Paths); std::stringstream ss(Paths);
std::string path; std::string path;
while (std::getline(ss, path, SepChar)) { while (std::getline(ss, path, SepChar))
{
fname = path + "/" + f; fname = path + "/" + f;
std::ifstream::open(fname); std::ifstream::open(fname);
if (is_open()) if (is_open())
@@ -565,7 +566,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
int buf64Size = 64; int buf64Size = 64;
Sym sym; Sym sym;
while (true) { while (true)
{
int len = 0; // This is the symbol length - d->min_sym_len int len = 0; // This is the symbol length - d->min_sym_len
// Now get the symbol length. For any symbol s64 of length l right-padded // Now get the symbol length. For any symbol s64 of length l right-padded
@@ -603,8 +605,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// We binary-search for our value recursively expanding into the left and // We binary-search for our value recursively expanding into the left and
// right child symbols until we reach a leaf node where symlen[sym] + 1 == 1 // right child symbols until we reach a leaf node where symlen[sym] + 1 == 1
// that will store the value we need. // that will store the value we need.
while (d->symlen[sym]) { while (d->symlen[sym])
{
Sym left = d->btree[sym].get<LR::Left>(); Sym left = d->btree[sym].get<LR::Left>();
// If a symbol contains 36 sub-symbols (d->symlen[sym] + 1 = 36) and // If a symbol contains 36 sub-symbols (d->symlen[sym] + 1 = 36) and
@@ -709,7 +711,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
leadPawns = b = pos.pieces(color_of(pc), PAWN); leadPawns = b = pos.pieces(color_of(pc), PAWN);
do do
squares[size++] = pop_lsb(&b) ^ flipSquares; squares[size++] = pop_lsb(b) ^ flipSquares;
while (b); while (b);
leadPawnsCnt = size; leadPawnsCnt = size;
@@ -729,7 +731,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// directly map them to the correct color and square. // directly map them to the correct color and square.
b = pos.pieces() ^ leadPawns; b = pos.pieces() ^ leadPawns;
do { do {
Square s = pop_lsb(&b); Square s = pop_lsb(b);
squares[size] = s ^ flipSquares; squares[size] = s ^ flipSquares;
pieces[size++] = Piece(pos.piece_on(s) ^ flipColor); pieces[size++] = Piece(pos.piece_on(s) ^ flipColor);
} while (b); } while (b);
@@ -768,7 +770,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
goto encode_remaining; // With pawns we have finished special treatments goto encode_remaining; // With pawns we have finished special treatments
} }
// In positions withouth pawns, we further flip the squares to ensure leading // In positions without pawns, we further flip the squares to ensure leading
// piece is below RANK_5. // piece is below RANK_5.
if (rank_of(squares[0]) > RANK_4) if (rank_of(squares[0]) > RANK_4)
for (int i = 0; i < size; ++i) for (int i = 0; i < size; ++i)
@@ -811,7 +813,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// Rs "together" in 62 * 61 / 2 ways (we divide by 2 because rooks can be // Rs "together" in 62 * 61 / 2 ways (we divide by 2 because rooks can be
// swapped and still get the same position.) // swapped and still get the same position.)
// //
// In case we have at least 3 unique pieces (inlcuded kings) we encode them // In case we have at least 3 unique pieces (included kings) we encode them
// together. // together.
if (entry->hasUniquePieces) { if (entry->hasUniquePieces) {
@@ -826,7 +828,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
+ (squares[1] - adjust1)) * 62 + (squares[1] - adjust1)) * 62
+ squares[2] - adjust2; + squares[2] - adjust2;
// First piece is on a1-h8 diagonal, second below: map this occurence to // First piece is on a1-h8 diagonal, second below: map this occurrence to
// 6 to differentiate from the above case, rank_of() maps a1-d4 diagonal // 6 to differentiate from the above case, rank_of() maps a1-d4 diagonal
// to 0...3 and finally MapB1H1H7[] maps the b1-h1-h7 triangle to 0..27. // to 0...3 and finally MapB1H1H7[] maps the b1-h1-h7 triangle to 0..27.
else if (off_A1H8(squares[1])) else if (off_A1H8(squares[1]))
@@ -856,7 +858,7 @@ encode_remaining:
idx *= d->groupIdx[0]; idx *= d->groupIdx[0];
Square* groupSq = squares + d->groupLen[0]; Square* groupSq = squares + d->groupLen[0];
// Encode remainig pawns then pieces according to square, in ascending order // Encode remaining pawns then pieces according to square, in ascending order
bool remainingPawns = entry->hasPawns && entry->pawnCount[1]; bool remainingPawns = entry->hasPawns && entry->pawnCount[1];
while (d->groupLen[++next]) while (d->groupLen[++next])
@@ -884,7 +886,7 @@ encode_remaining:
// Group together pieces that will be encoded together. The general rule is that // Group together pieces that will be encoded together. The general rule is that
// a group contains pieces of same type and color. The exception is the leading // a group contains pieces of same type and color. The exception is the leading
// group that, in case of positions withouth pawns, can be formed by 3 different // group that, in case of positions without pawns, can be formed by 3 different
// pieces (default) or by the king pair when there is not a unique piece apart // pieces (default) or by the king pair when there is not a unique piece apart
// from the kings. When there are pawns, pawns are always first in pieces[]. // from the kings. When there are pawns, pawns are always first in pieces[].
// //
@@ -916,7 +918,7 @@ void set_groups(T& e, PairsData* d, int order[], File f) {
// //
// This ensures unique encoding for the whole position. The order of the // This ensures unique encoding for the whole position. The order of the
// groups is a per-table parameter and could not follow the canonical leading // groups is a per-table parameter and could not follow the canonical leading
// pawns/pieces -> remainig pawns -> remaining pieces. In particular the // pawns/pieces -> remaining pawns -> remaining pieces. In particular the
// first group is at order[0] position and the remaining pawns, when present, // first group is at order[0] position and the remaining pawns, when present,
// are at order[1] position. // are at order[1] position.
bool pp = e.hasPawns && e.pawnCount[1]; // Pawns on both sides bool pp = e.hasPawns && e.pawnCount[1]; // Pawns on both sides
@@ -936,7 +938,7 @@ void set_groups(T& e, PairsData* d, int order[], File f) {
d->groupIdx[1] = idx; d->groupIdx[1] = idx;
idx *= Binomial[d->groupLen[1]][48 - d->groupLen[0]]; idx *= Binomial[d->groupLen[1]][48 - d->groupLen[0]];
} }
else // Remainig pieces else // Remaining pieces
{ {
d->groupIdx[next] = idx; d->groupIdx[next] = idx;
idx *= Binomial[d->groupLen[next]][freeSquares]; idx *= Binomial[d->groupLen[next]][freeSquares];
@@ -946,7 +948,7 @@ void set_groups(T& e, PairsData* d, int order[], File f) {
d->groupIdx[n] = idx; d->groupIdx[n] = idx;
} }
// In Recursive Pairing each symbol represents a pair of childern symbols. So // In Recursive Pairing each symbol represents a pair of children symbols. So
// read d->btree[] symbols data and expand each one in his left and right child // read d->btree[] symbols data and expand each one in his left and right child
// symbol until reaching the leafs that represent the symbol value. // symbol until reaching the leafs that represent the symbol value.
uint8_t set_symlen(PairsData* d, Sym s, std::vector<bool>& visited) { uint8_t set_symlen(PairsData* d, Sym s, std::vector<bool>& visited) {
@@ -1289,7 +1291,7 @@ void Tablebases::init(const std::string& paths) {
for (auto s : diagonal) for (auto s : diagonal)
MapA1D1D4[s] = code++; MapA1D1D4[s] = code++;
// MapKK[] encodes all the 461 possible legal positions of two kings where // MapKK[] encodes all the 462 possible legal positions of two kings where
// the first is in the a1-d1-d4 triangle. If the first king is on the a1-d4 // the first is in the a1-d1-d4 triangle. If the first king is on the a1-d4
// diagonal, the other one shall not to be above the a1-h8 diagonal. // diagonal, the other one shall not to be above the a1-h8 diagonal.
std::vector<std::pair<int, Square>> bothOnDiagonal; std::vector<std::pair<int, Square>> bothOnDiagonal;
@@ -1316,7 +1318,7 @@ void Tablebases::init(const std::string& paths) {
for (auto p : bothOnDiagonal) for (auto p : bothOnDiagonal)
MapKK[p.first][p.second] = code++; MapKK[p.first][p.second] = code++;
// Binomial[] stores the Binomial Coefficents using Pascal rule. There // Binomial[] stores the Binomial Coefficients using Pascal rule. There
// are Binomial[k][n] ways to choose k elements from a set of n elements. // are Binomial[k][n] ways to choose k elements from a set of n elements.
Binomial[0][0] = 1; Binomial[0][0] = 1;
@@ -1336,7 +1338,7 @@ void Tablebases::init(const std::string& paths) {
for (int leadPawnsCnt = 1; leadPawnsCnt <= 5; ++leadPawnsCnt) for (int leadPawnsCnt = 1; leadPawnsCnt <= 5; ++leadPawnsCnt)
for (File f = FILE_A; f <= FILE_D; ++f) for (File f = FILE_A; f <= FILE_D; ++f)
{ {
// Restart the index at every file because TB table is splitted // Restart the index at every file because TB table is split
// by file, so we can reuse the same index for different files. // by file, so we can reuse the same index for different files.
int idx = 0; int idx = 0;
@@ -1521,7 +1523,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) {
// Check whether a position was repeated since the last zeroing move. // Check whether a position was repeated since the last zeroing move.
bool rep = pos.has_repeated(); bool rep = pos.has_repeated();
int dtz, bound = Options["Syzygy50MoveRule"] ? 900 : 1; int dtz, bound = Options["Syzygy50MoveRule"] ? (MAX_DTZ - 100) : 1;
// Probe and rank each move // Probe and rank each move
for (auto& m : rootMoves) for (auto& m : rootMoves)
@@ -1535,6 +1537,14 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) {
WDLScore wdl = -probe_wdl(pos, &result); WDLScore wdl = -probe_wdl(pos, &result);
dtz = dtz_before_zeroing(wdl); dtz = dtz_before_zeroing(wdl);
} }
else if (pos.is_draw(1))
{
// In case a root move leads to a draw by repetition or
// 50-move rule, we set dtz to zero. Note: since we are
// only 1 ply from the root, this must be a true 3-fold
// repetition inside the game history.
dtz = 0;
}
else else
{ {
// Otherwise, take dtz for the new position and correct by 1 ply // Otherwise, take dtz for the new position and correct by 1 ply
@@ -1556,8 +1566,8 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) {
// Better moves are ranked higher. Certain wins are ranked equally. // Better moves are ranked higher. Certain wins are ranked equally.
// Losing moves are ranked equally unless a 50-move draw is in sight. // Losing moves are ranked equally unless a 50-move draw is in sight.
int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? 1000 : 1000 - (dtz + cnt50)) int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? MAX_DTZ : MAX_DTZ - (dtz + cnt50))
: dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -1000 : -1000 + (-dtz + cnt50)) : dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -MAX_DTZ : -MAX_DTZ + (-dtz + cnt50))
: 0; : 0;
m.tbRank = r; m.tbRank = r;
@@ -1565,9 +1575,9 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) {
// 1 cp to cursed wins and let it grow to 49 cp as the positions gets // 1 cp to cursed wins and let it grow to 49 cp as the positions gets
// closer to a real win. // closer to a real win.
m.tbScore = r >= bound ? VALUE_MATE - MAX_PLY - 1 m.tbScore = r >= bound ? VALUE_MATE - MAX_PLY - 1
: r > 0 ? Value((std::max( 3, r - 800) * int(PawnValueEg)) / 200) : r > 0 ? Value((std::max( 3, r - (MAX_DTZ - 200)) * int(PawnValueEg)) / 200)
: r == 0 ? VALUE_DRAW : r == 0 ? VALUE_DRAW
: r > -bound ? Value((std::min(-3, r + 800) * int(PawnValueEg)) / 200) : r > -bound ? Value((std::min(-3, r + (MAX_DTZ - 200)) * int(PawnValueEg)) / 200)
: -VALUE_MATE + MAX_PLY + 1; : -VALUE_MATE + MAX_PLY + 1;
} }
@@ -1581,10 +1591,11 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) {
// A return value false indicates that not all probes were successful. // A return value false indicates that not all probes were successful.
bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) { bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) {
static const int WDL_to_rank[] = { -1000, -899, 0, 899, 1000 }; static const int WDL_to_rank[] = { -MAX_DTZ, -MAX_DTZ + 101, 0, MAX_DTZ - 101, MAX_DTZ };
ProbeState result; ProbeState result;
StateInfo st; StateInfo st;
WDLScore wdl;
bool rule50 = Options["Syzygy50MoveRule"]; bool rule50 = Options["Syzygy50MoveRule"];
@@ -1593,7 +1604,10 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) {
{ {
pos.do_move(m.pv[0], st); pos.do_move(m.pv[0], st);
WDLScore wdl = -probe_wdl(pos, &result); if (pos.is_draw(1))
wdl = WDLDraw;
else
wdl = -probe_wdl(pos, &result);
pos.undo_move(m.pv[0]); pos.undo_move(m.pv[0]);
@@ -1610,3 +1624,5 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) {
return true; return true;
} }
} // namespace Stockfish
+4 -6
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
#include "../search.h" #include "../search.h"
namespace Tablebases { namespace Stockfish::Tablebases {
enum WDLScore { enum WDLScore {
WDLLoss = -2, // Loss WDLLoss = -2, // Loss
@@ -31,14 +31,12 @@ enum WDLScore {
WDLDraw = 0, // Draw WDLDraw = 0, // Draw
WDLCursedWin = 1, // Win, but draw under 50-move rule WDLCursedWin = 1, // Win, but draw under 50-move rule
WDLWin = 2, // Win WDLWin = 2, // Win
WDLScoreNone = -1000
}; };
// Possible states after a probing operation // Possible states after a probing operation
enum ProbeState { enum ProbeState {
FAIL = 0, // Probe failed (missing file table) FAIL = 0, // Probe failed (missing file table)
OK = 1, // Probe succesful OK = 1, // Probe successful
CHANGE_STM = -1, // DTZ should check the other side CHANGE_STM = -1, // DTZ should check the other side
ZEROING_BEST_MOVE = 2 // Best move zeroes DTZ (capture or pawn move) ZEROING_BEST_MOVE = 2 // Best move zeroes DTZ (capture or pawn move)
}; };
@@ -73,6 +71,6 @@ inline std::ostream& operator<<(std::ostream& os, const ProbeState v) {
return os; return os;
} }
} } // namespace Stockfish::Tablebases
#endif #endif
+23 -15
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
#include "syzygy/tbprobe.h" #include "syzygy/tbprobe.h"
#include "tt.h" #include "tt.h"
namespace Stockfish {
ThreadPool Threads; // Global object ThreadPool Threads; // Global object
@@ -57,17 +59,14 @@ void Thread::clear() {
counterMoves.fill(MOVE_NONE); counterMoves.fill(MOVE_NONE);
mainHistory.fill(0); mainHistory.fill(0);
lowPlyHistory.fill(0);
captureHistory.fill(0); captureHistory.fill(0);
previousDepth = 0;
for (bool inCheck : { false, true }) for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures }) for (StatsType c : { NoCaptures, Captures })
{
for (auto& to : continuationHistory[inCheck][c]) for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to) for (auto& h : to)
h->fill(0); h->fill(-71);
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
}
} }
@@ -126,14 +125,16 @@ void Thread::idle_loop() {
void ThreadPool::set(size_t requested) { void ThreadPool::set(size_t requested) {
if (size() > 0) { // destroy any existing thread(s) if (size() > 0) // destroy any existing thread(s)
{
main()->wait_for_search_finished(); main()->wait_for_search_finished();
while (size() > 0) while (size() > 0)
delete back(), pop_back(); delete back(), pop_back();
} }
if (requested > 0) { // create new thread(s) if (requested > 0) // create new thread(s)
{
push_back(new MainThread(0)); push_back(new MainThread(0));
while (size() < requested) while (size() < requested)
@@ -158,6 +159,7 @@ void ThreadPool::clear() {
main()->callsCnt = 0; main()->callsCnt = 0;
main()->bestPreviousScore = VALUE_INFINITE; main()->bestPreviousScore = VALUE_INFINITE;
main()->bestPreviousAverageScore = VALUE_INFINITE;
main()->previousTimeReduction = 1.0; main()->previousTimeReduction = 1.0;
} }
@@ -219,11 +221,14 @@ Thread* ThreadPool::get_best_thread() const {
minScore = std::min(minScore, th->rootMoves[0].score); minScore = std::min(minScore, th->rootMoves[0].score);
// Vote according to score and depth, and select the best thread // Vote according to score and depth, and select the best thread
for (Thread* th : *this) auto thread_value = [minScore](Thread* th) {
{ return (th->rootMoves[0].score - minScore + 14) * int(th->completedDepth);
votes[th->rootMoves[0].pv[0]] += };
(th->rootMoves[0].score - minScore + 14) * int(th->completedDepth);
for (Thread* th : *this)
votes[th->rootMoves[0].pv[0]] += thread_value(th);
for (Thread* th : *this)
if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY) if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY)
{ {
// Make sure we pick the shortest mate / TB conversion or stave off mate the longest // Make sure we pick the shortest mate / TB conversion or stave off mate the longest
@@ -232,9 +237,10 @@ Thread* ThreadPool::get_best_thread() const {
} }
else if ( th->rootMoves[0].score >= VALUE_TB_WIN_IN_MAX_PLY else if ( th->rootMoves[0].score >= VALUE_TB_WIN_IN_MAX_PLY
|| ( th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY || ( th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY
&& votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]])) && ( votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]]
|| ( votes[th->rootMoves[0].pv[0]] == votes[bestThread->rootMoves[0].pv[0]]
&& thread_value(th) > thread_value(bestThread)))))
bestThread = th; bestThread = th;
}
return bestThread; return bestThread;
} }
@@ -258,3 +264,5 @@ void ThreadPool::wait_for_search_finished() const {
if (th != front()) if (th != front())
th->wait_for_search_finished(); th->wait_for_search_finished();
} }
} // namespace Stockfish
+11 -7
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
#include "search.h" #include "search.h"
#include "thread_win32_osx.h" #include "thread_win32_osx.h"
namespace Stockfish {
/// Thread class keeps together all the thread-related stuff. We use /// Thread class keeps together all the thread-related stuff. We use
/// per-thread pawn and material hash tables so that once we get a /// per-thread pawn and material hash tables so that once we get a
@@ -54,26 +55,26 @@ public:
void idle_loop(); void idle_loop();
void start_searching(); void start_searching();
void wait_for_search_finished(); void wait_for_search_finished();
size_t id() const { return idx; }
Pawns::Table pawnsTable; Pawns::Table pawnsTable;
Material::Table materialTable; Material::Table materialTable;
size_t pvIdx, pvLast; size_t pvIdx, pvLast;
uint64_t ttHitAverage; RunningAverage complexityAverage;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly; int selDepth, nmpMinPly;
Color nmpColor; Color nmpColor;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges; Value bestValue, optimism[COLOR_NB];
Position rootPos; Position rootPos;
StateInfo rootState; StateInfo rootState;
Search::RootMoves rootMoves; Search::RootMoves rootMoves;
Depth rootDepth, completedDepth; Depth rootDepth, completedDepth, previousDepth;
Value rootDelta;
CounterMoveHistory counterMoves; CounterMoveHistory counterMoves;
ButterflyHistory mainHistory; ButterflyHistory mainHistory;
LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory; CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2]; ContinuationHistory continuationHistory[2][2];
Score contempt;
int failedHighCnt;
}; };
@@ -88,6 +89,7 @@ struct MainThread : public Thread {
double previousTimeReduction; double previousTimeReduction;
Value bestPreviousScore; Value bestPreviousScore;
Value bestPreviousAverageScore;
Value iterValue[4]; Value iterValue[4];
int callsCnt; int callsCnt;
bool stopOnPonderhit; bool stopOnPonderhit;
@@ -128,4 +130,6 @@ private:
extern ThreadPool Threads; extern ThreadPool Threads;
} // namespace Stockfish
#endif // #ifndef THREAD_H_INCLUDED #endif // #ifndef THREAD_H_INCLUDED
+9 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@
#include <pthread.h> #include <pthread.h>
namespace Stockfish {
static const size_t TH_STACK_SIZE = 8 * 1024 * 1024; static const size_t TH_STACK_SIZE = 8 * 1024 * 1024;
template <class T, class P = std::pair<T*, void(T::*)()>> template <class T, class P = std::pair<T*, void(T::*)()>>
@@ -57,10 +59,16 @@ public:
void join() { pthread_join(thread, NULL); } void join() { pthread_join(thread, NULL); }
}; };
} // namespace Stockfish
#else // Default case: use STL classes #else // Default case: use STL classes
namespace Stockfish {
typedef std::thread NativeThread; typedef std::thread NativeThread;
} // namespace Stockfish
#endif #endif
#endif // #ifndef THREAD_WIN32_OSX_H_INCLUDED #endif // #ifndef THREAD_WIN32_OSX_H_INCLUDED
+13 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
#include "timeman.h" #include "timeman.h"
#include "uci.h" #include "uci.h"
namespace Stockfish {
TimeManagement Time; // Our global time management object TimeManagement Time; // Our global time management object
@@ -66,6 +68,9 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
TimePoint timeLeft = std::max(TimePoint(1), TimePoint timeLeft = std::max(TimePoint(1),
limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * (2 + mtg)); limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * (2 + mtg));
// Use extra time with larger increments
double optExtra = std::clamp(1.0 + 12.0 * limits.inc[us] / limits.time[us], 1.0, 1.12);
// A user may scale time usage by setting UCI option "Slow Mover" // A user may scale time usage by setting UCI option "Slow Mover"
// Default is 100 and changing this value will probably lose elo. // Default is 100 and changing this value will probably lose elo.
timeLeft = slowMover * timeLeft / 100; timeLeft = slowMover * timeLeft / 100;
@@ -75,16 +80,17 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
// game time for the current move, so also cap to 20% of available game time. // game time for the current move, so also cap to 20% of available game time.
if (limits.movestogo == 0) if (limits.movestogo == 0)
{ {
optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042, optScale = std::min(0.0120 + std::pow(ply + 3.0, 0.45) * 0.0039,
0.2 * limits.time[us] / double(timeLeft)); 0.2 * limits.time[us] / double(timeLeft))
* optExtra;
maxScale = std::min(7.0, 4.0 + ply / 12.0); maxScale = std::min(7.0, 4.0 + ply / 12.0);
} }
// x moves in y seconds (+ z increment) // x moves in y seconds (+ z increment)
else else
{ {
optScale = std::min((0.8 + ply / 128.0) / mtg, optScale = std::min((0.88 + ply / 116.4) / mtg,
0.8 * limits.time[us] / double(timeLeft)); 0.88 * limits.time[us] / double(timeLeft));
maxScale = std::min(6.3, 1.5 + 0.11 * mtg); maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
} }
@@ -95,3 +101,5 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
if (Options["Ponder"]) if (Options["Ponder"])
optimumTime += optimumTime / 4; optimumTime += optimumTime / 4;
} }
} // namespace Stockfish
+5 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
#include "search.h" #include "search.h"
#include "thread.h" #include "thread.h"
namespace Stockfish {
/// The TimeManagement class computes the optimal time to think depending on /// The TimeManagement class computes the optimal time to think depending on
/// the maximum available time, the game move number and other parameters. /// the maximum available time, the game move number and other parameters.
@@ -44,4 +46,6 @@ private:
extern TimeManagement Time; extern TimeManagement Time;
} // namespace Stockfish
#endif // #ifndef TIMEMAN_H_INCLUDED #endif // #ifndef TIMEMAN_H_INCLUDED
+7 -3
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
#include "tt.h" #include "tt.h"
#include "uci.h" #include "uci.h"
namespace Stockfish {
TranspositionTable TT; // Our global transposition table TranspositionTable TT; // Our global transposition table
/// TTEntry::save() populates the TTEntry with a new node's data, possibly /// TTEntry::save() populates the TTEntry with a new node's data, possibly
@@ -38,9 +40,9 @@ void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev)
move16 = (uint16_t)m; move16 = (uint16_t)m;
// Overwrite less valuable entries (cheapest checks first) // Overwrite less valuable entries (cheapest checks first)
if (b == BOUND_EXACT if ( b == BOUND_EXACT
|| (uint16_t)k != key16 || (uint16_t)k != key16
|| d - DEPTH_OFFSET > depth8 - 4) || d - DEPTH_OFFSET + 2 * pv > depth8 - 4)
{ {
assert(d > DEPTH_OFFSET); assert(d > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET); assert(d < 256 + DEPTH_OFFSET);
@@ -156,3 +158,5 @@ int TranspositionTable::hashfull() const {
return cnt / ClusterSize; return cnt / ClusterSize;
} }
} // namespace Stockfish
+5 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
#include "misc.h" #include "misc.h"
#include "types.h" #include "types.h"
namespace Stockfish {
/// TTEntry struct is the 10 bytes transposition table entry, defined as below: /// TTEntry struct is the 10 bytes transposition table entry, defined as below:
/// ///
/// key 16 bit /// key 16 bit
@@ -100,4 +102,6 @@ private:
extern TranspositionTable TT; extern TranspositionTable TT;
} // namespace Stockfish
#endif // #ifndef TT_H_INCLUDED #endif // #ifndef TT_H_INCLUDED
+8 -19
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,9 +26,10 @@
using std::string; using std::string;
namespace Stockfish {
bool Tune::update_on_last; bool Tune::update_on_last;
const UCI::Option* LastOption = nullptr; const UCI::Option* LastOption = nullptr;
BoolConditions Conditions;
static std::map<std::string, int> TuneResults; static std::map<std::string, int> TuneResults;
string Tune::next(string& names, bool pop) { string Tune::next(string& names, bool pop) {
@@ -108,23 +109,7 @@ template<> void Tune::Entry<Score>::read_option() {
template<> void Tune::Entry<Tune::PostUpdate>::init_option() {} template<> void Tune::Entry<Tune::PostUpdate>::init_option() {}
template<> void Tune::Entry<Tune::PostUpdate>::read_option() { value(); } template<> void Tune::Entry<Tune::PostUpdate>::read_option() { value(); }
} // namespace Stockfish
// Set binary conditions according to a probability that depends
// on the corresponding parameter value.
void BoolConditions::set() {
static PRNG rng(now());
static bool startup = true; // To workaround fishtest bench
for (size_t i = 0; i < binary.size(); i++)
binary[i] = !startup && (values[i] + int(rng.rand<unsigned>() % variance) > threshold);
startup = false;
for (size_t i = 0; i < binary.size(); i++)
sync_cout << binary[i] << sync_endl;
}
// Init options with tuning session results instead of default values. Useful to // Init options with tuning session results instead of default values. Useful to
@@ -138,7 +123,11 @@ void BoolConditions::set() {
#include <cmath> #include <cmath>
namespace Stockfish {
void Tune::read_results() { void Tune::read_results() {
/* ...insert your values here... */ /* ...insert your values here... */
} }
} // namespace Stockfish
+5 -35
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
namespace Stockfish {
typedef std::pair<int, int> Range; // Option's min-max values typedef std::pair<int, int> Range; // Option's min-max values
typedef Range (RangeFun) (int); typedef Range (RangeFun) (int);
@@ -44,27 +46,6 @@ struct SetRange {
#define SetDefaultRange SetRange(default_range) #define SetDefaultRange SetRange(default_range)
/// BoolConditions struct is used to tune boolean conditions in the
/// code by toggling them on/off according to a probability that
/// depends on the value of a tuned integer parameter: for high
/// values of the parameter condition is always disabled, for low
/// values is always enabled, otherwise it is enabled with a given
/// probability that depnends on the parameter under tuning.
struct BoolConditions {
void init(size_t size) { values.resize(size, defaultValue), binary.resize(size, 0); }
void set();
std::vector<int> binary, values;
int defaultValue = 465, variance = 40, threshold = 500;
SetRange range = SetRange(0, 1000);
};
extern BoolConditions Conditions;
inline void set_conditions() { Conditions.set(); }
/// Tune class implements the 'magic' code that makes the setup of a fishtest /// Tune class implements the 'magic' code that makes the setup of a fishtest
/// tuning session as easy as it can be. Mainly you have just to remove const /// tuning session as easy as it can be. Mainly you have just to remove const
/// qualifiers from the variables you want to tune and flag them for tuning, so /// qualifiers from the variables you want to tune and flag them for tuning, so
@@ -103,7 +84,7 @@ class Tune {
static Tune& instance() { static Tune t; return t; } // Singleton static Tune& instance() { static Tune t; return t; } // Singleton
// Use polymorphism to accomodate Entry of different types in the same vector // Use polymorphism to accommodate Entry of different types in the same vector
struct EntryBase { struct EntryBase {
virtual ~EntryBase() = default; virtual ~EntryBase() = default;
virtual void init_option() = 0; virtual void init_option() = 0;
@@ -157,14 +138,6 @@ class Tune {
return add(value, (next(names), std::move(names)), args...); return add(value, (next(names), std::move(names)), args...);
} }
// Template specialization for BoolConditions
template<typename... Args>
int add(const SetRange& range, std::string&& names, BoolConditions& cond, Args&&... args) {
for (size_t size = cond.values.size(), i = 0; i < size; i++)
add(cond.range, next(names, i == size - 1) + "_" + std::to_string(i), cond.values[i]);
return add(range, std::move(names), args...);
}
std::vector<std::unique_ptr<EntryBase>> list; std::vector<std::unique_ptr<EntryBase>> list;
public: public:
@@ -185,9 +158,6 @@ public:
#define UPDATE_ON_LAST() bool UNIQUE(p, __LINE__) = Tune::update_on_last = true #define UPDATE_ON_LAST() bool UNIQUE(p, __LINE__) = Tune::update_on_last = true
// Some macro to tune toggling of boolean conditions } // namespace Stockfish
#define CONDITION(x) (Conditions.binary[__COUNTER__] || (x))
#define TUNE_CONDITIONS() int UNIQUE(c, __LINE__) = (Conditions.init(__COUNTER__), 0); \
TUNE(Conditions, set_conditions)
#endif // #ifndef TUNE_H_INCLUDED #endif // #ifndef TUNE_H_INCLUDED
+6 -7
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -83,6 +83,8 @@
# define pext(b, m) 0 # define pext(b, m) 0
#endif #endif
namespace Stockfish {
#ifdef USE_POPCNT #ifdef USE_POPCNT
constexpr bool HasPopCnt = true; constexpr bool HasPopCnt = true;
#else #else
@@ -189,7 +191,6 @@ enum Value : int {
BishopValueMg = 825, BishopValueEg = 915, BishopValueMg = 825, BishopValueEg = 915,
RookValueMg = 1276, RookValueEg = 1380, RookValueMg = 1276, RookValueEg = 1380,
QueenValueMg = 2538, QueenValueEg = 2682, QueenValueMg = 2538, QueenValueEg = 2682,
Tempo = 28,
MidgameLimit = 15258, EndgameLimit = 3915 MidgameLimit = 15258, EndgameLimit = 3915
}; };
@@ -449,7 +450,7 @@ constexpr Square to_sq(Move m) {
} }
constexpr int from_to(Move m) { constexpr int from_to(Move m) {
return m & 0xFFF; return m & 0xFFF;
} }
constexpr MoveType type_of(Move m) { constexpr MoveType type_of(Move m) {
@@ -464,10 +465,6 @@ constexpr Move make_move(Square from, Square to) {
return Move((from << 6) + to); return Move((from << 6) + to);
} }
constexpr Move reverse_move(Move m) {
return make_move(to_sq(m), from_sq(m));
}
template<MoveType T> template<MoveType T>
constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) { constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to); return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
@@ -482,6 +479,8 @@ constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL; return seed * 6364136223846793005ULL + 1442695040888963407ULL;
} }
} // namespace Stockfish
#endif // #ifndef TYPES_H_INCLUDED #endif // #ifndef TYPES_H_INCLUDED
#include "tune.h" // Global visibility to tuning setup #include "tune.h" // Global visibility to tuning setup
+87 -65
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -34,18 +34,20 @@
using namespace std; using namespace std;
namespace Stockfish {
extern vector<string> setup_bench(const Position&, istream&); extern vector<string> setup_bench(const Position&, istream&);
namespace { namespace {
// FEN string of the initial position, normal chess // FEN string for the initial position in standard chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
// position() is called when engine receives the "position" UCI command. // position() is called when the engine receives the "position" UCI command.
// The function sets up the position described in the given FEN string ("fen") // It sets up the position that is described in the given FEN string ("fen") or
// or the starting position ("startpos") and then makes the moves given in the // the initial position ("startpos") and then makes the moves given in the following
// following move list ("moves"). // move list ("moves").
void position(Position& pos, istringstream& is, StateListPtr& states) { void position(Position& pos, istringstream& is, StateListPtr& states) {
@@ -57,7 +59,7 @@ namespace {
if (token == "startpos") if (token == "startpos")
{ {
fen = StartFEN; fen = StartFEN;
is >> token; // Consume "moves" token if any is >> token; // Consume the "moves" token, if any
} }
else if (token == "fen") else if (token == "fen")
while (is >> token && token != "moves") while (is >> token && token != "moves")
@@ -65,10 +67,10 @@ namespace {
else else
return; return;
states = StateListPtr(new std::deque<StateInfo>(1)); // Drop old and create a new one states = StateListPtr(new std::deque<StateInfo>(1)); // Drop the old state and create a new one
pos.set(fen, Options["UCI_Chess960"], &states->back(), Threads.main()); pos.set(fen, Options["UCI_Chess960"], &states->back(), Threads.main());
// Parse move list (if any) // Parse the move list, if any
while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
{ {
states->emplace_back(); states->emplace_back();
@@ -76,8 +78,8 @@ namespace {
} }
} }
// trace_eval() prints the evaluation for the current position, consistent with the UCI // trace_eval() prints the evaluation of the current position, consistent with
// options set so far. // the UCI options set so far.
void trace_eval(Position& pos) { void trace_eval(Position& pos) {
@@ -91,20 +93,20 @@ namespace {
} }
// setoption() is called when engine receives the "setoption" UCI command. The // setoption() is called when the engine receives the "setoption" UCI command.
// function updates the UCI option ("name") to the given value ("value"). // The function updates the UCI option ("name") to the given value ("value").
void setoption(istringstream& is) { void setoption(istringstream& is) {
string token, name, value; string token, name, value;
is >> token; // Consume "name" token is >> token; // Consume the "name" token
// Read option name (can contain spaces) // Read the option name (can contain spaces)
while (is >> token && token != "value") while (is >> token && token != "value")
name += (name.empty() ? "" : " ") + token; name += (name.empty() ? "" : " ") + token;
// Read option value (can contain spaces) // Read the option value (can contain spaces)
while (is >> token) while (is >> token)
value += (value.empty() ? "" : " ") + token; value += (value.empty() ? "" : " ") + token;
@@ -115,9 +117,9 @@ namespace {
} }
// go() is called when engine receives the "go" UCI command. The function sets // go() is called when the engine receives the "go" UCI command. The function
// the thinking time and other parameters from the input string, then starts // sets the thinking time and other parameters from the input string, then starts
// the search. // with a search.
void go(Position& pos, istringstream& is, StateListPtr& states) { void go(Position& pos, istringstream& is, StateListPtr& states) {
@@ -125,7 +127,7 @@ namespace {
string token; string token;
bool ponderMode = false; bool ponderMode = false;
limits.startTime = now(); // As early as possible! limits.startTime = now(); // The search starts as early as possible
while (is >> token) while (is >> token)
if (token == "searchmoves") // Needs to be the last command on the line if (token == "searchmoves") // Needs to be the last command on the line
@@ -149,9 +151,9 @@ namespace {
} }
// bench() is called when engine receives the "bench" command. Firstly // bench() is called when the engine receives the "bench" command.
// a list of UCI commands is setup according to bench parameters, then // Firstly, a list of UCI commands is set up according to the bench
// it is run one by one printing a summary at the end. // parameters, then it is run one by one, printing a summary at the end.
void bench(Position& pos, istream& args, StateListPtr& states) { void bench(Position& pos, istream& args, StateListPtr& states) {
@@ -182,12 +184,12 @@ namespace {
} }
else if (token == "setoption") setoption(is); else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states); else if (token == "position") position(pos, is, states);
else if (token == "ucinewgame") { Search::clear(); elapsed = now(); } // Search::clear() may take some while else if (token == "ucinewgame") { Search::clear(); elapsed = now(); } // Search::clear() may take a while
} }
elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero' elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
dbg_print(); // Just before exiting dbg_print();
cerr << "\n===========================" cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed << "\nTotal time (ms) : " << elapsed
@@ -195,36 +197,40 @@ namespace {
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl; << "\nNodes/second : " << 1000 * nodes / elapsed << endl;
} }
// The win rate model returns the probability (per mille) of winning given an eval // The win rate model returns the probability of winning (in per mille units) given an
// and a game-ply. The model fits rather accurately the LTC fishtest statistics. // eval and a game ply. It fits the LTC fishtest statistics rather accurately.
int win_rate_model(Value v, int ply) { int win_rate_model(Value v, int ply) {
// The model captures only up to 240 plies, so limit input (and rescale) // The model only captures up to 240 plies, so limit the input and then rescale
double m = std::min(240, ply) / 64.0; double m = std::min(240, ply) / 64.0;
// Coefficients of a 3rd order polynomial fit based on fishtest data // The coefficients of a third-order polynomial fit is based on the fishtest data
// for two parameters needed to transform eval to the argument of a // for two parameters that need to transform eval to the argument of a logistic
// logistic function. // function.
double as[] = {-8.24404295, 64.23892342, -95.73056462, 153.86478679}; constexpr double as[] = { -0.58270499, 2.68512549, 15.24638015, 344.49745382};
double bs[] = {-3.37154371, 28.44489198, -56.67657741, 72.05858751}; constexpr double bs[] = { -2.65734562, 15.96509799, -20.69040836, 73.61029937 };
// Enforce that NormalizeToPawnValue corresponds to a 50% win rate at ply 64
static_assert(UCI::NormalizeToPawnValue == int(as[0] + as[1] + as[2] + as[3]));
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3]; double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3]; double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
// Transform eval to centipawns with limited range // Transform the eval to centipawns with limited range
double x = std::clamp(double(100 * v) / PawnValueEg, -1000.0, 1000.0); double x = std::clamp(double(v), -4000.0, 4000.0);
// Return win rate in per mille (rounded to nearest) // Return the win rate in per mille units rounded to the nearest value
return int(0.5 + 1000 / (1 + std::exp((a - x) / b))); return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));
} }
} // namespace } // namespace
/// UCI::loop() waits for a command from stdin, parses it and calls the appropriate /// UCI::loop() waits for a command from the stdin, parses it and then calls the appropriate
/// function. Also intercepts EOF from stdin to ensure gracefully exiting if the /// function. It also intercepts an end-of-file (EOF) indication from the stdin to ensure a
/// GUI dies unexpectedly. When called with some command line arguments, e.g. to /// graceful exit if the GUI dies unexpectedly. When called with some command-line arguments,
/// run 'bench', once the command is executed the function returns immediately. /// like running 'bench', the function returns immediately after the command is executed.
/// In addition to the UCI ones, also some additional debug commands are supported. /// In addition to the UCI ones, some additional debug commands are also supported.
void UCI::loop(int argc, char* argv[]) { void UCI::loop(int argc, char* argv[]) {
@@ -238,24 +244,24 @@ void UCI::loop(int argc, char* argv[]) {
cmd += std::string(argv[i]) + " "; cmd += std::string(argv[i]) + " ";
do { do {
if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF if (argc == 1 && !getline(cin, cmd)) // Wait for an input or an end-of-file (EOF) indication
cmd = "quit"; cmd = "quit";
istringstream is(cmd); istringstream is(cmd);
token.clear(); // Avoid a stale if getline() returns empty or blank line token.clear(); // Avoid a stale if getline() returns nothing or a blank line
is >> skipws >> token; is >> skipws >> token;
if ( token == "quit" if ( token == "quit"
|| token == "stop") || token == "stop")
Threads.stop = true; Threads.stop = true;
// The GUI sends 'ponderhit' to tell us the user has played the expected move. // The GUI sends 'ponderhit' to tell that the user has played the expected move.
// So 'ponderhit' will be sent if we were told to ponder on the same move the // So, 'ponderhit' is sent if pondering was done on the same move that the user
// user has played. We should continue searching but switch from pondering to // has played. The search should continue, but should also switch from pondering
// normal search. // to the normal search.
else if (token == "ponderhit") else if (token == "ponderhit")
Threads.main()->ponder = false; // Switch to normal search Threads.main()->ponder = false; // Switch to the normal search
else if (token == "uci") else if (token == "uci")
sync_cout << "id name " << engine_info(true) sync_cout << "id name " << engine_info(true)
@@ -268,26 +274,40 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "ucinewgame") Search::clear(); else if (token == "ucinewgame") Search::clear();
else if (token == "isready") sync_cout << "readyok" << sync_endl; else if (token == "isready") sync_cout << "readyok" << sync_endl;
// Additional custom non-UCI commands, mainly for debugging. // Add custom non-UCI commands, mainly for debugging purposes.
// Do not use these commands during a search! // These commands must not be used during a search!
else if (token == "flip") pos.flip(); else if (token == "flip") pos.flip();
else if (token == "bench") bench(pos, is, states); else if (token == "bench") bench(pos, is, states);
else if (token == "d") sync_cout << pos << sync_endl; else if (token == "d") sync_cout << pos << sync_endl;
else if (token == "eval") trace_eval(pos); else if (token == "eval") trace_eval(pos);
else if (token == "compiler") sync_cout << compiler_info() << sync_endl; else if (token == "compiler") sync_cout << compiler_info() << sync_endl;
else else if (token == "export_net")
sync_cout << "Unknown command: " << cmd << sync_endl; {
std::optional<std::string> filename;
std::string f;
if (is >> skipws >> f)
filename = f;
Eval::NNUE::save_eval(filename);
}
else if (token == "--help" || token == "help" || token == "--license" || token == "license")
sync_cout << "\nStockfish is a powerful chess engine for playing and analyzing."
"\nIt is released as free software licensed under the GNU GPLv3 License."
"\nStockfish is normally used with a graphical user interface (GUI) and implements"
"\nthe Universal Chess Interface (UCI) protocol to communicate with a GUI, an API, etc."
"\nFor any further information, visit https://github.com/official-stockfish/Stockfish#readme"
"\nor read the corresponding README.md and Copying.txt files distributed along with this program.\n" << sync_endl;
else if (!token.empty() && token[0] != '#')
sync_cout << "Unknown command: '" << cmd << "'. Type help for more information." << sync_endl;
} while (token != "quit" && argc == 1); // Command line args are one-shot } while (token != "quit" && argc == 1); // The command-line arguments are one-shot
} }
/// UCI::value() converts a Value to a string suitable for use with the UCI /// UCI::value() converts a Value to a string by adhering to the UCI protocol specification:
/// protocol specification:
/// ///
/// cp <x> The score from the engine's point of view in centipawns. /// cp <x> The score from the engine's point of view in centipawns.
/// mate <y> Mate in y moves, not plies. If the engine is getting mated /// mate <y> Mate in 'y' moves (not plies). If the engine is getting mated,
/// use negative values for y. /// uses negative values for 'y'.
string UCI::value(Value v) { string UCI::value(Value v) {
@@ -296,7 +316,7 @@ string UCI::value(Value v) {
stringstream ss; stringstream ss;
if (abs(v) < VALUE_MATE_IN_MAX_PLY) if (abs(v) < VALUE_MATE_IN_MAX_PLY)
ss << "cp " << v * 100 / PawnValueEg; ss << "cp " << v * 100 / NormalizeToPawnValue;
else else
ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
@@ -304,8 +324,8 @@ string UCI::value(Value v) {
} }
/// UCI::wdl() report WDL statistics given an evaluation and a game ply, based on /// UCI::wdl() reports the win-draw-loss (WDL) statistics given an evaluation
/// data gathered for fishtest LTC games. /// and a game ply based on the data gathered for fishtest LTC games.
string UCI::wdl(Value v, int ply) { string UCI::wdl(Value v, int ply) {
@@ -328,9 +348,9 @@ std::string UCI::square(Square s) {
/// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q). /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
/// The only special case is castling, where we print in the e1g1 notation in /// The only special case is castling where the e1g1 notation is printed in
/// normal chess mode, and in e1h1 notation in chess960 mode. Internally all /// standard chess mode and in e1h1 notation it is printed in Chess960 mode.
/// castling moves are always encoded as 'king captures rook'. /// Internally, all castling moves are always encoded as 'king captures rook'.
string UCI::move(Move m, bool chess960) { string UCI::move(Move m, bool chess960) {
@@ -360,8 +380,8 @@ string UCI::move(Move m, bool chess960) {
Move UCI::to_move(const Position& pos, string& str) { Move UCI::to_move(const Position& pos, string& str) {
if (str.length() == 5) // Junior could send promotion piece in uppercase if (str.length() == 5)
str[4] = char(tolower(str[4])); str[4] = char(tolower(str[4])); // The promotion piece character must be lowercased
for (const auto& m : MoveList<LEGAL>(pos)) for (const auto& m : MoveList<LEGAL>(pos))
if (str == UCI::move(m, pos.is_chess960())) if (str == UCI::move(m, pos.is_chess960()))
@@ -369,3 +389,5 @@ Move UCI::to_move(const Position& pos, string& str) {
return MOVE_NONE; return MOVE_NONE;
} }
} // namespace Stockfish
+16 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,21 +24,30 @@
#include "types.h" #include "types.h"
namespace Stockfish {
class Position; class Position;
namespace UCI { namespace UCI {
// Normalizes the internal value as reported by evaluate or search
// to the UCI centipawn result used in output. This value is derived from
// the win_rate_model() such that Stockfish outputs an advantage of
// "100 centipawns" for a position if the engine has a 50% probability to win
// from this position in selfplay at fishtest LTC time control.
const int NormalizeToPawnValue = 361;
class Option; class Option;
/// Custom comparator because UCI options should be case insensitive /// Define a custom comparator, because the UCI options should be case-insensitive
struct CaseInsensitiveLess { struct CaseInsensitiveLess {
bool operator() (const std::string&, const std::string&) const; bool operator() (const std::string&, const std::string&) const;
}; };
/// Our options container is actually a std::map /// The options container is defined as a std::map
typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap; typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
/// Option class implements an option as defined by UCI protocol /// The Option class implements each option as specified by the UCI protocol
class Option { class Option {
typedef void (*OnChange)(const Option&); typedef void (*OnChange)(const Option&);
@@ -70,7 +79,7 @@ void loop(int argc, char* argv[]);
std::string value(Value v); std::string value(Value v);
std::string square(Square s); std::string square(Square s);
std::string move(Move m, bool chess960); std::string move(Move m, bool chess960);
std::string pv(const Position& pos, Depth depth, Value alpha, Value beta); std::string pv(const Position& pos, Depth depth);
std::string wdl(Value v, int ply); std::string wdl(Value v, int ply);
Move to_move(const Position& pos, std::string& str); Move to_move(const Position& pos, std::string& str);
@@ -78,4 +87,6 @@ Move to_move(const Position& pos, std::string& str);
extern UCI::OptionsMap Options; extern UCI::OptionsMap Options;
} // namespace Stockfish
#endif // #ifndef UCI_H_INCLUDED #endif // #ifndef UCI_H_INCLUDED
+7 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@
using std::string; using std::string;
namespace Stockfish {
UCI::OptionsMap Options; // Global object UCI::OptionsMap Options; // Global object
namespace UCI { namespace UCI {
@@ -59,9 +61,7 @@ void init(OptionsMap& o) {
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048; constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
o["Debug Log File"] << Option("", on_logger); o["Debug Log File"] << Option("", on_logger);
o["Contempt"] << Option(24, -100, 100); o["Threads"] << Option(1, 1, 1024, on_threads);
o["Analysis Contempt"] << Option("Both var Off var White var Black var Both", "Both");
o["Threads"] << Option(1, 1, 512, on_threads);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Clear Hash"] << Option(on_clear_hash); o["Clear Hash"] << Option(on_clear_hash);
o["Ponder"] << Option(false); o["Ponder"] << Option(false);
@@ -164,7 +164,7 @@ Option& Option::operator=(const string& v) {
assert(!type.empty()); assert(!type.empty());
if ( (type != "button" && v.empty()) if ( (type != "button" && type != "string" && v.empty())
|| (type == "check" && v != "true" && v != "false") || (type == "check" && v != "true" && v != "false")
|| (type == "spin" && (stof(v) < min || stof(v) > max))) || (type == "spin" && (stof(v) < min || stof(v) > max)))
return *this; return *this;
@@ -190,3 +190,5 @@ Option& Option::operator=(const string& v) {
} }
} // namespace UCI } // namespace UCI
} // namespace Stockfish
+11 -11
View File
@@ -13,7 +13,7 @@ case $1 in
--valgrind) --valgrind)
echo "valgrind testing started" echo "valgrind testing started"
prefix='' prefix=''
exeprefix='valgrind --error-exitcode=42' exeprefix='valgrind --error-exitcode=42 --errors-for-leak-kinds=all --leak-check=full'
postfix='1>/dev/null' postfix='1>/dev/null'
threads="1" threads="1"
;; ;;
@@ -39,16 +39,16 @@ case $1 in
threads="2" threads="2"
cat << EOF > tsan.supp cat << EOF > tsan.supp
race:TTEntry::move race:Stockfish::TTEntry::move
race:TTEntry::depth race:Stockfish::TTEntry::depth
race:TTEntry::bound race:Stockfish::TTEntry::bound
race:TTEntry::save race:Stockfish::TTEntry::save
race:TTEntry::value race:Stockfish::TTEntry::value
race:TTEntry::eval race:Stockfish::TTEntry::eval
race:TTEntry::is_pv race:Stockfish::TTEntry::is_pv
race:TranspositionTable::probe race:Stockfish::TranspositionTable::probe
race:TranspositionTable::hashfull race:Stockfish::TranspositionTable::hashfull
EOF EOF
@@ -98,7 +98,7 @@ cat << EOF > game.exp
expect "bestmove" expect "bestmove"
send "position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1\n" send "position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1\n"
send "go depth 20\n" send "go depth 10\n"
expect "bestmove" expect "bestmove"
send "quit\n" send "quit\n"
+2 -2
View File
@@ -10,7 +10,7 @@ trap 'error ${LINENO}' ERR
echo "reprosearch testing started" echo "reprosearch testing started"
# repeat two short games, separated by ucinewgame. # repeat two short games, separated by ucinewgame.
# with go nodes $nodes they should result in exactly # with go nodes $nodes they should result in exactly
# the same node count for each iteration. # the same node count for each iteration.
cat << EOF > repeat.exp cat << EOF > repeat.exp
@@ -43,7 +43,7 @@ cat << EOF > repeat.exp
expect eof expect eof
EOF EOF
# to increase the likelyhood of finding a non-reproducible case, # to increase the likelihood of finding a non-reproducible case,
# the allowed number of nodes are varied systematically # the allowed number of nodes are varied systematically
for i in `seq 1 20` for i in `seq 1 20`
do do