Merge branch 'upstream/master' (4c7de9e8ab) into tools

This commit is contained in:
Tomasz Sobczyk
2022-05-30 12:07:07 +02:00
60 changed files with 2394 additions and 1784 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
@@ -19,6 +20,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,
@@ -34,18 +41,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}'
} }
@@ -54,33 +74,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}'
} }
@@ -97,14 +121,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: |
@@ -117,6 +141,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
@@ -238,6 +263,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
+12 -1
View File
@@ -1,4 +1,4 @@
# List of authors for Stockfish, as of June 14, 2021 # List of authors for Stockfish
# Founders of the Stockfish project and fishtest infrastructure # Founders of the Stockfish project and fishtest infrastructure
Tord Romstad (romstad) Tord Romstad (romstad)
@@ -21,6 +21,7 @@ Alexander Kure
Alexander Pagel (Lolligerhans) Alexander Pagel (Lolligerhans)
Alfredo Menezes (lonfom169) Alfredo Menezes (lonfom169)
Ali AlZhrani (Cooffe) Ali AlZhrani (Cooffe)
Andrei Vetrov (proukornew)
Andrew Grant (AndyGrant) Andrew Grant (AndyGrant)
Andrey Neporada (nepal) Andrey Neporada (nepal)
Andy Duplain Andy Duplain
@@ -30,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)
@@ -53,6 +55,7 @@ DiscanX
Dominik Schlösser (domschl) Dominik Schlösser (domschl)
double-beep double-beep
Douglas Matos Gomes (dsmsgms) Douglas Matos Gomes (dsmsgms)
Dubslow
Eduardo Cáceres (eduherminio) Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender) Eelco de Groot (KingDefender)
Elvin Liu (solarlight2) Elvin Liu (solarlight2)
@@ -102,6 +105,7 @@ jundery
Justin Blanchard (UncombedCoconut) Justin Blanchard (UncombedCoconut)
Kelly Wilson Kelly Wilson
Ken Takusagawa Ken Takusagawa
Kian E (KJE-98)
kinderchocolate kinderchocolate
Kiran Panditrao (Krgp) Kiran Panditrao (Krgp)
Kojirion Kojirion
@@ -122,6 +126,7 @@ marotear
Matt Ginsberg (mattginsberg) Matt Ginsberg (mattginsberg)
Matthew Lai (matthewlai) Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916) Matthew Sullivan (Matt14916)
Max A. (Disservin)
Maxim Molchanov (Maxim) Maxim Molchanov (Maxim)
Michael An (man) Michael An (man)
Michael Byrne (MichaelB7) Michael Byrne (MichaelB7)
@@ -131,6 +136,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)
@@ -143,6 +149,7 @@ Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham) Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather) Norman Schmidt (FireFather)
notruck notruck
Ofek Shochat (OfekShochat, ghostway)
Ondrej Mosnáček (WOnder93) Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin Oskar Werkelin Ahlin
Pablo Vazquez Pablo Vazquez
@@ -151,6 +158,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)
@@ -163,6 +171,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)
@@ -186,11 +195,13 @@ Tom Truscott
Tom Vijlbrief (tomtor) Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97) Tomasz Sobczyk (Sopel97)
Torsten Franz (torfranz, tfranzer) Torsten Franz (torfranz, tfranzer)
Torsten Hellwig (Torom)
Tracey Emery (basepr1me) Tracey Emery (basepr1me)
tttak tttak
Unai Corzo (unaiic) Unai Corzo (unaiic)
Uri Blass (uriblass) Uri Blass (uriblass)
Vince Negri (cuddlestmonkey) Vince Negri (cuddlestmonkey)
xefoci7612
zz4032 zz4032
+42 -33
View File
@@ -1,7 +1,6 @@
## Overview ## Overview
[![Build Status](https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml/badge.svg)](https://github.com/official-stockfish/Stockfish/actions) [![Build Status](https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml/badge.svg)](https://github.com/official-stockfish/Stockfish/actions)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master)
[Stockfish](https://stockfishchess.org) is a free, powerful UCI chess engine [Stockfish](https://stockfishchess.org) is a free, powerful UCI chess engine
derived from Glaurung 2.1. Stockfish is not a complete chess program and requires a derived from Glaurung 2.1. Stockfish is not a complete chess program and requires a
@@ -10,24 +9,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 +40,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 +71,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 +106,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 +141,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.
@@ -210,22 +214,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
``` ```
@@ -353,10 +362,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).
+233 -203
View File
@@ -1,205 +1,235 @@
Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021. Contributors to Fishtest with >10,000 CPU hours, as of 2022-04-14.
Thank you! Thank you!
Username CPU Hours Games played Username CPU Hours Games played
----------------------------------------------------- ------------------------------------------------------------------
noobpwnftw 27649494 1834734733 noobpwnftw 31714850 2267266129
mlang 1426107 89454622 mlang 2954099 198421098
dew 1380910 82831648 technologov 2324150 102449398
mibere 703840 46867607 dew 1670874 99276012
grandphish2 692707 41737913 grandphish2 1134273 68070459
tvijlbrief 669642 42371594 okrout 901194 77738874
JojoM 597778 35297180 TueRens 821388 50207666
TueRens 519226 31823562 tvijlbrief 795993 51894442
cw 458421 30307421 pemo 744463 32486677
fastgm 439667 25950040 JojoM 724378 43660674
gvreuls 436599 28177460 mibere 703840 46867607
crunchy 427035 27344275 linrock 626939 17408017
CSU_Dynasty 374765 25106278 gvreuls 534079 34352532
Fisherman 326901 21822979 cw 507221 34006775
ctoks 325477 21767943 fastgm 489749 29344518
velislav 295343 18844324 crunchy 427035 27344275
linrock 292789 10624427 CSU_Dynasty 424643 28525220
bcross 278584 19488961 ctoks 415771 27364603
okrout 262818 13803272 oz 369200 27017658
pemo 245982 11376085 bcross 342642 23671289
glinscott 217799 13780820 Fisherman 327231 21829379
leszek 212346 12959025 velislav 325670 20911076
nordlandia 211692 13484886 leszek 321295 19874113
bking_US 198894 11876016 Dantist 274747 16910258
drabel 196463 13450602 mgrabiak 237604 15418700
robal 195473 12375650 robal 217959 13840386
mgrabiak 187226 12016564 glinscott 217799 13780820
Dantist 183202 10990484 nordlandia 211692 13484886
Thanar 179852 12365359 drabel 201967 13798360
vdv 175274 9889046 bking_US 198894 11876016
spams 157128 10319326 mhoram 194862 12261809
marrco 150295 9402141 Thanar 179852 12365359
sqrt2 147963 9724586 vdv 175544 9904472
mhoram 141278 8901241 spams 157128 10319326
CoffeeOne 137100 5024116 rpngn 154081 9652139
vdbergh 137041 8926915 marrco 150300 9402229
malala 136182 8002293 sqrt2 147963 9724586
xoto 133702 9156676 vdbergh 137430 8955097
davar 122092 7960001 CoffeeOne 137100 5024116
dsmith 122059 7570238 malala 136182 8002293
Data 113305 8220352 xoto 133759 9159372
BrunoBanani 112960 7436849 davar 125240 8117121
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 DesolatedDodo 106811 6776980
amicic 89156 5392305 MaZePallas 102823 6633619
sunu 88851 6028873 sterni1971 100532 5880772
Vizvezdenec 83761 5344740 sunu 100167 7040199
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 zeryl 83680 5250995
solarlight 70517 5028306 sschnee 83003 4840890
dv8silencer 70287 3883992 0x3C33 82614 5271253
Bobo1239 68515 4652287 BRAVONE 81239 5054681
manap 66273 4121774 nssy 76497 5259388
skiminki 65088 4023328 teddybaer 75125 5407666
tinker 64333 4268790 jromang 74796 5175825
sschnee 60767 3500800 Pking_cda 73776 5293873
qurashee 57344 3168264 Calis007 72477 4088576
robnjr 57262 4053117 solarlight 70517 5028306
Freja 56938 3733019 dv8silencer 70287 3883992
ttruscott 56010 3680085 Bobo1239 68515 4652287
rkl 55132 4164467 manap 66273 4121774
renouve 53811 3501516 yurikvelo 65716 4457300
finfish 51360 3370515 tinker 64333 4268790
eva42 51272 3599691 Wolfgang 62644 3817410
rap 49985 3219146 qurashee 61208 3429862
pb00067 49727 3298270 robnjr 57262 4053117
ronaldjerum 47654 3240695 Freja 56938 3733019
bigpen0r 47653 3335327 ttruscott 56010 3680085
eastorwest 47585 3221629 rkl 55132 4164467
biffhero 46564 3111352 renouve 53811 3501516
VoyagerOne 45476 3452465 megaman7de 52434 3243016
yurikvelo 44834 3034550 MaxKlaxxMiner 51977 3153032
speedycpu 43842 3003273 finfish 51360 3370515
jbwiebe 43305 2805433 eva42 51272 3599691
Spprtr 42279 2680153 eastorwest 51058 3451555
DesolatedDodo 42007 2447516 rap 49985 3219146
Antihistamine 41788 2761312 pb00067 49727 3298270
mhunt 41735 2691355 Spprtr 48920 3161711
homyur 39893 2850481 bigpen0r 47667 3336927
gri 39871 2515779 ronaldjerum 47654 3240695
Fifis 38776 2529121 biffhero 46564 3111352
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 armo9494 39064 2832326
manapbk 30987 1810399 oryx 38867 2976992
Prcuvu 30377 2170122 SC 37299 2731694
anst 30301 2190091 Garf 37213 2986270
jkiiski 30136 1904470 tolkki963 37059 2154330
hyperbolic.tom 29840 2017394 csnodgrass 36207 2688994
Pyafue 29650 1902349 jmdana 36157 2210661
Wolfgang 29260 1658936 strelock 34716 2074055
zeryl 28156 1579911 DMBK 34010 2482916
OuaisBla 27636 1578800 EthanOConnor 33370 2090311
DMBK 27051 1999456 slakovv 32915 2021889
chriswk 26902 1868317 gopeto 30993 2028106
achambord 26582 1767323 manapbk 30987 1810399
Patrick_G 26276 1801617 Prcuvu 30377 2170122
yorkman 26193 1992080 anst 30301 2190091
SFTUser 25182 1675689 jkiiski 30136 1904470
nabildanial 24942 1519409 hyperbolic.tom 29840 2017394
Sharaf_DG 24765 1786697 chuckstablers 29659 2093438
ncfish1 24411 1520927 Pyafue 29650 1902349
rodneyc 24227 1409514 ncfish1 29105 1704011
agg177 23890 1395014 belzedar94 27935 1789106
JanErik 23408 1703875 OuaisBla 27636 1578800
Isidor 23388 1680691 chriswk 26902 1868317
Norabor 23164 1591830 achambord 26582 1767323
cisco2015 22897 1762669 Patrick_G 26276 1801617
Zirie 22542 1472937 yorkman 26193 1992080
team-oh 22272 1636708 SFTUser 25182 1675689
MazeOfGalious 21978 1629593 nabildanial 24942 1519409
sg4032 21947 1643265 Sharaf_DG 24765 1786697
ianh2105 21725 1632562 rodneyc 24275 1410450
xor12 21628 1680365 agg177 23890 1395014
dex 21612 1467203 JanErik 23408 1703875
nesoneg 21494 1463031 Isidor 23388 1680691
sphinx 21211 1384728 Norabor 23339 1602636
jjoshua2 21001 1423089 Ente 23270 1651432
horst.prack 20878 1465656 cisco2015 22897 1762669
Ente 20865 1477066 MarcusTullius 22688 1274821
0xB00B1ES 20590 1208666 Zirie 22542 1472937
j3corre 20405 941444 team-oh 22272 1636708
Adrian.Schmidt123 20316 1281436 MazeOfGalious 21978 1629593
wei 19973 1745989 sg4032 21947 1643265
MaxKlaxxMiner 19850 1009176 ianh2105 21725 1632562
rstoesser 19569 1293588 xor12 21628 1680365
gopeto 19491 1174952 dex 21612 1467203
eudhan 19274 1283717 nesoneg 21494 1463031
jundery 18445 1115855 Roady 21323 1433822
megaman7de 18377 1067540 sphinx 21211 1384728
iisiraider 18247 1101015 user213718 21196 1397710
ville 17883 1384026 spcc 21065 1311338
chris 17698 1487385 jjoshua2 21001 1423089
purplefishies 17595 1092533 horst.prack 20878 1465656
dju 17353 978595 0xB00B1ES 20590 1208666
DragonLord 17014 1162790 j3corre 20405 941444
IgorLeMasson 16064 1147232 kdave 20364 1389254
ako027ako 15671 1173203 Adrian.Schmidt123 20316 1281436
chuckstablers 15289 891576 Ulysses 20217 1351500
Nikolay.IT 15154 1068349 markkulix 19976 1115258
Andrew Grant 15114 895539 wei 19973 1745989
OssumOpossum 14857 1007129 rstoesser 19569 1293588
Karby 14808 867120 eudhan 19274 1283717
enedene 14476 905279 fishtester 18995 1238686
bpfliegel 14298 884523 vulcan 18871 1729392
mpx86 14019 759568 jundery 18445 1115855
jpulman 13982 870599 iisiraider 18247 1101015
crocogoat 13803 1117422 ville 17883 1384026
joster 13794 950160 chris 17698 1487385
Nesa92 13786 1114691 purplefishies 17595 1092533
Hjax 13535 915487 dju 17353 978595
jsys14 13459 785000 Wencey 17125 805964
Dark_wizzie 13422 1007152 DragonLord 17014 1162790
mabichito 12903 749391 thirdlife 16996 447356
thijsk 12886 722107 IgorLeMasson 16064 1147232
AdrianSA 12860 804972 ako027ako 15671 1173203
Flopzee 12698 894821 AndreasKrug 15550 1194497
fatmurphy 12547 853210 Nikolay.IT 15154 1068349
Rudolphous 12520 832340 Andrew Grant 15114 895539
scuzzi 12511 845761 scuzzi 14928 953313
SapphireBrand 12416 969604 OssumOpossum 14857 1007129
modolief 12386 896470 Karby 14808 867120
Machariel 12335 810784 jsys14 14652 855642
pgontarz 12151 848794 enedene 14476 905279
stocky 11954 699440 bpfliegel 14298 884523
mschmidt 11941 803401 mpx86 14019 759568
Maxim 11543 836024 jpulman 13982 870599
infinity 11470 727027 crocogoat 13803 1117422
torbjo 11395 729145 joster 13794 950160
Thomas A. Anderson 11372 732094 Nesa92 13786 1114691
savage84 11358 670860 mbeier 13650 1044928
d64 11263 789184 Hjax 13535 915487
MooTheCow 11237 720174 Dark_wizzie 13422 1007152
snicolet 11106 869170 Jopo12321 13367 678852
ali-al-zhrani 11086 767926 Rudolphous 13244 883140
AndreasKrug 10875 887457 Machariel 13010 863104
pirt 10806 836519 mabichito 12903 749391
basepi 10637 744851 thijsk 12886 722107
michaelrpg 10508 739039 AdrianSA 12860 804972
dzjp 10343 732529 infinigon 12807 937332
aga 10302 622975 Flopzee 12698 894821
ols 10259 570669 fatmurphy 12547 853210
lbraesch 10252 647825 SapphireBrand 12416 969604
FormazChar 10059 757283 modolief 12386 896470
Farseer 12249 694108
pgontarz 12151 848794
pirt 12008 923149
stocky 11954 699440
mschmidt 11941 803401
dbernier 11609 818636
Maxim 11543 836024
infinity 11470 727027
aga 11409 695071
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
FormazChar 11349 850327
d64 11263 789184
MooTheCow 11237 720174
snicolet 11106 869170
ali-al-zhrani 11098 768494
whelanh 11067 235676
Jackfish 10978 720078
deflectooor 10886 520116
basepi 10637 744851
Cubox 10621 826448
michaelrpg 10509 739239
OIVAS7572 10420 995586
dzjp 10343 732529
Garruk 10334 704065
ols 10259 570669
lbraesch 10252 647825
qoo_charly_cai 10212 620407
Naven94 10069 503192
-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 }
+139 -77
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
### Establish the operating system name ### Establish the operating system name
@@ -38,11 +56,11 @@ 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
PGOGENSFEN = ./$(EXE) gensfen depth 3 loop 1000 sfen_format bin output_file_name $(PGO_TRAINING_DATA_FILE) PGOGENSFEN = $(WINE_PATH) ./$(EXE) gensfen depth 3 loop 1000 sfen_format bin output_file_name $(PGO_TRAINING_DATA_FILE)
else else
PGOBENCH = $(SDE_PATH) -- ./$(EXE) bench PGOBENCH = $(SDE_PATH) -- $(WINE_PATH) ./$(EXE) bench
PGOGENSFEN = $(SDE_PATH) -- ./$(EXE) gensfen depth 3 loop 1000 sfen_format bin output_file_name $(PGO_TRAINING_DATA_FILE) PGOGENSFEN = $(SDE_PATH) -- $(WINE_PATH) ./$(EXE) gensfen depth 3 loop 1000 sfen_format bin output_file_name $(PGO_TRAINING_DATA_FILE)
endif endif
### Source and object files ### Source and object files
@@ -89,6 +107,7 @@ VPATH = syzygy:nnue:nnue/features:eval:extra:tools
# 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
@@ -99,7 +118,7 @@ VPATH = syzygy:nnue:nnue/features:eval:extra:tools
# at the end of the line for flag values. # at the end of the line for flag values.
# #
# Example of use for these flags: # Example of use for these flags:
# make build ARCH=x86-64-avx512 debug=on sanitize="address undefined" # make build ARCH=x86-64-avx512 debug=yes sanitize="address undefined"
### 2.1. General and architecture defaults ### 2.1. General and architecture defaults
@@ -111,8 +130,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
@@ -133,10 +152,12 @@ sse2 = no
ssse3 = no ssse3 = no
sse41 = no sse41 = no
avx2 = no avx2 = no
avxvnni = no
avx512 = no avx512 = no
vnni256 = no vnni256 = no
vnni512 = no vnni512 = no
neon = no neon = no
arm_version = 0
STRIP = strip STRIP = strip
### 2.2 Architecture specific ### 2.2 Architecture specific
@@ -148,7 +169,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
@@ -203,6 +224,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
@@ -273,6 +305,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)
@@ -281,6 +314,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)
@@ -288,6 +322,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)
@@ -295,6 +330,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)
@@ -326,10 +362,16 @@ endif
### ========================================================================== ### ==========================================================================
### 3.1 Selecting compiler (default = gcc) ### 3.1 Selecting compiler (default = gcc)
ifeq ($(MAKELEVEL),0)
export ENV_CXXFLAGS := $(CXXFLAGS)
export ENV_DEPENDFLAGS := $(DEPENDFLAGS)
export ENV_LDFLAGS := $(LDFLAGS)
endif
ADDITIONAL_INCLUDE_DIRECTORIES = -I. ADDITIONAL_INCLUDE_DIRECTORIES = -I.
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(ADDITIONAL_INCLUDE_DIRECTORIES) $(EXTRACXXFLAGS) CXXFLAGS = $(ENV_CXXFLAGS) -Wall -Wcast-qual -fno-exceptions -std=c++17 $(ADDITIONAL_INCLUDE_DIRECTORIES) $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++17 $(ADDITIONAL_INCLUDE_DIRECTORIES) DEPENDFLAGS = $(ENV_DEPENDFLAGS) -std=c++17 $(ADDITIONAL_INCLUDE_DIRECTORIES)
LDFLAGS += $(EXTRALDFLAGS) LDFLAGS = $(ENV_LDFLAGS) $(EXTRALDFLAGS)
ifeq ($(COMP),) ifeq ($(COMP),)
COMP=gcc COMP=gcc
@@ -359,29 +401,27 @@ ifeq ($(COMP),gcc)
endif endif
endif endif
ifeq ($(target_windows),yes)
LDFLAGS += -static
endif
ifeq ($(COMP),mingw) ifeq ($(COMP),mingw)
comp=mingw comp=mingw
ifeq ($(KERNEL),Linux) ifeq ($(bits),64)
ifeq ($(bits),64) ifeq ($(shell which x86_64-w64-mingw32-c++-posix 2> /dev/null),)
ifeq ($(shell which x86_64-w64-mingw32-c++-posix),) CXX=x86_64-w64-mingw32-c++
CXX=x86_64-w64-mingw32-c++
else
CXX=x86_64-w64-mingw32-c++-posix
endif
else else
ifeq ($(shell which i686-w64-mingw32-c++-posix),) CXX=x86_64-w64-mingw32-c++-posix
CXX=i686-w64-mingw32-c++
else
CXX=i686-w64-mingw32-c++-posix
endif
endif endif
else else
CXX=g++ ifeq ($(shell which i686-w64-mingw32-c++-posix 2> /dev/null),)
CXX=i686-w64-mingw32-c++
else
CXX=i686-w64-mingw32-c++-posix
endif
endif endif
CXXFLAGS += -pedantic -Wextra -Wshadow
CXXFLAGS += -Wextra -Wshadow
LDFLAGS += -static
endif endif
ifeq ($(COMP),icc) ifeq ($(COMP),icc)
@@ -393,17 +433,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)
@@ -435,11 +477,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
@@ -453,6 +503,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
@@ -513,10 +566,16 @@ ifeq ($(optimize),yes)
endif endif
endif endif
ifeq ($(comp),$(filter $(comp),gcc clang icc)) ifeq ($(KERNEL),Darwin)
ifeq ($(KERNEL),Darwin) ifeq ($(comp),$(filter $(comp),clang icc))
CXXFLAGS += -mdynamic-no-pic CXXFLAGS += -mdynamic-no-pic
endif endif
ifeq ($(comp),gcc)
ifneq ($(arch),arm64)
CXXFLAGS += -mdynamic-no-pic
endif
endif
endif endif
ifeq ($(comp),clang) ifeq ($(comp),clang)
@@ -529,7 +588,7 @@ ifeq ($(bits),64)
CXXFLAGS += -DIS_64BIT CXXFLAGS += -DIS_64BIT
endif endif
### 3.5 prefetch ### 3.5 prefetch and popcount
ifeq ($(prefetch),yes) ifeq ($(prefetch),yes)
ifeq ($(sse),yes) ifeq ($(sse),yes)
CXXFLAGS += -msse CXXFLAGS += -msse
@@ -538,7 +597,6 @@ else
CXXFLAGS += -DNO_PREFETCH CXXFLAGS += -DNO_PREFETCH
endif endif
### 3.6 popcnt
ifeq ($(popcnt),yes) ifeq ($(popcnt),yes)
ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64)) ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
CXXFLAGS += -DUSE_POPCNT CXXFLAGS += -DUSE_POPCNT
@@ -549,6 +607,7 @@ ifeq ($(popcnt),yes)
endif endif
endif endif
### 3.6 SIMD architectures
ifeq ($(avx2),yes) ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2 CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw)) ifeq ($(comp),$(filter $(comp),gcc clang mingw))
@@ -556,6 +615,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))
@@ -606,7 +672,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)
@@ -631,9 +697,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)
@@ -644,25 +708,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
@@ -701,6 +757,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"
@@ -763,8 +820,8 @@ 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
$(PGOGENSFEN) > /dev/null $(PGOGENSFEN) 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
@@ -779,7 +836,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
@@ -792,22 +849,22 @@ net:
$(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet)) $(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet))
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi)) $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
@if test -f "$(nnuenet)"; then \ @if test -f "$(nnuenet)"; then \
echo "Already available."; \ echo "Already available."; \
else \ else \
if [ "x$(curl_or_wget)" = "x" ]; then \ if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \ echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
else \ else \
echo "Downloading $(nnuedownloadurl)"; $(curl_or_wget) $(nnuedownloadurl) > $(nnuenet);\ echo "Downloading $(nnuedownloadurl)"; $(curl_or_wget) $(nnuedownloadurl) > $(nnuenet);\
fi; \ fi; \
fi; fi;
$(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi)) $(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
@if [ "x$(shasum_command)" != "x" ]; then \ @if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \ if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Failed download or $(nnuenet) corrupted, please delete!"; exit 1; \ echo "Failed download or $(nnuenet) corrupted, please delete!"; exit 1; \
fi \ fi \
else \ else \
echo "shasum / sha256sum not found, skipping net validation"; \ echo "shasum / sha256sum not found, skipping net validation"; \
fi fi
# clean binaries and objects # clean binaries and objects
objclean: objclean:
@@ -818,8 +875,9 @@ profileclean:
@rm -rf profdir @rm -rf profdir
@rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s ./tools/*.gcda ./extra/*.gcda ./eval/*.gcda @rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s ./tools/*.gcda ./extra/*.gcda ./eval/*.gcda
@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:
@@ -850,10 +908,12 @@ config-sanity: net
@echo "ssse3: '$(ssse3)'" @echo "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'" @echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'" @echo "avx2: '$(avx2)'"
@echo "avxvnni: '$(avxvnni)'"
@echo "avx512: '$(avx512)'" @echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'" @echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'" @echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'" @echo "neon: '$(neon)'"
@echo "arm_version: '$(arm_version)'"
@echo "" @echo ""
@echo "Flags:" @echo "Flags:"
@echo "CXX: $(CXX)" @echo "CXX: $(CXX)"
@@ -905,12 +965,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
@@ -925,7 +987,7 @@ icc-profile-use:
EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \ EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
all all
.depend: .depend: $(SRCS)
-@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
-include .depend -include .depend
+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
+74 -66
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,7 +61,7 @@ namespace Stockfish {
namespace Eval { namespace Eval {
namespace NNUE { namespace NNUE {
string eval_file_loaded = "None"; string currentEvalFileName = "None";
UseNNUEMode useNNUE; UseNNUEMode useNNUE;
static UseNNUEMode nnue_mode_from_option(const UCI::Option& mode) static UseNNUEMode nnue_mode_from_option(const UCI::Option& mode)
@@ -92,6 +92,8 @@ namespace Eval {
return; return;
string eval_file = string(Options["EvalFile"]); string eval_file = string(Options["EvalFile"]);
if (eval_file.empty())
eval_file = EvalFileDefaultName;
#if defined(DEFAULT_NNUE_DIRECTORY) #if defined(DEFAULT_NNUE_DIRECTORY)
#define stringify2(x) #x #define stringify2(x) #x
@@ -102,13 +104,13 @@ namespace Eval {
#endif #endif
for (string directory : dirs) for (string directory : dirs)
if (eval_file_loaded != eval_file) if (currentEvalFileName != eval_file)
{ {
if (directory != "<internal>") if (directory != "<internal>")
{ {
ifstream stream(directory + eval_file, ios::binary); ifstream stream(directory + eval_file, ios::binary);
if (load_eval(eval_file, stream)) if (load_eval(eval_file, stream))
eval_file_loaded = eval_file; currentEvalFileName = eval_file;
} }
if (directory == "<internal>" && eval_file == EvalFileDefaultName) if (directory == "<internal>" && eval_file == EvalFileDefaultName)
@@ -120,10 +122,11 @@ namespace Eval {
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)), MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
size_t(gEmbeddedNNUESize)); size_t(gEmbeddedNNUESize));
(void) gEmbeddedNNUEEnd; // Silence warning on unused variable
istream stream(&buffer); istream stream(&buffer);
if (load_eval(eval_file, stream)) if (load_eval(eval_file, stream))
eval_file_loaded = eval_file; currentEvalFileName = eval_file;
} }
} }
} }
@@ -132,16 +135,16 @@ namespace Eval {
void NNUE::verify() { void NNUE::verify() {
string eval_file = string(Options["EvalFile"]); string eval_file = string(Options["EvalFile"]);
if (eval_file.empty())
eval_file = EvalFileDefaultName;
if (useNNUE != UseNNUEMode::False && eval_file_loaded != eval_file) if (useNNUE != UseNNUEMode::False && currentEvalFileName != eval_file)
{ {
UCI::OptionsMap defaults;
UCI::init(defaults);
string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available."; string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available.";
string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully."; string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully.";
string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file."; string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file.";
string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + string(defaults["EvalFile"]); string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + std::string(EvalFileDefaultName);
string msg5 = "The engine will be terminated now."; string msg5 = "The engine will be terminated now.";
sync_cout << "info string ERROR: " << msg1 << sync_endl; sync_cout << "info string ERROR: " << msg1 << sync_endl;
@@ -204,17 +207,17 @@ 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
constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 }; constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 76, 46, 45, 14 };
// SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type, // SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
// higher if multiple safe checks are possible for that piece type. // higher if multiple safe checks are possible for that piece type.
constexpr int SafeCheck[][2] = { constexpr int SafeCheck[][2] = {
{}, {}, {803, 1292}, {639, 974}, {1087, 1878}, {759, 1132} {}, {}, {805, 1292}, {650, 984}, {1071, 1886}, {730, 1128}
}; };
#define S(mg, eg) make_score(mg, eg) #define S(mg, eg) make_score(mg, eg)
@@ -240,58 +243,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
@@ -1000,7 +1003,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))
@@ -1065,26 +1070,22 @@ make_v:
if ( pos.piece_on(SQ_A1) == W_BISHOP if ( pos.piece_on(SQ_A1) == W_BISHOP
&& pos.piece_on(SQ_B2) == W_PAWN) && pos.piece_on(SQ_B2) == W_PAWN)
correction += !pos.empty(SQ_B3) ? -CorneredBishop * 4 correction -= CorneredBishop;
: -CorneredBishop * 3;
if ( pos.piece_on(SQ_H1) == W_BISHOP if ( pos.piece_on(SQ_H1) == W_BISHOP
&& pos.piece_on(SQ_G2) == W_PAWN) && pos.piece_on(SQ_G2) == W_PAWN)
correction += !pos.empty(SQ_G3) ? -CorneredBishop * 4 correction -= CorneredBishop;
: -CorneredBishop * 3;
if ( pos.piece_on(SQ_A8) == B_BISHOP if ( pos.piece_on(SQ_A8) == B_BISHOP
&& pos.piece_on(SQ_B7) == B_PAWN) && pos.piece_on(SQ_B7) == B_PAWN)
correction += !pos.empty(SQ_B6) ? CorneredBishop * 4 correction += CorneredBishop;
: CorneredBishop * 3;
if ( pos.piece_on(SQ_H8) == B_BISHOP if ( pos.piece_on(SQ_H8) == B_BISHOP
&& pos.piece_on(SQ_G7) == B_PAWN) && pos.piece_on(SQ_G7) == B_PAWN)
correction += !pos.empty(SQ_G6) ? CorneredBishop * 4 correction += CorneredBishop;
: CorneredBishop * 3;
return pos.side_to_move() == WHITE ? Value(correction) return pos.side_to_move() == WHITE ? Value(3 * correction)
: -Value(correction); : -Value(3 * correction);
} }
} // namespace Eval } // namespace Eval
@@ -1107,37 +1108,39 @@ Value Eval::evaluate(const Position& pos) {
return v; return v;
} }
else if (NNUE::useNNUE == NNUE::UseNNUEMode::False)
v = Evaluation<NO_TRACE>(pos).value(); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical,
else // but we switch to NNUE during long shuffling or with high material on the board.
bool useClassical = (pos.this_thread()->depth > 9 || pos.count<ALL_PIECES>() > 7) &&
abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count());
// 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.
if (NNUE::useNNUE == NNUE::UseNNUEMode::False || useClassical)
{ {
// Scale and shift NNUE for compatibility with search and classical evaluation v = Evaluation<NO_TRACE>(pos).value(); // classical
auto adjusted_NNUE = [&]() useClassical = abs(v) >= 297;
{ }
int scale = 883
+ 32 * pos.count<PAWN>()
+ 32 * pos.non_pawn_material() / 1024;
Value nnue = NNUE::evaluate(pos, true) * scale / 1024; // If result of a classical evaluation is much lower than threshold fall back to NNUE
if (NNUE::useNNUE != NNUE::UseNNUEMode::False && !useClassical)
{
Value nnue = NNUE::evaluate(pos, true); // NNUE
int scale = 1080 + 110 * pos.non_pawn_material() / 5120;
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 = (278 * abs(nnue - psq)) / 256;
if (pos.is_chess960()) optimism = optimism * (251 + complexity) / 256;
nnue += fix_FRC(pos); v = (nnue * scale + optimism * (scale - 852)) / 1024;
return nnue; if (pos.is_chess960())
}; v += fix_FRC(pos);
// If there is PSQ imbalance we use the classical eval, but we switch to
// NNUE eval faster when shuffling or if the material on the board is high.
int r50 = pos.rule50_count();
Value psq = Value(abs(eg_value(pos.psq_score())));
bool classical = psq * 5 > (850 + pos.non_pawn_material() / 64) * (5 + r50);
v = classical ? Evaluation<NO_TRACE>(pos).value() // classical
: adjusted_NNUE(); // NNUE
} }
// Damp down the evaluation linearly when shuffling // Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100; v = v * (195 - pos.rule50_count()) / 211;
// Guarantee evaluation does not hit the tablebase range // Guarantee evaluation does not hit the tablebase range
v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
@@ -1162,7 +1165,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();
+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
@@ -36,7 +36,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-e8321e467bf6.nnue" #define EvalFileDefaultName "nn-3c0aa92af1da.nnue"
namespace NNUE { namespace NNUE {
enum struct UseNNUEMode enum struct UseNNUEMode
@@ -47,7 +47,7 @@ namespace Eval {
}; };
extern UseNNUEMode useNNUE; extern UseNNUEMode useNNUE;
extern std::string eval_file_loaded; extern std::string currentEvalFileName;
std::string trace(Position& pos); std::string trace(Position& pos);
Value evaluate(const Position& pos, bool adjusted = false); Value evaluate(const Position& pos, bool adjusted = 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
+38 -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
@@ -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
@@ -112,7 +114,14 @@ public:
static Logger l; static Logger l;
if (!fname.empty() && !l.file.is_open()) if (l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
if (!fname.empty())
{ {
l.file.open(fname, ifstream::out); l.file.open(fname, ifstream::out);
@@ -125,12 +134,6 @@ public:
cin.rdbuf(&l.in); cin.rdbuf(&l.in);
cout.rdbuf(&l.out); cout.rdbuf(&l.out);
} }
else if (fname.empty() && l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
} }
}; };
@@ -496,11 +499,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;
@@ -514,7 +517,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;
@@ -522,7 +526,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);
@@ -572,22 +576,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
+50 -14
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
@@ -108,19 +108,30 @@ static inline const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
static inline const bool IsLittleEndian = (Le.c[0] == 4); static inline const bool IsLittleEndian = (Le.c[0] == 4);
template <typename T> // RunningAverage : a class to calculate a running average of a series of values.
class ValueListInserter { // For efficiency, all computations are done with integers.
public: class RunningAverage {
ValueListInserter(T* v, std::size_t& s) : public:
values(v),
size(&s)
{
}
void push_back(const T& value) { values[(*size)++] = value; } // Reset the running average to rational value p / q
private: void set(int64_t p, int64_t q)
T* values; { average = p * PERIOD * RESOLUTION / q; }
std::size_t* size;
// Update average with value v
void update(int64_t v)
{ average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; }
// Test if average is strictly greater than rational a / b
bool is_greater(int64_t a, int64_t b) const
{ return b * average > a * (PERIOD * RESOLUTION); }
int64_t value() const
{ return average / (PERIOD * RESOLUTION); }
private :
static constexpr int64_t PERIOD = 4096;
static constexpr int64_t RESOLUTION = 1024;
int64_t average;
}; };
template <typename T, std::size_t MaxSize> template <typename T, std::size_t MaxSize>
@@ -136,7 +147,6 @@ public:
const T& operator[](std::size_t index) const { return values_[index]; } const T& operator[](std::size_t index) const { return values_[index]; }
const T* begin() const { return values_; } const T* begin() const { return values_; }
const T* end() const { return values_ + size_; } const T* end() const { return values_ + size_; }
operator ValueListInserter<T>() { return ValueListInserter(values_, size_); }
void swap(ValueList& other) { void swap(ValueList& other) {
const std::size_t maxSize = std::max(size_, other.size_); const std::size_t maxSize = std::max(size_, other.size_);
@@ -365,6 +375,32 @@ public:
extern SynchronizedRegionLogger sync_region_cout; extern SynchronizedRegionLogger sync_region_cout;
/// 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
+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
@@ -52,9 +52,9 @@ namespace {
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
const Bitboard emptySquares = Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces(); const Bitboard emptySquares = ~pos.pieces();
const Bitboard enemies = Type == EVASIONS ? pos.checkers() const Bitboard enemies = Type == EVASIONS ? pos.checkers()
: Type == CAPTURES ? target : pos.pieces(Them); : pos.pieces(Them);
Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB; Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB; Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
+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);
+8 -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
@@ -86,13 +86,7 @@ enum StatsType { NoCaptures, Captures };
/// unsuccessful during the current search, and is used for reduction and move /// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by /// ordering decisions. It uses 2 tables (one for each color) indexed by
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory; 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). It is cleared with each new
/// search and filled during iterative deepening.
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see www.chessprogramming.org/Countermove_Heuristic /// move, see www.chessprogramming.org/Countermove_Heuristic
@@ -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];
}; };
+15 -32
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,39 +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 = 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 output = network[bucket]->propagate(transformedFeatures, buffer); const auto positional = network[bucket]->propagate(transformedFeatures);
int materialist = psqt; // Give more value to positional evaluation when adjusted flag is set
int positional = output[0]; if (adjusted)
return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
int delta_npm = abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK)); else
int entertainment = (adjusted && delta_npm <= BishopValueMg - KnightValueMg ? 7 : 0); return static_cast<Value>((psqt + positional) / OutputScale);
int A = 128 - entertainment;
int B = 128 + entertainment;
int sum = (A * materialist + B * positional) / 128;
return static_cast<Value>( sum / OutputScale );
} }
struct NnueEvalTrace { struct NnueEvalTrace {
@@ -196,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 );
@@ -239,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)
@@ -396,7 +379,7 @@ namespace Stockfish::Eval::NNUE {
actualFilename = filename.value(); actualFilename = filename.value();
else else
{ {
if (eval_file_loaded != EvalFileDefaultName) if (currentEvalFileName != EvalFileDefaultName)
{ {
msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified"; msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified";
+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
+9 -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
@@ -39,7 +39,7 @@ namespace Stockfish::Eval::NNUE::Features {
void HalfKAv2_hm::append_active_indices( void HalfKAv2_hm::append_active_indices(
const Position& pos, const Position& pos,
Color perspective, Color perspective,
ValueListInserter<IndexType> active IndexList& active
) { ) {
Square ksq = pos.square<KING>(perspective); Square ksq = pos.square<KING>(perspective);
Bitboard bb = pos.pieces(); Bitboard bb = pos.pieces();
@@ -55,22 +55,20 @@ namespace Stockfish::Eval::NNUE::Features {
void HalfKAv2_hm::append_changed_indices( void HalfKAv2_hm::append_changed_indices(
Square ksq, Square ksq,
StateInfo* st, const DirtyPiece& dp,
Color perspective, Color perspective,
ValueListInserter<IndexType> removed, IndexList& removed,
ValueListInserter<IndexType> added IndexList& added
) { ) {
const auto& dp = st->dirtyPiece;
for (int i = 0; i < dp.dirty_num; ++i) { for (int i = 0; i < dp.dirty_num; ++i) {
Piece pc = dp.piece[i];
if (dp.from[i] != SQ_NONE) if (dp.from[i] != SQ_NONE)
removed.push_back(make_index(perspective, dp.from[i], pc, ksq)); removed.push_back(make_index(perspective, dp.from[i], dp.piece[i], ksq));
if (dp.to[i] != SQ_NONE) if (dp.to[i] != SQ_NONE)
added.push_back(make_index(perspective, dp.to[i], pc, ksq)); added.push_back(make_index(perspective, dp.to[i], dp.piece[i], ksq));
} }
} }
int HalfKAv2_hm::update_cost(StateInfo* st) { int HalfKAv2_hm::update_cost(const StateInfo* st) {
return st->dirtyPiece.dirty_num; return st->dirtyPiece.dirty_num;
} }
@@ -78,7 +76,7 @@ namespace Stockfish::Eval::NNUE::Features {
return pos.count<ALL_PIECES>(); return pos.count<ALL_PIECES>();
} }
bool HalfKAv2_hm::requires_refresh(StateInfo* st, Color perspective) { bool HalfKAv2_hm::requires_refresh(const StateInfo* st, Color perspective) {
return st->dirtyPiece.piece[0] == make_piece(perspective, KING); return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
} }
+13 -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
@@ -50,7 +50,7 @@ namespace Stockfish::Eval::NNUE::Features {
PS_W_QUEEN = 8 * SQUARE_NB, PS_W_QUEEN = 8 * SQUARE_NB,
PS_B_QUEEN = 9 * SQUARE_NB, PS_B_QUEEN = 9 * SQUARE_NB,
PS_KING = 10 * SQUARE_NB, PS_KING = 10 * SQUARE_NB,
PS_NB = 11 * SQUARE_NB PS_NB = 11 * SQUARE_NB
}; };
static constexpr IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = { static constexpr IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = {
@@ -85,36 +85,38 @@ namespace Stockfish::Eval::NNUE::Features {
-1, -1, -1, -1, 23, 22, 21, 20, -1, -1, -1, -1, 23, 22, 21, 20,
-1, -1, -1, -1, 19, 18, 17, 16, -1, -1, -1, -1, 19, 18, 17, 16,
-1, -1, -1, -1, 15, 14, 13, 12, -1, -1, -1, -1, 15, 14, 13, 12,
-1, -1, -1, -1, 11, 10, 9, 8, -1, -1, -1, -1, 11, 10, 9, 8,
-1, -1, -1, -1, 7, 6, 5, 4, -1, -1, -1, -1, 7, 6, 5, 4,
-1, -1, -1, -1, 3, 2, 1, 0 -1, -1, -1, -1, 3, 2, 1, 0
}; };
// Maximum number of simultaneously active features. // Maximum number of simultaneously active features.
static constexpr IndexType MaxActiveDimensions = 32; static constexpr IndexType MaxActiveDimensions = 32;
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
// Get a list of indices for active features // Get a list of indices for active features
static void append_active_indices( static void append_active_indices(
const Position& pos, const Position& pos,
Color perspective, Color perspective,
ValueListInserter<IndexType> active); IndexList& active);
// Get a list of indices for recently changed features // Get a list of indices for recently changed features
static void append_changed_indices( static void append_changed_indices(
Square ksq, Square ksq,
StateInfo* st, const DirtyPiece& dp,
Color perspective, Color perspective,
ValueListInserter<IndexType> removed, IndexList& removed,
ValueListInserter<IndexType> added); IndexList& added
);
// Returns the cost of updating one perspective, the most costly one. // Returns the cost of updating one perspective, the most costly one.
// Assumes no refresh needed. // Assumes no refresh needed.
static int update_cost(StateInfo* st); static int update_cost(const StateInfo* st);
static int refresh_cost(const Position& pos); static int refresh_cost(const Position& pos);
// Returns whether the change stored in this StateInfo means that // Returns whether the change stored in this StateInfo means that
// a full accumulator refresh is required. // a full accumulator refresh is required.
static bool requires_refresh(StateInfo* st, Color perspective); static bool requires_refresh(const StateInfo* st, Color perspective);
}; };
} // namespace Stockfish::Eval::NNUE::Features } // namespace Stockfish::Eval::NNUE::Features
File diff suppressed because it is too large Load Diff
+15 -26
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,50 +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 = static constexpr IndexType InputDimensions = InDims;
PreviousLayer::OutputDimensions;
static constexpr IndexType OutputDimensions = InputDimensions; static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
// Size of forward propagation buffer used in this layer using OutputBuffer = OutputType[PaddedOutputDimensions];
static constexpr std::size_t 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) {
@@ -179,11 +170,9 @@ namespace Stockfish::Eval::NNUE::Layers {
output[i] = static_cast<OutputType>( output[i] = static_cast<OutputType>(
std::max(0, std::min(127, input[i] >> WeightScaleBits))); std::max(0, std::min(127, input[i] >> WeightScaleBits)));
} }
return output; return output;
} }
private:
PreviousLayer previousLayer;
}; };
} // namespace Stockfish::Eval::NNUE::Layers } // namespace Stockfish::Eval::NNUE::Layers
-72
View File
@@ -1,72 +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
+120
View File
@@ -0,0 +1,120 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Definition of layer ClippedReLU of NNUE evaluation function
#ifndef NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#define NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Layers {
// Clipped ReLU
template <IndexType InDims>
class SqrClippedReLU {
public:
// Input/output type
using InputType = std::int32_t;
using OutputType = std::uint8_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
hashValue += prevHash;
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream&) {
return true;
}
// Write network parameters
bool write_parameters(std::ostream&) const {
return true;
}
// Forward propagation
const OutputType* propagate(
const InputType* input, OutputType* output) const {
#if defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / 16;
#ifdef USE_SSE41
const __m128i Zero = _mm_setzero_si128();
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
static_assert(WeightScaleBits == 6);
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
__m128i words0 = _mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1]));
__m128i words1 = _mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3]));
// Not sure if
words0 = _mm_srli_epi16(_mm_mulhi_epi16(words0, words0), 3);
words1 = _mm_srli_epi16(_mm_mulhi_epi16(words1, words1), 3);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, Zero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
constexpr IndexType Start = NumChunks * 16;
#else
constexpr IndexType Start = 0;
#endif
for (IndexType i = Start; i < InputDimensions; ++i) {
output[i] = static_cast<OutputType>(
// realy should be /127 but we need to make it fast
// needs to be accounted for in the trainer
std::max(0ll, std::min(127ll, (((long long)input[i] * input[i]) >> (2 * WeightScaleBits)) / 128)));
}
return output;
}
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
+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
+97 -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,117 @@
#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 "layers/sqr_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::SqrClippedReLU<FC_0_OUTPUTS + 1> ac_sqr_0;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 8>>; Layers::ClippedReLU<FC_0_OUTPUTS + 1> ac_0;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; Layers::AffineTransform<FC_0_OUTPUTS * 2, FC_1_OUTPUTS> fc_1;
using OutputLayer = AffineTransform<HiddenLayer2, 1>; Layers::ClippedReLU<FC_1_OUTPUTS> ac_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_sqr_0)::OutputType ac_sqr_0_out[ceil_to_multiple<IndexType>(FC_0_OUTPUTS * 2, 32)];
alignas(CacheLineSize) decltype(ac_0)::OutputBuffer ac_0_out;
alignas(CacheLineSize) decltype(fc_1)::OutputBuffer fc_1_out;
alignas(CacheLineSize) decltype(ac_1)::OutputBuffer ac_1_out;
alignas(CacheLineSize) decltype(fc_2)::OutputBuffer fc_2_out;
Buffer()
{
std::memset(this, 0, sizeof(*this));
}
};
#if defined(__clang__) && (__APPLE__)
// workaround for a bug reported with xcode 12
static thread_local auto tlsBuffer = std::make_unique<Buffer>();
// Access TLS only once, cache result.
Buffer& buffer = *tlsBuffer;
#else
alignas(CacheLineSize) static thread_local Buffer buffer;
#endif
fc_0.propagate(transformedFeatures, buffer.fc_0_out);
ac_sqr_0.propagate(buffer.fc_0_out, buffer.ac_sqr_0_out);
ac_0.propagate(buffer.fc_0_out, buffer.ac_0_out);
std::memcpy(buffer.ac_sqr_0_out + FC_0_OUTPUTS, buffer.ac_0_out, FC_0_OUTPUTS * sizeof(decltype(ac_0)::OutputType));
fc_1.propagate(buffer.ac_sqr_0_out, buffer.fc_1_out);
ac_1.propagate(buffer.fc_1_out, buffer.ac_1_out);
fc_2.propagate(buffer.ac_1_out, buffer.fc_2_out);
// buffer.fc_0_out[FC_0_OUTPUTS] is such that 1.0 is equal to 127*(1<<WeightScaleBits) in quantized form
// but we want 1.0 to be equal to 600*OutputScale
std::int32_t fwdOut = int(buffer.fc_0_out[FC_0_OUTPUTS]) * (600*OutputScale) / (127*(1<<WeightScaleBits));
std::int32_t outputValue = buffer.fc_2_out[0] + fwdOut;
return outputValue;
}
};
} // namespace Stockfish::Eval::NNUE } // 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
@@ -111,7 +111,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) {
@@ -129,11 +129,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));
} }
+102 -129
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -50,12 +50,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;
@@ -64,12 +74,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;
@@ -78,12 +98,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;
@@ -92,12 +119,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;
@@ -106,12 +147,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
@@ -126,8 +179,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,
@@ -159,9 +214,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
@@ -186,7 +241,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 =
@@ -194,7 +249,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
@@ -232,136 +287,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()
@@ -373,7 +347,6 @@ namespace Stockfish::Eval::NNUE {
// That might depend on the feature set and generally relies on the // That might depend on the feature set and generally relies on the
// feature set's update cost calculation to be correct and never // feature set's update cost calculation to be correct and never
// allow updates with more added/removed features than MaxActiveDimensions. // allow updates with more added/removed features than MaxActiveDimensions.
using IndexList = ValueList<IndexType, FeatureSet::MaxActiveDimensions>;
#ifdef VECTOR #ifdef VECTOR
// Gcc-10.2 unnecessarily spills AVX2 registers if this array // Gcc-10.2 unnecessarily spills AVX2 registers if this array
@@ -407,12 +380,12 @@ namespace Stockfish::Eval::NNUE {
// Gather all features to be updated. // Gather all features to be updated.
const Square ksq = pos.square<KING>(perspective); const Square ksq = pos.square<KING>(perspective);
IndexList removed[2], added[2]; FeatureSet::IndexList removed[2], added[2];
FeatureSet::append_changed_indices( FeatureSet::append_changed_indices(
ksq, next, perspective, removed[0], added[0]); ksq, next->dirtyPiece, perspective, removed[0], added[0]);
for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous) for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous)
FeatureSet::append_changed_indices( FeatureSet::append_changed_indices(
ksq, st2, perspective, removed[1], added[1]); ksq, st2->dirtyPiece, perspective, removed[1], added[1]);
// Mark the accumulators as computed. // Mark the accumulators as computed.
next->accumulator.computed[perspective] = true; next->accumulator.computed[perspective] = true;
@@ -537,7 +510,7 @@ namespace Stockfish::Eval::NNUE {
// Refresh the accumulator // Refresh the accumulator
auto& accumulator = pos.state()->accumulator; auto& accumulator = pos.state()->accumulator;
accumulator.computed[perspective] = true; accumulator.computed[perspective] = true;
IndexList active; FeatureSet::IndexList active;
FeatureSet::append_active_indices(pos, perspective, active); FeatureSet::append_active_indices(pos, perspective, active);
#ifdef VECTOR #ifdef VECTOR
+20 -20
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -32,30 +32,30 @@ namespace {
#define S(mg, eg) make_score(mg, eg) #define S(mg, eg) make_score(mg, eg)
// Pawn penalties // Pawn penalties
constexpr Score Backward = S( 9, 22); constexpr Score Backward = S( 6, 19);
constexpr Score Doubled = S(13, 51); constexpr Score Doubled = S(11, 51);
constexpr Score DoubledEarly = S(20, 7); constexpr Score DoubledEarly = S(17, 7);
constexpr Score Isolated = S( 3, 15); constexpr Score Isolated = S( 1, 20);
constexpr Score WeakLever = S( 4, 58); constexpr Score WeakLever = S( 2, 57);
constexpr Score WeakUnopposed = S(13, 24); constexpr Score WeakUnopposed = S(15, 18);
// Bonus for blocked pawns at 5th or 6th rank // Bonus for blocked pawns at 5th or 6th rank
constexpr Score BlockedPawn[2] = { S(-17, -6), S(-9, 2) }; constexpr Score BlockedPawn[2] = { S(-19, -8), S(-7, 3) };
constexpr Score BlockedStorm[RANK_NB] = { constexpr Score BlockedStorm[RANK_NB] = {
S(0, 0), S(0, 0), S(75, 78), S(-8, 16), S(-6, 10), S(-6, 6), S(0, 2) S(0, 0), S(0, 0), S(64, 75), S(-3, 14), S(-12, 19), S(-7, 4), S(-10, 5)
}; };
// Connected pawn bonus // Connected pawn bonus
constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 23, 48, 87 }; constexpr int Connected[RANK_NB] = { 0, 3, 7, 7, 15, 54, 86 };
// Strength of pawn shelter for our king by [distance from edge][rank]. // Strength of pawn shelter for our king by [distance from edge][rank].
// RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king. // RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king.
constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = { constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = {
{ V( -5), V( 82), V( 92), V( 54), V( 36), V( 22), V( 28) }, { V(-2), V(85), V(95), V(53), V(39), V(23), V(25) },
{ V(-44), V( 63), V( 33), V(-50), V(-30), V(-12), V( -62) }, { V(-55), V(64), V(32), V(-55), V(-30), V(-11), V(-61) },
{ V(-11), V( 77), V( 22), V( -6), V( 31), V( 8), V( -45) }, { V(-11), V(75), V(19), V(-6), V(26), V(9), V(-47) },
{ V(-39), V(-12), V(-29), V(-50), V(-43), V(-68), V(-164) } { V(-41), V(-11), V(-27), V(-58), V(-42), V(-66), V(-163) }
}; };
// Danger of enemy pawns moving toward our king by [distance from edge][rank]. // Danger of enemy pawns moving toward our king by [distance from edge][rank].
@@ -63,17 +63,17 @@ namespace {
// is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn // is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn
// on edge, likely blocked by our king. // on edge, likely blocked by our king.
constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = { constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = {
{ V( 87), V(-288), V(-168), V( 96), V( 47), V( 44), V( 46) }, { V(94), V(-280), V(-170), V(90), V(59), V(47), V(53) },
{ V( 42), V( -25), V( 120), V( 45), V( 34), V( -9), V( 24) }, { V(43), V(-17), V(128), V(39), V(26), V(-17), V(15) },
{ V( -8), V( 51), V( 167), V( 35), V( -4), V(-16), V(-12) }, { V(-9), V(62), V(170), V(34), V(-5), V(-20), V(-11) },
{ V(-17), V( -13), V( 100), V( 4), V( 9), V(-16), V(-31) } { V(-27), V(-19), V(106), V(10), V(2), V(-13), V(-24) }
}; };
// KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties // KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties
// for king when the king is on a semi-open or open file. // for king when the king is on a semi-open or open file.
constexpr Score KingOnFile[2][2] = {{ S(-21,10), S(-7, 1) }, constexpr Score KingOnFile[2][2] = {{ S(-18,11), S(-6,-3) },
{ S( 0,-3), S( 9,-4) }}; { S( 0, 0), S( 5,-4) }};
#undef S #undef S
#undef V #undef V
+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
@@ -1019,9 +1019,9 @@ void Position::do_null_move(StateInfo& newSt) {
} }
st->key ^= Zobrist::side; st->key ^= Zobrist::side;
++st->rule50;
prefetch(TT.first_entry(key())); prefetch(TT.first_entry(key()));
++st->rule50;
st->pliesFromNull = 0; st->pliesFromNull = 0;
sideToMove = ~sideToMove; sideToMove = ~sideToMove;
+18 -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
@@ -123,6 +123,7 @@ 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;
@@ -312,6 +313,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;
} }
+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
+341 -295
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -55,6 +55,7 @@ struct Stack {
bool ttPv; bool ttPv;
bool ttHit; bool ttHit;
int doubleExtensions; int doubleExtensions;
int cutoffCnt;
}; };
@@ -74,6 +75,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;
+387
View File
@@ -0,0 +1,387 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STOCKFISH_SIMD_H_INCLUDED
#define STOCKFISH_SIMD_H_INCLUDED
#if defined(USE_AVX2)
# include <immintrin.h>
#elif defined(USE_SSE41)
# include <smmintrin.h>
#elif defined(USE_SSSE3)
# include <tmmintrin.h>
#elif defined(USE_SSE2)
# include <emmintrin.h>
#elif defined(USE_MMX)
# include <mmintrin.h>
#elif defined(USE_NEON)
# include <arm_neon.h>
#endif
// The inline asm is only safe for GCC, where it is necessary to get good codegen.
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101693
// Clang does fine without it.
// Play around here: https://godbolt.org/z/7EWqrYq51
#if (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER))
#define USE_INLINE_ASM
#endif
// Use either the AVX512 or AVX-VNNI version of the VNNI instructions.
#if defined(USE_AVXVNNI)
#define VNNI_PREFIX "%{vex%} "
#else
#define VNNI_PREFIX ""
#endif
namespace Stockfish::Simd {
#if defined (USE_AVX512)
[[maybe_unused]] static int m512_hadd(__m512i sum, int bias) {
return _mm512_reduce_add_epi32(sum) + bias;
}
/*
Parameters:
sum0 = [zmm0.i128[0], zmm0.i128[1], zmm0.i128[2], zmm0.i128[3]]
sum1 = [zmm1.i128[0], zmm1.i128[1], zmm1.i128[2], zmm1.i128[3]]
sum2 = [zmm2.i128[0], zmm2.i128[1], zmm2.i128[2], zmm2.i128[3]]
sum3 = [zmm3.i128[0], zmm3.i128[1], zmm3.i128[2], zmm3.i128[3]]
Returns:
ret = [
reduce_add_epi32(zmm0.i128[0]), reduce_add_epi32(zmm1.i128[0]), reduce_add_epi32(zmm2.i128[0]), reduce_add_epi32(zmm3.i128[0]),
reduce_add_epi32(zmm0.i128[1]), reduce_add_epi32(zmm1.i128[1]), reduce_add_epi32(zmm2.i128[1]), reduce_add_epi32(zmm3.i128[1]),
reduce_add_epi32(zmm0.i128[2]), reduce_add_epi32(zmm1.i128[2]), reduce_add_epi32(zmm2.i128[2]), reduce_add_epi32(zmm3.i128[2]),
reduce_add_epi32(zmm0.i128[3]), reduce_add_epi32(zmm1.i128[3]), reduce_add_epi32(zmm2.i128[3]), reduce_add_epi32(zmm3.i128[3])
]
*/
[[maybe_unused]] static __m512i m512_hadd128x16_interleave(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) {
__m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
__m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
__m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
__m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
__m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
__m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
__m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
__m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
return _mm512_add_epi32(sum0123a, sum0123b);
}
[[maybe_unused]] static __m128i m512_haddx4(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3,
__m128i bias) {
__m512i sum = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
__m256i sum256lo = _mm512_castsi512_si256(sum);
__m256i sum256hi = _mm512_extracti64x4_epi64(sum, 1);
sum256lo = _mm256_add_epi32(sum256lo, sum256hi);
__m128i sum128lo = _mm256_castsi256_si128(sum256lo);
__m128i sum128hi = _mm256_extracti128_si256(sum256lo, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m512_add_dpbusd_epi32(
__m512i& acc,
__m512i a,
__m512i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm512_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp = _mm512_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a, b);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m512_add_dpbusd_epi32x2(
__m512i& acc,
__m512i a0, __m512i b0,
__m512i a1, __m512i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b0], %[a0], %[acc]\n\t"
"vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm512_dpbusd_epi32(acc, a0, b0);
acc = _mm512_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp0 = _mm512_maddubs_epi16(a0, b0);
__m512i tmp1 = _mm512_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a0, b0);
__m512i product1 = _mm512_maddubs_epi16(a1, b1);
product0 = _mm512_adds_epi16(product0, product1);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_AVX2)
[[maybe_unused]] static int m256_hadd(__m256i sum, int bias) {
__m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
return _mm_cvtsi128_si32(sum128) + bias;
}
[[maybe_unused]] static __m128i m256_haddx4(
__m256i sum0, __m256i sum1, __m256i sum2, __m256i sum3,
__m128i bias) {
sum0 = _mm256_hadd_epi32(sum0, sum1);
sum2 = _mm256_hadd_epi32(sum2, sum3);
sum0 = _mm256_hadd_epi32(sum0, sum2);
__m128i sum128lo = _mm256_castsi256_si128(sum0);
__m128i sum128hi = _mm256_extracti128_si256(sum0, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m256_add_dpbusd_epi32(
__m256i& acc,
__m256i a,
__m256i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
VNNI_PREFIX "vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm256_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp = _mm256_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a, b);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m256_add_dpbusd_epi32x2(
__m256i& acc,
__m256i a0, __m256i b0,
__m256i a1, __m256i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
VNNI_PREFIX "vpdpbusd %[b0], %[a0], %[acc]\n\t"
VNNI_PREFIX "vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm256_dpbusd_epi32(acc, a0, b0);
acc = _mm256_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp0 = _mm256_maddubs_epi16(a0, b0);
__m256i tmp1 = _mm256_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a0, b0);
__m256i product1 = _mm256_maddubs_epi16(a1, b1);
product0 = _mm256_adds_epi16(product0, product1);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_SSSE3)
[[maybe_unused]] static int m128_hadd(__m128i sum, int bias) {
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
return _mm_cvtsi128_si32(sum) + bias;
}
[[maybe_unused]] static __m128i m128_haddx4(
__m128i sum0, __m128i sum1, __m128i sum2, __m128i sum3,
__m128i bias) {
sum0 = _mm_hadd_epi32(sum0, sum1);
sum2 = _mm_hadd_epi32(sum2, sum3);
sum0 = _mm_hadd_epi32(sum0, sum2);
return _mm_add_epi32(sum0, bias);
}
[[maybe_unused]] static void m128_add_dpbusd_epi32(
__m128i& acc,
__m128i a,
__m128i b) {
# if defined (USE_INLINE_ASM)
__m128i tmp = _mm_maddubs_epi16(a, b);
asm(
"pmaddwd %[ones], %[tmp]\n\t"
"paddd %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
[[maybe_unused]] static void m128_add_dpbusd_epi32x2(
__m128i& acc,
__m128i a0, __m128i b0,
__m128i a1, __m128i b1) {
# if defined (USE_INLINE_ASM)
__m128i tmp0 = _mm_maddubs_epi16(a0, b0);
__m128i tmp1 = _mm_maddubs_epi16(a1, b1);
asm(
"paddsw %[tmp1], %[tmp0]\n\t"
"pmaddwd %[ones], %[tmp0]\n\t"
"paddd %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a0, b0);
__m128i product1 = _mm_maddubs_epi16(a1, b1);
product0 = _mm_adds_epi16(product0, product1);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
#endif
#if defined (USE_NEON)
[[maybe_unused]] static int neon_m128_reduce_add_epi32(int32x4_t s) {
# if USE_NEON >= 8
return vaddvq_s32(s);
# else
return s[0] + s[1] + s[2] + s[3];
# endif
}
[[maybe_unused]] static int neon_m128_hadd(int32x4_t sum, int bias) {
return neon_m128_reduce_add_epi32(sum) + bias;
}
[[maybe_unused]] static int32x4_t neon_m128_haddx4(
int32x4_t sum0, int32x4_t sum1, int32x4_t sum2, int32x4_t sum3,
int32x4_t bias) {
int32x4_t hsums {
neon_m128_reduce_add_epi32(sum0),
neon_m128_reduce_add_epi32(sum1),
neon_m128_reduce_add_epi32(sum2),
neon_m128_reduce_add_epi32(sum3)
};
return vaddq_s32(hsums, bias);
}
[[maybe_unused]] static void neon_m128_add_dpbusd_epi32x2(
int32x4_t& acc,
int8x8_t a0, int8x8_t b0,
int8x8_t a1, int8x8_t b1) {
int16x8_t product = vmull_s8(a0, b0);
product = vmlal_s8(product, a1, b1);
acc = vpadalq_s16(acc, product);
}
#endif
}
#endif // STOCKFISH_SIMD_H_INCLUDED
+12 -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
@@ -769,7 +769,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)
@@ -812,7 +812,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) {
@@ -827,7 +827,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]))
@@ -857,7 +857,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])
@@ -885,7 +885,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[].
// //
@@ -917,7 +917,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
@@ -937,7 +937,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];
@@ -947,7 +947,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) {
@@ -1290,7 +1290,7 @@ void Tablebases::init(const std::string& paths) {
for (auto s : diagonal) for (auto s : diagonal)
MapA1D1D4[s] = code++; MapA1D1D4[s] = code++;
// MapKK[] encodes all the 461 possible legal positions of two kings where // MapKK[] encodes all the 462 possible legal positions of two kings where
// the first is in the a1-d1-d4 triangle. If the first king is on the a1-d4 // the first is in the a1-d1-d4 triangle. If the first king is on the a1-d4
// diagonal, the other one shall not to be above the a1-h8 diagonal. // diagonal, the other one shall not to be above the a1-h8 diagonal.
std::vector<std::pair<int, Square>> bothOnDiagonal; std::vector<std::pair<int, Square>> bothOnDiagonal;
@@ -1317,7 +1317,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;
@@ -1337,7 +1337,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)
}; };
+4 -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
@@ -60,15 +60,15 @@ void Thread::clear() {
counterMoves.fill(MOVE_NONE); counterMoves.fill(MOVE_NONE);
mainHistory.fill(0); mainHistory.fill(0);
lowPlyHistory.fill(0);
captureHistory.fill(0); captureHistory.fill(0);
previousDepth = 0;
for (bool inCheck : { false, true }) for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures }) for (StatsType c : { NoCaptures, Captures })
{ {
for (auto& to : continuationHistory[inCheck][c]) for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to) for (auto& h : to)
h->fill(0); h->fill(-71);
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1); continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
} }
} }
@@ -187,6 +187,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;
} }
+7 -5
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -88,19 +88,20 @@ public:
Pawns::Table pawnsTable; Pawns::Table pawnsTable;
Material::Table materialTable; Material::Table materialTable;
size_t pvIdx, pvLast; size_t pvIdx, pvLast;
uint64_t ttHitAverage; RunningAverage complexityAverage;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly; int selDepth, nmpMinPly;
Color nmpColor; Color nmpColor;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges; Value bestValue, optimism[COLOR_NB];
uint64_t maxNodes; uint64_t maxNodes;
Position rootPos; Position rootPos;
StateInfo rootState; StateInfo rootState;
Search::RootMoves rootMoves; Search::RootMoves rootMoves;
Depth rootDepth, completedDepth; Depth rootDepth, completedDepth, depth, previousDepth;
Value rootDelta;
CounterMoveHistory counterMoves; CounterMoveHistory counterMoves;
ButterflyHistory mainHistory; ButterflyHistory mainHistory;
LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory; CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2]; ContinuationHistory continuationHistory[2][2];
Score trend; Score trend;
@@ -123,6 +124,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
+8 -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
@@ -68,6 +68,9 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
TimePoint timeLeft = std::max(TimePoint(1), TimePoint timeLeft = std::max(TimePoint(1),
limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * (2 + mtg)); limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * (2 + mtg));
// Use extra time with larger increments
double optExtra = std::clamp(1.0 + 12.0 * limits.inc[us] / limits.time[us], 1.0, 1.12);
// A user may scale time usage by setting UCI option "Slow Mover" // A user may scale time usage by setting UCI option "Slow Mover"
// Default is 100 and changing this value will probably lose elo. // Default is 100 and changing this value will probably lose elo.
timeLeft = slowMover * timeLeft / 100; timeLeft = slowMover * timeLeft / 100;
@@ -78,15 +81,16 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
if (limits.movestogo == 0) if (limits.movestogo == 0)
{ {
optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042, optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042,
0.2 * limits.time[us] / double(timeLeft)); 0.2 * limits.time[us] / double(timeLeft))
* optExtra;
maxScale = std::min(7.0, 4.0 + ply / 12.0); maxScale = std::min(7.0, 4.0 + ply / 12.0);
} }
// x moves in y seconds (+ z increment) // x moves in y seconds (+ z increment)
else else
{ {
optScale = std::min((0.8 + ply / 128.0) / mtg, optScale = std::min((0.88 + ply / 116.4) / mtg,
0.8 * limits.time[us] / double(timeLeft)); 0.88 * limits.time[us] / double(timeLeft));
maxScale = std::min(6.3, 1.5 + 0.11 * mtg); maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
} }
+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
@@ -45,9 +45,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;
+2 -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
@@ -457,7 +457,7 @@ constexpr Square rotate180(Square sq) {
} }
constexpr int from_to(Move m) { constexpr int from_to(Move m) {
return m & 0xFFF; return m & 0xFFF;
} }
constexpr MoveType type_of(Move m) { constexpr MoveType type_of(Move m) {
@@ -472,10 +472,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);
+10 -4
View File
@@ -1,6 +1,6 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -220,8 +220,8 @@ namespace UCI {
// Coefficients of a 3rd order polynomial fit based on fishtest data // Coefficients of a 3rd order polynomial fit based on fishtest data
// for two parameters needed to transform eval to the argument of a // for two parameters needed to transform eval to the argument of a
// logistic function. // logistic function.
double as[] = {-3.68389304, 30.07065921, -60.52878723, 149.53378557}; double as[] = {-1.17202460e-01, 5.94729104e-01, 1.12065546e+01, 1.22606222e+02};
double bs[] = {-2.0181857, 15.85685038, -29.83452023, 47.59078827}; double bs[] = {-1.79066759, 11.30759193, -17.43677612, 36.47147479};
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3]; double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3]; double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
@@ -380,8 +380,14 @@ void UCI::loop(int argc, char* argv[]) {
std::cout << th.id() << '\n'; std::cout << th.id() << '\n';
}); });
} }
else if (token == "--help" || token == "help" || token == "--license" || token == "license")
sync_cout << "\nStockfish is a powerful chess engine and free software licensed under the GNU GPLv3."
"\nStockfish is normally used with a separate graphical user interface (GUI)."
"\nStockfish implements the universal chess interface (UCI) to exchange information."
"\nFor further information see https://github.com/official-stockfish/Stockfish#readme"
"\nor the corresponding README.md and Copying.txt files distributed with this program.\n" << sync_endl;
else if (!token.empty() && token[0] != '#') else if (!token.empty() && token[0] != '#')
sync_cout << "Unknown command: " << cmd << sync_endl; sync_cout << "Unknown command: '" << cmd << "'. Type help for more information." << sync_endl;
} while (token != "quit" && argc == 1); // Command line args are one-shot } while (token != "quit" && argc == 1); // Command line args are one-shot
} }
+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
@@ -185,7 +185,7 @@ Option& Option::operator=(const string& v) {
assert(!type.empty()); assert(!type.empty());
if ( (type != "button" && v.empty()) if ( (type != "button" && type != "string" && v.empty())
|| (type == "check" && v != "true" && v != "false") || (type == "check" && v != "true" && v != "false")
|| (type == "spin" && (stof(v) < min || stof(v) > max))) || (type == "spin" && (stof(v) < min || stof(v) > max)))
return *this; return *this;
+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