Merge branch 'master' into clusterMergeMaster14

closes https://github.com/official-stockfish/Stockfish/pull/3980
This commit is contained in:
Joost VandeVondele
2022-04-15 09:27:16 +02:00
59 changed files with 1344 additions and 1232 deletions
+75 -19
View File
@@ -5,6 +5,7 @@ on:
- master - master
- tools - tools
- github_ci - github_ci
- github_ci_armv7
pull_request: pull_request:
branches: branches:
- master - master
@@ -20,6 +21,12 @@ jobs:
strategy: strategy:
matrix: matrix:
config: config:
# set the variable for the required tests:
# run_expensive_tests: true
# run_32bit_tests: true
# run_64bit_tests: true
# run_armv8_tests: true
# run_armv7_tests: true
- { - {
name: "Ubuntu 20.04 GCC", name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04, os: ubuntu-20.04,
@@ -35,18 +42,31 @@ jobs:
os: ubuntu-20.04, os: ubuntu-20.04,
compiler: clang++, compiler: clang++,
comp: clang, comp: clang,
run_expensive_tests: false,
run_32bit_tests: true, run_32bit_tests: true,
run_64bit_tests: true, run_64bit_tests: true,
shell: 'bash {0}' shell: 'bash {0}'
} }
- {
name: "Ubuntu 20.04 NDK armv8",
os: ubuntu-20.04,
compiler: aarch64-linux-android21-clang++,
comp: ndk,
run_armv8_tests: true,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 NDK armv7",
os: ubuntu-20.04,
compiler: armv7a-linux-androideabi21-clang++,
comp: ndk,
run_armv7_tests: true,
shell: 'bash {0}'
}
- { - {
name: "MacOS 10.15 Apple Clang", name: "MacOS 10.15 Apple Clang",
os: macos-10.15, os: macos-10.15,
compiler: clang++, compiler: clang++,
comp: clang, comp: clang,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true, run_64bit_tests: true,
shell: 'bash {0}' shell: 'bash {0}'
} }
@@ -55,33 +75,37 @@ jobs:
os: macos-10.15, os: macos-10.15,
compiler: g++-10, compiler: g++-10,
comp: gcc, comp: gcc,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true, run_64bit_tests: true,
shell: 'bash {0}' shell: 'bash {0}'
} }
- { - {
name: "Windows 2019 Mingw-w64 GCC x86_64", name: "Windows 2022 Mingw-w64 GCC x86_64",
os: windows-2019, os: windows-2022,
compiler: g++, compiler: g++,
comp: gcc, comp: mingw,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true, run_64bit_tests: true,
msys_sys: 'mingw64', msys_sys: 'mingw64',
msys_env: 'x86_64', msys_env: 'x86_64-gcc',
shell: 'msys2 {0}' shell: 'msys2 {0}'
} }
- { - {
name: "Windows 2019 Mingw-w64 GCC i686", name: "Windows 2022 Mingw-w64 GCC i686",
os: windows-2019, os: windows-2022,
compiler: g++, compiler: g++,
comp: gcc, comp: mingw,
run_expensive_tests: false,
run_32bit_tests: true, run_32bit_tests: true,
run_64bit_tests: false,
msys_sys: 'mingw32', msys_sys: 'mingw32',
msys_env: 'i686', 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}' shell: 'msys2 {0}'
} }
@@ -98,14 +122,14 @@ jobs:
if: runner.os == 'Linux' if: runner.os == 'Linux'
run: | run: |
sudo apt update sudo apt update
sudo apt install expect valgrind g++-multilib sudo apt install expect valgrind g++-multilib qemu-user
- name: Setup msys and install required packages - name: Setup msys and install required packages
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: ${{matrix.config.msys_sys}} msystem: ${{matrix.config.msys_sys}}
install: mingw-w64-${{matrix.config.msys_env}}-gcc make git expect install: mingw-w64-${{matrix.config.msys_env}} make git expect
- name: Download the used network from the fishtest framework - name: Download the used network from the fishtest framework
run: | run: |
@@ -118,6 +142,7 @@ jobs:
- name: Check compiler - name: Check compiler
run: | run: |
export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
$COMPILER -v $COMPILER -v
- name: Test help target - name: Test help target
@@ -239,6 +264,37 @@ jobs:
make clean make clean
make -j2 ARCH=x86-64-vnni256 build make -j2 ARCH=x86-64-vnni256 build
# armv8 tests
- name: Test armv8 build
if: ${{ matrix.config.run_armv8_tests }}
run: |
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: |
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: |
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 # Other tests
- name: Check perft and search reproducibility - name: Check perft and search reproducibility
+5
View File
@@ -31,6 +31,7 @@ Arjun Temurnikar
Artem Solopiy (EntityFX) 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)
@@ -132,6 +133,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)
@@ -153,6 +155,7 @@ Pascal Romaret
Pasquale Pigazzini (ppigazzini) Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere) Patrick Jansen (mibere)
pellanda pellanda
Peter Schneider (pschneider1968)
Peter Zsifkovits (CoffeeOne) Peter Zsifkovits (CoffeeOne)
Praveen Kumar Tummala (praveentml) Praveen Kumar Tummala (praveentml)
Rahul Dsilva (silversolver1) Rahul Dsilva (silversolver1)
@@ -165,6 +168,7 @@ Rodrigo Exterckötter Tjäder
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)
@@ -194,6 +198,7 @@ tttak
Unai Corzo (unaiic) Unai Corzo (unaiic)
Uri Blass (uriblass) Uri Blass (uriblass)
Vince Negri (cuddlestmonkey) Vince Negri (cuddlestmonkey)
xefoci7612
zz4032 zz4032
+42 -32
View File
@@ -10,24 +10,28 @@ Cute Chess, eboard, Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in ord
to be used comfortably. Read the documentation for your GUI of choice for information to be used comfortably. Read the documentation for your GUI of choice for information
about how to use Stockfish with it. about how to use Stockfish with it.
The Stockfish engine features two evaluation functions for chess, the classical The Stockfish engine features two evaluation functions for chess. The efficiently
evaluation based on handcrafted terms, and the NNUE evaluation based on efficiently updatable neural network (NNUE) based evaluation is the default and by far the strongest.
updatable neural networks. The classical evaluation runs efficiently on almost all The classical evaluation based on handcrafted terms remains available. The strongest
CPU architectures, while the NNUE evaluation benefits from the vector network is integrated in the binary and downloaded automatically during the build process.
intrinsics available on most CPUs (sse2, avx2, neon, or similar). 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](https://github.com/official-stockfish/Stockfish/blob/master/README.md), the file you are currently reading. * [Readme.md](https://github.com/official-stockfish/Stockfish/blob/master/README.md),
the file you are currently reading.
* [Copying.txt](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt), a text file containing the GNU General Public License version 3. * [Copying.txt](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt),
a text file containing the GNU General Public License version 3.
* [AUTHORS](https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS), a text file with the list of authors for the project * [AUTHORS](https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS),
a text file with the list of authors for the project
* [src](https://github.com/official-stockfish/Stockfish/tree/master/src), a subdirectory containing the full source code, including a Makefile * [src](https://github.com/official-stockfish/Stockfish/tree/master/src),
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
@@ -37,7 +41,7 @@ This distribution of Stockfish consists of the following files:
The Universal Chess Interface (UCI) is a standard protocol used to communicate with 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 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 it options as described (GUI) or chess tools. Stockfish implements the majority of its options as described
in [the UCI protocol](https://www.shredderchess.com/download/div/uci.zip). in [the UCI protocol](https://www.shredderchess.com/download/div/uci.zip).
Developers can see the default values for UCI options available in Stockfish by typing Developers can see the default values for UCI options available in Stockfish by typing
@@ -68,9 +72,9 @@ change them via a chess GUI. This is a list of available UCI options in Stockfis
* #### 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.
@@ -103,7 +107,7 @@ change them via a chess GUI. This is a list of available UCI options in Stockfis
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.
@@ -138,8 +142,9 @@ change them via a chess GUI. This is a list of available UCI options in Stockfis
For developers the following non-standard commands might be of interest, mainly useful for debugging: For developers the following non-standard commands might be of interest, mainly useful for debugging:
* #### bench *ttSize threads limit fenFile limitType evalType* * #### bench *ttSize threads limit fenFile limitType evalType*
Performs a standard benchmark using various options. The signature of a version (standard node Performs a standard benchmark using various options. The signature of a version
count) is obtained using all defaults. `bench` is currently `bench 16 1 13 default depth mixed`. (standard node count) is obtained using all defaults. `bench` is currently
`bench 16 1 13 default depth mixed`.
* #### compiler * #### compiler
Give information about the compiler and environment used for building a binary. Give information about the compiler and environment used for building a binary.
@@ -175,22 +180,27 @@ 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](https://github.com/nodchip/Stockfish) provided the first
tools to train and develop the NNUE networks. On CPUs supporting modern vector instructions version of the needed tools to train and develop the NNUE networks. Today, more
(avx2 and similar), the NNUE evaluation results in much stronger playing strength, even advanced training tools are available in
if the nodes per second computed by the engine is somewhat lower (roughly 80% of nps [the nnue-pytorch repository](https://github.com/glinscott/nnue-pytorch/),
is typical). while data generation tools are available in
[a dedicated branch](https://github.com/official-stockfish/Stockfish/tree/tools).
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
``` ```
@@ -345,10 +355,10 @@ 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*](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt). [*Copying.txt*](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt).
+228 -203
View File
@@ -1,205 +1,230 @@
Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021. Contributors to Fishtest with >10,000 CPU hours, as of 2022-02-05.
Thank you! Thank you!
Username CPU Hours Games played Username CPU Hours Games played
----------------------------------------------------- ------------------------------------------------------------------
noobpwnftw 27649494 1834734733 noobpwnftw 30730952 2158431735
mlang 1426107 89454622 mlang 2729669 187335452
dew 1380910 82831648 technologov 1696847 74478658
mibere 703840 46867607 dew 1635640 97483012
grandphish2 692707 41737913 grandphish2 1062754 64955639
tvijlbrief 669642 42371594 tvijlbrief 795993 51894442
JojoM 597778 35297180 okrout 773704 63465204
TueRens 519226 31823562 TueRens 766198 47770388
cw 458421 30307421 mibere 703840 46867607
fastgm 439667 25950040 JojoM 703005 42689868
gvreuls 436599 28177460 pemo 634102 29868807
crunchy 427035 27344275 linrock 626939 17408017
CSU_Dynasty 374765 25106278 gvreuls 517442 33605006
Fisherman 326901 21822979 cw 503905 33850487
ctoks 325477 21767943 fastgm 482847 29004732
velislav 295343 18844324 crunchy 427035 27344275
linrock 292789 10624427 CSU_Dynasty 415864 28116776
bcross 278584 19488961 ctoks 403102 26737127
okrout 262818 13803272 oz 357710 26490208
pemo 245982 11376085 bcross 331095 23165889
glinscott 217799 13780820 Fisherman 327231 21829379
leszek 212346 12959025 velislav 321708 20729264
nordlandia 211692 13484886 leszek 303654 19063973
bking_US 198894 11876016 Dantist 251015 15843226
drabel 196463 13450602 mgrabiak 231973 15162494
robal 195473 12375650 glinscott 217799 13780820
mgrabiak 187226 12016564 robal 213960 13665726
Dantist 183202 10990484 nordlandia 211692 13484886
Thanar 179852 12365359 drabel 200914 13755384
vdv 175274 9889046 bking_US 198894 11876016
spams 157128 10319326 mhoram 180229 11610075
marrco 150295 9402141 Thanar 179852 12365359
sqrt2 147963 9724586 vdv 175544 9904472
mhoram 141278 8901241 spams 157128 10319326
CoffeeOne 137100 5024116 marrco 150300 9402229
vdbergh 137041 8926915 sqrt2 147963 9724586
malala 136182 8002293 vdbergh 137429 8955089
xoto 133702 9156676 CoffeeOne 137100 5024116
davar 122092 7960001 malala 136182 8002293
dsmith 122059 7570238 xoto 133759 9159372
Data 113305 8220352 rpngn 131285 8657757
BrunoBanani 112960 7436849 davar 122661 7996937
MaZePallas 102823 6633619 dsmith 122059 7570238
sterni1971 100532 5880772 amicic 119659 7937885
ElbertoOne 99028 7023771 Data 113305 8220352
brabos 92118 6186135 BrunoBanani 112960 7436849
oz 92100 6486640 CypressChess 108321 7759588
psk 89957 5984901 MaZePallas 102823 6633619
amicic 89156 5392305 sterni1971 100532 5880772
sunu 88851 6028873 sunu 100167 7040199
Vizvezdenec 83761 5344740 DesolatedDodo 99038 6414626
0x3C33 82614 5271253 ElbertoOne 99028 7023771
BRAVONE 81239 5054681 skiminki 98123 6478402
racerschmacer 80899 5759262 brabos 92118 6186135
cuistot 80300 4606144 cuistot 90358 5351004
nssy 76497 5259388 psk 89957 5984901
teddybaer 75125 5407666 racerschmacer 85712 6119648
Pking_cda 73776 5293873 Vizvezdenec 83761 5344740
jromang 72192 5057715 sschnee 83003 4840890
solarlight 70517 5028306 0x3C33 82614 5271253
dv8silencer 70287 3883992 BRAVONE 81239 5054681
Bobo1239 68515 4652287 nssy 76497 5259388
manap 66273 4121774 teddybaer 75125 5407666
skiminki 65088 4023328 Pking_cda 73776 5293873
tinker 64333 4268790 zeryl 73335 4774257
sschnee 60767 3500800 jromang 72192 5057715
qurashee 57344 3168264 solarlight 70517 5028306
robnjr 57262 4053117 dv8silencer 70287 3883992
Freja 56938 3733019 Bobo1239 68515 4652287
ttruscott 56010 3680085 manap 66273 4121774
rkl 55132 4164467 tinker 64333 4268790
renouve 53811 3501516 yurikvelo 63371 4335060
finfish 51360 3370515 qurashee 61208 3429862
eva42 51272 3599691 robnjr 57262 4053117
rap 49985 3219146 Wolfgang 57014 3561352
pb00067 49727 3298270 Freja 56938 3733019
ronaldjerum 47654 3240695 ttruscott 56010 3680085
bigpen0r 47653 3335327 rkl 55132 4164467
eastorwest 47585 3221629 renouve 53811 3501516
biffhero 46564 3111352 finfish 51360 3370515
VoyagerOne 45476 3452465 eva42 51272 3599691
yurikvelo 44834 3034550 Calis007 51182 3131552
speedycpu 43842 3003273 eastorwest 51058 3451555
jbwiebe 43305 2805433 rap 49985 3219146
Spprtr 42279 2680153 pb00067 49727 3298270
DesolatedDodo 42007 2447516 Spprtr 48260 3141959
Antihistamine 41788 2761312 bigpen0r 47667 3336927
mhunt 41735 2691355 ronaldjerum 47654 3240695
homyur 39893 2850481 MaxKlaxxMiner 47584 2972142
gri 39871 2515779 biffhero 46564 3111352
Fifis 38776 2529121 megaman7de 45992 2952006
oryx 38724 2966648 Fifis 45843 3088497
SC 37290 2731014 VoyagerOne 45476 3452465
csnodgrass 36207 2688994 speedycpu 43842 3003273
jmdana 36157 2210661 jbwiebe 43305 2805433
strelock 34716 2074055 Antihistamine 41788 2761312
rpngn 33951 2057395 mhunt 41735 2691355
Garf 33922 2751802 homyur 39893 2850481
EthanOConnor 33370 2090311 gri 39871 2515779
slakovv 32915 2021889 oryx 38867 2976992
manapbk 30987 1810399 SC 37299 2731694
Prcuvu 30377 2170122 Garf 37213 2986270
anst 30301 2190091 csnodgrass 36207 2688994
jkiiski 30136 1904470 jmdana 36157 2210661
hyperbolic.tom 29840 2017394 strelock 34716 2074055
Pyafue 29650 1902349 EthanOConnor 33370 2090311
Wolfgang 29260 1658936 slakovv 32915 2021889
zeryl 28156 1579911 armo9494 32129 2551682
OuaisBla 27636 1578800 tolkki963 32114 1932256
DMBK 27051 1999456 manapbk 30987 1810399
chriswk 26902 1868317 DMBK 30675 2383552
achambord 26582 1767323 Prcuvu 30377 2170122
Patrick_G 26276 1801617 anst 30301 2190091
yorkman 26193 1992080 jkiiski 30136 1904470
SFTUser 25182 1675689 gopeto 29886 1979118
nabildanial 24942 1519409 hyperbolic.tom 29840 2017394
Sharaf_DG 24765 1786697 chuckstablers 29659 2093438
ncfish1 24411 1520927 Pyafue 29650 1902349
rodneyc 24227 1409514 OuaisBla 27636 1578800
agg177 23890 1395014 chriswk 26902 1868317
JanErik 23408 1703875 achambord 26582 1767323
Isidor 23388 1680691 Patrick_G 26276 1801617
Norabor 23164 1591830 yorkman 26193 1992080
cisco2015 22897 1762669 SFTUser 25182 1675689
Zirie 22542 1472937 nabildanial 24942 1519409
team-oh 22272 1636708 Sharaf_DG 24765 1786697
MazeOfGalious 21978 1629593 ncfish1 24411 1520927
sg4032 21947 1643265 rodneyc 24275 1410450
ianh2105 21725 1632562 agg177 23890 1395014
xor12 21628 1680365 belzedar94 23707 1593860
dex 21612 1467203 JanErik 23408 1703875
nesoneg 21494 1463031 Isidor 23388 1680691
sphinx 21211 1384728 Norabor 23339 1602636
jjoshua2 21001 1423089 Ente 23093 1642458
horst.prack 20878 1465656 cisco2015 22897 1762669
Ente 20865 1477066 Zirie 22542 1472937
0xB00B1ES 20590 1208666 team-oh 22272 1636708
j3corre 20405 941444 MazeOfGalious 21978 1629593
Adrian.Schmidt123 20316 1281436 sg4032 21947 1643265
wei 19973 1745989 ianh2105 21725 1632562
MaxKlaxxMiner 19850 1009176 xor12 21628 1680365
rstoesser 19569 1293588 dex 21612 1467203
gopeto 19491 1174952 nesoneg 21494 1463031
eudhan 19274 1283717 sphinx 21211 1384728
jundery 18445 1115855 jjoshua2 21001 1423089
megaman7de 18377 1067540 horst.prack 20878 1465656
iisiraider 18247 1101015 user213718 20783 1379584
ville 17883 1384026 0xB00B1ES 20590 1208666
chris 17698 1487385 j3corre 20405 941444
purplefishies 17595 1092533 Adrian.Schmidt123 20316 1281436
dju 17353 978595 wei 19973 1745989
DragonLord 17014 1162790 Roady 19848 1335928
IgorLeMasson 16064 1147232 rstoesser 19569 1293588
ako027ako 15671 1173203 eudhan 19274 1283717
chuckstablers 15289 891576 vulcan 18871 1729392
Nikolay.IT 15154 1068349 jundery 18445 1115855
Andrew Grant 15114 895539 iisiraider 18247 1101015
OssumOpossum 14857 1007129 ville 17883 1384026
Karby 14808 867120 chris 17698 1487385
enedene 14476 905279 purplefishies 17595 1092533
bpfliegel 14298 884523 dju 17353 978595
mpx86 14019 759568 kdave 17183 1242754
jpulman 13982 870599 DragonLord 17014 1162790
crocogoat 13803 1117422 thirdlife 16996 447356
joster 13794 950160 spcc 16932 1130940
Nesa92 13786 1114691 fishtester 16644 1123000
Hjax 13535 915487 Ulysses 16490 1184400
jsys14 13459 785000 IgorLeMasson 16064 1147232
Dark_wizzie 13422 1007152 ako027ako 15671 1173203
mabichito 12903 749391 Nikolay.IT 15154 1068349
thijsk 12886 722107 Andrew Grant 15114 895539
AdrianSA 12860 804972 OssumOpossum 14857 1007129
Flopzee 12698 894821 Karby 14808 867120
fatmurphy 12547 853210 AndreasKrug 14608 1152093
Rudolphous 12520 832340 enedene 14476 905279
scuzzi 12511 845761 jsys14 14340 844792
SapphireBrand 12416 969604 bpfliegel 14298 884523
modolief 12386 896470 mpx86 14019 759568
Machariel 12335 810784 jpulman 13982 870599
pgontarz 12151 848794 crocogoat 13803 1117422
stocky 11954 699440 joster 13794 950160
mschmidt 11941 803401 Nesa92 13786 1114691
Maxim 11543 836024 mbeier 13650 1044928
infinity 11470 727027 Hjax 13535 915487
torbjo 11395 729145 Dark_wizzie 13422 1007152
Thomas A. Anderson 11372 732094 Rudolphous 13244 883140
savage84 11358 670860 MarcusTullius 13221 843169
d64 11263 789184 Machariel 13010 863104
MooTheCow 11237 720174 mabichito 12903 749391
snicolet 11106 869170 thijsk 12886 722107
ali-al-zhrani 11086 767926 AdrianSA 12860 804972
AndreasKrug 10875 887457 infinigon 12807 937332
pirt 10806 836519 Flopzee 12698 894821
basepi 10637 744851 fatmurphy 12547 853210
michaelrpg 10508 739039 scuzzi 12511 845761
dzjp 10343 732529 SapphireBrand 12416 969604
aga 10302 622975 modolief 12386 896470
ols 10259 570669 Farseer 12249 694108
lbraesch 10252 647825 pgontarz 12151 848794
FormazChar 10059 757283 stocky 11954 699440
mschmidt 11941 803401
dbernier 11609 818636
Maxim 11543 836024
pirt 11516 894513
infinity 11470 727027
aga 11409 695071
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
markkulix 11331 739098
FormazChar 11308 847735
d64 11263 789184
MooTheCow 11237 720174
snicolet 11106 869170
ali-al-zhrani 11098 768494
whelanh 11067 235676
basepi 10637 744851
Cubox 10621 826448
michaelrpg 10509 739239
OIVAS7572 10420 995586
dzjp 10343 732529
Garruk 10332 703905
ols 10259 570669
lbraesch 10252 647825
Jackfish 10098 682338
-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 }
+111 -61
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
@@ -32,9 +50,9 @@ BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds ### Built-in benchmark for pgo-builds
ifeq ($(SDE_PATH),) ifeq ($(SDE_PATH),)
PGOBENCH = ./$(EXE) bench PGOBENCH = $(WINE_PATH) ./$(EXE) bench
else else
PGOBENCH = $(SDE_PATH) -- ./$(EXE) bench PGOBENCH = $(SDE_PATH) -- $(WINE_PATH) ./$(EXE) bench
endif endif
### Source and object files ### Source and object files
@@ -47,12 +65,6 @@ 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
### ========================================================================== ### ==========================================================================
@@ -78,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
@@ -101,8 +114,8 @@ 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 e2k \ 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))
SUPPORTED_ARCH=true SUPPORTED_ARCH=true
@@ -123,11 +136,13 @@ 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
mpi = no mpi = no
arm_version = 0
STRIP = strip STRIP = strip
### 2.2 Architecture specific ### 2.2 Architecture specific
@@ -139,7 +154,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
@@ -194,6 +209,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
@@ -264,6 +290,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)
@@ -272,6 +299,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)
@@ -279,6 +307,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)
@@ -286,6 +315,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)
@@ -349,29 +379,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 += -pedantic -Wextra -Wshadow
LDFLAGS += -static
endif endif
ifeq ($(COMP),icc) ifeq ($(COMP),icc)
@@ -383,17 +411,19 @@ 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) ifneq ($(RTLIB),compiler-rt)
LDFLAGS += -latomic LDFLAGS += -latomic
endif endif
endif endif
endif endif
endif
ifeq ($(arch),$(filter $(arch),armv7 armv8)) ifeq ($(arch),$(filter $(arch),armv7 armv8))
ifeq ($(OS),Android) ifeq ($(OS),Android)
@@ -425,11 +455,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
@@ -443,6 +481,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
@@ -503,11 +544,17 @@ 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
endif
ifeq ($(comp),gcc)
ifneq ($(arch),arm64)
CXXFLAGS += -mdynamic-no-pic
endif
endif
endif
ifeq ($(comp),clang) ifeq ($(comp),clang)
CXXFLAGS += -fexperimental-new-pass-manager CXXFLAGS += -fexperimental-new-pass-manager
@@ -546,6 +593,13 @@ ifeq ($(avx2),yes)
endif endif
endif endif
ifeq ($(avxvnni),yes)
CXXFLAGS += -DUSE_VNNI -DUSE_AVXVNNI
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavxvnni
endif
endif
ifeq ($(avx512),yes) ifeq ($(avx512),yes)
CXXFLAGS += -DUSE_AVX512 CXXFLAGS += -DUSE_AVX512
ifeq ($(comp),$(filter $(comp),gcc clang mingw)) ifeq ($(comp),$(filter $(comp),gcc clang mingw))
@@ -596,7 +650,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)
@@ -621,9 +675,7 @@ ifeq ($(optimize),yes)
ifeq ($(debug), no) ifeq ($(debug), no)
ifeq ($(comp),clang) ifeq ($(comp),clang)
CXXFLAGS += -flto CXXFLAGS += -flto
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)
@@ -634,25 +686,17 @@ ifeq ($(debug), no)
ifeq ($(gccisclang),) ifeq ($(gccisclang),)
CXXFLAGS += -flto CXXFLAGS += -flto
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
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)
ifneq ($(arch),i386) ifneq ($(arch),i386)
CXXFLAGS += -flto CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS) -flto=jobserver LDFLAGS += $(CXXFLAGS) -save-temps
endif
endif endif
endif endif
endif endif
@@ -700,6 +744,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"
@@ -762,7 +807,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
@@ -777,7 +822,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
@@ -809,15 +854,16 @@ net:
# 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.exe.lto_wrapper_args @rm -f stockfish.*args*
@rm -f stockfish.exe.ltrans.out @rm -f stockfish.*lt*
@rm -f stockfish.res
@rm -f ./-lstdc++.res @rm -f ./-lstdc++.res
default: default:
@@ -848,11 +894,13 @@ 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 "mpi: '$(mpi)'" @echo "mpi: '$(mpi)'"
@echo "arm_version: '$(arm_version)'"
@echo "" @echo ""
@echo "Flags:" @echo "Flags:"
@echo "CXX: $(CXX)" @echo "CXX: $(CXX)"
@@ -904,12 +952,14 @@ gcc-profile-make:
@mkdir -p profdir @mkdir -p profdir
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-generate=profdir' \ 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=profdir -fno-peel-loops -fno-tracer' \ EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
EXTRALDFLAGS='-lgcov' \ EXTRALDFLAGS='-lgcov' \
all all
+2 -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,6 +87,7 @@ 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"
}; };
+1 -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
+1 -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
+1 -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
+1 -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
+1 -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
+52 -34
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
@@ -109,6 +109,7 @@ 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))
@@ -196,8 +197,8 @@ using namespace Trace;
namespace { namespace {
// Threshold for lazy and space evaluation // Threshold for lazy and space evaluation
constexpr Value LazyThreshold1 = Value(3130); constexpr Value LazyThreshold1 = Value(3631);
constexpr Value LazyThreshold2 = Value(2204); constexpr Value LazyThreshold2 = Value(2084);
constexpr Value SpaceThreshold = Value(11551); constexpr Value SpaceThreshold = Value(11551);
// KingAttackWeights[PieceType] contains king attack weights by piece type // KingAttackWeights[PieceType] contains king attack weights by piece type
@@ -232,58 +233,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); 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 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
@@ -992,7 +993,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)) > lazyThreshold + pos.non_pawn_material() / 32; 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))
@@ -1071,8 +1074,8 @@ make_v:
&& pos.piece_on(SQ_G7) == B_PAWN) && pos.piece_on(SQ_G7) == B_PAWN)
correction += CorneredBishop; correction += CorneredBishop;
return pos.side_to_move() == WHITE ? Value(5 * correction) return pos.side_to_move() == WHITE ? Value(3 * correction)
: -Value(5 * correction); : -Value(3 * correction);
} }
} // namespace Eval } // namespace Eval
@@ -1084,27 +1087,37 @@ make_v:
Value Eval::evaluate(const Position& pos) { Value Eval::evaluate(const Position& pos) {
Value v; Value v;
bool useClassical = false;
// Deciding between classical and NNUE eval: for high PSQ imbalance we use classical, // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical,
// but we switch to NNUE during long shuffling or with high material on the board. // but we switch to NNUE during long shuffling or with high material on the board.
if ( !useNNUE if ( !useNNUE
|| abs(eg_value(pos.psq_score())) * 5 > (850 + pos.non_pawn_material() / 64) * (5 + pos.rule50_count())) || ((pos.this_thread()->depth > 9 || pos.count<ALL_PIECES>() > 7) &&
v = Evaluation<NO_TRACE>(pos).value(); // classical abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (5 + pos.rule50_count())))
else
{ {
int scale = 883 v = Evaluation<NO_TRACE>(pos).value(); // classical
+ 32 * pos.count<PAWN>() useClassical = abs(v) >= 297;
+ 32 * pos.non_pawn_material() / 1024; }
v = NNUE::evaluate(pos, true) * scale / 1024; // NNUE // If result of a classical evaluation is much lower than threshold fall back to NNUE
if (useNNUE && !useClassical)
{
Value nnue = NNUE::evaluate(pos, true); // NNUE
int scale = 1036 + 20 * pos.non_pawn_material() / 1024;
Color stm = pos.side_to_move();
Value optimism = pos.this_thread()->optimism[stm];
Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score());
int complexity = 35 * abs(nnue - psq) / 256;
optimism = optimism * (44 + complexity) / 31;
v = (nnue + optimism) * scale / 1024 - optimism;
if (pos.is_chess960()) if (pos.is_chess960())
v += fix_FRC(pos); v += fix_FRC(pos);
} }
// Damp down the evaluation linearly when shuffling // Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100; v = v * (207 - pos.rule50_count()) / 207;
// 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);
@@ -1129,7 +1142,12 @@ std::string Eval::trace(Position& pos) {
std::memset(scores, 0, sizeof(scores)); std::memset(scores, 0, sizeof(scores));
pos.this_thread()->trend = SCORE_ZERO; // Reset any dynamic contempt // Reset any global variable used in eval
pos.this_thread()->depth = 0;
pos.this_thread()->trend = SCORE_ZERO;
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();
+2 -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
@@ -39,7 +39,7 @@ namespace Eval {
// 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-13406b1dcbe0.nnue" #define EvalFileDefaultName "nn-6877cd24400e.nnue"
namespace NNUE { namespace NNUE {
+1 -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
+1 -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
+1 -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 -12
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
@@ -67,7 +69,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format /// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info. /// DD-MM-YY and show in engine_info.
const string Version = "14.1"; const string Version = "";
/// 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
@@ -495,11 +497,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;
@@ -513,7 +515,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;
@@ -521,7 +524,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);
@@ -571,22 +574,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
+34 -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
@@ -90,9 +90,6 @@ static inline const bool IsLittleEndian = (Le.c[0] == 4);
class RunningAverage { class RunningAverage {
public: public:
// Constructor
RunningAverage() {}
// Reset the running average to rational value p / q // Reset the running average to rational value p / q
void set(int64_t p, int64_t q) void set(int64_t p, int64_t q)
{ average = p * PERIOD * RESOLUTION / q; } { average = p * PERIOD * RESOLUTION / q; }
@@ -102,8 +99,11 @@ class RunningAverage {
{ average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; } { average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; }
// Test if average is strictly greater than rational a / b // Test if average is strictly greater than rational a / b
bool is_greater(int64_t a, int64_t b) bool is_greater(int64_t a, int64_t b) const
{ return b * average > a * PERIOD * RESOLUTION ; } { return b * average > a * (PERIOD * RESOLUTION); }
int64_t value() const
{ return average / (PERIOD * RESOLUTION); }
private : private :
static constexpr int64_t PERIOD = 4096; static constexpr int64_t PERIOD = 4096;
@@ -138,6 +138,34 @@ private:
std::size_t size_ = 0; std::size_t size_ = 0;
}; };
/// sigmoid(t, x0, y0, C, P, Q) implements a sigmoid-like function using only integers,
/// with the following properties:
///
/// - sigmoid is centered in (x0, y0)
/// - sigmoid has amplitude [-P/Q , P/Q] instead of [-1 , +1]
/// - limit is (y0 - P/Q) when t tends to -infinity
/// - limit is (y0 + P/Q) when t tends to +infinity
/// - the slope can be adjusted using C > 0, smaller C giving a steeper sigmoid
/// - the slope of the sigmoid when t = x0 is P/(Q*C)
/// - sigmoid is increasing with t when P > 0 and Q > 0
/// - to get a decreasing sigmoid, change sign of P
/// - mean value of the sigmoid is y0
///
/// Use <https://www.desmos.com/calculator/jhh83sqq92> to draw the sigmoid
inline int64_t sigmoid(int64_t t, int64_t x0,
int64_t y0,
int64_t C,
int64_t P,
int64_t Q)
{
assert(C > 0);
assert(Q != 0);
return y0 + P * (t-x0) / (Q * (std::abs(t-x0) + C)) ;
}
/// 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).
+1 -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
+1 -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
+55 -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
@@ -18,6 +18,7 @@
#include <cassert> #include <cassert>
#include "bitboard.h"
#include "movepick.h" #include "movepick.h"
namespace Stockfish { namespace Stockfish {
@@ -56,11 +57,14 @@ 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) +
@@ -69,9 +73,11 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
/// 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) +
@@ -82,9 +88,9 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
/// 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, Depth d, const CapturePieceToHistory* cph)
: pos(p), captureHistory(cph), ttMove(ttm), threshold(th) { : pos(p), captureHistory(cph), ttMove(ttm), threshold(th), depth(d)
{
assert(!pos.checkers()); assert(!pos.checkers());
stage = PROBCUT_TT + !(ttm && pos.capture(ttm) stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
@@ -100,10 +106,35 @@ void MovePicker::score() {
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
Bitboard threatened, threatenedByPawn, threatenedByMinor, threatenedByRook;
if constexpr (Type == QUIETS)
{
Color us = pos.side_to_move();
// squares threatened by pawns
threatenedByPawn = pos.attacks_by<PAWN>(~us);
// squares threatened by minors or pawns
threatenedByMinor = pos.attacks_by<KNIGHT>(~us) | pos.attacks_by<BISHOP>(~us) | threatenedByPawn;
// squares threatened by rooks, minors or pawns
threatenedByRook = pos.attacks_by<ROOK>(~us) | threatenedByMinor;
// pieces threatened by pieces of lesser material value
threatened = (pos.pieces(us, QUEEN) & threatenedByRook)
| (pos.pieces(us, ROOK) & threatenedByMinor)
| (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn);
}
else
{
// Silence unused variable warnings
(void) threatened;
(void) threatenedByPawn;
(void) threatenedByMinor;
(void) threatenedByRook;
}
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 = (*mainHistory)[pos.side_to_move()][from_to(m)]
@@ -111,7 +142,12 @@ void MovePicker::score() {
+ (*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 ? 6 * (*lowPlyHistory)[ply][from_to(m)] : 0); + (threatened & 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);
else // Type == EVASIONS else // Type == EVASIONS
{ {
@@ -165,11 +201,12 @@ top:
endMoves = generate<CAPTURES>(pos, cur); endMoves = generate<CAPTURES>(pos, cur);
score<CAPTURES>(); score<CAPTURES>();
partial_insertion_sort(cur, endMoves, -3000 * depth);
++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); }))
@@ -237,10 +274,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);
+7 -17
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
@@ -88,12 +88,6 @@ enum StatsType { NoCaptures, Captures };
/// 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, 14365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory; typedef Stats<int16_t, 14365, 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). LowPlyHistory is populated during
/// iterative deepening and at each new search the data is shifted down by 2 plies
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
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory; typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
@@ -123,18 +117,16 @@ 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, Depth, const CapturePieceToHistory*);
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Move,
const Move*,
int);
Move next_move(bool skipQuiets = false); Move next_move(bool skipQuiets = false);
private: private:
@@ -145,7 +137,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;
@@ -154,7 +145,6 @@ private:
Square recaptureSquare; Square recaptureSquare;
Value threshold; Value threshold;
Depth depth; Depth depth;
int ply;
ExtMove moves[MAX_MOVES]; ExtMove moves[MAX_MOVES];
}; };
+13 -25
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
@@ -109,7 +109,7 @@ namespace Stockfish::Eval::NNUE {
{ {
write_little_endian<std::uint32_t>(stream, Version); write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue); write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, desc.size()); write_little_endian<std::uint32_t>(stream, (std::uint32_t)desc.size());
stream.write(&desc[0], desc.size()); stream.write(&desc[0], desc.size());
return !stream.fail(); return !stream.fail();
} }
@@ -143,34 +143,29 @@ namespace Stockfish::Eval::NNUE {
// overaligning stack variables with alignas() doesn't work correctly. // overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize; constexpr uint64_t alignment = CacheLineSize;
int delta = 7; int delta = 10 - pos.non_pawn_material() / 1515;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned[ TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)]; FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
char bufferUnaligned[Network::BufferSize + alignment];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]); auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
#else #else
alignas(alignment) alignas(alignment)
TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize]; TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
alignas(alignment) char buffer[Network::BufferSize];
#endif #endif
ASSERT_ALIGNED(transformedFeatures, alignment); ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
const std::size_t bucket = (pos.count<ALL_PIECES>() - 1) / 4; const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto positional = network[bucket]->propagate(transformedFeatures, buffer)[0]; const auto positional = network[bucket]->propagate(transformedFeatures);
// Give more value to positional evaluation when material is balanced // Give more value to positional evaluation when adjusted flag is set
if ( adjusted if (adjusted)
&& abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK)) <= RookValueMg - BishopValueMg) return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
else else
return static_cast<Value>((psqt + positional) / OutputScale); return static_cast<Value>((psqt + positional) / OutputScale);
} }
struct NnueEvalTrace { struct NnueEvalTrace {
@@ -191,27 +186,20 @@ namespace Stockfish::Eval::NNUE {
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned[ TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)]; FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
char bufferUnaligned[Network::BufferSize + alignment];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]); auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
#else #else
alignas(alignment) alignas(alignment)
TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize]; TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
alignas(alignment) char buffer[Network::BufferSize];
#endif #endif
ASSERT_ALIGNED(transformedFeatures, alignment); ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
NnueEvalTrace t{}; NnueEvalTrace t{};
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4; t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) { for (IndexType bucket = 0; bucket < LayerStacks; ++bucket) {
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); const auto materialist = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto output = network[bucket]->propagate(transformedFeatures, buffer); const auto positional = network[bucket]->propagate(transformedFeatures);
int materialist = psqt;
int positional = output[0];
t.psqt[bucket] = static_cast<Value>( materialist / OutputScale ); t.psqt[bucket] = static_cast<Value>( materialist / OutputScale );
t.positional[bucket] = static_cast<Value>( positional / OutputScale ); t.positional[bucket] = static_cast<Value>( positional / OutputScale );
@@ -234,7 +222,7 @@ namespace Stockfish::Eval::NNUE {
{ {
buffer[1] = '0' + cp / 10000; cp %= 10000; buffer[1] = '0' + cp / 10000; cp %= 10000;
buffer[2] = '0' + cp / 1000; cp %= 1000; buffer[2] = '0' + cp / 1000; cp %= 1000;
buffer[3] = '0' + cp / 100; cp %= 100; buffer[3] = '0' + cp / 100;
buffer[4] = ' '; buffer[4] = ' ';
} }
else if (cp >= 1000) else if (cp >= 1000)
+1 -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
+1 -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
+1 -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
+78 -93
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
@@ -63,20 +63,17 @@ namespace Stockfish::Eval::NNUE::Layers {
{ {
# if defined(USE_SSE2) # if defined(USE_SSE2)
// At least a multiple of 16, with SSE2. // At least a multiple of 16, with SSE2.
static_assert(PaddedInputDimensions % 16 == 0); constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
constexpr IndexType NumChunks = PaddedInputDimensions / 16;
const __m128i Zeros = _mm_setzero_si128(); const __m128i Zeros = _mm_setzero_si128();
const auto inputVector = reinterpret_cast<const __m128i*>(input); const auto inputVector = reinterpret_cast<const __m128i*>(input);
# elif defined(USE_MMX) # elif defined(USE_MMX)
static_assert(InputDimensions % 8 == 0); constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / 8;
constexpr IndexType NumChunks = InputDimensions / 8;
const __m64 Zeros = _mm_setzero_si64(); const __m64 Zeros = _mm_setzero_si64();
const auto inputVector = reinterpret_cast<const __m64*>(input); const auto inputVector = reinterpret_cast<const __m64*>(input);
# elif defined(USE_NEON) # elif defined(USE_NEON)
static_assert(PaddedInputDimensions % 16 == 0); constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
constexpr IndexType NumChunks = PaddedInputDimensions / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input); const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
# endif # endif
@@ -151,24 +148,27 @@ namespace Stockfish::Eval::NNUE::Layers {
} }
#endif #endif
template <typename PreviousLayer, IndexType OutDims, typename Enabled = void> template <IndexType InDims, IndexType OutDims, typename Enabled = void>
class AffineTransform; class AffineTransform;
// A specialization for large inputs. // A specialization for large inputs.
template <typename PreviousLayer, IndexType OutDims> template <IndexType InDims, IndexType OutDims>
class AffineTransform<PreviousLayer, OutDims, std::enable_if_t<(PreviousLayer::OutputDimensions >= 2*64-1)>> { class AffineTransform<InDims, OutDims, std::enable_if_t<(ceil_to_multiple<IndexType>(InDims, MaxSimdWidth) >= 2*64)>> {
public: public:
// Input/output type // Input/output type
using InputType = typename PreviousLayer::OutputType; using InputType = std::uint8_t;
using OutputType = std::int32_t; using OutputType = std::int32_t;
static_assert(std::is_same<InputType, std::uint8_t>::value, "");
// Number of input/output dimensions // Number of input/output dimensions
static constexpr IndexType InputDimensions = PreviousLayer::OutputDimensions; static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = OutDims; static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions = static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth); ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
using OutputBuffer = OutputType[PaddedOutputDimensions];
static_assert(PaddedInputDimensions >= 128, "Something went wrong. This specialization should not have been chosen."); static_assert(PaddedInputDimensions >= 128, "Something went wrong. This specialization should not have been chosen.");
@@ -181,6 +181,9 @@ namespace Stockfish::Eval::NNUE::Layers {
#elif defined (USE_SSSE3) #elif defined (USE_SSSE3)
static constexpr const IndexType InputSimdWidth = 16; static constexpr const IndexType InputSimdWidth = 16;
static constexpr const IndexType MaxNumOutputRegs = 8; static constexpr const IndexType MaxNumOutputRegs = 8;
#elif defined (USE_NEON)
static constexpr const IndexType InputSimdWidth = 8;
static constexpr const IndexType MaxNumOutputRegs = 8;
#else #else
// The fallback implementation will not have permuted weights. // The fallback implementation will not have permuted weights.
// We define these to avoid a lot of ifdefs later. // We define these to avoid a lot of ifdefs later.
@@ -200,20 +203,12 @@ namespace Stockfish::Eval::NNUE::Layers {
static_assert(OutputDimensions % NumOutputRegs == 0); static_assert(OutputDimensions % NumOutputRegs == 0);
// Size of forward propagation buffer used in this layer
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() { static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u; std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions; hashValue += OutputDimensions;
hashValue ^= PreviousLayer::get_hash_value() >> 1; hashValue ^= prevHash >> 1;
hashValue ^= PreviousLayer::get_hash_value() << 31; hashValue ^= prevHash << 31;
return hashValue; return hashValue;
} }
@@ -240,11 +235,10 @@ namespace Stockfish::Eval::NNUE::Layers {
// Read network parameters // Read network parameters
bool read_parameters(std::istream& stream) { bool read_parameters(std::istream& stream) {
if (!previousLayer.read_parameters(stream)) return false; for (IndexType i = 0; i < OutputDimensions; ++i)
for (std::size_t i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream); biases[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream); weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail(); return !stream.fail();
@@ -252,11 +246,10 @@ namespace Stockfish::Eval::NNUE::Layers {
// Write network parameters // Write network parameters
bool write_parameters(std::ostream& stream) const { bool write_parameters(std::ostream& stream) const {
if (!previousLayer.write_parameters(stream)) return false; for (IndexType i = 0; i < OutputDimensions; ++i)
for (std::size_t i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]); write_little_endian<BiasType>(stream, biases[i]);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]); write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail(); return !stream.fail();
@@ -264,58 +257,66 @@ namespace Stockfish::Eval::NNUE::Layers {
// Forward propagation // Forward propagation
const OutputType* propagate( const OutputType* propagate(
const TransformedFeatureType* transformedFeatures, char* buffer) const { const InputType* input, OutputType* output) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
OutputType* output = reinterpret_cast<OutputType*>(buffer);
#if defined (USE_AVX512) #if defined (USE_AVX512)
using vec_t = __m512i; using acc_vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512 using bias_vec_t = __m128i;
#define vec_set_32 _mm512_set1_epi32 using weight_vec_t = __m512i;
#define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32 using in_vec_t = __m512i;
#define vec_zero _mm512_setzero_si512()
#define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2 #define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2
#define vec_hadd Simd::m512_hadd #define vec_hadd Simd::m512_hadd
#define vec_haddx4 Simd::m512_haddx4 #define vec_haddx4 Simd::m512_haddx4
#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;
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32 using in_vec_t = __m256i;
#define vec_zero _mm256_setzero_si256()
#define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2 #define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_hadd Simd::m256_hadd #define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4 #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;
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32 using in_vec_t = __m128i;
#define vec_zero _mm_setzero_si128()
#define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2 #define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_hadd Simd::m128_hadd #define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4 #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 vec_t* invec = reinterpret_cast<const vec_t*>(input); const in_vec_t* invec = reinterpret_cast<const in_vec_t*>(input);
// Perform accumulation to registers for each big block // Perform accumulation to registers for each big block
for (IndexType bigBlock = 0; bigBlock < NumBigBlocks; ++bigBlock) for (IndexType bigBlock = 0; bigBlock < NumBigBlocks; ++bigBlock)
{ {
vec_t acc[NumOutputRegs] = { vec_setzero() }; acc_vec_t acc[NumOutputRegs] = { vec_zero };
// Each big block has NumOutputRegs small blocks in each "row", one per register. // Each big block has NumOutputRegs small blocks in each "row", one per register.
// We process two small blocks at a time to save on one addition without VNNI. // We process two small blocks at a time to save on one addition without VNNI.
for (IndexType smallBlock = 0; smallBlock < NumSmallBlocksPerOutput; smallBlock += 2) for (IndexType smallBlock = 0; smallBlock < NumSmallBlocksPerOutput; smallBlock += 2)
{ {
const vec_t* weightvec = const weight_vec_t* weightvec =
reinterpret_cast<const vec_t*>( reinterpret_cast<const weight_vec_t*>(
weights weights
+ bigBlock * BigBlockSize + bigBlock * BigBlockSize
+ smallBlock * SmallBlockSize * NumOutputRegs); + smallBlock * SmallBlockSize * NumOutputRegs);
const vec_t in0 = invec[smallBlock + 0]; const in_vec_t in0 = invec[smallBlock + 0];
const vec_t in1 = invec[smallBlock + 1]; const in_vec_t in1 = invec[smallBlock + 1];
for (IndexType k = 0; k < NumOutputRegs; ++k) for (IndexType k = 0; k < NumOutputRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, weightvec[k], in1, weightvec[k + NumOutputRegs]); vec_add_dpbusd_32x2(acc[k], in0, weightvec[k], in1, weightvec[k + NumOutputRegs]);
@@ -324,8 +325,8 @@ namespace Stockfish::Eval::NNUE::Layers {
// Horizontally add all accumulators. // Horizontally add all accumulators.
if constexpr (NumOutputRegs % 4 == 0) if constexpr (NumOutputRegs % 4 == 0)
{ {
__m128i* outputvec = reinterpret_cast<__m128i*>(output); bias_vec_t* outputvec = reinterpret_cast<bias_vec_t*>(output);
const __m128i* biasvec = reinterpret_cast<const __m128i*>(biases); const bias_vec_t* biasvec = reinterpret_cast<const bias_vec_t*>(biases);
for (IndexType k = 0; k < NumOutputRegs; k += 4) for (IndexType k = 0; k < NumOutputRegs; k += 4)
{ {
@@ -343,9 +344,7 @@ namespace Stockfish::Eval::NNUE::Layers {
} }
} }
# undef vec_setzero # undef vec_zero
# undef vec_set_32
# undef vec_add_dpbusd_32
# undef vec_add_dpbusd_32x2 # undef vec_add_dpbusd_32x2
# undef vec_hadd # undef vec_hadd
# undef vec_haddx4 # undef vec_haddx4
@@ -365,26 +364,28 @@ namespace Stockfish::Eval::NNUE::Layers {
using BiasType = OutputType; using BiasType = OutputType;
using WeightType = std::int8_t; using WeightType = std::int8_t;
PreviousLayer previousLayer;
alignas(CacheLineSize) BiasType biases[OutputDimensions]; alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions]; alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
}; };
template <typename PreviousLayer, IndexType OutDims> template <IndexType InDims, IndexType OutDims>
class AffineTransform<PreviousLayer, OutDims, std::enable_if_t<(PreviousLayer::OutputDimensions < 2*64-1)>> { class AffineTransform<InDims, OutDims, std::enable_if_t<(ceil_to_multiple<IndexType>(InDims, MaxSimdWidth) < 2*64)>> {
public: public:
// Input/output type // Input/output type
using InputType = typename PreviousLayer::OutputType; // Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t; using OutputType = std::int32_t;
static_assert(std::is_same<InputType, std::uint8_t>::value, "");
// Number of input/output dimensions // Number of input/output dimensions
static constexpr IndexType InputDimensions = static constexpr IndexType InputDimensions = InDims;
PreviousLayer::OutputDimensions;
static constexpr IndexType OutputDimensions = OutDims; static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions = static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth); ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
using OutputBuffer = OutputType[PaddedOutputDimensions];
static_assert(PaddedInputDimensions < 128, "Something went wrong. This specialization should not have been chosen."); static_assert(PaddedInputDimensions < 128, "Something went wrong. This specialization should not have been chosen.");
@@ -393,20 +394,12 @@ namespace Stockfish::Eval::NNUE::Layers {
static constexpr const IndexType InputSimdWidth = SimdWidth; static constexpr const IndexType InputSimdWidth = SimdWidth;
#endif #endif
// Size of forward propagation buffer used in this layer
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() { static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u; std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions; hashValue += OutputDimensions;
hashValue ^= PreviousLayer::get_hash_value() >> 1; hashValue ^= prevHash >> 1;
hashValue ^= PreviousLayer::get_hash_value() << 31; hashValue ^= prevHash << 31;
return hashValue; return hashValue;
} }
@@ -429,10 +422,9 @@ namespace Stockfish::Eval::NNUE::Layers {
// Read network parameters // Read network parameters
bool read_parameters(std::istream& stream) { bool read_parameters(std::istream& stream) {
if (!previousLayer.read_parameters(stream)) return false; for (IndexType i = 0; i < OutputDimensions; ++i)
for (std::size_t i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream); biases[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream); weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail(); return !stream.fail();
@@ -440,21 +432,17 @@ namespace Stockfish::Eval::NNUE::Layers {
// Write network parameters // Write network parameters
bool write_parameters(std::ostream& stream) const { bool write_parameters(std::ostream& stream) const {
if (!previousLayer.write_parameters(stream)) return false; for (IndexType i = 0; i < OutputDimensions; ++i)
for (std::size_t i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]); write_little_endian<BiasType>(stream, biases[i]);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(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* transformedFeatures, char* buffer) const { const InputType* input, OutputType* output) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
#if defined (USE_AVX2) #if defined (USE_AVX2)
using vec_t = __m256i; using vec_t = __m256i;
@@ -479,12 +467,11 @@ namespace Stockfish::Eval::NNUE::Layers {
#if defined (USE_SSSE3) #if defined (USE_SSSE3)
const auto inputVector = reinterpret_cast<const vec_t*>(input); const auto inputVector = reinterpret_cast<const vec_t*>(input);
static_assert(InputDimensions % 8 == 0);
static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1); static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1);
if constexpr (OutputDimensions % OutputSimdWidth == 0) if constexpr (OutputDimensions % OutputSimdWidth == 0)
{ {
constexpr IndexType NumChunks = InputDimensions / 4; constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / 4;
constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth; constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth;
const auto input32 = reinterpret_cast<const std::int32_t*>(input); const auto input32 = reinterpret_cast<const std::int32_t*>(input);
@@ -543,8 +530,6 @@ namespace Stockfish::Eval::NNUE::Layers {
using BiasType = OutputType; using BiasType = OutputType;
using WeightType = std::int8_t; using WeightType = std::int8_t;
PreviousLayer previousLayer;
alignas(CacheLineSize) BiasType biases[OutputDimensions]; alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions]; alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
}; };
+12 -33
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,51 +26,41 @@
namespace Stockfish::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 InputDimensions = PreviousLayer::OutputDimensions; static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = InputDimensions; static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions = static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32); ceil_to_multiple<IndexType>(OutputDimensions, 32);
// Size of forward propagation buffer used in this layer using OutputBuffer = OutputType[PaddedOutputDimensions];
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() { static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u; std::uint32_t hashValue = 0x538D24C7u;
hashValue += PreviousLayer::get_hash_value(); hashValue += prevHash;
return hashValue; return hashValue;
} }
// Read network parameters // Read network parameters
bool read_parameters(std::istream& stream) { bool read_parameters(std::istream&) {
return previousLayer.read_parameters(stream); return true;
} }
// Write network parameters // Write network parameters
bool write_parameters(std::ostream& stream) const { bool write_parameters(std::ostream&) const {
return previousLayer.write_parameters(stream); return true;
} }
// Forward propagation // Forward propagation
const OutputType* propagate( const OutputType* propagate(
const TransformedFeatureType* transformedFeatures, char* buffer) const { const InputType* input, OutputType* output) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
#if defined(USE_AVX2) #if defined(USE_AVX2)
if constexpr (InputDimensions % SimdWidth == 0) { if constexpr (InputDimensions % SimdWidth == 0) {
@@ -181,19 +171,8 @@ namespace Stockfish::Eval::NNUE::Layers {
std::max(0, std::min(127, input[i] >> WeightScaleBits))); std::max(0, std::min(127, input[i] >> WeightScaleBits)));
} }
// Affine transform layers expect that there is at least
// ceil_to_multiple(OutputDimensions, 32) initialized values.
// We cannot do this in the affine transform because it requires
// preallocating space here.
for (IndexType i = OutputDimensions; i < PaddedOutputDimensions; ++i) {
output[i] = 0;
}
return output; return output;
} }
private:
PreviousLayer previousLayer;
}; };
} // namespace Stockfish::Eval::NNUE::Layers } // namespace Stockfish::Eval::NNUE::Layers
-73
View File
@@ -1,73 +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 Stockfish::Eval::NNUE::Layers {
// Input layer
template <IndexType OutDims, IndexType Offset = 0>
class InputSlice {
public:
// Need to maintain alignment
static_assert(Offset % MaxSimdWidth == 0, "");
// Output type
using OutputType = TransformedFeatureType;
// Output dimensionality
static constexpr IndexType OutputDimensions = OutDims;
// Size of forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize = 0;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
std::uint32_t hashValue = 0xEC42E90Du;
hashValue ^= OutputDimensions ^ (Offset << 10);
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream& /*stream*/) {
return true;
}
// Write network parameters
bool write_parameters(std::ostream& /*stream*/) const {
return true;
}
// Forward propagation
const OutputType* propagate(
const TransformedFeatureType* transformedFeatures,
char* /*buffer*/) const {
return transformedFeatures + Offset;
}
private:
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
+1 -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
+92 -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
@@ -21,39 +21,112 @@
#ifndef NNUE_ARCHITECTURE_H_INCLUDED #ifndef NNUE_ARCHITECTURE_H_INCLUDED
#define NNUE_ARCHITECTURE_H_INCLUDED #define NNUE_ARCHITECTURE_H_INCLUDED
#include <memory>
#include "nnue_common.h" #include "nnue_common.h"
#include "features/half_ka_v2_hm.h" #include "features/half_ka_v2_hm.h"
#include "layers/input_slice.h"
#include "layers/affine_transform.h" #include "layers/affine_transform.h"
#include "layers/clipped_relu.h" #include "layers/clipped_relu.h"
#include "../misc.h"
namespace Stockfish::Eval::NNUE { namespace Stockfish::Eval::NNUE {
// Input features used in evaluation function // Input features used in evaluation function
using FeatureSet = Features::HalfKAv2_hm; using FeatureSet = Features::HalfKAv2_hm;
// Number of input feature dimensions after conversion // Number of input feature dimensions after conversion
constexpr IndexType TransformedFeatureDimensions = 1024; constexpr IndexType TransformedFeatureDimensions = 1024;
constexpr IndexType PSQTBuckets = 8; constexpr IndexType PSQTBuckets = 8;
constexpr IndexType LayerStacks = 8; constexpr IndexType LayerStacks = 8;
namespace Layers { struct Network
{
static constexpr int FC_0_OUTPUTS = 15;
static constexpr int FC_1_OUTPUTS = 32;
// Define network structure Layers::AffineTransform<TransformedFeatureDimensions, FC_0_OUTPUTS + 1> fc_0;
using InputLayer = InputSlice<TransformedFeatureDimensions * 2>; Layers::ClippedReLU<FC_0_OUTPUTS + 1> ac_0;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 8>>; Layers::AffineTransform<FC_0_OUTPUTS, FC_1_OUTPUTS> fc_1;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; Layers::ClippedReLU<FC_1_OUTPUTS> ac_1;
using OutputLayer = AffineTransform<HiddenLayer2, 1>; Layers::AffineTransform<FC_1_OUTPUTS, 1> fc_2;
} // namespace Layers // 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;
using Network = Layers::OutputLayer; 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);
static_assert(TransformedFeatureDimensions % MaxSimdWidth == 0, ""); return hashValue;
static_assert(Network::OutputDimensions == 1, ""); }
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
// 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_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_0.propagate(buffer.fc_0_out, buffer.ac_0_out);
fc_1.propagate(buffer.ac_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 } // namespace Stockfish::Eval::NNUE
+4 -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
@@ -109,7 +109,7 @@ namespace Stockfish::Eval::NNUE {
// write_little_endian() is our utility to write an integer (signed or unsigned, any size) // 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 // to a stream in little-endian order. We swap the byte order before the write if
// necessary to always write in little endian order, independantly of the byte // necessary to always write in little endian order, independently of the byte
// ordering of the compiling machine. // ordering of the compiling machine.
template <typename IntType> template <typename IntType>
inline void write_little_endian(std::ostream& stream, IntType value) { inline void write_little_endian(std::ostream& stream, IntType value) {
@@ -127,11 +127,11 @@ namespace Stockfish::Eval::NNUE {
{ {
for (; i + 1 < sizeof(IntType); ++i) for (; i + 1 < sizeof(IntType); ++i)
{ {
u[i] = v; u[i] = (std::uint8_t)v;
v >>= 8; v >>= 8;
} }
} }
u[i] = v; u[i] = (std::uint8_t)v;
stream.write(reinterpret_cast<char*>(u), sizeof(IntType)); stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
} }
+98 -124
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
@@ -47,12 +47,22 @@ namespace Stockfish::Eval::NNUE {
#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)
#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_load_psqt(a) _mm256_load_si256(a)
#define vec_store_psqt(a,b) _mm256_store_si256(a,b) #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_add_psqt_32(a,b) _mm256_add_epi32(a,b)
#define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b) #define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b)
#define vec_zero_psqt() _mm256_setzero_si256() #define vec_zero_psqt() _mm256_setzero_si256()
#define NumRegistersSIMD 32 #define NumRegistersSIMD 32
#define MaxChunkSize 64
#elif USE_AVX2 #elif USE_AVX2
typedef __m256i vec_t; typedef __m256i vec_t;
@@ -61,12 +71,22 @@ namespace Stockfish::Eval::NNUE {
#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)
#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_load_psqt(a) _mm256_load_si256(a)
#define vec_store_psqt(a,b) _mm256_store_si256(a,b) #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_add_psqt_32(a,b) _mm256_add_epi32(a,b)
#define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b) #define vec_sub_psqt_32(a,b) _mm256_sub_epi32(a,b)
#define vec_zero_psqt() _mm256_setzero_si256() #define vec_zero_psqt() _mm256_setzero_si256()
#define NumRegistersSIMD 16 #define NumRegistersSIMD 16
#define MaxChunkSize 32
#elif USE_SSE2 #elif USE_SSE2
typedef __m128i vec_t; typedef __m128i vec_t;
@@ -75,12 +95,19 @@ namespace Stockfish::Eval::NNUE {
#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)
#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_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b) #define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) _mm_add_epi32(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_sub_psqt_32(a,b) _mm_sub_epi32(a,b)
#define vec_zero_psqt() _mm_setzero_si128() #define vec_zero_psqt() _mm_setzero_si128()
#define NumRegistersSIMD (Is64Bit ? 16 : 8) #define NumRegistersSIMD (Is64Bit ? 16 : 8)
#define MaxChunkSize 16
#elif USE_MMX #elif USE_MMX
typedef __m64 vec_t; typedef __m64 vec_t;
@@ -89,12 +116,26 @@ namespace Stockfish::Eval::NNUE {
#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)
#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_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b) #define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) _mm_add_pi32(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_sub_psqt_32(a,b) _mm_sub_pi32(a,b)
#define vec_zero_psqt() _mm_setzero_si64() #define vec_zero_psqt() _mm_setzero_si64()
#define vec_cleanup() _mm_empty()
#define NumRegistersSIMD 8 #define NumRegistersSIMD 8
#define MaxChunkSize 8
#elif USE_NEON #elif USE_NEON
typedef int16x8_t vec_t; typedef int16x8_t vec_t;
@@ -103,12 +144,24 @@ namespace Stockfish::Eval::NNUE {
#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)
#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_load_psqt(a) (*(a))
#define vec_store_psqt(a,b) *(a)=(b) #define vec_store_psqt(a,b) *(a)=(b)
#define vec_add_psqt_32(a,b) vaddq_s32(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_sub_psqt_32(a,b) vsubq_s32(a,b)
#define vec_zero_psqt() psqt_vec_t{0} #define vec_zero_psqt() psqt_vec_t{0}
#define NumRegistersSIMD 16 #define NumRegistersSIMD 16
#define MaxChunkSize 16
#else #else
#undef VECTOR #undef VECTOR
@@ -123,8 +176,10 @@ namespace Stockfish::Eval::NNUE {
// We use __m* types as template arguments, which causes GCC to emit warnings // 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 // about losing some attribute information. This is irrelevant to us as we
// only take their size, so the following pragma are harmless. // only take their size, so the following pragma are harmless.
#if defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes" #pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
template <typename SIMDRegisterType, template <typename SIMDRegisterType,
typename LaneType, typename LaneType,
@@ -156,9 +211,9 @@ namespace Stockfish::Eval::NNUE {
static constexpr int NumRegs = BestRegisterCount<vec_t, WeightType, TransformedFeatureDimensions, NumRegistersSIMD>(); static constexpr int NumRegs = BestRegisterCount<vec_t, WeightType, TransformedFeatureDimensions, NumRegistersSIMD>();
static constexpr int NumPsqtRegs = BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>(); static constexpr int NumPsqtRegs = BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>();
#if defined(__GNUC__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif
#endif #endif
@@ -183,7 +238,7 @@ namespace Stockfish::Eval::NNUE {
// Number of input/output dimensions // Number of input/output dimensions
static constexpr IndexType InputDimensions = FeatureSet::Dimensions; static constexpr IndexType InputDimensions = FeatureSet::Dimensions;
static constexpr IndexType OutputDimensions = HalfDimensions * 2; static constexpr IndexType OutputDimensions = HalfDimensions;
// Size of forward propagation buffer // Size of forward propagation buffer
static constexpr std::size_t BufferSize = static constexpr std::size_t BufferSize =
@@ -191,7 +246,7 @@ namespace Stockfish::Eval::NNUE {
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() { static constexpr std::uint32_t get_hash_value() {
return FeatureSet::HashValue ^ OutputDimensions; return FeatureSet::HashValue ^ (OutputDimensions * 2);
} }
// Read network parameters // Read network parameters
@@ -229,136 +284,55 @@ namespace Stockfish::Eval::NNUE {
) / 2; ) / 2;
#if defined(USE_AVX512)
constexpr IndexType NumChunks = HalfDimensions / (SimdWidth * 2);
static_assert(HalfDimensions % (SimdWidth * 2) == 0);
const __m512i Control = _mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7);
const __m512i Zero = _mm512_setzero_si512();
for (IndexType p = 0; p < 2; ++p) for (IndexType p = 0; p < 2; ++p)
{ {
const IndexType offset = HalfDimensions * p; const IndexType offset = (HalfDimensions / 2) * p;
auto out = reinterpret_cast<__m512i*>(&output[offset]);
for (IndexType j = 0; j < NumChunks; ++j) #if defined(VECTOR)
constexpr IndexType OutputChunkSize = MaxChunkSize;
static_assert((HalfDimensions / 2) % OutputChunkSize == 0);
constexpr IndexType NumOutputChunks = HalfDimensions / 2 / OutputChunkSize;
vec_t Zero = vec_zero();
vec_t One = vec_set_16(127);
const vec_t* in0 = reinterpret_cast<const vec_t*>(&(accumulation[perspectives[p]][0]));
const vec_t* in1 = reinterpret_cast<const vec_t*>(&(accumulation[perspectives[p]][HalfDimensions / 2]));
vec_t* out = reinterpret_cast< vec_t*>(output + offset);
for (IndexType j = 0; j < NumOutputChunks; j += 1)
{ {
__m512i sum0 = _mm512_load_si512(&reinterpret_cast<const __m512i*> const vec_t sum0a = vec_max_16(vec_min_16(in0[j * 2 + 0], One), Zero);
(accumulation[perspectives[p]])[j * 2 + 0]); const vec_t sum0b = vec_max_16(vec_min_16(in0[j * 2 + 1], One), Zero);
__m512i sum1 = _mm512_load_si512(&reinterpret_cast<const __m512i*> const vec_t sum1a = vec_max_16(vec_min_16(in1[j * 2 + 0], One), Zero);
(accumulation[perspectives[p]])[j * 2 + 1]); const vec_t sum1b = vec_max_16(vec_min_16(in1[j * 2 + 1], One), Zero);
_mm512_store_si512(&out[j], _mm512_permutexvar_epi64(Control, const vec_t pa = vec_mul_16(sum0a, sum1a);
_mm512_max_epi8(_mm512_packs_epi16(sum0, sum1), Zero))); const vec_t pb = vec_mul_16(sum0b, sum1b);
out[j] = vec_msb_pack_16(pa, pb);
} }
}
return psqt;
#elif defined(USE_AVX2) #else
constexpr IndexType NumChunks = HalfDimensions / SimdWidth; for (IndexType j = 0; j < HalfDimensions / 2; ++j) {
constexpr int Control = 0b11011000; BiasType sum0 = accumulation[static_cast<int>(perspectives[p])][j + 0];
const __m256i Zero = _mm256_setzero_si256(); BiasType sum1 = accumulation[static_cast<int>(perspectives[p])][j + HalfDimensions / 2];
sum0 = std::max<int>(0, std::min<int>(127, sum0));
for (IndexType p = 0; p < 2; ++p) sum1 = std::max<int>(0, std::min<int>(127, sum1));
{ output[offset + j] = static_cast<OutputType>(sum0 * sum1 / 128);
const IndexType offset = HalfDimensions * p;
auto out = reinterpret_cast<__m256i*>(&output[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
__m256i sum0 = _mm256_load_si256(&reinterpret_cast<const __m256i*>
(accumulation[perspectives[p]])[j * 2 + 0]);
__m256i sum1 = _mm256_load_si256(&reinterpret_cast<const __m256i*>
(accumulation[perspectives[p]])[j * 2 + 1]);
_mm256_store_si256(&out[j], _mm256_permute4x64_epi64(
_mm256_max_epi8(_mm256_packs_epi16(sum0, sum1), Zero), Control));
} }
#endif
} }
#if defined(vec_cleanup)
vec_cleanup();
#endif
return psqt; return psqt;
#elif defined(USE_SSE2)
#ifdef USE_SSE41
constexpr IndexType NumChunks = HalfDimensions / SimdWidth;
const __m128i Zero = _mm_setzero_si128();
#else
constexpr IndexType NumChunks = HalfDimensions / SimdWidth;
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
for (IndexType p = 0; p < 2; ++p)
{
const IndexType offset = HalfDimensions * p;
auto out = reinterpret_cast<__m128i*>(&output[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
__m128i sum0 = _mm_load_si128(&reinterpret_cast<const __m128i*>
(accumulation[perspectives[p]])[j * 2 + 0]);
__m128i sum1 = _mm_load_si128(&reinterpret_cast<const __m128i*>
(accumulation[perspectives[p]])[j * 2 + 1]);
const __m128i packedbytes = _mm_packs_epi16(sum0, sum1);
#ifdef USE_SSE41
_mm_store_si128(&out[j], _mm_max_epi8(packedbytes, Zero));
#else
_mm_store_si128(&out[j], _mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s));
#endif
}
}
return psqt;
#elif defined(USE_MMX)
constexpr IndexType NumChunks = HalfDimensions / SimdWidth;
const __m64 k0x80s = _mm_set1_pi8(-128);
for (IndexType p = 0; p < 2; ++p)
{
const IndexType offset = HalfDimensions * p;
auto out = reinterpret_cast<__m64*>(&output[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
__m64 sum0 = *(&reinterpret_cast<const __m64*>(accumulation[perspectives[p]])[j * 2 + 0]);
__m64 sum1 = *(&reinterpret_cast<const __m64*>(accumulation[perspectives[p]])[j * 2 + 1]);
const __m64 packedbytes = _mm_packs_pi16(sum0, sum1);
out[j] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
}
}
_mm_empty();
return psqt;
#elif defined(USE_NEON)
constexpr IndexType NumChunks = HalfDimensions / (SimdWidth / 2);
const int8x8_t Zero = {0};
for (IndexType p = 0; p < 2; ++p)
{
const IndexType offset = HalfDimensions * p;
const auto out = reinterpret_cast<int8x8_t*>(&output[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
int16x8_t sum = reinterpret_cast<const int16x8_t*>(accumulation[perspectives[p]])[j];
out[j] = vmax_s8(vqmovn_s16(sum), Zero);
}
}
return psqt;
#else
for (IndexType p = 0; p < 2; ++p)
{
const IndexType offset = HalfDimensions * p;
for (IndexType j = 0; j < HalfDimensions; ++j)
{
BiasType sum = accumulation[perspectives[p]][j];
output[offset + j] = static_cast<OutputType>(std::max<int>(0, std::min<int>(127, sum)));
}
}
return psqt;
#endif
} // end of function transform() } // end of function transform()
+1 -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
+1 -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
+1 -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
+18 -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
@@ -120,12 +120,12 @@ public:
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;
Piece moved_piece(Move m) const; Piece moved_piece(Move m) const;
Piece captured_piece() const; Piece captured_piece() const;
@@ -285,6 +285,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;
} }
@@ -352,11 +368,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"
+1 -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
+1 -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
+277 -290
View File
File diff suppressed because it is too large Load Diff
+2 -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
@@ -74,6 +74,7 @@ struct RootMove {
Value score = -VALUE_INFINITE; Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE; Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
int selDepth = 0; int selDepth = 0;
int tbRank = 0; int tbRank = 0;
Value tbScore; Value tbScore;
+50 -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
@@ -46,6 +46,13 @@
#define USE_INLINE_ASM #define USE_INLINE_ASM
#endif #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 { namespace Stockfish::Simd {
#if defined (USE_AVX512) #if defined (USE_AVX512)
@@ -208,7 +215,7 @@ namespace Stockfish::Simd {
# if defined (USE_VNNI) # if defined (USE_VNNI)
# if defined (USE_INLINE_ASM) # if defined (USE_INLINE_ASM)
asm( asm(
"vpdpbusd %[b], %[a], %[acc]\n\t" VNNI_PREFIX "vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc) : [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b) : [a]"v"(a), [b]"vm"(b)
); );
@@ -240,8 +247,8 @@ namespace Stockfish::Simd {
# if defined (USE_VNNI) # if defined (USE_VNNI)
# if defined (USE_INLINE_ASM) # if defined (USE_INLINE_ASM)
asm( asm(
"vpdpbusd %[b0], %[a0], %[acc]\n\t" VNNI_PREFIX "vpdpbusd %[b0], %[a0], %[acc]\n\t"
"vpdpbusd %[b1], %[a1], %[acc]\n\t" VNNI_PREFIX "vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc) : [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1) : [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
); );
@@ -336,6 +343,45 @@ namespace Stockfish::Simd {
#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 #endif // STOCKFISH_SIMD_H_INCLUDED
+11 -11
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
@@ -770,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)
@@ -813,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) {
@@ -828,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]))
@@ -858,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])
@@ -886,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[].
// //
@@ -918,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
@@ -938,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];
@@ -948,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) {
@@ -1318,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;
@@ -1338,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;
+2 -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
@@ -38,7 +38,7 @@ enum WDLScore {
// 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)
}; };
+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
@@ -59,7 +59,6 @@ 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);
for (bool inCheck : { false, true }) for (bool inCheck : { false, true })
@@ -67,7 +66,7 @@ void Thread::clear() {
{ {
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); continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
} }
} }
@@ -165,6 +164,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;
} }
+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
@@ -61,21 +61,19 @@ public:
Pawns::Table pawnsTable; Pawns::Table pawnsTable;
Material::Table materialTable; Material::Table materialTable;
size_t pvIdx, pvLast; size_t pvIdx, pvLast;
RunningAverage doubleExtensionAverage[COLOR_NB]; RunningAverage complexityAverage;
uint64_t nodesLastExplosive;
uint64_t nodesLastNormal;
std::atomic<uint64_t> nodes, tbHits, TTsaves, bestMoveChanges; std::atomic<uint64_t> nodes, tbHits, TTsaves, bestMoveChanges;
int selDepth, nmpMinPly; int selDepth, nmpMinPly;
Color nmpColor; Color nmpColor;
ExplosionState state; 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, depth;
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 trend; Score trend;
@@ -99,6 +97,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;
+1 -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
+1 -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
+1 -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
+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
@@ -40,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);
+1 -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
+1 -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
+2 -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
@@ -84,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;
+1 -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
@@ -173,11 +173,6 @@ enum Bound {
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
}; };
enum ExplosionState {
EXPLOSION_NONE,
MUST_CALM_DOWN
};
enum Value : int { enum Value : int {
VALUE_ZERO = 0, VALUE_ZERO = 0,
VALUE_DRAW = 0, VALUE_DRAW = 0,
@@ -470,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);
+1 -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
+1 -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
+1 -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
+1 -1
View File
@@ -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