From e8caa6640df15b1823d5d4b94e759d52923769e6 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Thu, 8 Dec 2022 20:33:32 +0100 Subject: [PATCH 001/192] Restore development version No functional change --- src/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.cpp b/src/misc.cpp index 2d86969f..c7fa0e9a 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -68,7 +68,7 @@ namespace Stockfish { namespace { /// Version number or dev. -const string version = "15.1"; +const string version = "dev"; /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We From 9fc203a3d05262ac74bfca8b4618155e18d76003 Mon Sep 17 00:00:00 2001 From: ppigazzini Date: Thu, 8 Dec 2022 18:32:30 +0100 Subject: [PATCH 002/192] Set the right PATH for ARM compiler and build tests in CI Fix for the GitHub upgrade: https://github.com/actions/runner-images/issues/5879 that broke our ARM workflows because it changed the value of the ANDROID_NDK_HOME variable referenced in our PATH. closes https://github.com/official-stockfish/Stockfish/pull/4267 No functional change --- .github/workflows/stockfish_test.yml | 43 ++++++++++++---------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/.github/workflows/stockfish_test.yml b/.github/workflows/stockfish_test.yml index 46b4e26f..e4e6205f 100644 --- a/.github/workflows/stockfish_test.yml +++ b/.github/workflows/stockfish_test.yml @@ -35,7 +35,7 @@ jobs: os: ubuntu-20.04, compiler: aarch64-linux-android21-clang++, comp: ndk, - run_armv8_tests: false, + run_armv8_tests: true, shell: 'bash {0}' } - { @@ -43,7 +43,7 @@ jobs: os: ubuntu-20.04, compiler: armv7a-linux-androideabi21-clang++, comp: ndk, - run_armv7_tests: false, + run_armv7_tests: true, shell: 'bash {0}' } - { @@ -92,15 +92,6 @@ jobs: msys_env: 'clang-x86_64-clang', shell: 'msys2 {0}' } - exclude: - - config: - { - name: "Ubuntu 20.04 NDK armv7" - } - - config: - { - name: "Ubuntu 20.04 NDK armv8" - } defaults: run: working-directory: src @@ -120,8 +111,8 @@ jobs: if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 with: - msystem: ${{matrix.config.msys_sys}} - install: mingw-w64-${{matrix.config.msys_env}} make git expect + msystem: ${{ matrix.config.msys_sys }} + install: mingw-w64-${{ matrix.config.msys_env }} make git expect - name: Download the used network from the fishtest framework run: | @@ -134,7 +125,14 @@ jobs: - name: Check compiler run: | - export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin + if [ $COMP == ndk ]; then + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk + SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + fi $COMPILER -v - name: Test help target @@ -233,9 +231,8 @@ jobs: ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle - ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT - export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv8 build @@ -250,9 +247,8 @@ jobs: ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle - ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT - export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv7 build @@ -265,9 +261,8 @@ jobs: ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle - ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT - export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv7-neon build @@ -281,4 +276,4 @@ jobs: make clean make -j2 ARCH=x86-64-modern build ../tests/perft.sh - ../tests/reprosearch.sh \ No newline at end of file + ../tests/reprosearch.sh From 98965c139df1483a3d684ee8bc7a60dc4b95efa1 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Fri, 2 Dec 2022 18:23:28 +0300 Subject: [PATCH 003/192] doEvenDeeperSearch + tuning Credit for the main idea of doEvenDeeperSearch goes to Vizvezdenec, tuning by FauziAkram: Expansion of existing logic of doDeeperSearch - if value from LMR is really really good do full depth search not 1 ply deeper but rather 2 instead. Passed STC: LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 330048 W: 87672 L: 86942 D: 155434 Ptnml(0-2): 1012, 36739, 88912, 37229, 1132 https://tests.stockfishchess.org/tests/view/638a1cadd2b9c924c4c621d2 Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 216696 W: 57891 L: 57240 D: 101565 Ptnml(0-2): 72, 21221, 65152, 21790, 113 https://tests.stockfishchess.org/tests/view/638c7d52a971f1f096c68fe2 closes https://github.com/official-stockfish/Stockfish/pull/4256 Bench: 3461830 --- src/evaluate.cpp | 14 +++++++------- src/search.cpp | 7 ++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 87412b81..93e665df 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { else { int nnueComplexity; - int scale = 1064 + 106 * pos.non_pawn_material() / 5120; + int scale = 1076 + 96 * pos.non_pawn_material() / 5120; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; @@ -1071,21 +1071,21 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 416 * nnueComplexity - + 424 * abs(psq - nnue) + nnueComplexity = ( 412 * nnueComplexity + + 428 * abs(psq - nnue) + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) - ) / 1024; + ) / 1026; // Return hybrid NNUE complexity to caller if (complexity) *complexity = nnueComplexity; - optimism = optimism * (269 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 754)) / 1024; + optimism = optimism * (278 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 755)) / 1024; } // Damp down the evaluation linearly when shuffling - v = v * (195 - pos.rule50_count()) / 211; + v = v * (197 - pos.rule50_count()) / 214; // 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); diff --git a/src/search.cpp b/src/search.cpp index c8163d1f..343c098a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((12 * d + 282) * d - 349 , 1594); + return std::min((12 * d + 282) * d - 349 , 1480); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -1172,7 +1172,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13628 + 4000 * (depth > 7 && depth < 19)); + r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension @@ -1187,9 +1187,10 @@ moves_loop: // When in check, search starts here // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 582; const bool doShallowerSearch = value < bestValue + newDepth; - newDepth += doDeeperSearch - doShallowerSearch; + newDepth += doDeeperSearch - doShallowerSearch + doEvenDeeperSearch; if (newDepth > d) value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); From cb0c7a98485fbef4e5d6ed5f5b08201113ce0b4e Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Tue, 6 Dec 2022 19:09:33 +0100 Subject: [PATCH 004/192] Correctly output lowerbound/upperbound scores fixes the lowerbound/upperbound output by avoiding scores outside the alpha,beta bracket. Since SF search uses fail-soft we can't simply take the returned value as score. closes https://github.com/official-stockfish/Stockfish/pull/4259 No functional change --- src/search.cpp | 14 ++++++++++---- src/search.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 343c098a..04f73e1c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1245,10 +1245,16 @@ moves_loop: // When in check, search starts here // PV move or new best move? if (moveCount == 1 || value > alpha) { - rm.score = value; + rm.score = rm.uciScore = value; rm.selDepth = thisThread->selDepth; - rm.scoreLowerbound = value >= beta; - rm.scoreUpperbound = value <= alpha; + if (value >= beta) { + rm.scoreLowerbound = true; + rm.uciScore = beta; + } + else if (value <= alpha) { + rm.scoreUpperbound = true; + rm.uciScore = alpha; + } rm.pv.resize(1); assert((ss+1)->pv); @@ -1841,7 +1847,7 @@ string UCI::pv(const Position& pos, Depth depth) { continue; Depth d = updated ? depth : std::max(1, depth - 1); - Value v = updated ? rootMoves[i].score : rootMoves[i].previousScore; + Value v = updated ? rootMoves[i].uciScore : rootMoves[i].previousScore; if (v == -VALUE_INFINITE) v = VALUE_ZERO; diff --git a/src/search.h b/src/search.h index 60f2762a..b620202d 100644 --- a/src/search.h +++ b/src/search.h @@ -71,6 +71,7 @@ struct RootMove { Value score = -VALUE_INFINITE; Value previousScore = -VALUE_INFINITE; Value averageScore = -VALUE_INFINITE; + Value uciScore = -VALUE_INFINITE; bool scoreLowerbound = false; bool scoreUpperbound = false; int selDepth = 0; From 74fb936dbd49c61bf3352febd1c57a68888100d0 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Tue, 6 Dec 2022 21:32:42 +0900 Subject: [PATCH 005/192] Invoke .depend only on build targets Add a constraint so that the dependency build only occurs when users actually run build tasks. This fixes a bug on some systems where gcc/g++ is not available. closes https://github.com/official-stockfish/Stockfish/pull/4255 No functional change --- src/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 917bd5c0..0c98391b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -512,7 +512,7 @@ endif ### Sometimes gcc is really clang ifeq ($(COMP),gcc) - gccversion = $(shell $(CXX) --version) + gccversion = $(shell $(CXX) --version 2>/dev/null) gccisclang = $(findstring clang,$(gccversion)) ifneq ($(gccisclang),) profile_make = clang-profile-make @@ -1006,4 +1006,6 @@ icc-profile-use: .depend: $(SRCS) -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null +ifneq (, $(filter $(MAKECMDGOALS), build profile-build)) -include .depend +endif From aa603cfeeb6e902bcf996758515170b996ec1fb6 Mon Sep 17 00:00:00 2001 From: ppigazzini Date: Thu, 8 Dec 2022 20:50:32 +0100 Subject: [PATCH 006/192] GitHub Action: upload ARM artifacts And some clean up in other files. closes https://github.com/official-stockfish/Stockfish/pull/4269 No functional change --- .github/workflows/stockfish.yml | 3 + .github/workflows/stockfish_arm_binaries.yml | 117 +++++++++++++++++++ .github/workflows/stockfish_binaries.yml | 7 +- .github/workflows/stockfish_compile_test.yml | 5 +- .github/workflows/stockfish_sanitizers.yml | 5 +- .github/workflows/stockfish_test.yml | 20 ++-- 6 files changed, 137 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/stockfish_arm_binaries.yml diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index 07ecfc07..6345b27c 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -19,3 +19,6 @@ jobs: Binaries: if: github.ref == 'refs/heads/master' uses: ./.github/workflows/stockfish_binaries.yml + ARM_Binaries: + if: github.ref == 'refs/heads/master' + uses: ./.github/workflows/stockfish_arm_binaries.yml diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml new file mode 100644 index 00000000..cf3ae710 --- /dev/null +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -0,0 +1,117 @@ +name: Stockfish +on: + workflow_call: +jobs: + Stockfish: + name: ${{ matrix.config.name }} ${{ matrix.binaries }} + runs-on: ${{ matrix.config.os }} + env: + COMPILER: ${{ matrix.config.compiler }} + COMP: ${{ matrix.config.comp }} + EMU: ${{ matrix.config.emu }} + EXT: ${{ matrix.config.ext }} + OS: ${{ matrix.config.os }} + BINARY: ${{ matrix.binaries }} + strategy: + matrix: + config: + - { + name: "Android NDK aarch64", + os: ubuntu-20.04, + compiler: aarch64-linux-android21-clang++, + emu: qemu-aarch64, + comp: ndk, + shell: 'bash {0}' + } + - { + name: "Android NDK arm", + os: ubuntu-20.04, + compiler: armv7a-linux-androideabi21-clang++, + emu: qemu-arm, + comp: ndk, + shell: 'bash {0}' + } + binaries: + - armv8 + - armv7 + - armv7-neon + exclude: + - binaries: armv8 + config: {compiler: armv7a-linux-androideabi21-clang++} + - binaries: armv7 + config: {compiler: aarch64-linux-android21-clang++} + - binaries: armv7-neon + config: {compiler: aarch64-linux-android21-clang++} + defaults: + run: + working-directory: src + shell: ${{ matrix.config.shell }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Download required linux packages + if: runner.os == 'Linux' + run: | + sudo apt update + sudo apt install qemu-user + + - name: Download the used network from the fishtest framework + run: | + make net + + - name: Check compiler + run: | + if [ $COMP == ndk ]; then + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + fi + $COMPILER -v + + - name: Test help target + run: | + make help + + # Compile profile guided builds + + - name: Compile ${{ matrix.binaries }} build + run: | + if [ $COMP == ndk ]; then + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 + export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export LDFLAGS="-static -Wno-unused-command-line-argument" + fi + make clean + make -j2 profile-build ARCH=$BINARY COMP=$COMP WINE_PATH=$EMU + make strip ARCH=$BINARY COMP=$COMP + mv ./stockfish$EXT ../stockfish-android-$BINARY$EXT + + - name: Remove non src files + run: rm -f *.o .depend *.nnue + + - name: Create tar archive. + run: | + cd .. + mkdir stockfish + cp -r src stockfish/ + cp stockfish-android-$BINARY$EXT stockfish/ + cp "Top CPU Contributors.txt" stockfish/ + cp Copying.txt stockfish/ + cp AUTHORS stockfish/ + tar -cvf stockfish-android-$BINARY.tar stockfish + + - name: Upload binaries + uses: actions/upload-artifact@v3 + with: + name: stockfish-android-${{ matrix.binaries }} + path: | + stockfish-android-${{ matrix.binaries }}.tar diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 0b205ded..1fa123fa 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -63,8 +63,8 @@ jobs: if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 with: - msystem: ${{matrix.config.msys_sys}} - install: mingw-w64-${{matrix.config.msys_env}} make git expect + msystem: ${{ matrix.config.msys_sys }} + install: mingw-w64-${{ matrix.config.msys_env }} make - name: Download the used network from the fishtest framework run: | @@ -72,7 +72,6 @@ jobs: - name: Check compiler run: | - export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin $COMPILER -v - name: Test help target @@ -85,7 +84,7 @@ jobs: run: | make clean make -j2 profile-build ARCH=$BINARY COMP=$COMP - strip ./stockfish$EXT + make strip ARCH=$BINARY COMP=$COMP mv ./stockfish$EXT ../stockfish-$OS-$BINARY$EXT - name: Remove non src files diff --git a/.github/workflows/stockfish_compile_test.yml b/.github/workflows/stockfish_compile_test.yml index 63136737..8467f52d 100644 --- a/.github/workflows/stockfish_compile_test.yml +++ b/.github/workflows/stockfish_compile_test.yml @@ -72,7 +72,7 @@ jobs: uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.config.msys_sys}} - install: mingw-w64-${{matrix.config.msys_env}} make git expect + install: mingw-w64-${{matrix.config.msys_env}} make - name: Download the used network from the fishtest framework run: | @@ -80,7 +80,6 @@ jobs: - name: Check compiler run: | - export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin $COMPILER -v - name: Test help target @@ -112,4 +111,4 @@ jobs: - name: Compile x86-64-vnni256 build run: | make clean - make -j2 ARCH=x86-64-vnni256 build \ No newline at end of file + make -j2 ARCH=x86-64-vnni256 build diff --git a/.github/workflows/stockfish_sanitizers.yml b/.github/workflows/stockfish_sanitizers.yml index 61eaf0c9..b74c2f97 100644 --- a/.github/workflows/stockfish_sanitizers.yml +++ b/.github/workflows/stockfish_sanitizers.yml @@ -52,7 +52,7 @@ jobs: - name: Download required linux packages run: | sudo apt update - sudo apt install expect valgrind g++-multilib qemu-user + sudo apt install expect valgrind g++-multilib - name: Download the used network from the fishtest framework run: | @@ -60,7 +60,6 @@ jobs: - name: Check compiler run: | - export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin $COMPILER -v - name: Test help target @@ -74,4 +73,4 @@ jobs: export CXXFLAGS="-O1 -fno-inline" make clean make -j2 ARCH=x86-64-modern ${{ matrix.sanitizers.make_option }} debug=yes optimize=no build > /dev/null - ../tests/instrumented.sh --${{ matrix.sanitizers.instrumented_option }} \ No newline at end of file + ../tests/instrumented.sh --${{ matrix.sanitizers.instrumented_option }} diff --git a/.github/workflows/stockfish_test.yml b/.github/workflows/stockfish_test.yml index e4e6205f..3cb89d39 100644 --- a/.github/workflows/stockfish_test.yml +++ b/.github/workflows/stockfish_test.yml @@ -31,7 +31,7 @@ jobs: shell: 'bash {0}' } - { - name: "Ubuntu 20.04 NDK armv8", + name: "Android NDK aarch64", os: ubuntu-20.04, compiler: aarch64-linux-android21-clang++, comp: ndk, @@ -39,7 +39,7 @@ jobs: shell: 'bash {0}' } - { - name: "Ubuntu 20.04 NDK armv7", + name: "Android NDK arm", os: ubuntu-20.04, compiler: armv7a-linux-androideabi21-clang++, comp: ndk, @@ -127,8 +127,8 @@ jobs: run: | if [ $COMP == ndk ]; then ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk - SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH @@ -228,8 +228,8 @@ jobs: if: ${{ matrix.config.run_armv8_tests }} run: | ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk - SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH @@ -244,8 +244,8 @@ jobs: if: ${{ matrix.config.run_armv7_tests }} run: | ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk - SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH @@ -258,8 +258,8 @@ jobs: if: ${{ matrix.config.run_armv7_tests }} run: | ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk - SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager echo "y" | $SDKMANAGER "ndk;21.4.7075529" ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH From 9d3fd011f1bc9ef6f3a3091aae10634b31e0032c Mon Sep 17 00:00:00 2001 From: Alfredo Menezes Date: Fri, 9 Dec 2022 12:11:43 -0300 Subject: [PATCH 007/192] Extend all moves at low depth if ttMove is doubly extended If ttMove is doubly extended, we allow a depth growth of the remaining moves. The idea is to get a more realistic score comparison, because of the depth difference. We take some care to avoid this extension for high depths, in order to avoid the cost, since the search result is supposed to be more accurate in this case. This pull request includes some small cleanups. STC: LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 60256 W: 16189 L: 15848 D: 28219 Ptnml(0-2): 182, 6546, 16330, 6889, 181 https://tests.stockfishchess.org/tests/view/639109a1792a529ae8f27777 LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 106232 W: 28487 L: 28053 D: 49692 Ptnml(0-2): 46, 10224, 32145, 10652, 49 https://tests.stockfishchess.org/tests/view/63914cba792a529ae8f282ee closes https://github.com/official-stockfish/Stockfish/pull/4271 Bench: 3622368 --- src/search.cpp | 6 ++++-- src/types.h | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 04f73e1c..ec7cff54 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1067,7 +1067,10 @@ moves_loop: // When in check, search starts here if ( !PvNode && value < singularBeta - 25 && ss->doubleExtensions <= 9) + { extension = 2; + depth += depth < 12; + } } // Multi-cut pruning @@ -1296,7 +1299,7 @@ moves_loop: // When in check, search starts here && depth < 6 && beta < VALUE_KNOWN_WIN && alpha > -VALUE_KNOWN_WIN) - depth -= 1; + depth -= 1; assert(depth > 0); } @@ -1521,7 +1524,6 @@ moves_loop: // When in check, search starts here && futilityBase > -VALUE_KNOWN_WIN && type_of(move) != PROMOTION) { - if (moveCount > 2) continue; diff --git a/src/types.h b/src/types.h index c2087c6c..29c16ce7 100644 --- a/src/types.h +++ b/src/types.h @@ -186,6 +186,9 @@ enum Value : int { VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY, VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY, + // In the code, we make the assumption that these values + // are such that non_pawn_material() can be used to uniquely + // identify the material on the board. PawnValueMg = 126, PawnValueEg = 208, KnightValueMg = 781, KnightValueEg = 854, BishopValueMg = 825, BishopValueEg = 915, From 44ecadee10111f028e28f47df6dfc9accd908293 Mon Sep 17 00:00:00 2001 From: Douglas Matos Gomes Date: Thu, 8 Dec 2022 21:40:07 -0300 Subject: [PATCH 008/192] Simplify redundant condition. closes https://github.com/official-stockfish/Stockfish/pull/4270 No functional change --- src/evaluate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 93e665df..71c4e8d1 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1091,7 +1091,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); // When not using NNUE, return classical complexity to caller - if (complexity && (!useNNUE || useClassical)) + if (complexity && useClassical) *complexity = abs(v - psq); return v; From aedf0251e6170a631b56a24dff31e83b9656933d Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 9 Dec 2022 17:56:55 +0100 Subject: [PATCH 009/192] CI workflows, install git on windows ensures the SF dev version is reported correctly No functional change --- .github/workflows/stockfish_binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 1fa123fa..5ba4784e 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -64,7 +64,7 @@ jobs: uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.config.msys_sys }} - install: mingw-w64-${{ matrix.config.msys_env }} make + install: mingw-w64-${{ matrix.config.msys_env }} make git - name: Download the used network from the fishtest framework run: | From 3a30b478d20c16a357d1e538f1ce9428e7285736 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 9 Dec 2022 18:24:54 +0100 Subject: [PATCH 010/192] CI workflows, install git on windows ensures the SF dev version is reported correctly closes https://github.com/official-stockfish/Stockfish/pull/4272 No functional change --- .github/workflows/stockfish_arm_binaries.yml | 12 ++++++------ .github/workflows/stockfish_binaries.yml | 18 ++++++++---------- .github/workflows/stockfish_compile_test.yml | 14 +++++++------- .github/workflows/stockfish_sanitizers.yml | 12 ++++++------ .github/workflows/stockfish_test.yml | 9 +++++---- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml index cf3ae710..ea738cef 100644 --- a/.github/workflows/stockfish_arm_binaries.yml +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -58,8 +58,7 @@ jobs: sudo apt install qemu-user - name: Download the used network from the fishtest framework - run: | - make net + run: make net - name: Check compiler run: | @@ -74,8 +73,10 @@ jobs: $COMPILER -v - name: Test help target - run: | - make help + run: make help + + - name: Check git + run: git --version # Compile profile guided builds @@ -113,5 +114,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: stockfish-android-${{ matrix.binaries }} - path: | - stockfish-android-${{ matrix.binaries }}.tar + path: stockfish-android-${{ matrix.binaries }}.tar diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 5ba4784e..57535296 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -56,8 +56,7 @@ jobs: - name: Download required linux packages if: runner.os == 'Linux' - run: | - sudo apt update + run: sudo apt update - name: Setup msys and install required packages if: runner.os == 'Windows' @@ -67,16 +66,16 @@ jobs: install: mingw-w64-${{ matrix.config.msys_env }} make git - name: Download the used network from the fishtest framework - run: | - make net + run: make net - name: Check compiler - run: | - $COMPILER -v + run: $COMPILER -v - name: Test help target - run: | - make help + run: make help + + - name: Check git + run: git --version # Compile profile guided builds @@ -105,5 +104,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }} - path: | - stockfish-${{ matrix.config.os }}-${{ matrix.binaries }}.tar + path: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }}.tar diff --git a/.github/workflows/stockfish_compile_test.yml b/.github/workflows/stockfish_compile_test.yml index 8467f52d..eeb4229c 100644 --- a/.github/workflows/stockfish_compile_test.yml +++ b/.github/workflows/stockfish_compile_test.yml @@ -72,19 +72,19 @@ jobs: uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.config.msys_sys}} - install: mingw-w64-${{matrix.config.msys_env}} make + install: mingw-w64-${{matrix.config.msys_env}} make git - name: Download the used network from the fishtest framework - run: | - make net + run: make net - name: Check compiler - run: | - $COMPILER -v + run: $COMPILER -v - name: Test help target - run: | - make help + run: make help + + - name: Check git + run: git --version # x86-64 with newer extensions tests diff --git a/.github/workflows/stockfish_sanitizers.yml b/.github/workflows/stockfish_sanitizers.yml index b74c2f97..fa679330 100644 --- a/.github/workflows/stockfish_sanitizers.yml +++ b/.github/workflows/stockfish_sanitizers.yml @@ -55,16 +55,16 @@ jobs: sudo apt install expect valgrind g++-multilib - name: Download the used network from the fishtest framework - run: | - make net + run: make net - name: Check compiler - run: | - $COMPILER -v + run: $COMPILER -v - name: Test help target - run: | - make help + run: make help + + - name: Check git + run: git --version # Sanitizers diff --git a/.github/workflows/stockfish_test.yml b/.github/workflows/stockfish_test.yml index 3cb89d39..953f6820 100644 --- a/.github/workflows/stockfish_test.yml +++ b/.github/workflows/stockfish_test.yml @@ -115,8 +115,7 @@ jobs: install: mingw-w64-${{ matrix.config.msys_env }} make git expect - name: Download the used network from the fishtest framework - run: | - make net + run: make net - name: Extract the bench number from the commit history run: | @@ -136,8 +135,10 @@ jobs: $COMPILER -v - name: Test help target - run: | - make help + run: make help + + - name: Check git + run: git --version # x86-32 tests From 8f817ef0824e4d940128f5701573f74819f50da5 Mon Sep 17 00:00:00 2001 From: disservin Date: Fri, 9 Dec 2022 21:48:03 +0100 Subject: [PATCH 011/192] Fix lower/upper bounds output Commit cb0c7a98485fbef4e5d6ed5f5b08201113ce0b4e doesnt reset the lower/upper bounds back to false. fixes #4273 closes https://github.com/official-stockfish/Stockfish/pull/4274 No functional change --- src/search.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index ec7cff54..b2a5b940 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1250,6 +1250,8 @@ moves_loop: // When in check, search starts here { rm.score = rm.uciScore = value; rm.selDepth = thisThread->selDepth; + rm.scoreLowerbound = rm.scoreUpperbound = false; + if (value >= beta) { rm.scoreLowerbound = true; rm.uciScore = beta; From 955edf1d1d4f5643b450b1ee1e95dc3f094e1884 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 12 Dec 2022 08:12:10 +0100 Subject: [PATCH 012/192] Revert "doEvenDeeperSearch + tuning" This reverts commit 98965c139df1483a3d684ee8bc7a60dc4b95efa1. The increase of depth could lead to search explosions, most visible with TB. fixes https://github.com/official-stockfish/Stockfish/issues/4276 closes https://github.com/official-stockfish/Stockfish/pull/4256 Bench: 3872306 --- src/evaluate.cpp | 14 +++++++------- src/search.cpp | 7 +++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 71c4e8d1..6a0fae9e 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { else { int nnueComplexity; - int scale = 1076 + 96 * pos.non_pawn_material() / 5120; + int scale = 1064 + 106 * pos.non_pawn_material() / 5120; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; @@ -1071,21 +1071,21 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 412 * nnueComplexity - + 428 * abs(psq - nnue) + nnueComplexity = ( 416 * nnueComplexity + + 424 * abs(psq - nnue) + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) - ) / 1026; + ) / 1024; // Return hybrid NNUE complexity to caller if (complexity) *complexity = nnueComplexity; - optimism = optimism * (278 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 755)) / 1024; + optimism = optimism * (269 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 754)) / 1024; } // Damp down the evaluation linearly when shuffling - v = v * (197 - pos.rule50_count()) / 214; + v = v * (195 - pos.rule50_count()) / 211; // 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); diff --git a/src/search.cpp b/src/search.cpp index b2a5b940..b58a344a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((12 * d + 282) * d - 349 , 1480); + return std::min((12 * d + 282) * d - 349 , 1594); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -1175,7 +1175,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); + r -= ss->statScore / (13628 + 4000 * (depth > 7 && depth < 19)); // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension @@ -1190,10 +1190,9 @@ moves_loop: // When in check, search starts here // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); - const bool doEvenDeeperSearch = value > alpha + 582; const bool doShallowerSearch = value < bestValue + newDepth; - newDepth += doDeeperSearch - doShallowerSearch + doEvenDeeperSearch; + newDepth += doDeeperSearch - doShallowerSearch; if (newDepth > d) value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); From 310928e985a6d87bdd73542e2109f93c31e2cc41 Mon Sep 17 00:00:00 2001 From: mstembera Date: Fri, 9 Dec 2022 18:50:06 -0800 Subject: [PATCH 013/192] Avoid truncated PV in the threaded case strongly prefer to pick as bestThread those threads with a longer PV, among those threads that all found the same bestmove. extended discussion in #4244 closes https://github.com/official-stockfish/Stockfish/pull/4278 No functional change --- src/thread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/thread.cpp b/src/thread.cpp index b7471f60..e8723eb7 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -239,7 +239,8 @@ Thread* ThreadPool::get_best_thread() const { || ( th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY && ( votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]] || ( votes[th->rootMoves[0].pv[0]] == votes[bestThread->rootMoves[0].pv[0]] - && thread_value(th) > thread_value(bestThread))))) + && thread_value(th) * int(th->rootMoves[0].pv.size() > 2) + > thread_value(bestThread) * int(bestThread->rootMoves[0].pv.size() > 2))))) bestThread = th; return bestThread; From 5fe1fa0210e25cecc9de5520da56173ef94b8e59 Mon Sep 17 00:00:00 2001 From: ppigazzini Date: Sun, 11 Dec 2022 12:06:22 +0100 Subject: [PATCH 014/192] GitHub Actions: install NDK once and clean up yaml Use Ubuntu 22.04 as runner for NDK to avoid a qemu bug with `profile-build` closes https://github.com/official-stockfish/Stockfish/pull/4280 No functional change --- .github/workflows/stockfish_arm_binaries.yml | 56 +++--- .github/workflows/stockfish_binaries.yml | 42 ++--- .github/workflows/stockfish_compile_test.yml | 80 ++++---- .github/workflows/stockfish_sanitizers.yml | 44 ++--- .github/workflows/stockfish_test.yml | 184 ++++++++----------- 5 files changed, 177 insertions(+), 229 deletions(-) diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml index ea738cef..a1b3cdab 100644 --- a/.github/workflows/stockfish_arm_binaries.yml +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -15,22 +15,18 @@ jobs: strategy: matrix: config: - - { - name: "Android NDK aarch64", - os: ubuntu-20.04, - compiler: aarch64-linux-android21-clang++, - emu: qemu-aarch64, - comp: ndk, - shell: 'bash {0}' - } - - { - name: "Android NDK arm", - os: ubuntu-20.04, - compiler: armv7a-linux-androideabi21-clang++, - emu: qemu-arm, - comp: ndk, - shell: 'bash {0}' - } + - name: Android NDK aarch64 + os: ubuntu-22.04 + compiler: aarch64-linux-android21-clang++ + emu: qemu-aarch64 + comp: ndk + shell: bash {0} + - name: Android NDK arm + os: ubuntu-22.04 + compiler: armv7a-linux-androideabi21-clang++ + emu: qemu-arm + comp: ndk + shell: bash {0} binaries: - armv8 - armv7 @@ -57,18 +53,27 @@ jobs: sudo apt update sudo apt install qemu-user + - name: Install NDK + if: runner.os == 'Linux' + run: | + if [ $COMP == ndk ]; then + NDKV="21.4.7075529" + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;$NDKV" + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$NDKV + ANDROID_NDK_BIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin + echo "ANDROID_NDK_BIN=$ANDROID_NDK_BIN" >> $GITHUB_ENV + fi + - name: Download the used network from the fishtest framework run: make net - name: Check compiler run: | if [ $COMP == ndk ]; then - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH fi $COMPILER -v @@ -83,12 +88,7 @@ jobs: - name: Compile ${{ matrix.binaries }} build run: | if [ $COMP == ndk ]; then - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" fi make clean diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 57535296..06b13a9e 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -14,30 +14,24 @@ jobs: strategy: matrix: config: - - { - name: "Ubuntu 20.04 GCC", - os: ubuntu-20.04, - compiler: g++, - comp: gcc, - shell: 'bash {0}' - } - - { - name: "MacOS 12 Apple Clang", - os: macos-12, - compiler: clang++, - comp: clang, - shell: 'bash {0}' - } - - { - name: "Windows 2022 Mingw-w64 GCC x86_64", - os: windows-2022, - compiler: g++, - comp: mingw, - msys_sys: 'mingw64', - msys_env: 'x86_64-gcc', - shell: 'msys2 {0}', - ext: .exe - } + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 + compiler: g++ + comp: gcc + shell: bash {0} + - name: MacOS 12 Apple Clang + os: macos-12 + compiler: clang++ + comp: clang + shell: bash {0} + - name: Windows 2022 Mingw-w64 GCC x86_64 + os: windows-2022 + compiler: g++ + comp: mingw + msys_sys: mingw64 + msys_env: x86_64-gcc + shell: msys2 {0} + ext: .exe binaries: - x86-64 - x86-64-modern diff --git a/.github/workflows/stockfish_compile_test.yml b/.github/workflows/stockfish_compile_test.yml index eeb4229c..c7280a85 100644 --- a/.github/workflows/stockfish_compile_test.yml +++ b/.github/workflows/stockfish_compile_test.yml @@ -11,52 +11,40 @@ jobs: strategy: matrix: config: - - { - name: "Ubuntu 20.04 GCC", - os: ubuntu-20.04, - compiler: g++, - comp: gcc, - shell: 'bash {0}' - } - - { - name: "Ubuntu 20.04 Clang", - os: ubuntu-20.04, - compiler: clang++, - comp: clang, - shell: 'bash {0}' - } - - { - name: "MacOS 12 Apple Clang", - os: macos-12, - compiler: clang++, - comp: clang, - shell: 'bash {0}' - } - - { - name: "MacOS 12 GCC 11", - os: macos-12, - compiler: g++-11, - comp: gcc, - shell: 'bash {0}' - } - - { - name: "Windows 2022 Mingw-w64 GCC x86_64", - os: windows-2022, - compiler: g++, - comp: mingw, - msys_sys: 'mingw64', - msys_env: 'x86_64-gcc', - shell: 'msys2 {0}' - } - - { - name: "Windows 2022 Mingw-w64 Clang x86_64", - os: windows-2022, - compiler: clang++, - comp: clang, - msys_sys: 'clang64', - msys_env: 'clang-x86_64-clang', - shell: 'msys2 {0}' - } + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 + compiler: g++ + comp: gcc + shell: bash {0} + - name: Ubuntu 20.04 Clang + os: ubuntu-20.04 + compiler: clang++ + comp: clang + shell: bash {0} + - name: MacOS 12 Apple Clang + os: macos-12 + compiler: clang++ + comp: clang + shell: bash {0} + - name: MacOS 12 GCC 11 + os: macos-12 + compiler: g++-11 + comp: gcc + shell: bash {0} + - name: Windows 2022 Mingw-w64 GCC x86_64 + os: windows-2022 + compiler: g++ + comp: mingw + msys_sys: mingw64 + msys_env: x86_64-gcc + shell: msys2 {0} + - name: Windows 2022 Mingw-w64 Clang x86_64 + os: windows-2022 + compiler: clang++ + comp: clang + msys_sys: clang64 + msys_env: clang-x86_64-clang + shell: msys2 {0} defaults: run: diff --git a/.github/workflows/stockfish_sanitizers.yml b/.github/workflows/stockfish_sanitizers.yml index fa679330..708c9227 100644 --- a/.github/workflows/stockfish_sanitizers.yml +++ b/.github/workflows/stockfish_sanitizers.yml @@ -12,34 +12,24 @@ jobs: strategy: matrix: config: - - { - name: "Ubuntu 20.04 GCC", - os: ubuntu-20.04, - compiler: g++, - comp: gcc, - shell: 'bash {0}' - } + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 + compiler: g++ + comp: gcc + shell: bash {0} sanitizers: - - { - name: Run with thread sanitizer, - make_option: sanitize=thread, - instrumented_option: sanitizer-thread - } - - { - name: Run with UB sanitizer, - make_option: sanitize=undefined, - instrumented_option: sanitizer-undefined - } - - { - name: Run under valgrind, - make_option: "", - instrumented_option: valgrind - } - - { - name: Run under valgrind-thread, - make_option: "", - instrumented_option: valgrind-thread - } + - name: Run with thread sanitizer + make_option: sanitize=thread + instrumented_option: sanitizer-thread + - name: Run with UB sanitizer + make_option: sanitize=undefined + instrumented_option: sanitizer-undefined + - name: Run under valgrind + make_option: "" + instrumented_option: valgrind + - name: Run under valgrind-thread + make_option: "" + instrumented_option: valgrind-thread defaults: run: working-directory: src diff --git a/.github/workflows/stockfish_test.yml b/.github/workflows/stockfish_test.yml index 953f6820..8c383fe7 100644 --- a/.github/workflows/stockfish_test.yml +++ b/.github/workflows/stockfish_test.yml @@ -12,86 +12,68 @@ jobs: strategy: matrix: config: - - { - name: "Ubuntu 20.04 GCC", - os: ubuntu-20.04, - compiler: g++, - comp: gcc, - run_32bit_tests: true, - run_64bit_tests: true, - shell: 'bash {0}' - } - - { - name: "Ubuntu 20.04 Clang", - os: ubuntu-20.04, - compiler: clang++, - comp: clang, - run_32bit_tests: true, - run_64bit_tests: true, - shell: 'bash {0}' - } - - { - name: "Android NDK aarch64", - os: ubuntu-20.04, - compiler: aarch64-linux-android21-clang++, - comp: ndk, - run_armv8_tests: true, - shell: 'bash {0}' - } - - { - name: "Android NDK arm", - os: ubuntu-20.04, - compiler: armv7a-linux-androideabi21-clang++, - comp: ndk, - run_armv7_tests: true, - shell: 'bash {0}' - } - - { - name: "MacOS 12 Apple Clang", - os: macos-12, - compiler: clang++, - comp: clang, - run_64bit_tests: true, - shell: 'bash {0}' - } - - { - name: "MacOS 12 GCC 11", - os: macos-12, - compiler: g++-11, - comp: gcc, - run_64bit_tests: true, - shell: 'bash {0}' - } - - { - name: "Windows 2022 Mingw-w64 GCC x86_64", - os: windows-2022, - compiler: g++, - comp: mingw, - run_64bit_tests: true, - msys_sys: 'mingw64', - msys_env: 'x86_64-gcc', - shell: 'msys2 {0}' - } - - { - name: "Windows 2022 Mingw-w64 GCC i686", - os: windows-2022, - compiler: g++, - comp: mingw, - run_32bit_tests: true, - msys_sys: 'mingw32', - msys_env: 'i686-gcc', - shell: 'msys2 {0}' - } - - { - name: "Windows 2022 Mingw-w64 Clang x86_64", - os: windows-2022, - compiler: clang++, - comp: clang, - run_64bit_tests: true, - msys_sys: 'clang64', - msys_env: 'clang-x86_64-clang', - shell: 'msys2 {0}' - } + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 + compiler: g++ + comp: gcc + run_32bit_tests: true + run_64bit_tests: true + shell: bash {0} + - name: Ubuntu 20.04 Clang + os: ubuntu-20.04 + compiler: clang++ + comp: clang + run_32bit_tests: true + run_64bit_tests: true + shell: bash {0} + - name: Android NDK aarch64 + os: ubuntu-22.04 + compiler: aarch64-linux-android21-clang++ + comp: ndk + run_armv8_tests: true + shell: bash {0} + - name: Android NDK arm + os: ubuntu-22.04 + compiler: armv7a-linux-androideabi21-clang++ + comp: ndk + run_armv7_tests: true + shell: bash {0} + - name: MacOS 12 Apple Clang + os: macos-12 + compiler: clang++ + comp: clang + run_64bit_tests: true + shell: bash {0} + - name: MacOS 12 GCC 11 + os: macos-12 + compiler: g++-11 + comp: gcc + run_64bit_tests: true + shell: bash {0} + - name: Windows 2022 Mingw-w64 GCC x86_64 + os: windows-2022 + compiler: g++ + comp: mingw + run_64bit_tests: true + msys_sys: mingw64 + msys_env: x86_64-gcc + shell: msys2 {0} + - name: Windows 2022 Mingw-w64 GCC i686 + os: windows-2022 + compiler: g++ + comp: mingw + run_32bit_tests: true + msys_sys: mingw32 + msys_env: i686-gcc + shell: msys2 {0} + - name: Windows 2022 Mingw-w64 Clang x86_64 + os: windows-2022 + compiler: clang++ + comp: clang + run_64bit_tests: true + msys_sys: clang64 + msys_env: clang-x86_64-clang + shell: msys2 {0} defaults: run: working-directory: src @@ -107,6 +89,20 @@ jobs: sudo apt update sudo apt install expect valgrind g++-multilib qemu-user + - name: Install NDK + if: runner.os == 'Linux' + run: | + if [ $COMP == ndk ]; then + NDKV="21.4.7075529" + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk + SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;$NDKV" + ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$NDKV + ANDROID_NDK_BIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin + echo "ANDROID_NDK_BIN=$ANDROID_NDK_BIN" >> $GITHUB_ENV + fi + - name: Setup msys and install required packages if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 @@ -125,12 +121,7 @@ jobs: - name: Check compiler run: | if [ $COMP == ndk ]; then - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH fi $COMPILER -v @@ -228,12 +219,7 @@ jobs: - name: Test armv8 build if: ${{ matrix.config.run_armv8_tests }} run: | - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv8 build @@ -244,12 +230,7 @@ jobs: - name: Test armv7 build if: ${{ matrix.config.run_armv7_tests }} run: | - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv7 build @@ -258,12 +239,7 @@ jobs: - name: Test armv7-neon build if: ${{ matrix.config.run_armv7_tests }} run: | - ANDROID_ROOT=/usr/local/lib/android - ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk - SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager - echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529 - export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH + export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean make -j2 ARCH=armv7-neon build From 7cf93f8b7101e5cf5df3f7921861f27b3beb9525 Mon Sep 17 00:00:00 2001 From: VoyagerOne Date: Sun, 11 Dec 2022 12:36:13 -0500 Subject: [PATCH 015/192] Simplify Capture Scoring The parameters are now in one place for easier tuning. New formula is very similar to current. STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 48176 W: 12819 L: 12616 D: 22741 Ptnml(0-2): 139, 5316, 13001, 5467, 165 LTC: LLR: 2.97 (-2.94,2.94) <-1.75,0.25> Total: 176752 W: 47364 L: 47304 D: 82084 Ptnml(0-2): 83, 17302, 53536, 17382, 73 https://tests.stockfishchess.org/tests/view/638ec7d068532fcbf79dfa15 closes https://github.com/official-stockfish/Stockfish/pull/4281 Bench: 3410998 --- src/movepick.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 188d6bd8..564adc28 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -100,7 +100,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePiece /// MovePicker::score() assigns a numerical value to each move in a list, used /// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring -/// captures with a good history. Quiets moves are ordered using the histories. +/// captures with a good history. Quiets moves are ordered using the history tables. template void MovePicker::score() { @@ -123,8 +123,8 @@ void MovePicker::score() { for (auto& m : *this) if constexpr (Type == CAPTURES) - 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)))]; + m.value = (7 * 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)))]) / 16; else if constexpr (Type == QUIETS) m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)] @@ -197,7 +197,7 @@ top: case GOOD_CAPTURE: if (select([&](){ - return pos.see_ge(*cur, Value(-69 * cur->value / 1024)) ? + return pos.see_ge(*cur, Value(-cur->value)) ? // Move losing capture to endBadCaptures to be tried later true : (*endBadCaptures++ = *cur, false); })) return *(cur - 1); From 3659a9fda0096cac091458df2c259e5636bc9106 Mon Sep 17 00:00:00 2001 From: NguyenPham Date: Thu, 15 Dec 2022 17:29:23 +1100 Subject: [PATCH 016/192] Fixed the help of Makefile make profile-build more prominent, adjust comments closes https://github.com/official-stockfish/Stockfish/pull/4284 No functional change --- src/Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0c98391b..da81ceb4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -747,9 +747,9 @@ help: @echo "Supported targets:" @echo "" @echo "help > Display architecture details" - @echo "build > Standard build" + @echo "profile-build > standard build with profile-guided optimization" + @echo "build > skip profile-guided optimization" @echo "net > Download the default nnue net" - @echo "profile-build > Faster build (with profile-guided optimization)" @echo "strip > Strip executable" @echo "install > Install executable" @echo "clean > Clean up" @@ -789,14 +789,15 @@ help: @echo "icc > Intel compiler" @echo "ndk > Google NDK to cross-compile for Android" @echo "" - @echo "Simple examples. If you don't know what to do, you likely want to run: " + @echo "Simple examples. If you don't know what to do, you likely want to run one of: " @echo "" - @echo "make -j build ARCH=x86-64 (A portable, slow compile for 64-bit systems)" - @echo "make -j build ARCH=x86-32 (A portable, slow compile for 32-bit systems)" + @echo "make -j profile-build ARCH=x86-64-avx2 # typically a fast compile for common systems " + @echo "make -j profile-build ARCH=x86-64-modern # A more portable compile for 64-bit systems " + @echo "make -j profile-build ARCH=x86-64 # A portable compile for 64-bit systems " @echo "" - @echo "Advanced examples, for experienced users looking for performance: " + @echo "Advanced examples, for experienced users: " @echo "" - @echo "make help ARCH=x86-64-bmi2" + @echo "make -j profile-build ARCH=x86-64-bmi2" @echo "make -j profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-9.0" @echo "make -j build ARCH=x86-64-ssse3 COMP=clang" @echo "" From 726e90ccfaea85c5831ad4834a6a08f5bec3f2f2 Mon Sep 17 00:00:00 2001 From: PikaCat <73384062+PikaCat-OuO@users.noreply.github.com> Date: Fri, 16 Dec 2022 10:28:31 +0800 Subject: [PATCH 017/192] Badge link fix Fix the badge link issue mentioned in https://github.com/badges/shields/issues/8671 closes https://github.com/official-stockfish/Stockfish/pull/4285 No functional change --- AUTHORS | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 432d9b90..0c1c5529 100644 --- a/AUTHORS +++ b/AUTHORS @@ -163,6 +163,7 @@ Pasquale Pigazzini (ppigazzini) Patrick Jansen (mibere) Peter Schneider (pschneider1968) Peter Zsifkovits (CoffeeOne) +PikaCat Praveen Kumar Tummala (praveentml) Rahul Dsilva (silversolver1) Ralph Stößer (Ralph Stoesser) diff --git a/README.md b/README.md index ac15fbfa..4cd5968e 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ For full details, read the copy of the GPL v3 found in the file named [website-link]: https://stockfishchess.org [worker-link]: https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview -[build-badge]: https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github +[build-badge]: https://img.shields.io/github/actions/workflow/status/official-stockfish/Stockfish/stockfish.yml?branch=master&style=for-the-badge&label=stockfish&logo=github [commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge [discord-badge]: https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord [fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests%2Ffinished From 39af98c807d236b6511b6e399caf40102398900c Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sat, 17 Dec 2022 12:48:03 +0300 Subject: [PATCH 018/192] Reintroduce doEvenDeeperSearch This patch is basically the same as a reverted patch but now has some guarding against search being stuck - the same way as we do with double extensions. This should help with search explosions - albeit slowly but they eventually should be resolved. passed STC: https://tests.stockfishchess.org/tests/view/639733d0b4e52c95053f3485 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 514048 W: 136423 L: 135435 D: 242190 Ptnml(0-2): 1425, 56945, 139420, 57685, 1549 passed LTC: https://tests.stockfishchess.org/tests/view/639ab79b93ed41c57eded5c3 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 113800 W: 30642 L: 30190 D: 52968 Ptnml(0-2): 53, 11092, 34178, 11504, 73 closes https://github.com/official-stockfish/Stockfish/pull/4287 bench 3611278 --- src/evaluate.cpp | 12 ++++++------ src/search.cpp | 11 +++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 6a0fae9e..7619398e 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { else { int nnueComplexity; - int scale = 1064 + 106 * pos.non_pawn_material() / 5120; + int scale = 1076 + 96 * pos.non_pawn_material() / 5120; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; @@ -1071,8 +1071,8 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 416 * nnueComplexity - + 424 * abs(psq - nnue) + nnueComplexity = ( 412 * nnueComplexity + + 428 * abs(psq - nnue) + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) ) / 1024; @@ -1080,12 +1080,12 @@ Value Eval::evaluate(const Position& pos, int* complexity) { if (complexity) *complexity = nnueComplexity; - optimism = optimism * (269 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 754)) / 1024; + optimism = optimism * (278 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 755)) / 1024; } // Damp down the evaluation linearly when shuffling - v = v * (195 - pos.rule50_count()) / 211; + v = v * (197 - pos.rule50_count()) / 214; // 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); diff --git a/src/search.cpp b/src/search.cpp index b58a344a..4507460a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((12 * d + 282) * d - 349 , 1594); + return std::min((12 * d + 282) * d - 349 , 1480); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -1066,7 +1066,7 @@ moves_loop: // When in check, search starts here // Avoid search explosion by limiting the number of double extensions if ( !PvNode && value < singularBeta - 25 - && ss->doubleExtensions <= 9) + && ss->doubleExtensions <= 10) { extension = 2; depth += depth < 12; @@ -1175,7 +1175,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13628 + 4000 * (depth > 7 && depth < 19)); + r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension @@ -1190,9 +1190,12 @@ moves_loop: // When in check, search starts here // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 582 && ss->doubleExtensions <= 5; const bool doShallowerSearch = value < bestValue + newDepth; - newDepth += doDeeperSearch - doShallowerSearch; + ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch; + + newDepth += doDeeperSearch - doShallowerSearch + doEvenDeeperSearch; if (newDepth > d) value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); From 3a32d3e00cca23648f10a40c5b322f2fd56dc0ae Mon Sep 17 00:00:00 2001 From: mstembera Date: Mon, 12 Dec 2022 23:22:02 -0800 Subject: [PATCH 019/192] Don't reset increaseDepth back to true after it has been set to false Resetting increaseDepth back to true each time on the very next iteration was not intended so this is a bug fix and a simplification. See more discussion here #2482 (comment) Thanks to xoto10 STC: https://tests.stockfishchess.org/tests/view/6398c74693ed41c57ede7bfd LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 51128 W: 13543 L: 13220 D: 24365 Ptnml(0-2): 165, 5363, 14174, 5708, 154 LTC: https://tests.stockfishchess.org/tests/view/6399bcd393ed41c57edea750 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 290864 W: 77282 L: 77334 D: 136248 Ptnml(0-2): 107, 28127, 89029, 28049, 120 closes https://github.com/official-stockfish/Stockfish/pull/4288 bench: 3611278 --- src/search.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4507460a..d39a8ad2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -487,12 +487,11 @@ void Thread::search() { else Threads.stop = true; } - else if ( Threads.increaseDepth - && !mainThread->ponder + else if ( !mainThread->ponder && Time.elapsed() > totalTime * 0.53) - Threads.increaseDepth = false; + Threads.increaseDepth = false; else - Threads.increaseDepth = true; + Threads.increaseDepth = true; } mainThread->iterValue[iterIdx] = bestValue; From 61ea1534ff7026009a3435575c7beee91534db83 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 19 Dec 2022 17:54:36 +0100 Subject: [PATCH 020/192] No error if net available but wget/curl missing do not error out on missing wget/curl if these tools are not needed later on, i.e. if the net is available already. closes https://github.com/official-stockfish/Stockfish/pull/4291 closes https://github.com/official-stockfish/Stockfish/pull/4253 No functional change --- src/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index da81ceb4..bcf0abdf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -853,7 +853,7 @@ net: $(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet)) $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi)) @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 "Neither curl nor wget is installed. Install one of these tools unless the net has been downloaded manually"; \ 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 \ @@ -864,7 +864,9 @@ net: echo "$(nnuenet) available."; \ else \ if [ "x$(curl_or_wget)" != "x" ]; then \ - echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\ + echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\ + else \ + echo "No net found and download not possible"; exit 1;\ fi; \ fi; \ if [ "x$(shasum_command)" != "x" ]; then \ From c2d507005c51145211a7963af7c41026bd759d08 Mon Sep 17 00:00:00 2001 From: Alfredo Menezes Date: Mon, 19 Dec 2022 16:07:09 -0300 Subject: [PATCH 021/192] Sometimes do a reduced search if LMR is skipped If the node doesn't go through LMR and r is too big, reduce search depth by one ply. STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 664888 W: 176375 L: 175169 D: 313344 Ptnml(0-2): 1965, 73754, 179851, 74858, 2016 https://tests.stockfishchess.org/tests/view/6399414c93ed41c57ede8fb8 LTC: LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 150784 W: 40553 L: 40031 D: 70200 Ptnml(0-2): 76, 14668, 45387, 15180, 81 https://tests.stockfishchess.org/tests/view/639dee6e11c576d919dc2b38 closes https://github.com/official-stockfish/Stockfish/pull/4290 Bench: 3727508 --- src/search.cpp | 96 +++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index d39a8ad2..7f2f5284 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1120,6 +1120,52 @@ moves_loop: // When in check, search starts here // Step 16. Make the move pos.do_move(move, st, givesCheck); + Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); + + // Decrease reduction if position is or has been on the PV + // and node is not likely to fail low. (~3 Elo) + if ( ss->ttPv + && !likelyFailLow) + r -= 2; + + // Decrease reduction if opponent's move count is high (~1 Elo) + if ((ss-1)->moveCount > 7) + r--; + + // Increase reduction for cut nodes (~3 Elo) + if (cutNode) + r += 2; + + // Increase reduction if ttMove is a capture (~3 Elo) + if (ttCapture) + r++; + + // Decrease reduction for PvNodes based on depth + if (PvNode) + r -= 1 + 11 / (3 + depth); + + // Decrease reduction if ttMove has been singularly extended (~1 Elo) + if (singularQuietLMR) + r--; + + // Decrease reduction if we move a threatened piece (~1 Elo) + if ( depth > 9 + && (mp.threatenedPieces & from_sq(move))) + r--; + + // Increase reduction if next ply has a lot of fail high + if ((ss+1)->cutoffCnt > 3) + r++; + + ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + + (*contHist[0])[movedPiece][to_sq(move)] + + (*contHist[1])[movedPiece][to_sq(move)] + + (*contHist[3])[movedPiece][to_sq(move)] + - 4433; + + // Decrease/increase reduction for moves with a good/bad history (~30 Elo) + r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); + // Step 17. Late moves reduction / extension (LMR, ~98 Elo) // We use various heuristics for the sons of a node after the first son has // been searched. In general we would like to reduce them, but there are many @@ -1130,52 +1176,6 @@ moves_loop: // When in check, search starts here || !capture || (cutNode && (ss-1)->moveCount > 1))) { - Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); - - // Decrease reduction if position is or has been on the PV - // and node is not likely to fail low. (~3 Elo) - if ( ss->ttPv - && !likelyFailLow) - r -= 2; - - // Decrease reduction if opponent's move count is high (~1 Elo) - if ((ss-1)->moveCount > 7) - r--; - - // Increase reduction for cut nodes (~3 Elo) - if (cutNode) - r += 2; - - // Increase reduction if ttMove is a capture (~3 Elo) - if (ttCapture) - r++; - - // Decrease reduction for PvNodes based on depth - if (PvNode) - r -= 1 + 11 / (3 + depth); - - // Decrease reduction if ttMove has been singularly extended (~1 Elo) - if (singularQuietLMR) - r--; - - // Decrease reduction if we move a threatened piece (~1 Elo) - if ( depth > 9 - && (mp.threatenedPieces & from_sq(move))) - r--; - - // Increase reduction if next ply has a lot of fail high - if ((ss+1)->cutoffCnt > 3) - r++; - - ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] - + (*contHist[0])[movedPiece][to_sq(move)] - + (*contHist[1])[movedPiece][to_sq(move)] - + (*contHist[3])[movedPiece][to_sq(move)] - - 4433; - - // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); - // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension // beyond the first move depth. This may lead to hidden double extensions. @@ -1209,10 +1209,10 @@ moves_loop: // When in check, search starts here } } - // Step 18. Full depth search when LMR is skipped + // Step 18. Full depth search when LMR is skipped. If expected reduction is high, reduce its depth by 1. else if (!PvNode || moveCount > 1) { - value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode); } // For PV nodes only, do a full PV search on the first move or after a fail From 20b02264620397eacf4e43736ec7f7c48a9a7068 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Tue, 20 Dec 2022 16:01:05 +0900 Subject: [PATCH 022/192] Fix a dependency bug Instead of allowing .depend for specific build-related targets, filter non-build-related targets (i.e. help, clean) so that other targets can normally execute .depend target. closes https://github.com/official-stockfish/Stockfish/pull/4293 No functional change --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index bcf0abdf..500c1006 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1009,6 +1009,6 @@ icc-profile-use: .depend: $(SRCS) -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null -ifneq (, $(filter $(MAKECMDGOALS), build profile-build)) +ifeq (, $(filter $(MAKECMDGOALS), help strip install clean net objclean profileclean config-sanity)) -include .depend endif From c620886181b5c0fb4a0c067b4173143a81819199 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Mon, 19 Dec 2022 16:10:22 -0500 Subject: [PATCH 023/192] Update default net to nn-335a9b2d8a80.nnue Created by retraining the master net with a combination of: the previous best dataset (Leela-dfrc_n5000.binpack), with about half the dataset filtered using depth6 multipv2 search to throw away positions where either of the 2 best moves are captures Leela T80 Oct and Nov training data rescored with best moves, adding ~9.5 billion positions Trained effectively the same way as the previous master net: python3 easy_train.py \ --experiment-name=leela-dfrc-filtered-T80-oct-nov \ --training-dataset=/data/leela-dfrc-filtered-T80-oct-nov.binpack \ --start-from-engine-test-net True \ --gpus="0," \ --start-lambda=1.0 \ --end-lambda=0.75 \ --gamma=0.995 \ --lr=4.375e-4 \ --tui=False \ --seed=$RANDOM \ --max_epoch=800 \ --auto-exit-timeout-on-training-finished=900 \ --network-testing-threads 20 \ --num-workers 6 Local testing at a fixed 25k nodes: experiments/experiment_leela-dfrc-filtered-T80-oct-nov/training/run_0/nn-epoch779.nnue localElo: run_0/nn-epoch779.nnue : 4.7 +/- 3.1 The new Leela T80 part of the dataset was prepared by downloading test80 training data from all of Oct 2022 and Nov 2022, rescoring with syzygy 6-piece tablebases and ~600 GB of 7-piece tablebases, saving best moves to exported .plain files, removing all positions with castling flags, then converting to binpacks and using interleave_binpacks.py to merge them together. Scripts used in this data conversion process are available at: https://github.com/linrock/lc0-data-converter Filtering binpack data using depth6 multipv2 search was done by modifying transform.cpp in the tools branch: https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-no-rescore Links for downloading the training data (total size: 338 GB) are available at: https://robotmoon.com/nnue-training-data/ Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 30544 W: 8244 L: 7947 D: 14353 Ptnml(0-2): 93, 3243, 8302, 3542, 92 https://tests.stockfishchess.org/tests/view/63a0d377264a0cf18f86f82b Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 32464 W: 8866 L: 8573 D: 15025 Ptnml(0-2): 19, 3054, 9794, 3345, 20 https://tests.stockfishchess.org/tests/view/63a10bc9fb452d3c44b1e016 closes https://github.com/official-stockfish/Stockfish/pull/4295 Bench 3554904 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index f5ac3263..d1398dd5 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-ad9b42354671.nnue" + #define EvalFileDefaultName "nn-335a9b2d8a80.nnue" namespace NNUE { From b2bd8699eccc149cdda1f7bf6e1eed42088ec827 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Tue, 20 Dec 2022 22:54:12 +0300 Subject: [PATCH 024/192] Update Elo estimates for terms in search based on 25k games per term, using the UHO_XXL_+0.90_+1.19.epd book, at STC. More detailed information in the PR. closes https://github.com/official-stockfish/Stockfish/pull/4294 No functional change --- src/search.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 7f2f5284..77d23ac2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -633,16 +633,16 @@ namespace { && ttValue != VALUE_NONE // Possible in case of TT access race && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) { - // If ttMove is quiet, update move sorting heuristics on TT hit (~1 Elo) + // If ttMove is quiet, update move sorting heuristics on TT hit (~2 Elo) if (ttMove) { if (ttValue >= beta) { - // Bonus for a quiet ttMove that fails high (~3 Elo) + // Bonus for a quiet ttMove that fails high (~2 Elo) if (!ttCapture) update_quiet_stats(pos, ss, ttMove, stat_bonus(depth)); - // Extra penalty for early quiet moves of the previous ply (~0 Elo) + // Extra penalty for early quiet moves of the previous ply (~0 Elo on STC, ~2 Elo on LTC) if ((ss-1)->moveCount <= 2 && !priorCapture) update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + 1)); } @@ -734,7 +734,7 @@ namespace { else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost complexity = abs(ss->staticEval - pos.psq_eg_stm()); - // ttValue can be used as a better position evaluation (~4 Elo) + // ttValue can be used as a better position evaluation (~7 Elo) if ( ttValue != VALUE_NONE && (tte->bound() & (ttValue > eval ? BOUND_LOWER : BOUND_UPPER))) eval = ttValue; @@ -750,7 +750,7 @@ namespace { thisThread->complexityAverage.update(complexity); - // Use static evaluation difference to improve quiet move ordering (~3 Elo) + // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1914, 1914); @@ -766,7 +766,7 @@ namespace { : 168; improving = improvement > 0; - // Step 7. Razoring. + // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. if (eval < alpha - 369 - 254 * depth * depth) @@ -776,7 +776,7 @@ namespace { return value; } - // Step 8. Futility pruning: child node (~25 Elo). + // Step 8. Futility pruning: child node (~40 Elo). // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 8 @@ -785,7 +785,7 @@ namespace { && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; - // Step 9. Null move search with verification search (~22 Elo) + // Step 9. Null move search with verification search (~35 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL && (ss-1)->statScore < 17139 @@ -837,7 +837,7 @@ namespace { probCutBeta = beta + 191 - 54 * improving; - // Step 10. ProbCut (~4 Elo) + // Step 10. ProbCut (~10 Elo) // If we have a good enough capture and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode @@ -888,7 +888,7 @@ namespace { } // Step 11. If the position is not in TT, decrease depth by 3. - // Use qsearch if depth is equal or below zero (~4 Elo) + // Use qsearch if depth is equal or below zero (~9 Elo) if ( PvNode && !ttMove) depth -= 3; @@ -903,7 +903,7 @@ namespace { moves_loop: // When in check, search starts here - // Step 12. A small Probcut idea, when we are in check (~0 Elo) + // Step 12. A small Probcut idea, when we are in check (~4 Elo) probCutBeta = beta + 417; if ( ss->inCheck && !PvNode @@ -980,12 +980,12 @@ moves_loop: // When in check, search starts here Value delta = beta - alpha; - // Step 14. Pruning at shallow depth (~98 Elo). Depth conditions are important for mate finding. + // Step 14. Pruning at shallow depth (~120 Elo). Depth conditions are important for mate finding. if ( !rootNode && pos.non_pawn_material(us) && bestValue > VALUE_TB_LOSS_IN_MAX_PLY) { - // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold (~7 Elo) + // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold (~8 Elo) moveCountPruning = moveCount >= futility_move_count(improving, depth); // Reduced depth of the next LMR search @@ -994,7 +994,7 @@ moves_loop: // When in check, search starts here if ( capture || givesCheck) { - // Futility pruning for captures (~0 Elo) + // Futility pruning for captures (~2 Elo) if ( !givesCheck && !PvNode && lmrDepth < 7 @@ -1003,7 +1003,7 @@ moves_loop: // When in check, search starts here + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha) continue; - // SEE based pruning (~9 Elo) + // SEE based pruning (~11 Elo) if (!pos.see_ge(move, Value(-222) * depth)) continue; } @@ -1020,23 +1020,23 @@ moves_loop: // When in check, search starts here history += 2 * thisThread->mainHistory[us][from_to(move)]; - // Futility pruning: parent node (~9 Elo) + // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck && lmrDepth < 13 && ss->staticEval + 106 + 145 * lmrDepth + history / 52 <= alpha) continue; - // Prune moves with negative SEE (~3 Elo) + // Prune moves with negative SEE (~4 Elo) if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) continue; } } - // Step 15. Extensions (~66 Elo) + // Step 15. Extensions (~100 Elo) // We take care to not overdo to avoid search getting stuck. if (ss->ply < thisThread->rootDepth * 2) { - // Singular extension search (~58 Elo). If all moves but one fail low on a + // Singular extension search (~94 Elo). If all moves but one fail low on a // search of (alpha-s, beta-s), and just one fails high on (alpha, beta), // then that move is singular and should be extended. To verify this we do // a reduced search on all the other moves but the ttMove and if the @@ -1095,7 +1095,7 @@ moves_loop: // When in check, search starts here && abs(ss->staticEval) > 82) extension = 1; - // Quiet ttMove extensions (~0 Elo) + // Quiet ttMove extensions (~1 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] @@ -1166,7 +1166,7 @@ moves_loop: // When in check, search starts here // Decrease/increase reduction for moves with a good/bad history (~30 Elo) r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); - // Step 17. Late moves reduction / extension (LMR, ~98 Elo) + // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has // been searched. In general we would like to reduce them, but there are many // cases where we extend a son if it has good chances to be "interesting". @@ -1462,7 +1462,7 @@ moves_loop: // When in check, search starts here if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE) ss->staticEval = bestValue = evaluate(pos); - // ttValue can be used as a better position evaluation (~7 Elo) + // ttValue can be used as a better position evaluation (~13 Elo) if ( ttValue != VALUE_NONE && (tte->bound() & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER))) bestValue = ttValue; @@ -1520,7 +1520,7 @@ moves_loop: // When in check, search starts here moveCount++; - // Futility pruning and moveCount pruning (~5 Elo) + // Futility pruning and moveCount pruning (~10 Elo) if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY && !givesCheck && to_sq(move) != prevSq @@ -1559,7 +1559,7 @@ moves_loop: // When in check, search starts here [pos.moved_piece(move)] [to_sq(move)]; - // Continuation history based pruning (~2 Elo) + // Continuation history based pruning (~3 Elo) if ( !capture && bestValue > VALUE_TB_LOSS_IN_MAX_PLY && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 From 64656f8583dde88d558d5367b4cf8fc136c3214a Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Sat, 24 Dec 2022 13:05:24 +0800 Subject: [PATCH 025/192] Add double bonus for prior countermove fail low Add a double extra bonus for particularly bad fail low cases. Original idea by Yoshie2000. STC: https://tests.stockfishchess.org/tests/view/63a2f0d86b5bf07ac7fad543 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 146488 W: 38992 L: 38532 D: 68964 Ptnml(0-2): 385, 16036, 39965, 16450, 408 LTC: https://tests.stockfishchess.org/tests/view/63a3eaeb6b5bf07ac7fafdec LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 103992 W: 27853 L: 27423 D: 48716 Ptnml(0-2): 41, 10029, 31435, 10441, 50 closes https://github.com/official-stockfish/Stockfish/pull/4302 Bench: 3801857 --- AUTHORS | 1 + src/search.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0c1c5529..70b500ea 100644 --- a/AUTHORS +++ b/AUTHORS @@ -145,6 +145,7 @@ Mira Miroslav Fontán (Hexik) Moez Jellouli (MJZ1977) Mohammed Li (tthsqe12) +Muzhen J (XInTheDark) Nathan Rugg (nmrugg) Nick Pelling (nickpelling) Nicklas Persson (NicklasPersson) diff --git a/src/search.cpp b/src/search.cpp index 77d23ac2..0c8377d0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1353,16 +1353,17 @@ moves_loop: // When in check, search starts here quietsSearched, quietCount, capturesSearched, captureCount, depth); // Bonus for prior countermove that caused the fail low - else if ( (depth >= 5 || PvNode) + else if ( (depth >= 5 || PvNode || bestValue < alpha - 62 * depth) && !priorCapture) { //Assign extra bonus if current node is PvNode or cutNode //or fail low was really bad bool extraBonus = PvNode - || cutNode - || bestValue < alpha - 62 * depth; + || cutNode; - update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus)); + bool doubleExtraBonus = extraBonus && bestValue < alpha - 85 * depth; + + update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus + doubleExtraBonus)); } if (PvNode) From f09b391ceb5ea282538b721b069db67e3b6e098f Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Tue, 27 Dec 2022 13:33:26 +0100 Subject: [PATCH 026/192] Fix comparison with uninitialized variable In both modified methods, the variable 'result' is checked to detect whether the probe operation failed. However, the variable is not initialized on all paths, so the check might test an uninitialized value. A test position (with TB) is given by: position fen 3K1k2/R7/8/8/8/8/8/R6Q w - - 0 1 moves a1b1 f8g8 b1a1 g8f8 a1b1 f8g8 b1a1 This is now fixed by always initializing the variable. closes https://github.com/official-stockfish/Stockfish/pull/4309 No functional change --- src/syzygy/tbprobe.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index f2de036d..4df495a8 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1514,7 +1514,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) { // A return value false indicates that not all probes were successful. bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { - ProbeState result; + ProbeState result = OK; StateInfo st; // Obtain 50-move counter for the root position @@ -1593,7 +1593,7 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) { static const int WDL_to_rank[] = { -MAX_DTZ, -MAX_DTZ + 101, 0, MAX_DTZ - 101, MAX_DTZ }; - ProbeState result; + ProbeState result = OK; StateInfo st; WDLScore wdl; From 258c13ba8cc8d054b803a04c433a766d0c5a1e8f Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Tue, 27 Dec 2022 10:31:24 +0100 Subject: [PATCH 027/192] Remove redundant extern modifier for function declarations Functions have external linkage by default, so there's no need to declare them extern. closes https://github.com/official-stockfish/Stockfish/pull/4308 No functional change --- src/position.h | 2 +- src/psqt.h | 2 +- src/uci.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/position.h b/src/position.h index 078ff5b7..90247cb1 100644 --- a/src/position.h +++ b/src/position.h @@ -204,7 +204,7 @@ private: bool chess960; }; -extern std::ostream& operator<<(std::ostream& os, const Position& pos); +std::ostream& operator<<(std::ostream& os, const Position& pos); inline Color Position::side_to_move() const { return sideToMove; diff --git a/src/psqt.h b/src/psqt.h index 4ee0e379..bd78be90 100644 --- a/src/psqt.h +++ b/src/psqt.h @@ -30,7 +30,7 @@ namespace Stockfish::PSQT extern Score psq[PIECE_NB][SQUARE_NB]; // Fill psqt array from a set of internally linked parameters -extern void init(); +void init(); } // namespace Stockfish::PSQT diff --git a/src/uci.cpp b/src/uci.cpp index 5d842d25..dc5f10e1 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -36,7 +36,7 @@ using namespace std; namespace Stockfish { -extern vector setup_bench(const Position&, istream&); +vector setup_bench(const Position&, istream&); namespace { From be9bc420afa11314c886c0aede4c4ae3d76f8a50 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Thu, 29 Dec 2022 10:34:28 -0500 Subject: [PATCH 028/192] Update default net to nn-60fa44e376d9.nnue Created by retraining the master net on the previous best dataset with additional filtering. No new data was added. More of the Leela-dfrc_n5000.binpack part of the dataset was pre-filtered with depth6 multipv2 search to remove bestmove captures. About 93% of the previous Leela/SF data and 99% of the SF dfrc data was filtered. Unfiltered parts of the dataset were left out. The new Leela T80 oct+nov data is the same as before. All early game positions with ply count <= 28 were skipped during training by modifying the training data loader in nnue-pytorch. Trained in a similar way as recent master nets, with a different nnue-pytorch branch for early ply skipping: python3 easy_train.py \ --experiment-name=leela93-dfrc99-filt-only-T80-oct-nov-skip28 \ --training-dataset=/data/leela93-dfrc99-filt-only-T80-oct-nov.binpack \ --start-from-engine-test-net True \ --nnue-pytorch-branch=linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \ --gpus="0," \ --start-lambda=1.0 \ --end-lambda=0.75 \ --gamma=0.995 \ --lr=4.375e-4 \ --tui=False \ --seed=$RANDOM \ --max_epoch=800 \ --network-testing-threads 20 \ --num-workers 6 For the exact training data used: https://robotmoon.com/nnue-training-data/ Details about the previous best dataset: #4295 Local testing at a fixed 25k nodes: experiment_leela93-dfrc99-filt-only-T80-oct-nov-skip28 Local Elo: run_0/nn-epoch779.nnue : 5.1 +/- 1.5 Passed STC https://tests.stockfishchess.org/tests/view/63adb3acae97a464904fd4e8 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 36504 W: 9847 L: 9538 D: 17119 Ptnml(0-2): 108, 3981, 9784, 4252, 127 Passed LTC https://tests.stockfishchess.org/tests/view/63ae0ae25bd1e5f27f13d884 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 36592 W: 10017 L: 9717 D: 16858 Ptnml(0-2): 17, 3461, 11037, 3767, 14 closes https://github.com/official-stockfish/Stockfish/pull/4314 bench 4015511 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index d1398dd5..4001166b 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-335a9b2d8a80.nnue" + #define EvalFileDefaultName "nn-60fa44e376d9.nnue" namespace NNUE { From b60f9cc4515cdfb657a0166abb29a60257cc59e1 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sun, 1 Jan 2023 14:45:08 +0100 Subject: [PATCH 029/192] Update copyright years Happy New Year! closes https://github.com/official-stockfish/Stockfish/pull/4315 No functional change --- src/Makefile | 2 +- src/benchmark.cpp | 2 +- src/bitbase.cpp | 2 +- src/bitboard.cpp | 2 +- src/bitboard.h | 2 +- src/endgame.cpp | 2 +- src/endgame.h | 2 +- src/evaluate.cpp | 2 +- src/evaluate.h | 2 +- src/main.cpp | 2 +- src/material.cpp | 2 +- src/material.h | 2 +- src/misc.cpp | 2 +- src/misc.h | 2 +- src/movegen.cpp | 2 +- src/movegen.h | 2 +- src/movepick.cpp | 2 +- src/movepick.h | 2 +- src/nnue/evaluate_nnue.cpp | 2 +- src/nnue/evaluate_nnue.h | 2 +- src/nnue/features/half_ka_v2_hm.cpp | 2 +- src/nnue/features/half_ka_v2_hm.h | 2 +- src/nnue/layers/affine_transform.h | 2 +- src/nnue/layers/clipped_relu.h | 2 +- src/nnue/layers/simd.h | 2 +- src/nnue/layers/sqr_clipped_relu.h | 2 +- src/nnue/nnue_accumulator.h | 2 +- src/nnue/nnue_architecture.h | 2 +- src/nnue/nnue_common.h | 2 +- src/nnue/nnue_feature_transformer.h | 2 +- src/pawns.cpp | 2 +- src/pawns.h | 2 +- src/position.cpp | 2 +- src/position.h | 2 +- src/psqt.cpp | 2 +- src/psqt.h | 2 +- src/search.cpp | 2 +- src/search.h | 2 +- src/syzygy/tbprobe.cpp | 2 +- src/syzygy/tbprobe.h | 2 +- src/thread.cpp | 2 +- src/thread.h | 2 +- src/thread_win32_osx.h | 2 +- src/timeman.cpp | 2 +- src/timeman.h | 2 +- src/tt.cpp | 2 +- src/tt.h | 2 +- src/tune.cpp | 2 +- src/tune.h | 2 +- src/types.h | 2 +- src/uci.cpp | 2 +- src/uci.h | 2 +- src/ucioption.cpp | 2 +- 53 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/Makefile b/src/Makefile index 500c1006..d4f089ee 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ # Stockfish, a UCI chess playing engine derived from Glaurung 2.1 -# Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) +# Copyright (C) 2004-2023 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 diff --git a/src/benchmark.cpp b/src/benchmark.cpp index e1c025ad..2abb9c8f 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/bitbase.cpp b/src/bitbase.cpp index 84300baf..e21d1fe9 100644 --- a/src/bitbase.cpp +++ b/src/bitbase.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/bitboard.cpp b/src/bitboard.cpp index fd0ba235..0ed13fd0 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/bitboard.h b/src/bitboard.h index 2b6e2a69..d4485fcb 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/endgame.cpp b/src/endgame.cpp index e773e7a9..9021f242 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/endgame.h b/src/endgame.h index e79f696f..c184cb3f 100644 --- a/src/endgame.h +++ b/src/endgame.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 7619398e..3b6cbbcd 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/evaluate.h b/src/evaluate.h index 4001166b..db9e6424 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/main.cpp b/src/main.cpp index fad0ef84..c40e0fa3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/material.cpp b/src/material.cpp index 1567358a..7102f879 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/material.h b/src/material.h index 3ca169ce..f6db85c4 100644 --- a/src/material.h +++ b/src/material.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/misc.cpp b/src/misc.cpp index c7fa0e9a..5bb8da69 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/misc.h b/src/misc.h index 77b81d50..4c1150f8 100644 --- a/src/misc.h +++ b/src/misc.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/movegen.cpp b/src/movegen.cpp index c7a3c29b..a960f863 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/movegen.h b/src/movegen.h index bbb35b39..b8df3e65 100644 --- a/src/movegen.h +++ b/src/movegen.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/movepick.cpp b/src/movepick.cpp index 564adc28..dbe67357 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/movepick.h b/src/movepick.h index e4c4a5bf..90f60b8a 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 4715fed0..8d720ccb 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/evaluate_nnue.h b/src/nnue/evaluate_nnue.h index 2e4f1f50..9499f7d9 100644 --- a/src/nnue/evaluate_nnue.h +++ b/src/nnue/evaluate_nnue.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/features/half_ka_v2_hm.cpp b/src/nnue/features/half_ka_v2_hm.cpp index 7dbd3415..19ebb15f 100644 --- a/src/nnue/features/half_ka_v2_hm.cpp +++ b/src/nnue/features/half_ka_v2_hm.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/features/half_ka_v2_hm.h b/src/nnue/features/half_ka_v2_hm.h index a95d4328..78063c36 100644 --- a/src/nnue/features/half_ka_v2_hm.h +++ b/src/nnue/features/half_ka_v2_hm.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 461a7b83..710ab8a7 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/layers/clipped_relu.h b/src/nnue/layers/clipped_relu.h index f94d3082..51e562da 100644 --- a/src/nnue/layers/clipped_relu.h +++ b/src/nnue/layers/clipped_relu.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/layers/simd.h b/src/nnue/layers/simd.h index 7b9e8fb2..aeab39c4 100644 --- a/src/nnue/layers/simd.h +++ b/src/nnue/layers/simd.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/layers/sqr_clipped_relu.h b/src/nnue/layers/sqr_clipped_relu.h index b603a277..df539b39 100644 --- a/src/nnue/layers/sqr_clipped_relu.h +++ b/src/nnue/layers/sqr_clipped_relu.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/nnue_accumulator.h b/src/nnue/nnue_accumulator.h index 600483b5..8eba4497 100644 --- a/src/nnue/nnue_accumulator.h +++ b/src/nnue/nnue_accumulator.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index cac83730..c43a23c3 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/nnue_common.h b/src/nnue/nnue_common.h index 17956189..12309d26 100644 --- a/src/nnue/nnue_common.h +++ b/src/nnue/nnue_common.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index b6dd54d3..62f1615d 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/pawns.cpp b/src/pawns.cpp index fdcfa022..0ccafd9e 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/pawns.h b/src/pawns.h index af0370fc..95c9ea3c 100644 --- a/src/pawns.h +++ b/src/pawns.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/position.cpp b/src/position.cpp index 5befcaf2..e82425af 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/position.h b/src/position.h index 90247cb1..3de24f22 100644 --- a/src/position.h +++ b/src/position.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/psqt.cpp b/src/psqt.cpp index ca5664c2..d3ebb20d 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/psqt.h b/src/psqt.h index bd78be90..9630f446 100644 --- a/src/psqt.h +++ b/src/psqt.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/search.cpp b/src/search.cpp index 0c8377d0..dd240366 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/search.h b/src/search.h index b620202d..48a0f7ce 100644 --- a/src/search.h +++ b/src/search.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 4df495a8..b7ba3240 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index 179c7572..159c6865 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/thread.cpp b/src/thread.cpp index e8723eb7..7e71edf1 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/thread.h b/src/thread.h index 5f0b2c3e..680da209 100644 --- a/src/thread.h +++ b/src/thread.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/thread_win32_osx.h b/src/thread_win32_osx.h index 77d1c3c7..01ff1c77 100644 --- a/src/thread_win32_osx.h +++ b/src/thread_win32_osx.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/timeman.cpp b/src/timeman.cpp index cab0d767..5c826b4f 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/timeman.h b/src/timeman.h index a86f0769..3462b823 100644 --- a/src/timeman.h +++ b/src/timeman.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/tt.cpp b/src/tt.cpp index c7118aea..39f18d3d 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/tt.h b/src/tt.h index 03fe3e14..3e335b44 100644 --- a/src/tt.h +++ b/src/tt.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/tune.cpp b/src/tune.cpp index a885845f..41f6664d 100644 --- a/src/tune.cpp +++ b/src/tune.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/tune.h b/src/tune.h index 75ab484a..f5b787af 100644 --- a/src/tune.h +++ b/src/tune.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/types.h b/src/types.h index 29c16ce7..8a021342 100644 --- a/src/types.h +++ b/src/types.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/uci.cpp b/src/uci.cpp index dc5f10e1..c49b9b78 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/uci.h b/src/uci.h index 3b5a6764..bd3df323 100644 --- a/src/uci.h +++ b/src/uci.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 9fb48345..78711c18 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2023 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 From a6fa683418c6a74491035601e16497851eea6be6 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Thu, 29 Dec 2022 10:34:28 -0500 Subject: [PATCH 030/192] Update default net to nn-a3dc078bafc7.nnue This is a later epoch (epoch 859) from the same experiment run that trained yesterday's master net nn-60fa44e376d9.nnue (epoch 779). The experiment was manually paused around epoch 790 and unpaused with max epoch increased to 900 mainly to get more local elo data without letting the GPU idle. nn-60fa44e376d9.nnue is from #4314 nn-335a9b2d8a80.nnue is from #4295 Local elo vs. nn-335a9b2d8a80.nnue at 25k nodes per move: experiment_leela93-dfrc99-filt-only-T80-oct-nov-skip28 run_0/nn-epoch779.nnue (nn-60fa44e376d9.nnue) : 5.0 +/- 1.2 run_0/nn-epoch859.nnue (nn-a3dc078bafc7.nnue) : 5.6 +/- 1.6 Passed STC vs. nn-335a9b2d8a80.nnue https://tests.stockfishchess.org/tests/view/63ae10495bd1e5f27f13d94f LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 37536 W: 10088 L: 9781 D: 17667 Ptnml(0-2): 110, 4006, 10223, 4325, 104 An LTC test vs. nn-335a9b2d8a80.nnue was paused due to nn-60fa44e376d9.nnue passing LTC first: https://tests.stockfishchess.org/tests/view/63ae5d34331d5fca5113703b Passed LTC vs. nn-60fa44e376d9.nnue https://tests.stockfishchess.org/tests/view/63af1e41465d2b022dbce4e7 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 148704 W: 39672 L: 39155 D: 69877 Ptnml(0-2): 59, 14443, 44843, 14936, 71 closes https://github.com/official-stockfish/Stockfish/pull/4319 bench 3984365 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index db9e6424..0a00faa7 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-60fa44e376d9.nnue" + #define EvalFileDefaultName "nn-a3dc078bafc7.nnue" namespace NNUE { From fc5b59b88bae00b7e74bbad0de7c3c33136937cf Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Mon, 2 Jan 2023 17:19:41 +0300 Subject: [PATCH 031/192] Parameter Tweaks This patch is a parameter tweak that passed both STC and LTC tests. STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 80944 W: 21557 L: 21189 D: 38198 Ptnml(0-2): 192, 8883, 22028, 9103, 266 https://tests.stockfishchess.org/tests/view/63b07fe2d421d8f75795a03b LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 30440 W: 8296 L: 8007 D: 14137 Ptnml(0-2): 6, 2893, 9143, 3162, 16 https://tests.stockfishchess.org/tests/view/63b167d02ab1290f961644db closes https://github.com/official-stockfish/Stockfish/pull/4318 Bench: 4182223 --- src/evaluate.cpp | 12 +++++----- src/search.cpp | 60 ++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 3b6cbbcd..d5cda3d8 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1056,7 +1056,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // We use the much less accurate but faster Classical eval when the NNUE // option is set to false. Otherwise we use the NNUE eval unless the // PSQ advantage is decisive and several pieces remain. (~3 Elo) - bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1760); + bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1781); if (useClassical) v = Evaluation(pos).value(); @@ -1071,8 +1071,8 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 412 * nnueComplexity - + 428 * abs(psq - nnue) + nnueComplexity = ( 406 * nnueComplexity + + 424 * abs(psq - nnue) + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) ) / 1024; @@ -1080,12 +1080,12 @@ Value Eval::evaluate(const Position& pos, int* complexity) { if (complexity) *complexity = nnueComplexity; - optimism = optimism * (278 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 755)) / 1024; + optimism = optimism * (272 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 748)) / 1024; } // Damp down the evaluation linearly when shuffling - v = v * (197 - pos.rule50_count()) / 214; + v = v * (200 - pos.rule50_count()) / 214; // 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); diff --git a/src/search.cpp b/src/search.cpp index dd240366..d0ed44fa 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -63,7 +63,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(165 * (d - improving)); + return Value(158 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -71,7 +71,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1642 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 916); + return (r + 1460 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 937); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((12 * d + 282) * d - 349 , 1480); + return std::min((11 * d + 284) * d - 363 , 1650); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -307,7 +307,7 @@ void Thread::search() { multiPV = std::min(multiPV, rootMoves.size()); - complexityAverage.set(155, 1); + complexityAverage.set(153, 1); optimism[us] = optimism[~us] = VALUE_ZERO; @@ -351,12 +351,12 @@ void Thread::search() { if (rootDepth >= 4) { Value prev = rootMoves[pvIdx].averageScore; - delta = Value(10) + int(prev) * prev / 15620; + delta = Value(10) + int(prev) * prev / 15400; alpha = std::max(prev - delta,-VALUE_INFINITE); beta = std::min(prev + delta, VALUE_INFINITE); // Adjust optimism based on root move's previousScore - int opt = 118 * prev / (std::abs(prev) + 169); + int opt = 116 * prev / (std::abs(prev) + 170); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; } @@ -753,7 +753,7 @@ namespace { // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { - int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1914, 1914); + int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1940, 1940); thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus; } @@ -763,13 +763,13 @@ namespace { // margin and the improving flag are used in various pruning heuristics. improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval - : 168; + : 172; improving = improvement > 0; // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if (eval < alpha - 369 - 254 * depth * depth) + if (eval < alpha - 394 - 255 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -780,18 +780,18 @@ namespace { // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 8 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 303 >= beta + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 304 >= beta && eval >= beta - && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 28580) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~35 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 17139 + && (ss-1)->statScore < 18200 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 20 * depth - improvement / 13 + 233 + complexity / 25 + && ss->staticEval >= beta - 20 * depth - improvement / 14 + 235 + complexity / 24 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) @@ -799,7 +799,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 168, 7) + depth / 3 + 4 - (complexity > 861); + Depth R = std::min(int(eval - beta) / 165, 6) + depth / 3 + 4 - (complexity > 800); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -835,7 +835,7 @@ namespace { } } - probCutBeta = beta + 191 - 54 * improving; + probCutBeta = beta + 180 - 54 * improving; // Step 10. ProbCut (~10 Elo) // If we have a good enough capture and a reduced search returns a value @@ -904,7 +904,7 @@ namespace { moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~4 Elo) - probCutBeta = beta + 417; + probCutBeta = beta + 402; if ( ss->inCheck && !PvNode && depth >= 2 @@ -999,12 +999,12 @@ moves_loop: // When in check, search starts here && !PvNode && lmrDepth < 7 && !ss->inCheck - && ss->staticEval + 180 + 201 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + && ss->staticEval + 185 + 203 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha) continue; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, Value(-222) * depth)) + if (!pos.see_ge(move, Value(-220) * depth)) continue; } else @@ -1015,7 +1015,7 @@ moves_loop: // When in check, search starts here // Continuation history based pruning (~2 Elo) if ( lmrDepth < 5 - && history < -3875 * (depth - 1)) + && history < -4180 * (depth - 1)) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; @@ -1023,11 +1023,11 @@ moves_loop: // When in check, search starts here // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck && lmrDepth < 13 - && ss->staticEval + 106 + 145 * lmrDepth + history / 52 <= alpha) + && ss->staticEval + 103 + 136 * lmrDepth + history / 53 <= alpha) continue; // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) + if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 16 * lmrDepth))) continue; } } @@ -1092,14 +1092,14 @@ moves_loop: // When in check, search starts here // Check extensions (~1 Elo) else if ( givesCheck && depth > 9 - && abs(ss->staticEval) > 82) + && abs(ss->staticEval) > 78) extension = 1; // Quiet ttMove extensions (~1 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 5177) + && (*contHist[0])[movedPiece][to_sq(move)] >= 5600) extension = 1; } @@ -1161,10 +1161,10 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4433; + - 4467; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); + r -= ss->statScore / (12800 + 4410 * (depth > 7 && depth < 19)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has @@ -1188,7 +1188,7 @@ moves_loop: // When in check, search starts here { // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower - const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); + const bool doDeeperSearch = value > (alpha + 66 + 11 * (newDepth - d)); const bool doEvenDeeperSearch = value > alpha + 582 && ss->doubleExtensions <= 5; const bool doShallowerSearch = value < bestValue + newDepth; @@ -1353,7 +1353,7 @@ moves_loop: // When in check, search starts here quietsSearched, quietCount, capturesSearched, captureCount, depth); // Bonus for prior countermove that caused the fail low - else if ( (depth >= 5 || PvNode || bestValue < alpha - 62 * depth) + else if ( (depth >= 5 || PvNode || bestValue < alpha - 65 * depth) && !priorCapture) { //Assign extra bonus if current node is PvNode or cutNode @@ -1361,7 +1361,7 @@ moves_loop: // When in check, search starts here bool extraBonus = PvNode || cutNode; - bool doubleExtraBonus = extraBonus && bestValue < alpha - 85 * depth; + bool doubleExtraBonus = extraBonus && bestValue < alpha - 88 * depth; update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus + doubleExtraBonus)); } @@ -1488,7 +1488,7 @@ moves_loop: // When in check, search starts here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = bestValue + 153; + futilityBase = bestValue + 158; } const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, @@ -1690,7 +1690,7 @@ moves_loop: // When in check, search starts here if (!pos.capture(bestMove)) { - int bonus2 = bestValue > beta + 137 ? bonus1 // larger bonus + int bonus2 = bestValue > beta + 146 ? bonus1 // larger bonus : stat_bonus(depth); // smaller bonus // Increase stats for the best move in case it was a quiet move From 9fe9ff00823a0d1e989fcfc45410396e94345987 Mon Sep 17 00:00:00 2001 From: mstembera Date: Tue, 27 Dec 2022 16:44:32 -0800 Subject: [PATCH 032/192] Fix stack initialization This fixes a bug where on line 278 the Stack::staticEvals are initialized to 0. However VALUE_NONE is defined to be 32002 so this is a bug in master. It is probably due to the calculation of improvement, where staticEval prior to rootPos can be accessed. https://tests.stockfishchess.org/tests/view/63ab91cf39af998100ce1666 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 53736 W: 14285 L: 13955 D: 25496 Ptnml(0-2): 121, 5921, 14500, 6159, 167 https://tests.stockfishchess.org/tests/view/63b2af5ee28ed36c814bed52 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 33776 W: 9130 L: 8934 D: 15712 Ptnml(0-2): 14, 3240, 10185, 3434, 15 closes https://github.com/official-stockfish/Stockfish/pull/4320 Bench: 4068510 --- src/search.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index d0ed44fa..d27b21d2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -276,8 +276,11 @@ void Thread::search() { int iterIdx = 0; std::memset(ss-7, 0, 10 * sizeof(Stack)); - for (int i = 7; i > 0; i--) + for (int i = 7; i > 0; --i) + { (ss-i)->continuationHistory = &this->continuationHistory[0][0][NO_PIECE][0]; // Use as a sentinel + (ss-i)->staticEval = VALUE_NONE; + } for (int i = 0; i <= MAX_PLY + 2; ++i) (ss+i)->ply = i; From ea0f34120fbc1ab7aa8047a1319714b87a1f3b87 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sat, 24 Dec 2022 09:43:22 -0600 Subject: [PATCH 033/192] Late countermove bonus: remove "extraBonus &&" passed stc: https://tests.stockfishchess.org/tests/view/63a71e409c0589b83751dc25 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 432480 W: 113846 L: 114055 D: 204579 Ptnml(0-2): 1164, 48205, 117701, 48016, 1154 passed ltc: https://tests.stockfishchess.org/tests/view/63aba66639af998100ce1aa9 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 245344 W: 65309 L: 65317 D: 114718 Ptnml(0-2): 117, 24257, 73903, 24307, 88 closes https://github.com/official-stockfish/Stockfish/pull/4322 bench 4379218 --- src/search.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index d27b21d2..55af6aba 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1359,14 +1359,9 @@ moves_loop: // When in check, search starts here else if ( (depth >= 5 || PvNode || bestValue < alpha - 65 * depth) && !priorCapture) { - //Assign extra bonus if current node is PvNode or cutNode - //or fail low was really bad - bool extraBonus = PvNode - || cutNode; - - bool doubleExtraBonus = extraBonus && bestValue < alpha - 88 * depth; - - update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus + doubleExtraBonus)); + // Extra bonuses for PV/Cut nodes or bad fail lows + int bonus = 1 + (PvNode || cutNode) + (bestValue < alpha - 88 * depth); + update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } if (PvNode) From 4101893a28b4d34262ed1fba10f2365e964b6537 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:26:51 +0100 Subject: [PATCH 034/192] On step 18 increase reduction by 2 if not ttmove and cutnode stc: https://tests.stockfishchess.org/tests/view/63babc9fcd3db0c8d399f723 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 43104 W: 11711 L: 11389 D: 20004 Ptnml(0-2): 211, 4518, 11793, 4798, 232 ltc: https://tests.stockfishchess.org/tests/view/63bb1857cd3db0c8d39a0661 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 127104 W: 33810 L: 33339 D: 59955 Ptnml(0-2): 39, 12155, 38702, 12608, 48 closes https://github.com/official-stockfish/Stockfish/pull/4334 Bench: 4035725 --- src/search.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 55af6aba..f5eeb23b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1215,6 +1215,10 @@ moves_loop: // When in check, search starts here // Step 18. Full depth search when LMR is skipped. If expected reduction is high, reduce its depth by 1. else if (!PvNode || moveCount > 1) { + // Increase reduction for cut nodes and not ttMove (~1 Elo) + if (!ttMove && cutNode) + r += 2; + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode); } From fcee83810a5bcf774d3e13cf9e65ccf3b29e3319 Mon Sep 17 00:00:00 2001 From: Jake Senne <26696846+w1wwwwww@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:16:45 -0600 Subject: [PATCH 035/192] Only close file if already open Ensures that the tablebase file is only closed if already open. Fixes #4268 Closes https://github.com/official-stockfish/Stockfish/pull/4321 No functional change --- AUTHORS | 1 + src/syzygy/tbprobe.cpp | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index 70b500ea..998399b9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -92,6 +92,7 @@ Ivan Ivec (IIvec) Jacques B. (Timshel) Jan Ondruš (hxim) Jared Kish (Kurtbusch, kurt22i) +Jake Senne (w1wwwwww) Jarrod Torriero (DU-jdto) Jean Gauthier (OuaisBla) Jean-Francois Romang (jromang) diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index b7ba3240..cc5e2852 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -199,13 +199,10 @@ public: } } - // Memory map the file and check it. File should be already open and will be - // closed after mapping. + // Memory map the file and check it. uint8_t* map(void** baseAddress, uint64_t* mapping, TBType type) { - - assert(is_open()); - - close(); // Need to re-open to get native file descriptor + if (is_open()) + close(); // Need to re-open to get native file descriptor #ifndef _WIN32 struct stat statbuf; From 31acd6bab70f4661316986c2c93163d39736fd61 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Tue, 27 Dec 2022 21:06:10 +0100 Subject: [PATCH 036/192] Warn if a global function has no previous declaration If a global function has no previous declaration, either the declaration is missing in the corresponding header file or the function should be declared static. Static functions are local to the translation unit, which allows the compiler to apply some optimizations earlier (when compiling the translation unit rather than during link-time optimization). The commit enables the warning for gcc, clang, and mingw. It also fixes the reported warnings by declaring the functions static or by adding a header file (benchmark.h). closes https://github.com/official-stockfish/Stockfish/pull/4325 No functional change --- src/Makefile | 6 +++--- src/benchmark.cpp | 2 ++ src/benchmark.h | 34 ++++++++++++++++++++++++++++++++++ src/evaluate.cpp | 10 +++++----- src/misc.cpp | 2 +- src/nnue/evaluate_nnue.cpp | 10 +++++----- src/uci.cpp | 3 +-- src/ucioption.cpp | 14 +++++++------- 8 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 src/benchmark.h diff --git a/src/Makefile b/src/Makefile index d4f089ee..30c1be5e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -366,7 +366,7 @@ endif ifeq ($(COMP),gcc) comp=gcc CXX=g++ - CXXFLAGS += -pedantic -Wextra -Wshadow + CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64)) ifeq ($(OS),Android) @@ -410,7 +410,7 @@ ifeq ($(COMP),mingw) CXX=i686-w64-mingw32-c++-posix endif endif - CXXFLAGS += -pedantic -Wextra -Wshadow + CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations endif ifeq ($(COMP),icc) @@ -426,7 +426,7 @@ ifeq ($(COMP),clang) CXX=x86_64-w64-mingw32-clang++ endif - CXXFLAGS += -pedantic -Wextra -Wshadow + CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-prototypes ifeq ($(filter $(KERNEL),Darwin OpenBSD FreeBSD),) ifeq ($(target_windows),) diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 2abb9c8f..a1ad0550 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -16,6 +16,8 @@ along with this program. If not, see . */ +#include "benchmark.h" + #include #include #include diff --git a/src/benchmark.h b/src/benchmark.h new file mode 100644 index 00000000..64acf833 --- /dev/null +++ b/src/benchmark.h @@ -0,0 +1,34 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2023 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 . +*/ + +#ifndef BENCHMARK_H_INCLUDED +#define BENCHMARK_H_INCLUDED + +#include +#include +#include + +namespace Stockfish { + +class Position; + +std::vector setup_bench(const Position&, std::istream&); + +} // namespace Stockfish + +#endif // #ifndef BENCHMARK_H_INCLUDED diff --git a/src/evaluate.cpp b/src/evaluate.cpp index d5cda3d8..3aae9f1c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -159,24 +159,24 @@ namespace Trace { Score scores[TERM_NB][COLOR_NB]; - double to_cp(Value v) { return double(v) / UCI::NormalizeToPawnValue; } + static double to_cp(Value v) { return double(v) / UCI::NormalizeToPawnValue; } - void add(int idx, Color c, Score s) { + static void add(int idx, Color c, Score s) { scores[idx][c] = s; } - void add(int idx, Score w, Score b = SCORE_ZERO) { + static void add(int idx, Score w, Score b = SCORE_ZERO) { scores[idx][WHITE] = w; scores[idx][BLACK] = b; } - std::ostream& operator<<(std::ostream& os, Score s) { + static std::ostream& operator<<(std::ostream& os, Score s) { os << std::setw(5) << to_cp(mg_value(s)) << " " << std::setw(5) << to_cp(eg_value(s)); return os; } - std::ostream& operator<<(std::ostream& os, Term t) { + static std::ostream& operator<<(std::ostream& os, Term t) { if (t == MATERIAL || t == IMBALANCE || t == WINNABLE || t == TOTAL) os << " ---- ----" << " | " << " ---- ----"; diff --git a/src/misc.cpp b/src/misc.cpp index 5bb8da69..1cb515c3 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -517,7 +517,7 @@ void bindThisThread(size_t) {} /// API and returns the best node id for the thread with index idx. Original /// code from Texel by Peter Österlund. -int best_node(size_t idx) { +static int best_node(size_t idx) { int threads = 0; int nodes = 0; diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 8d720ccb..a06c1978 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -83,7 +83,7 @@ namespace Stockfish::Eval::NNUE { } // namespace Detail // Initialize the evaluation function parameters - void initialize() { + static void initialize() { Detail::initialize(featureTransformer); for (std::size_t i = 0; i < LayerStacks; ++i) @@ -91,7 +91,7 @@ namespace Stockfish::Eval::NNUE { } // Read network header - bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) + static bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) { std::uint32_t version, size; @@ -105,7 +105,7 @@ namespace Stockfish::Eval::NNUE { } // Write network header - bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) + static bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) { write_little_endian(stream, Version); write_little_endian(stream, hashValue); @@ -115,7 +115,7 @@ namespace Stockfish::Eval::NNUE { } // Read network parameters - bool read_parameters(std::istream& stream) { + static bool read_parameters(std::istream& stream) { std::uint32_t hashValue; if (!read_header(stream, &hashValue, &netDescription)) return false; @@ -127,7 +127,7 @@ namespace Stockfish::Eval::NNUE { } // Write network parameters - bool write_parameters(std::ostream& stream) { + static bool write_parameters(std::ostream& stream) { if (!write_header(stream, HashValue, netDescription)) return false; if (!Detail::write_parameters(stream, *featureTransformer)) return false; diff --git a/src/uci.cpp b/src/uci.cpp index c49b9b78..eb158e72 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -22,6 +22,7 @@ #include #include +#include "benchmark.h" #include "evaluate.h" #include "movegen.h" #include "position.h" @@ -36,8 +37,6 @@ using namespace std; namespace Stockfish { -vector setup_bench(const Position&, istream&); - namespace { // FEN string for the initial position in standard chess diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 78711c18..b4ce70b4 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -38,13 +38,13 @@ UCI::OptionsMap Options; // Global object namespace UCI { /// 'On change' actions, triggered by an option's value change -void on_clear_hash(const Option&) { Search::clear(); } -void on_hash_size(const Option& o) { TT.resize(size_t(o)); } -void on_logger(const Option& o) { start_logger(o); } -void on_threads(const Option& o) { Threads.set(size_t(o)); } -void on_tb_path(const Option& o) { Tablebases::init(o); } -void on_use_NNUE(const Option& ) { Eval::NNUE::init(); } -void on_eval_file(const Option& ) { Eval::NNUE::init(); } +static void on_clear_hash(const Option&) { Search::clear(); } +static void on_hash_size(const Option& o) { TT.resize(size_t(o)); } +static void on_logger(const Option& o) { start_logger(o); } +static void on_threads(const Option& o) { Threads.set(size_t(o)); } +static void on_tb_path(const Option& o) { Tablebases::init(o); } +static void on_use_NNUE(const Option&) { Eval::NNUE::init(); } +static void on_eval_file(const Option&) { Eval::NNUE::init(); } /// Our case insensitive less() function as required by UCI protocol bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const { From 5a88c5bb9b3e5ee431ac85abb8981b1571b68b2d Mon Sep 17 00:00:00 2001 From: Stefano Di Martino Date: Sat, 7 Jan 2023 01:08:30 +0100 Subject: [PATCH 037/192] Modernize code base a little bit Removed sprintf() which generated a warning, because of security reasons. Replace NULL with nullptr Replace typedef with using Do not inherit from std::vector. Use composition instead. optimize mutex-unlocking closes https://github.com/official-stockfish/Stockfish/pull/4327 No functional change --- AUTHORS | 1 + src/material.h | 2 +- src/misc.cpp | 8 ++++---- src/nnue/evaluate_nnue.cpp | 31 ++++++++++++------------------- src/thread.cpp | 38 +++++++++++++++++++------------------- src/thread.h | 14 +++++++++++--- src/thread_win32_osx.h | 6 +++--- 7 files changed, 51 insertions(+), 49 deletions(-) diff --git a/AUTHORS b/AUTHORS index 998399b9..87fed7b8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -192,6 +192,7 @@ Shawn Varghese (xXH4CKST3RXx) Siad Daboul (Topologist) Stefan Geschwentner (locutus2) Stefano Cardanobile (Stefano80) +Stefano Di Martino (StefanoD) Steinar Gunderson (sesse) Stéphane Nicolet (snicolet) Syine Mineta (MinetaS) diff --git a/src/material.h b/src/material.h index f6db85c4..73c83100 100644 --- a/src/material.h +++ b/src/material.h @@ -28,7 +28,7 @@ namespace Stockfish::Material { /// Material::Entry contains various information about a material configuration. /// It contains a material imbalance evaluation, a function pointer to a special -/// endgame evaluation function (which in most cases is NULL, meaning that the +/// endgame evaluation function (which in most cases is nullptr, meaning that the /// standard evaluation function will be used), and scale factors. /// /// The scale factors are used to scale the evaluation score up or down. For diff --git a/src/misc.cpp b/src/misc.cpp index 1cb515c3..be7abba5 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -413,7 +413,7 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken)) return nullptr; - if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid)) + if (LookupPrivilegeValue(nullptr, SE_LOCK_MEMORY_NAME, &luid)) { TOKEN_PRIVILEGES tp { }; TOKEN_PRIVILEGES prevTp { }; @@ -432,10 +432,10 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize // Round up size to full pages and allocate allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1); mem = VirtualAlloc( - NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); // Privilege no longer needed, restore previous state - AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL); + AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr); } } @@ -453,7 +453,7 @@ void* aligned_large_pages_alloc(size_t allocSize) { // Fall back to regular, page aligned, allocation if necessary if (!mem) - mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); return mem; } diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index a06c1978..06281da0 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -26,7 +26,6 @@ #include "../evaluate.h" #include "../position.h" -#include "../misc.h" #include "../uci.h" #include "../types.h" @@ -245,14 +244,15 @@ namespace Stockfish::Eval::NNUE { } - // format_cp_aligned_dot() converts a Value into (centi)pawns and writes it in a buffer, - // always keeping two decimals. The buffer must have capacity for at least 7 chars. - static void format_cp_aligned_dot(Value v, char* buffer) { + // format_cp_aligned_dot() converts a Value into (centi)pawns, always keeping two decimals. + static void format_cp_aligned_dot(Value v, std::stringstream &stream) { + const double cp = 1.0 * std::abs(int(v)) / UCI::NormalizeToPawnValue; - buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' '); - - double cp = 1.0 * std::abs(int(v)) / UCI::NormalizeToPawnValue; - sprintf(&buffer[1], "%6.2f", cp); + stream << (v < 0 ? '-' : v > 0 ? '+' : ' ') + << std::setiosflags(std::ios::fixed) + << std::setw(6) + << std::setprecision(2) + << cp; } @@ -332,17 +332,10 @@ namespace Stockfish::Eval::NNUE { for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) { - char buffer[3][8]; - std::memset(buffer, '\0', sizeof(buffer)); - - format_cp_aligned_dot(t.psqt[bucket], buffer[0]); - format_cp_aligned_dot(t.positional[bucket], buffer[1]); - format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], buffer[2]); - - ss << "| " << bucket << " " - << " | " << buffer[0] << " " - << " | " << buffer[1] << " " - << " | " << buffer[2] << " " + ss << "| " << bucket << " "; + ss << " | "; format_cp_aligned_dot(t.psqt[bucket], ss); ss << " " + << " | "; format_cp_aligned_dot(t.positional[bucket], ss); ss << " " + << " | "; format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], ss); ss << " " << " |"; if (bucket == t.correctBucket) ss << " <-- this bucket is used"; diff --git a/src/thread.cpp b/src/thread.cpp index 7e71edf1..ca1a7c85 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -73,9 +73,9 @@ void Thread::clear() { /// Thread::start_searching() wakes up the thread that will start the search void Thread::start_searching() { - - std::lock_guard lk(mutex); + mutex.lock(); searching = true; + mutex.unlock(); // Unlock before notifying saves a few CPU-cycles cv.notify_one(); // Wake up the thread in idle_loop() } @@ -125,20 +125,20 @@ void Thread::idle_loop() { void ThreadPool::set(size_t requested) { - if (size() > 0) // destroy any existing thread(s) + if (threads.size() > 0) // destroy any existing thread(s) { main()->wait_for_search_finished(); - while (size() > 0) - delete back(), pop_back(); + while (threads.size() > 0) + delete threads.back(), threads.pop_back(); } if (requested > 0) // create new thread(s) { - push_back(new MainThread(0)); + threads.push_back(new MainThread(0)); - while (size() < requested) - push_back(new Thread(size())); + while (threads.size() < requested) + threads.push_back(new Thread(threads.size())); clear(); // Reallocate the hash with the new threadpool size @@ -154,7 +154,7 @@ void ThreadPool::set(size_t requested) { void ThreadPool::clear() { - for (Thread* th : *this) + for (Thread* th : threads) th->clear(); main()->callsCnt = 0; @@ -187,7 +187,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states, Tablebases::rank_root_moves(pos, rootMoves); // After ownership transfer 'states' becomes empty, so if we stop the search - // and call 'go' again without setting a new position states.get() == NULL. + // and call 'go' again without setting a new position states.get() == nullptr. assert(states.get() || setupStates.get()); if (states.get()) @@ -198,7 +198,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states, // be deduced from a fen string, so set() clears them and they are set from // setupStates->back() later. The rootState is per thread, earlier states are shared // since they are read-only. - for (Thread* th : *this) + for (Thread* th : threads) { th->nodes = th->tbHits = th->nmpMinPly = th->bestMoveChanges = 0; th->rootDepth = th->completedDepth = 0; @@ -212,12 +212,12 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states, Thread* ThreadPool::get_best_thread() const { - Thread* bestThread = front(); + Thread* bestThread = threads.front(); std::map votes; Value minScore = VALUE_NONE; // Find minimum score of all threads - for (Thread* th: *this) + for (Thread* th: threads) minScore = std::min(minScore, th->rootMoves[0].score); // Vote according to score and depth, and select the best thread @@ -225,10 +225,10 @@ Thread* ThreadPool::get_best_thread() const { return (th->rootMoves[0].score - minScore + 14) * int(th->completedDepth); }; - for (Thread* th : *this) + for (Thread* th : threads) votes[th->rootMoves[0].pv[0]] += thread_value(th); - for (Thread* th : *this) + for (Thread* th : threads) if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY) { // Make sure we pick the shortest mate / TB conversion or stave off mate the longest @@ -251,8 +251,8 @@ Thread* ThreadPool::get_best_thread() const { void ThreadPool::start_searching() { - for (Thread* th : *this) - if (th != front()) + for (Thread* th : threads) + if (th != threads.front()) th->start_searching(); } @@ -261,8 +261,8 @@ void ThreadPool::start_searching() { void ThreadPool::wait_for_search_finished() const { - for (Thread* th : *this) - if (th != front()) + for (Thread* th : threads) + if (th != threads.front()) th->wait_for_search_finished(); } diff --git a/src/thread.h b/src/thread.h index 680da209..7566322c 100644 --- a/src/thread.h +++ b/src/thread.h @@ -101,13 +101,13 @@ struct MainThread : public Thread { /// parking and, most importantly, launching a thread. All the access to threads /// is done through this class. -struct ThreadPool : public std::vector { +struct ThreadPool { void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false); void clear(); void set(size_t); - MainThread* main() const { return static_cast(front()); } + MainThread* main() const { return static_cast(threads.front()); } uint64_t nodes_searched() const { return accumulate(&Thread::nodes); } uint64_t tb_hits() const { return accumulate(&Thread::tbHits); } Thread* get_best_thread() const; @@ -116,13 +116,21 @@ struct ThreadPool : public std::vector { std::atomic_bool stop, increaseDepth; + auto cbegin() const noexcept { return threads.cbegin(); } + auto begin() noexcept { return threads.begin(); } + auto end() noexcept { return threads.end(); } + auto cend() const noexcept { return threads.cend(); } + auto size() const noexcept { return threads.size(); } + auto empty() const noexcept { return threads.empty(); } + private: StateListPtr setupStates; + std::vector threads; uint64_t accumulate(std::atomic Thread::* member) const { uint64_t sum = 0; - for (Thread* th : *this) + for (Thread* th : threads) sum += (th->*member).load(std::memory_order_relaxed); return sum; } diff --git a/src/thread_win32_osx.h b/src/thread_win32_osx.h index 01ff1c77..330a8341 100644 --- a/src/thread_win32_osx.h +++ b/src/thread_win32_osx.h @@ -41,7 +41,7 @@ void* start_routine(void* ptr) P* p = reinterpret_cast(ptr); (p->first->*(p->second))(); // Call member function pointer delete p; - return NULL; + return nullptr; } class NativeThread { @@ -56,7 +56,7 @@ public: pthread_attr_setstacksize(attr, TH_STACK_SIZE); pthread_create(&thread, attr, start_routine, new P(obj, fun)); } - void join() { pthread_join(thread, NULL); } + void join() { pthread_join(thread, nullptr); } }; } // namespace Stockfish @@ -65,7 +65,7 @@ public: namespace Stockfish { -typedef std::thread NativeThread; +using NativeThread = std::thread; } // namespace Stockfish From e9e7a7b83f78b5c7d29f69083589b449d9b52390 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sat, 7 Jan 2023 14:53:59 +0100 Subject: [PATCH 038/192] Replace some std::string occurrences with std::string_view std::string_view is more lightweight than std::string. Furthermore, std::string_view variables can be declared constexpr. closes https://github.com/official-stockfish/Stockfish/pull/4328 No functional change --- src/misc.cpp | 9 +++++---- src/nnue/evaluate_nnue.cpp | 7 ++++--- src/position.cpp | 3 ++- src/syzygy/tbprobe.cpp | 7 ++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index be7abba5..b651972b 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -41,12 +41,13 @@ typedef WORD(*fun5_t)(); } #endif +#include #include #include #include #include +#include #include -#include #if defined(__linux__) && !defined(__ANDROID__) #include @@ -68,7 +69,7 @@ namespace Stockfish { namespace { /// Version number or dev. -const string version = "dev"; +constexpr string_view version = "dev"; /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We @@ -151,13 +152,13 @@ string engine_info(bool to_uci) { stringstream ss; ss << "Stockfish " << version << setfill('0'); - if (version == "dev") + if constexpr (version == "dev") { ss << "-"; #ifdef GIT_DATE ss << GIT_DATE; #else - const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); + constexpr string_view months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); string month, day, year; stringstream date(__DATE__); // From compiler, format is "Sep 21 2008" diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 06281da0..f132de71 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -18,11 +18,12 @@ // Code for calculating NNUE evaluation function +#include +#include #include #include #include -#include -#include +#include #include "../evaluate.h" #include "../position.h" @@ -210,7 +211,7 @@ namespace Stockfish::Eval::NNUE { return t; } - static const std::string PieceToChar(" PNBRQK pnbrqk"); + constexpr std::string_view PieceToChar(" PNBRQK pnbrqk"); // format_cp_compact() converts a Value into (centi)pawns and writes it in a buffer. diff --git a/src/position.cpp b/src/position.cpp index e82425af..cfd98f68 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -22,6 +22,7 @@ #include // For std::memset, std::memcmp #include #include +#include #include "bitboard.h" #include "misc.h" @@ -46,7 +47,7 @@ namespace Zobrist { namespace { -const string PieceToChar(" PNBRQK pnbrqk"); +constexpr std::string_view PieceToChar(" PNBRQK pnbrqk"); constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index cc5e2852..bbfd819d 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -24,9 +24,10 @@ #include #include #include -#include -#include #include +#include +#include +#include #include "../bitboard.h" #include "../movegen.h" @@ -70,7 +71,7 @@ enum TBFlag { STM = 1, Mapped = 2, WinPlies = 4, LossPlies = 8, Wide = 16, Singl inline WDLScore operator-(WDLScore d) { return WDLScore(-int(d)); } inline Square operator^(Square s, int i) { return Square(int(s) ^ i); } -const std::string PieceToChar = " PNBRQK pnbrqk"; +constexpr std::string_view PieceToChar = " PNBRQK pnbrqk"; int MapPawns[SQUARE_NB]; int MapB1H1H7[SQUARE_NB]; From 4f4e652ecaf8d42a9bd1092f72c3704435ddba12 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Fri, 6 Jan 2023 18:13:21 +0100 Subject: [PATCH 039/192] Avoid unnecessary string copies closes https://github.com/official-stockfish/Stockfish/pull/4326 also fixes typo, closes https://github.com/official-stockfish/Stockfish/pull/4332 No functional change --- src/evaluate.cpp | 2 +- src/nnue/layers/sqr_clipped_relu.h | 2 +- src/uci.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 3aae9f1c..6db977a4 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -89,7 +89,7 @@ namespace Eval { vector dirs = { "" , "" , CommandLine::binaryDirectory }; #endif - for (string directory : dirs) + for (const string& directory : dirs) if (currentEvalFileName != eval_file) { if (directory != "") diff --git a/src/nnue/layers/sqr_clipped_relu.h b/src/nnue/layers/sqr_clipped_relu.h index df539b39..3fbb243c 100644 --- a/src/nnue/layers/sqr_clipped_relu.h +++ b/src/nnue/layers/sqr_clipped_relu.h @@ -106,7 +106,7 @@ namespace Stockfish::Eval::NNUE::Layers { for (IndexType i = Start; i < InputDimensions; ++i) { output[i] = static_cast( - // realy should be /127 but we need to make it fast + // really 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))); } diff --git a/src/uci.cpp b/src/uci.cpp index eb158e72..30c1fa0c 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -160,7 +160,7 @@ namespace { uint64_t num, nodes = 0, cnt = 1; vector list = setup_bench(pos, args); - num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0 || s.find("eval") == 0; }); + num = count_if(list.begin(), list.end(), [](const string& s) { return s.find("go ") == 0 || s.find("eval") == 0; }); TimePoint elapsed = now(); From 3d2381d76d7bf9686ef0e0671f60c3b885a7058a Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Wed, 11 Jan 2023 10:07:56 -0500 Subject: [PATCH 040/192] Update default net to nn-1e7ca356472e.nnue Created by retraining the master net on a dataset composed of: * The Leela-dfrc_n5000.binpack dataset filtered with depth6 multipv2 search to remove positions with only one good move, in addition to removing positions where either of the two best moves are captures * The same Leela T80 oct+nov 2022 training data used in recent best datasets * Additional Leela training data from T60 nov+dec 2021 and T79 apr+may 2022 Trained with end lambda 0.7 and started with max epoch 800. All positions with ply <= 28 were skipped: ``` python easy_train.py \ --experiment-name leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p-sk28-lambda7 \ --training-dataset /data/leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \ --start-from-engine-test-net True \ --gpus "0," \ --start-lambda 1.0 \ --end-lambda 0.7 \ --gamma 0.995 \ --lr 4.375e-4 \ --tui False \ --seed $RANDOM \ --max_epoch 800 ``` Around epoch 780, training was manually paused and max epoch increased to 920 before resuming. During depth6 multipv2 data filtering, positions were considered to have only one good move if the score of the best move was significantly better than the 2nd best move in a way that changes the outcome of the game: * the best move leads to a significant advantage while the 2nd best move equalizes or loses * the best move is about equal while the 2nd best move loses The modified stockfish branch and exact score thresholds used for filtering are at: https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-eval-diff/src/filter About 95% of the Leela portion and 96% of the DFRC portion of the Leela-dfrc_n5000.binpack dataset was filtered. Unfiltered parts of the dataset were left out. The additional Leela training data from T60 nov+dec 2021 and T79 apr+may 2022 was WDL-rescored with about 12TB of syzygy 7-piece tablebases where the material difference is less than around 6 pawns. Best moves were exported to .plain data files during data conversion with the lc0 rescorer. The exact training data can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move experiment_leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p-sk28-lambda7 run_0/nn-epoch899.nnue : 3.8 +/- 1.6 Passed STC https://tests.stockfishchess.org/tests/view/63bed1f540aa064159b9c89b LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 103344 W: 27392 L: 26991 D: 48961 Ptnml(0-2): 333, 11223, 28099, 11744, 273 Passed LTC https://tests.stockfishchess.org/tests/view/63c010415705810de2deb3ec LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 21712 W: 5891 L: 5619 D: 10202 Ptnml(0-2): 12, 2022, 6511, 2304, 7 closes https://github.com/official-stockfish/Stockfish/pull/4338 bench 4106793 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 0a00faa7..643e8540 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-a3dc078bafc7.nnue" + #define EvalFileDefaultName "nn-1e7ca356472e.nnue" namespace NNUE { From da5bcec481dc22ad2de2e2c8e5c6e8304a373445 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sat, 14 Jan 2023 16:09:31 +0100 Subject: [PATCH 041/192] Fix asm modifiers in add_dpbusd_epi32x2 implementations The accumulator should be an earlyclobber because it is written before all input operands are read. Otherwise, the asm code computes a wrong result if the accumulator shares a register with one of the other input operands (which happens if we pass in the same expression for the accumulator and the operand). Closes https://github.com/official-stockfish/Stockfish/pull/4339 No functional change --- src/nnue/layers/simd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nnue/layers/simd.h b/src/nnue/layers/simd.h index aeab39c4..231f7891 100644 --- a/src/nnue/layers/simd.h +++ b/src/nnue/layers/simd.h @@ -153,7 +153,7 @@ namespace Stockfish::Simd { asm( "vpdpbusd %[b0], %[a0], %[acc]\n\t" "vpdpbusd %[b1], %[a1], %[acc]\n\t" - : [acc]"+v"(acc) + : [acc]"+&v"(acc) : [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1) ); # else @@ -249,7 +249,7 @@ namespace Stockfish::Simd { asm( VNNI_PREFIX "vpdpbusd %[b0], %[a0], %[acc]\n\t" VNNI_PREFIX "vpdpbusd %[b1], %[a1], %[acc]\n\t" - : [acc]"+v"(acc) + : [acc]"+&v"(acc) : [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1) ); # else From a08b8d4e9711c20acedbfe17d618c3c384b339ec Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 15 Jan 2023 00:23:24 +0100 Subject: [PATCH 042/192] Update UCI_Elo parameterization The old parameterization (https://github.com/official-stockfish/Stockfish/pull/2225/files) has now become quite inaccurate. This updates the formula based on updated results with master. The formula is based on a fit of the Elo results for games played between master at various skill levels, and various versions of the Stash engine, which have been ranked at CCRL. ``` # PLAYER : RATING ERROR POINTS PLAYED (%) 1 master-skill-19 : 3191.1 40.4 940.0 1707 55 2 master-skill-18 : 3170.3 39.3 1343.0 2519 53 3 master-skill-17 : 3141.3 37.8 2282.0 4422 52 4 master-skill-16 : 3111.2 37.1 2773.0 5423 51 5 master-skill-15 : 3069.5 37.2 2728.5 5386 51 6 master-skill-14 : 3024.8 36.1 2702.0 5339 51 7 master-skill-13 : 2972.9 35.4 2645.5 5263 50 8 master-skill-12 : 2923.1 35.0 2653.5 5165 51 9 master-skill-11 : 2855.5 33.6 2524.0 5081 50 10 master-skill-10 : 2788.3 32.0 2724.5 5511 49 11 stash-bot-v25.0 : 2744.0 31.5 1952.5 3840 51 12 master-skill-9 : 2702.8 30.5 2670.0 5018 53 13 master-skill-8 : 2596.2 28.5 2669.5 4975 54 14 stash-bot-v21.0 : 2561.2 30.0 1338.0 3366 40 15 master-skill-7 : 2499.5 28.5 1934.0 4178 46 16 stash-bot-v20.0 : 2452.6 27.7 1606.5 3378 48 17 stash-bot-v19.0 : 2425.3 26.7 1787.0 3365 53 18 master-skill-6 : 2363.2 26.4 2510.5 4379 57 19 stash-bot-v17.0 : 2280.7 25.4 2209.0 4378 50 20 master-skill-5 : 2203.7 25.3 2859.5 5422 53 21 stash-bot-v15.3 : 2200.0 25.4 1757.0 4383 40 22 stash-bot-v14 : 2145.9 25.5 2890.0 5167 56 23 stash-bot-v13 : 2042.7 25.8 2263.5 4363 52 24 stash-bot-v12 : 1963.4 25.8 1769.5 4210 42 25 master-skill-4 : 1922.9 25.9 2690.0 5399 50 26 stash-bot-v11 : 1873.0 26.3 2203.5 4335 51 27 stash-bot-v10 : 1783.8 27.8 2568.5 4301 60 28 master-skill-3 : 1742.3 27.8 1909.5 4439 43 29 master-skill-2 : 1608.4 29.4 2064.5 4389 47 30 stash-bot-v9 : 1582.6 30.2 2130.0 4230 50 31 master-skill-1 : 1467.6 31.3 2015.5 4244 47 32 stash-bot-v8 : 1452.8 31.5 1953.5 3780 52 33 master-skill-0 : 1320.1 32.9 651.5 2083 31 ``` Skill 0 .. 19, now covers CCRL Blitz Elo from 1320 to 3190, approximately. Indeed, the Elo of stash in this analysis is only to within +- 100 Elo of CCRL, probably because it depends quite a bit on the opponent pool. To obtain a skill level for a given Elo number, the above data is fit as a 3rd degree polynomial Skill(Elo). A quick test confirms the correspondence to the above table: ``` Score of master-elo-2721 vs stash-bot-v21.0: 51 - 16 - 19 [0.703] 86 Elo difference: 150.1 +/- 70.2, LOS: 100.0 %, DrawRatio: 22.1 % ``` closes https://github.com/official-stockfish/Stockfish/pull/4341 No functional change. --- README.md | 2 +- src/search.cpp | 5 ++++- src/ucioption.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4cd5968e..ca90d5d4 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ change them via a chess GUI. This is a list of available UCI options in Stockfis * #### UCI_Elo If enabled by UCI_LimitStrength, aim for an engine strength of the given Elo. - This Elo rating has been calibrated at a time control of 60s+0.6s and anchored to CCRL 40/4. + This Elo rating has been calibrated at a time control of 120s+1.0s and anchored to +- 100 Elo to CCRL Blitz. * #### Skill Level Lower the Skill Level in order to make Stockfish play weaker (see also UCI_LimitStrength). diff --git a/src/search.cpp b/src/search.cpp index f5eeb23b..346fd6c3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -96,7 +96,10 @@ namespace { struct Skill { Skill(int skill_level, int uci_elo) { if (uci_elo) - level = std::clamp(std::pow((uci_elo - 1346.6) / 143.4, 1 / 0.806), 0.0, 20.0); + { + double e = double(uci_elo - 1320) / (3190 - 1320); + level = std::clamp((((37.2473 * e - 40.8525) * e + 22.2943) * e - 0.311438), 0.0, 19.0); + } else level = double(skill_level); } diff --git a/src/ucioption.cpp b/src/ucioption.cpp index b4ce70b4..39933ea5 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -73,7 +73,7 @@ void init(OptionsMap& o) { o["UCI_Chess960"] << Option(false); o["UCI_AnalyseMode"] << Option(false); o["UCI_LimitStrength"] << Option(false); - o["UCI_Elo"] << Option(1350, 1350, 2850); + o["UCI_Elo"] << Option(1320, 1320, 3190); o["UCI_ShowWDL"] << Option(false); o["SyzygyPath"] << Option("", on_tb_path); o["SyzygyProbeDepth"] << Option(1, 1, 100); From 734315ff3099564c80737ad2be8121008870d28b Mon Sep 17 00:00:00 2001 From: Stephen Touset Date: Mon, 16 Jan 2023 14:25:47 -0800 Subject: [PATCH 043/192] Remove precomputed SquareBB Bit-shifting is a single instruction, and should be faster than an array lookup on supported architectures. Besides (ever so slightly) speeding up the conversion of a square into a bitboard, we may see minor general performance improvements due to preserving more of the CPU's existing cache. passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 47280 W: 12469 L: 12271 D: 22540 Ptnml(0-2): 128, 4893, 13402, 5087, 130 https://tests.stockfishchess.org/tests/view/63c5cfe618c20f4929c5fe46 Small speedup locally: ``` Result of 20 runs ================== base (./stockfish.master ) = 1752135 +/- 10943 test (./stockfish.patch ) = 1763939 +/- 10818 diff = +11804 +/- 4731 speedup = +0.0067 P(speedup > 0) = 1.0000 CPU: 16 x AMD Ryzen 9 3950X 16-Core Processor ``` Closes https://github.com/official-stockfish/Stockfish/pull/4343 Bench: 4106793 --- src/bitboard.cpp | 4 ---- src/bitboard.h | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index 0ed13fd0..fd5c3c22 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -27,7 +27,6 @@ namespace Stockfish { uint8_t PopCnt16[1 << 16]; uint8_t SquareDistance[SQUARE_NB][SQUARE_NB]; -Bitboard SquareBB[SQUARE_NB]; Bitboard LineBB[SQUARE_NB][SQUARE_NB]; Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; @@ -82,9 +81,6 @@ void Bitboards::init() { for (unsigned i = 0; i < (1 << 16); ++i) PopCnt16[i] = uint8_t(std::bitset<16>(i).count()); - for (Square s = SQ_A1; s <= SQ_H8; ++s) - SquareBB[s] = (1ULL << s); - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); diff --git a/src/bitboard.h b/src/bitboard.h index d4485fcb..42fd0e97 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -74,7 +74,6 @@ constexpr Bitboard KingFlank[FILE_NB] = { extern uint8_t PopCnt16[1 << 16]; extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB]; -extern Bitboard SquareBB[SQUARE_NB]; extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; extern Bitboard LineBB[SQUARE_NB][SQUARE_NB]; extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; @@ -108,7 +107,7 @@ extern Magic BishopMagics[SQUARE_NB]; inline Bitboard square_bb(Square s) { assert(is_ok(s)); - return SquareBB[s]; + return (1ULL << s); } From a2038c1a011552c3d56d3b318780f7f5eadaf05d Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 17 Jan 2023 21:30:50 -0700 Subject: [PATCH 044/192] apply if constexpr to additional instances as a form of documentation, and a hint to the compiler. closes https://github.com/official-stockfish/Stockfish/pull/4345 No functional change --- AUTHORS | 1 + src/evaluate.cpp | 10 +++++----- src/movegen.cpp | 16 ++++++++-------- src/movepick.cpp | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/AUTHORS b/AUTHORS index 87fed7b8..42ba5930 100644 --- a/AUTHORS +++ b/AUTHORS @@ -101,6 +101,7 @@ Jerry Donald Watson (jerrydonaldwatson) jjoshua2 Jonathan Calovski (Mysseno) Jonathan Buladas Dumale (SFisGOD) +Jonathan McDermid (jonathanmcdermid) Joost VandeVondele (vondele) Jörg Oster (joergoster) Joseph Ellis (jhellis3) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 6db977a4..8683182c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -388,10 +388,10 @@ namespace { template template Score Evaluation::pieces() { - constexpr Color Them = ~Us; - constexpr Direction Down = -pawn_push(Us); - constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB - : Rank5BB | Rank4BB | Rank3BB); + constexpr Color Them = ~Us; + [[maybe_unused]] constexpr Direction Down = -pawn_push(Us); + [[maybe_unused]] constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB + : Rank5BB | Rank4BB | Rank3BB); Bitboard b1 = pos.pieces(Us, Pt); Bitboard b, bb; Score score = SCORE_ZERO; @@ -430,7 +430,7 @@ namespace { int mob = popcount(b & mobilityArea[Us]); mobility[Us] += MobilityBonus[Pt - 2][mob]; - if (Pt == BISHOP || Pt == KNIGHT) + if constexpr (Pt == BISHOP || Pt == KNIGHT) { // Bonus if the piece is on an outpost square or can reach one // Bonus for knights (UncontestedOutpost) if few relevant targets diff --git a/src/movegen.cpp b/src/movegen.cpp index a960f863..47154164 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -26,12 +26,12 @@ namespace Stockfish { namespace { template - ExtMove* make_promotions(ExtMove* moveList, Square to) { + ExtMove* make_promotions(ExtMove* moveList, [[maybe_unused]] Square to) { - if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) + if constexpr (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) *moveList++ = make(to - D, to, QUEEN); - if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS) + if constexpr (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS) { *moveList++ = make(to - D, to, ROOK); *moveList++ = make(to - D, to, BISHOP); @@ -60,18 +60,18 @@ namespace { Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB; // Single and double pawn pushes, no promotions - if (Type != CAPTURES) + if constexpr (Type != CAPTURES) { Bitboard b1 = shift(pawnsNotOn7) & emptySquares; Bitboard b2 = shift(b1 & TRank3BB) & emptySquares; - if (Type == EVASIONS) // Consider only blocking squares + if constexpr (Type == EVASIONS) // Consider only blocking squares { b1 &= target; b2 &= target; } - if (Type == QUIET_CHECKS) + if constexpr (Type == QUIET_CHECKS) { // To make a quiet check, you either make a direct check by pushing a pawn // or push a blocker pawn that is not on the same file as the enemy king. @@ -102,7 +102,7 @@ namespace { Bitboard b2 = shift(pawnsOn7) & enemies; Bitboard b3 = shift(pawnsOn7) & emptySquares; - if (Type == EVASIONS) + if constexpr (Type == EVASIONS) b3 &= target; while (b1) @@ -116,7 +116,7 @@ namespace { } // Standard and en passant captures - if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) + if constexpr (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) { Bitboard b1 = shift(pawnsNotOn7) & enemies; Bitboard b2 = shift(pawnsNotOn7) & enemies; diff --git a/src/movepick.cpp b/src/movepick.cpp index dbe67357..65155a73 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -158,7 +158,7 @@ Move MovePicker::select(Pred filter) { while (cur < endMoves) { - if (T == Best) + if constexpr (T == Best) std::swap(*cur, *std::max_element(cur, endMoves)); if (*cur != ttMove && filter()) From 596a528c6a9ace6fb1a8407c86d972d96653418d Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Fri, 20 Jan 2023 10:41:46 -0500 Subject: [PATCH 045/192] Update default net to nn-bc24c101ada0.nnue Created by retraining the master net with Leela T78 data from Aug+Sep 2022 added to the previous best dataset. Trained with end lambda 0.7 and started with max epoch 800. All positions with ply <= 28 were skipped: ``` python easy_train.py \ --experiment-name leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p-sk28-lambda7 \ --training-dataset /data/leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \ --start-from-engine-test-net True \ --gpus "0," \ --start-lambda 1.0 \ --end-lambda 0.7 \ --gamma 0.995 \ --lr 4.375e-4 \ --tui False \ --seed $RANDOM \ --max_epoch 800 ``` Around epoch 750, training was manually paused and max epoch increased to 950 before resuming. The additional Leela training data from T78 was prepared in the same way as the previous best dataset. The exact training data used can be found at: https://robotmoon.com/nnue-training-data/ While the local elo ratings during this experiment were much lower than in recent master nets, several later epochs had a consistent elo above zero, and this was hypothesized to represent potential strength at slower time controls. Local elo at 25k nodes per move leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p-sk28-lambda7 nn-epoch819.nnue : 0.4 +/- 1.1 (nn-bc24c101ada0.nnue) nn-epoch799.nnue : 0.3 +/- 1.2 nn-epoch759.nnue : 0.3 +/- 1.1 nn-epoch839.nnue : 0.2 +/- 1.4 Passed STC https://tests.stockfishchess.org/tests/view/63cabf6f0eefe8694a0c6013 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 41608 W: 11161 L: 10848 D: 19599 Ptnml(0-2): 116, 4496, 11281, 4781, 130 Passed LTC https://tests.stockfishchess.org/tests/view/63cb1856344bb01c191af263 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 76760 W: 20517 L: 20137 D: 36106 Ptnml(0-2): 34, 7435, 23070, 7799, 42 closes https://github.com/official-stockfish/Stockfish/pull/4351 bench 3941848 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 643e8540..f7ecaac9 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-1e7ca356472e.nnue" + #define EvalFileDefaultName "nn-bc24c101ada0.nnue" namespace NNUE { From 3dd0a7a7cd9daf306cffc795c343459de6d6f54b Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 20 Jan 2023 03:02:25 -0600 Subject: [PATCH 046/192] `stat_bonus`: replace quadratic with nearly identical line passed stc: https://tests.stockfishchess.org/tests/view/63ca58c90eefe8694a0c4eac LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 287960 W: 76146 L: 76201 D: 135613 Ptnml(0-2): 947, 31890, 78307, 31943, 893 passed ltc: https://tests.stockfishchess.org/tests/view/63cc8a51344bb01c191b30f0 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 73784 W: 19559 L: 19402 D: 34823 Ptnml(0-2): 33, 7171, 22327, 7328, 33 closes https://github.com/official-stockfish/Stockfish/pull/4352 bench 3990490 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 346fd6c3..b9ba3811 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((11 * d + 284) * d - 363 , 1650); + return std::min(350 * d - 400, 1650); } // Add a small random component to draw evaluations to avoid 3-fold blindness From d3860f8d5efa4d9df726fa605b24689d6a829c7e Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 25 Jan 2023 08:12:40 +0300 Subject: [PATCH 047/192] Rebalance usage of history heuristics in pruning This patch has multiple effects: * history heuristics sum in futility pruning now can't exceed some negative value so futility pruning for moves with negative histories should become slightly less aggressive; * history heuristics are now used in SEE pruning for quiet moves; Passed STC: https://tests.stockfishchess.org/tests/view/63cde339c93e8828d0f02e3a LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 88424 W: 23681 L: 23303 D: 41440 Ptnml(0-2): 258, 9559, 24219, 9899, 277 Passed LTC: https://tests.stockfishchess.org/tests/view/63ce9009c93e8828d0f04e4f LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 79536 W: 21223 L: 20843 D: 37470 Ptnml(0-2): 22, 7599, 24146, 7979, 22 closes https://github.com/official-stockfish/Stockfish/pull/4355 Bench: 4208265 --- src/search.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index b9ba3811..4b2deadd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1026,12 +1026,17 @@ moves_loop: // When in check, search starts here history += 2 * thisThread->mainHistory[us][from_to(move)]; + lmrDepth += history / 7208; + lmrDepth = std::max(lmrDepth, -2); + // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck && lmrDepth < 13 - && ss->staticEval + 103 + 136 * lmrDepth + history / 53 <= alpha) + && ss->staticEval + 103 + 136 * lmrDepth <= alpha) continue; + lmrDepth = std::max(lmrDepth, 0); + // Prune moves with negative SEE (~4 Elo) if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 16 * lmrDepth))) continue; From def296670dbde6cfad446a735f37f25cfe9df6a2 Mon Sep 17 00:00:00 2001 From: disservin Date: Mon, 23 Jan 2023 19:32:26 +0100 Subject: [PATCH 048/192] Fixed UCI TB win values This patch results in search values for a TB win/loss to be reported in a way that does not change with normalization, i.e. will be consistent over time. A value of 200.00 pawns is now reported upon entering a TB won position. Values smaller than 200.00 relate to the distance in plies from the root to the probed position position, with 1 cp being 1 ply distance. closes https://github.com/official-stockfish/Stockfish/pull/4353 No functional change --- src/uci.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/uci.cpp b/src/uci.cpp index 30c1fa0c..2afd2de7 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -314,8 +314,13 @@ string UCI::value(Value v) { stringstream ss; - if (abs(v) < VALUE_MATE_IN_MAX_PLY) + if (abs(v) < VALUE_TB_WIN_IN_MAX_PLY) ss << "cp " << v * 100 / NormalizeToPawnValue; + else if (abs(v) < VALUE_MATE_IN_MAX_PLY) + { + const int ply = VALUE_MATE_IN_MAX_PLY - 1 - std::abs(v); // recompute ss->ply + ss << "cp " << (v > 0 ? 20000 - ply : -20000 + ply); + } else ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; From 2167942b6eab54bafb6aed96d7360c74fec95358 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Wed, 25 Jan 2023 22:25:18 +0100 Subject: [PATCH 049/192] Simplify functions to read/write network parameters closes https://github.com/official-stockfish/Stockfish/pull/4358 No functional change --- src/nnue/nnue_architecture.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index c43a23c3..508f3aae 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -72,22 +72,20 @@ struct Network // 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; + return fc_0.read_parameters(stream) + && ac_0.read_parameters(stream) + && fc_1.read_parameters(stream) + && ac_1.read_parameters(stream) + && fc_2.read_parameters(stream); } - // Read network parameters + // Write 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; + return fc_0.write_parameters(stream) + && ac_0.write_parameters(stream) + && fc_1.write_parameters(stream) + && ac_1.write_parameters(stream) + && fc_2.write_parameters(stream); } std::int32_t propagate(const TransformedFeatureType* transformedFeatures) From 2f67409506e65a47f038055de834462b4a707ccd Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Wed, 25 Jan 2023 22:04:02 +0100 Subject: [PATCH 050/192] Remove redundant const qualifiers The const qualifiers are already implied by the constexpr qualifiers. closes https://github.com/official-stockfish/Stockfish/pull/4359 No functional change --- src/nnue/layers/affine_transform.h | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 710ab8a7..363b4916 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -179,33 +179,33 @@ namespace Stockfish::Eval::NNUE::Layers { static_assert(PaddedInputDimensions >= LargeInputSize, "Something went wrong. This specialization should not have been chosen."); #if defined (USE_AVX512) - static constexpr const IndexType InputSimdWidth = 64; - static constexpr const IndexType MaxNumOutputRegs = 16; + static constexpr IndexType InputSimdWidth = 64; + static constexpr IndexType MaxNumOutputRegs = 16; #elif defined (USE_AVX2) - static constexpr const IndexType InputSimdWidth = 32; - static constexpr const IndexType MaxNumOutputRegs = 8; + static constexpr IndexType InputSimdWidth = 32; + static constexpr IndexType MaxNumOutputRegs = 8; #elif defined (USE_SSSE3) - static constexpr const IndexType InputSimdWidth = 16; - static constexpr const IndexType MaxNumOutputRegs = 8; + static constexpr IndexType InputSimdWidth = 16; + static constexpr IndexType MaxNumOutputRegs = 8; #elif defined (USE_NEON) - static constexpr const IndexType InputSimdWidth = 8; - static constexpr const IndexType MaxNumOutputRegs = 8; + static constexpr IndexType InputSimdWidth = 8; + static constexpr IndexType MaxNumOutputRegs = 8; #else // The fallback implementation will not have permuted weights. // We define these to avoid a lot of ifdefs later. - static constexpr const IndexType InputSimdWidth = 1; - static constexpr const IndexType MaxNumOutputRegs = 1; + static constexpr IndexType InputSimdWidth = 1; + static constexpr IndexType MaxNumOutputRegs = 1; #endif // A big block is a region in the weight matrix of the size [PaddedInputDimensions, NumOutputRegs]. // A small block is a region of size [InputSimdWidth, 1] - static constexpr const IndexType NumOutputRegs = std::min(MaxNumOutputRegs, OutputDimensions); - static constexpr const IndexType SmallBlockSize = InputSimdWidth; - static constexpr const IndexType BigBlockSize = NumOutputRegs * PaddedInputDimensions; - static constexpr const IndexType NumSmallBlocksInBigBlock = BigBlockSize / SmallBlockSize; - static constexpr const IndexType NumSmallBlocksPerOutput = PaddedInputDimensions / SmallBlockSize; - static constexpr const IndexType NumBigBlocks = OutputDimensions / NumOutputRegs; + static constexpr IndexType NumOutputRegs = std::min(MaxNumOutputRegs, OutputDimensions); + static constexpr IndexType SmallBlockSize = InputSimdWidth; + static constexpr IndexType BigBlockSize = NumOutputRegs * PaddedInputDimensions; + static constexpr IndexType NumSmallBlocksInBigBlock = BigBlockSize / SmallBlockSize; + static constexpr IndexType NumSmallBlocksPerOutput = PaddedInputDimensions / SmallBlockSize; + static constexpr IndexType NumBigBlocks = OutputDimensions / NumOutputRegs; static_assert(OutputDimensions % NumOutputRegs == 0); @@ -396,8 +396,8 @@ namespace Stockfish::Eval::NNUE::Layers { static_assert(PaddedInputDimensions < LargeInputSize, "Something went wrong. This specialization should not have been chosen."); #if defined (USE_SSSE3) - static constexpr const IndexType OutputSimdWidth = SimdWidth / 4; - static constexpr const IndexType InputSimdWidth = SimdWidth; + static constexpr IndexType OutputSimdWidth = SimdWidth / 4; + static constexpr IndexType InputSimdWidth = SimdWidth; #endif // Hash value embedded in the evaluation file From d4d1cec29631f041adeec98adc5893b5c6a54969 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sun, 15 Jan 2023 04:08:33 -0600 Subject: [PATCH 051/192] Remove `previousDepth` in favor of `completedDepth + 2` Beyond the simplification, this could be considered a bugfix from a certain point of view. However, the effect is very subtle and essentially impossible for users to notice. 5372f81cc8 added about 2 Elo at LTC, but only for second and later `go` commands; now, with this patch, the first `go` command will also benefit from that gain. Games under time controls are unaffected (as per the tests). STC: https://tests.stockfishchess.org/tests/view/63c3d291330c0d3d051d48a8 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 473792 W: 124858 L: 125104 D: 223830 Ptnml(0-2): 1338, 49653, 135063, 49601, 1241 LTC: https://tests.stockfishchess.org/tests/view/63c8cd56a83c702aac083bc9 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 290728 W: 76926 L: 76978 D: 136824 Ptnml(0-2): 106, 27987, 89221, 27953, 97 closes https://github.com/official-stockfish/Stockfish/pull/4361 bench 4208265 --- src/search.cpp | 5 +---- src/thread.cpp | 1 - src/thread.h | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4b2deadd..c748f1ff 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -242,9 +242,6 @@ void MainThread::search() { bestPreviousScore = bestThread->rootMoves[0].score; bestPreviousAverageScore = bestThread->rootMoves[0].averageScore; - for (Thread* th : Threads) - th->previousDepth = bestThread->completedDepth; - // Send again PV info if we have a new best thread if (bestThread != this) sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth) << sync_endl; @@ -1053,7 +1050,7 @@ moves_loop: // When in check, search starts here // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( !rootNode - && depth >= 4 - (thisThread->previousDepth > 24) + 2 * (PvNode && tte->is_pv()) + && depth >= 4 - (thisThread->completedDepth > 22) + 2 * (PvNode && tte->is_pv()) && move == ttMove && !excludedMove // Avoid recursive singular search /* && ttValue != VALUE_NONE Already implicit in the next condition */ diff --git a/src/thread.cpp b/src/thread.cpp index ca1a7c85..c680393e 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -60,7 +60,6 @@ void Thread::clear() { counterMoves.fill(MOVE_NONE); mainHistory.fill(0); captureHistory.fill(0); - previousDepth = 0; for (bool inCheck : { false, true }) for (StatsType c : { NoCaptures, Captures }) diff --git a/src/thread.h b/src/thread.h index 7566322c..46cdb11c 100644 --- a/src/thread.h +++ b/src/thread.h @@ -69,7 +69,7 @@ public: Position rootPos; StateInfo rootState; Search::RootMoves rootMoves; - Depth rootDepth, completedDepth, previousDepth; + Depth rootDepth, completedDepth; Value rootDelta; CounterMoveHistory counterMoves; ButterflyHistory mainHistory; From e4e61cd9cc953e6bc17070da84639d53b7514709 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Thu, 19 Jan 2023 09:49:42 +0900 Subject: [PATCH 052/192] Remove maxNextDepth This patch allows full PV search to have double extensions as well when extension == 1 && doDeeperSearch && doEvenDeeperSearch && !doShallowerSearch is true, which is extremely rare to occur. Passed non-regression STC (master 3d2381d): LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 370824 W: 97835 L: 97974 D: 175015 Ptnml(0-2): 1073, 38814, 105731, 38767, 1027 https://tests.stockfishchess.org/tests/view/63c89416a83c702aac08314c Passed non-regression LTC (master 3d2381d): LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 306048 W: 81173 L: 81237 D: 143638 Ptnml(0-2): 117, 27977, 96901, 27911, 118 https://tests.stockfishchess.org/tests/view/63cc4e84344bb01c191b2658 Bench: 4208265 --- src/search.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index c748f1ff..41096c9c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -522,7 +522,6 @@ namespace { constexpr bool PvNode = nodeType != NonPV; constexpr bool rootNode = nodeType == Root; - const Depth maxNextDepth = rootNode ? depth : depth + 1; // Check if we have an upcoming move which draws by repetition, or // if the opponent had an alternative move earlier to this position. @@ -1235,8 +1234,7 @@ moves_loop: // When in check, search starts here (ss+1)->pv = pv; (ss+1)->pv[0] = MOVE_NONE; - value = -search(pos, ss+1, -beta, -alpha, - std::min(maxNextDepth, newDepth), false); + value = -search(pos, ss+1, -beta, -alpha, newDepth, false); } // Step 19. Undo move From 0827e00f10709a4475ece44f0588277fc8cdcd9d Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:44:53 +0800 Subject: [PATCH 053/192] Decrease reduction for killer moves with good history If move is a main killer and we have a good history, decrease reduction. STC: https://tests.stockfishchess.org/tests/view/63d38b37721fe2bff693069a LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 46688 W: 12542 L: 12222 D: 21924 Ptnml(0-2): 126, 5013, 12769, 5287, 149 LTC: https://tests.stockfishchess.org/tests/view/63d471e2bde6e5f3cb4be5d3 LLR: 2.93 (-2.94,2.94) <0.50,2.50> Total: 130976 W: 35033 L: 34555 D: 61388 Ptnml(0-2): 38, 12551, 39833, 13027, 39 closes https://github.com/official-stockfish/Stockfish/pull/4369 Bench: 4069938 --- src/search.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 41096c9c..7d618a65 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1164,6 +1164,11 @@ moves_loop: // When in check, search starts here if ((ss+1)->cutoffCnt > 3) r++; + // Decrease reduction if move is a killer and we have a good history + if (move == ss->killers[0] + && (*contHist[0])[movedPiece][to_sq(move)] >= 3600) + r--; + ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] From 7fc0f589d601cb013f995ff44a49b5d2ae6bb253 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Thu, 2 Feb 2023 00:08:23 +0900 Subject: [PATCH 054/192] Add -Wconditional-uninitialized when using Clang Add -Wconditional-uninitialized as it is not controlled by -Wall. closes https://github.com/official-stockfish/Stockfish/pull/4371 No functional change --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 30c1be5e..775c72c3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -426,7 +426,8 @@ ifeq ($(COMP),clang) CXX=x86_64-w64-mingw32-clang++ endif - CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-prototypes + CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-prototypes \ + -Wconditional-uninitialized ifeq ($(filter $(KERNEL),Darwin OpenBSD FreeBSD),) ifeq ($(target_windows),) From 3589bd008a3470336b3587e3a292a4cd6b02bf6b Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Thu, 2 Feb 2023 08:41:32 +0100 Subject: [PATCH 055/192] Update WLD model update the WLD model with about 400M positions extracted from recent LTC games after the net updates. This ensures that the 50% win rate is again at 1.0 eval. closes https://github.com/official-stockfish/Stockfish/pull/4373 No functional change. --- src/uci.cpp | 4 ++-- src/uci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index 2afd2de7..3883b3d3 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -206,8 +206,8 @@ namespace { // The coefficients of a third-order polynomial fit is based on the fishtest data // for two parameters that need to transform eval to the argument of a logistic // function. - constexpr double as[] = { -0.58270499, 2.68512549, 15.24638015, 344.49745382}; - constexpr double bs[] = { -2.65734562, 15.96509799, -20.69040836, 73.61029937 }; + constexpr double as[] = { 0.33677609, -4.30175627, 33.08810557, 365.60223431}; + constexpr double bs[] = { -2.50471102, 14.23235405, -14.33066859, 71.42705250 }; // Enforce that NormalizeToPawnValue corresponds to a 50% win rate at ply 64 static_assert(UCI::NormalizeToPawnValue == int(as[0] + as[1] + as[2] + as[3])); diff --git a/src/uci.h b/src/uci.h index bd3df323..5d8ccf1a 100644 --- a/src/uci.h +++ b/src/uci.h @@ -35,7 +35,7 @@ namespace UCI { // the win_rate_model() such that Stockfish outputs an advantage of // "100 centipawns" for a position if the engine has a 50% probability to win // from this position in selfplay at fishtest LTC time control. -const int NormalizeToPawnValue = 361; +const int NormalizeToPawnValue = 394; class Option; From da8513f0eae439f526ab0a905a3433bdb44bcf66 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Thu, 2 Feb 2023 13:05:54 +0300 Subject: [PATCH 056/192] Do less SEE pruning in qsearch Current master prunes all moves with negative SEE values in qsearch. This patch sets constant negative threshold thus allowing some moves with negative SEE values to be searched. Value of threshold is completely arbitrary and can be tweaked - also it as function of depth can be tried. Original idea by author of Alexandria engine. Passed STC https://tests.stockfishchess.org/tests/view/63d79a59a67dd929a5564976 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 34864 W: 9392 L: 9086 D: 16386 Ptnml(0-2): 113, 3742, 9429, 4022, 126 Passed LTC https://tests.stockfishchess.org/tests/view/63d8074aa67dd929a5565bc2 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 91616 W: 24532 L: 24126 D: 42958 Ptnml(0-2): 32, 8840, 27662, 9238, 36 closes https://github.com/official-stockfish/Stockfish/pull/4376 Bench: 4010877 --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 7d618a65..b9ca3961 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1556,9 +1556,9 @@ moves_loop: // When in check, search starts here } } - // Do not search moves with negative SEE values (~5 Elo) + // Do not search moves with bad enough SEE values (~5 Elo) if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && !pos.see_ge(move)) + && !pos.see_ge(move, Value(-108))) continue; // Speculative prefetch as early as possible From 5a30b087c3a3c4435e680e6c61082d5432fa0ace Mon Sep 17 00:00:00 2001 From: MinetaS Date: Wed, 25 Jan 2023 07:32:02 +0900 Subject: [PATCH 057/192] Expand statistics tools for engine development This patch adds more debugging slots up to 32 per type and provide tools to calculate standard deviation and Pearson's correlation coefficient. However, due to slot being 0 at default, dbg_hit_on(c, b) has to be removed. Initial idea from snicolet/Stockfish@d8ab604 closes https://github.com/official-stockfish/Stockfish/pull/4354 No functional change --- src/misc.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++------ src/misc.h | 7 ++-- 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index b651972b..7d848d32 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -41,6 +41,7 @@ typedef WORD(*fun5_t)(); } #endif +#include #include #include #include @@ -299,21 +300,94 @@ std::string compiler_info() { /// Debug functions used mainly to collect run-time statistics -static std::atomic hits[2], means[2]; +constexpr int MaxDebugSlots = 32; -void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; } -void dbg_hit_on(bool c, bool b) { if (c) dbg_hit_on(b); } -void dbg_mean_of(int v) { ++means[0]; means[1] += v; } +namespace { + +template +struct DebugInfo { + std::atomic data[N] = { 0 }; + + constexpr inline std::atomic& operator[](int index) { return data[index]; } +}; + +DebugInfo<2> hit[MaxDebugSlots]; +DebugInfo<2> mean[MaxDebugSlots]; +DebugInfo<3> stdev[MaxDebugSlots]; +DebugInfo<6> correl[MaxDebugSlots]; + +} // namespace + +void dbg_hit_on(bool cond, int slot) { + + ++hit[slot][0]; + if (cond) + ++hit[slot][1]; +} + +void dbg_mean_of(int64_t value, int slot) { + + ++mean[slot][0]; + mean[slot][1] += value; +} + +void dbg_stdev_of(int64_t value, int slot) { + + ++stdev[slot][0]; + stdev[slot][1] += value; + stdev[slot][2] += value * value; +} + +void dbg_correl_of(int64_t value1, int64_t value2, int slot) { + + ++correl[slot][0]; + correl[slot][1] += value1; + correl[slot][2] += value1 * value1; + correl[slot][3] += value2; + correl[slot][4] += value2 * value2; + correl[slot][5] += value1 * value2; +} void dbg_print() { - if (hits[0]) - cerr << "Total " << hits[0] << " Hits " << hits[1] - << " hit rate (%) " << 100 * hits[1] / hits[0] << endl; + int64_t n; + auto E = [&n](int64_t x) { return double(x) / n; }; + auto sqr = [](double x) { return x * x; }; - if (means[0]) - cerr << "Total " << means[0] << " Mean " - << (double)means[1] / means[0] << endl; + for (int i = 0; i < MaxDebugSlots; ++i) + if ((n = hit[i][0])) + std::cerr << "Hit #" << i + << ": Total " << n << " Hits " << hit[i][1] + << " Hit Rate (%) " << 100.0 * E(hit[i][1]) + << std::endl; + + for (int i = 0; i < MaxDebugSlots; ++i) + if ((n = mean[i][0])) + { + std::cerr << "Mean #" << i + << ": Total " << n << " Mean " << E(mean[i][1]) + << std::endl; + } + + for (int i = 0; i < MaxDebugSlots; ++i) + if ((n = stdev[i][0])) + { + double r = sqrtl(E(stdev[i][2]) - sqr(E(stdev[i][1]))); + std::cerr << "Stdev #" << i + << ": Total " << n << " Stdev " << r + << std::endl; + } + + for (int i = 0; i < MaxDebugSlots; ++i) + if ((n = correl[i][0])) + { + double r = (E(correl[i][5]) - E(correl[i][1]) * E(correl[i][3])) + / ( sqrtl(E(correl[i][2]) - sqr(E(correl[i][1]))) + * sqrtl(E(correl[i][4]) - sqr(E(correl[i][3])))); + std::cerr << "Correl. #" << i + << ": Total " << n << " Coefficient " << r + << std::endl; + } } diff --git a/src/misc.h b/src/misc.h index 4c1150f8..9761da8a 100644 --- a/src/misc.h +++ b/src/misc.h @@ -39,9 +39,10 @@ void std_aligned_free(void* ptr); void* aligned_large_pages_alloc(size_t size); // memory aligned by page size, min alignment: 4096 bytes void aligned_large_pages_free(void* mem); // nop if mem == nullptr -void dbg_hit_on(bool b); -void dbg_hit_on(bool c, bool b); -void dbg_mean_of(int v); +void dbg_hit_on(bool cond, int slot = 0); +void dbg_mean_of(int64_t value, int slot = 0); +void dbg_stdev_of(int64_t value, int slot = 0); +void dbg_correl_of(int64_t value1, int64_t value2, int slot = 0); void dbg_print(); typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds From 1cdc0f78bd937637128ad10f5168cdb80390f6fb Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 3 Feb 2023 10:52:14 +0300 Subject: [PATCH 058/192] Simplify usage of optimism in complexity This patch removes one condition in optimism usage in complexity, now negative optimism also impacts it. Passed STC: https://tests.stockfishchess.org/tests/view/63d34f43721fe2bff692fb12 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 204920 W: 54343 L: 54309 D: 96268 Ptnml(0-2): 598, 22648, 55897, 22756, 561 Passed LTC: https://tests.stockfishchess.org/tests/view/63d612a2a67dd929a556075c LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 200712 W: 53207 L: 53172 D: 94333 Ptnml(0-2): 58, 19664, 60901, 19651, 82 closes https://github.com/official-stockfish/Stockfish/pull/4377 bench 4204964 --- src/evaluate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 8683182c..6d5a8a0c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1073,7 +1073,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // Blend nnue complexity with (semi)classical complexity nnueComplexity = ( 406 * nnueComplexity + 424 * abs(psq - nnue) - + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) + + int(optimism) * int(psq - nnue) ) / 1024; // Return hybrid NNUE complexity to caller From d2f79ff0e0efc33797120f59355c2a5571b4ab80 Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:54:30 +0800 Subject: [PATCH 059/192] Remove reduced LMR capture bonus In LMR, simplify away the reduced capture bonus (i.e. if (capture) bonus /= 6). Non-regression STC: https://tests.stockfishchess.org/tests/view/63da1da9bbadd17b3787dced LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 28152 W: 7521 L: 7296 D: 13335 Ptnml(0-2): 76, 3069, 7568, 3280, 83 Non-regression LTC: https://tests.stockfishchess.org/tests/view/63da6ad4bbadd17b3787e98c LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 52472 W: 14120 L: 13941 D: 24411 Ptnml(0-2): 16, 5071, 15887, 5242, 20 closes https://github.com/official-stockfish/Stockfish/pull/4378 Bench: 4034016 --- src/search.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index b9ca3961..f6bc0aa9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1214,9 +1214,6 @@ moves_loop: // When in check, search starts here int bonus = value > alpha ? stat_bonus(newDepth) : -stat_bonus(newDepth); - if (capture) - bonus /= 6; - update_continuation_histories(ss, movedPiece, to_sq(move), bonus); } } From 8d3457a9966f8c744ab7f8536be408196ccd8af9 Mon Sep 17 00:00:00 2001 From: pb00067 Date: Fri, 3 Feb 2023 17:57:19 +0100 Subject: [PATCH 060/192] Improve excluded move logic PR consists of 2 improvements on nodes with excludeMove: 1. Remove xoring the posKey with make_key(excludedMove) Since we never call tte->save anymore with excludedMove, the unique left purpose of the xoring was to avoid a TT hit. Nevertheless on a normal bench run this produced ~25 false positives (key collisions) To avoid that we now forbid early TT cutoff's with excludeMove Maybe these accesses to TT with xored key caused useless misses in the CPU caches (L1, L2 ...) Now doing the probe with the same key as the enclosing search does, should hit the CPU cache. 2. Don't probe Tablebases with excludedMove. This can't be tested on fishtest, but it's obvious that tablebases don't deliver any information about suboptimal moves. Side note: Very surprisingly it looks like we cannot use static eval's from TT since they slightly differ over time due to changing optimism. Attempts to use static eval's from TT did loose about 13 ELO. This is something about to investigate. LTC: https://tests.stockfishchess.org/tests/view/63dc0f8de9d4cdfbe672d0c6 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 44736 W: 12046 L: 11733 D: 20957 Ptnml(0-2): 12, 4212, 13617, 4505, 22 An analogue of this passed STC & LTC see PR #4374 (thanks Dubslow for reviewing!) closes https://github.com/official-stockfish/Stockfish/pull/4380 Bench: 4758694 --- src/search.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index f6bc0aa9..30a08cb7 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -615,22 +615,24 @@ namespace { if (!rootNode) (ss+2)->statScore = 0; - // Step 4. Transposition table lookup. We don't want the score of a partial - // search to overwrite a previous full search TT value, so we use a different - // position key in case of an excluded move. + // Step 4. Transposition table lookup. excludedMove = ss->excludedMove; - posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove); + posKey = pos.key(); tte = TT.probe(posKey, ss->ttHit); ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0] : ss->ttHit ? tte->move() : MOVE_NONE; ttCapture = ttMove && pos.capture(ttMove); + + // At this point, if excluded, skip straight to step 6, static eval. However, + // to save indentation, we list the condition in all code between here and there. if (!excludedMove) ss->ttPv = PvNode || (ss->ttHit && tte->is_pv()); // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ss->ttHit + && !excludedMove && tte->depth() > depth - (tte->bound() == BOUND_EXACT) && ttValue != VALUE_NONE // Possible in case of TT access race && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) @@ -664,7 +666,7 @@ namespace { } // Step 5. Tablebases probe - if (!rootNode && TB::Cardinality) + if (!rootNode && !excludedMove && TB::Cardinality) { int piecesCount = pos.count(); @@ -727,6 +729,12 @@ namespace { complexity = 0; goto moves_loop; } + else if (excludedMove) { + // excludeMove implies that we had a ttHit on the containing non-excluded search with ss->staticEval filled from TT + // However static evals from the TT aren't good enough (-13 elo), presumably due to changing optimism context + // Recalculate value with current optimism (without updating thread avgComplexity) + ss->staticEval = eval = evaluate(pos, &complexity); + } else if (ss->ttHit) { // Never assume anything about values stored in TT @@ -735,6 +743,7 @@ namespace { ss->staticEval = eval = evaluate(pos, &complexity); else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost complexity = abs(ss->staticEval - pos.psq_eg_stm()); + thisThread->complexityAverage.update(complexity); // ttValue can be used as a better position evaluation (~7 Elo) if ( ttValue != VALUE_NONE @@ -744,14 +753,12 @@ namespace { else { ss->staticEval = eval = evaluate(pos, &complexity); + thisThread->complexityAverage.update(complexity); // Save static evaluation into transposition table - if (!excludedMove) - tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); + tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } - thisThread->complexityAverage.update(complexity); - // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { @@ -1061,6 +1068,7 @@ moves_loop: // When in check, search starts here Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; + // the search with excludedMove will update ss->staticEval value = search(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode); ss->excludedMove = MOVE_NONE; From d5817a5896a8d93c4560b405da576a02aaa0c08a Mon Sep 17 00:00:00 2001 From: Disservin Date: Sat, 4 Feb 2023 14:16:58 +0100 Subject: [PATCH 061/192] remove unnecessary variable pinned already has to be true for the bitwise & closes https://github.com/official-stockfish/Stockfish/pull/4381 No functional change --- src/movegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/movegen.cpp b/src/movegen.cpp index 47154164..255dce04 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -264,7 +264,7 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { moveList = pos.checkers() ? generate(pos, moveList) : generate(pos, moveList); while (cur != moveList) - if ( ((pinned && pinned & from_sq(*cur)) || from_sq(*cur) == ksq || type_of(*cur) == EN_PASSANT) + if ( ((pinned & from_sq(*cur)) || from_sq(*cur) == ksq || type_of(*cur) == EN_PASSANT) && !pos.legal(*cur)) *cur = (--moveList)->move; else From 8f843633db3faaf447cc191cbaed9f5ddfd374bd Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sat, 4 Feb 2023 23:46:44 +0300 Subject: [PATCH 062/192] Cleanup and reorder in qsearch This patch is a simplification / code normalisation in qsearch. Adds steps in comments the same way we have in search; Makes a separate "pruning" stage instead of heuristics randomly being spread over qsearch code; Reorders pruning heuristics from least taxing ones to more taxing ones; Removes repeated check for best value not being mated, instead uses 1 check - thus removes some lines of code. Moves prefetch and move setup after pruning - makes no sense to do them if move will actually get pruned. Passed non-regression test: https://tests.stockfishchess.org/tests/view/63dd2c5ff9a50a69252c1413 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 113504 W: 29898 L: 29770 D: 53836 Ptnml(0-2): 287, 11861, 32327, 11991, 286 https://github.com/official-stockfish/Stockfish/pull/4382 Non-functional change. --- src/search.cpp | 54 ++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 30a08cb7..aa87948b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1427,6 +1427,7 @@ moves_loop: // When in check, search starts here bool pvHit, givesCheck, capture; int moveCount; + // Step 1. Initialize node if (PvNode) { (ss+1)->pv = pv; @@ -1438,7 +1439,7 @@ moves_loop: // When in check, search starts here ss->inCheck = pos.checkers(); moveCount = 0; - // Check for an immediate draw or maximum ply reached + // Step 2. Check for an immediate draw or maximum ply reached if ( pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : VALUE_DRAW; @@ -1450,13 +1451,14 @@ moves_loop: // When in check, search starts here // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS. ttDepth = ss->inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS : DEPTH_QS_NO_CHECKS; - // Transposition table lookup + // Step 3. Transposition table lookup posKey = pos.key(); tte = TT.probe(posKey, ss->ttHit); ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttMove = ss->ttHit ? tte->move() : MOVE_NONE; pvHit = ss->ttHit && tte->is_pv(); + // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ss->ttHit && tte->depth() >= ttDepth @@ -1464,7 +1466,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) return ttValue; - // Evaluate the position statically + // Step 4. Static evaluation of the position if (ss->inCheck) { ss->staticEval = VALUE_NONE; @@ -1522,7 +1524,8 @@ moves_loop: // When in check, search starts here int quietCheckEvasions = 0; - // Loop through the moves until no moves remain or a beta cutoff occurs + // Step 5. Loop through all pseudo-legal moves until no moves remain + // or a beta cutoff occurs. while ((move = mp.next_move()) != MOVE_NONE) { assert(is_ok(move)); @@ -1536,9 +1539,11 @@ moves_loop: // When in check, search starts here moveCount++; + // Step 6. Pruning. + if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY) + { // Futility pruning and moveCount pruning (~10 Elo) - if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && !givesCheck + if ( !givesCheck && to_sq(move) != prevSq && futilityBase > -VALUE_KNOWN_WIN && type_of(move) != PROMOTION) @@ -1561,43 +1566,43 @@ moves_loop: // When in check, search starts here } } - // Do not search moves with bad enough SEE values (~5 Elo) - if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && !pos.see_ge(move, Value(-108))) + // We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter + // and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead. + if (quietCheckEvasions > 1) + break; + + // Continuation history based pruning (~3 Elo) + if ( !capture + && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 + && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) continue; + // Do not search moves with bad enough SEE values (~5 Elo) + if (!pos.see_ge(move, Value(-108))) + continue; + + } + // Speculative prefetch as early as possible prefetch(TT.first_entry(pos.key_after(move))); + // Update the current move ss->currentMove = move; ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] [capture] [pos.moved_piece(move)] [to_sq(move)]; - // Continuation history based pruning (~3 Elo) - if ( !capture - && bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 - && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) - continue; - - // We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter - // and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead. - if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && quietCheckEvasions > 1) - break; - quietCheckEvasions += !capture && ss->inCheck; - // Make and search the move + // Step 7. Make and search the move pos.do_move(move, st, givesCheck); value = -qsearch(pos, ss+1, -beta, -alpha, depth - 1); pos.undo_move(move); assert(value > -VALUE_INFINITE && value < VALUE_INFINITE); - // Check for a new best move + // Step 8. Check for a new best move if (value > bestValue) { bestValue = value; @@ -1617,6 +1622,7 @@ moves_loop: // When in check, search starts here } } + // Step 9. Check for mate // All legal moves have been searched. A special case: if we're in check // and no legal moves were found, it is checkmate. if (ss->inCheck && bestValue == -VALUE_INFINITE) From e25bcaed3cb69406cec4cd3d212cdf5232234949 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 3 Feb 2023 18:18:55 -0600 Subject: [PATCH 063/192] Update `complexityAverage` in all branches of static eval STC: https://tests.stockfishchess.org/tests/view/63dda49573223e7f52ad0f8c LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 117416 W: 31173 L: 31049 D: 55194 Ptnml(0-2): 290, 12246, 33533, 12328, 311 LTC: https://tests.stockfishchess.org/tests/view/63dfa90873223e7f52ad69b8 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 44416 W: 11924 L: 11744 D: 20748 Ptnml(0-2): 5, 4036, 13968, 4172, 27 closes https://github.com/official-stockfish/Stockfish/pull/4385 bench 4758694 --- src/search.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index aa87948b..2eed74b8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -743,7 +743,6 @@ namespace { ss->staticEval = eval = evaluate(pos, &complexity); else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost complexity = abs(ss->staticEval - pos.psq_eg_stm()); - thisThread->complexityAverage.update(complexity); // ttValue can be used as a better position evaluation (~7 Elo) if ( ttValue != VALUE_NONE @@ -753,11 +752,10 @@ namespace { else { ss->staticEval = eval = evaluate(pos, &complexity); - thisThread->complexityAverage.update(complexity); - // Save static evaluation into transposition table tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } + thisThread->complexityAverage.update(complexity); // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) From 05dea2ca4657dec10637bb53c4ad583f680e0677 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sun, 5 Feb 2023 13:00:30 -0500 Subject: [PATCH 064/192] Update default net to nn-1337b1adec5b.nnue Created by retraining the master net on a dataset composed of: * Most of the previous best dataset filtered to remove positions likely having only one good move * Adding training data from Leela T77 dec2021 rescored with 16tb of 7-piece tablebases Trained with end lambda 0.7 and max epoch 900. Positions with ply <= 28 were removed from most of the previous best dataset before training began. A new nnue-pytorch trainer param for skipping early plies was used to skip plies <= 24 in the unfiltered and additional Leela T77 parts of the dataset. ``` python easy_train.py \ --experiment-name leela96-dfrc99-T80octnovT79aprmayT60novdec-eval-filt-v2-T78augsep-12tb-T77dec-16tb-lambda7-sk24 \ --training-dataset /data/leela96-dfrc99-T80octnovT79aprmayT60novdec-eval-filt-v2-T78augsep-12tb-T77dec-16tb.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/easy-train-early-fen-skipping \ --early-fen-skipping 24 \ --gpus "0," \ --start-from-engine-test-net True \ --start-lambda 1.0 \ --end-lambda 0.7 \ --gamma 0.995 \ --lr 4.375e-4 \ --tui False \ --seed $RANDOM \ --max_epoch 900 ``` The depth6 multipv2 search filtering method is the same as the one used for filtering recent best datasets, with a lower eval difference threshold to remove slightly more positions than before. These parts of the dataset were filtered: * 96% of T60T70wIsRightFarseerT60T74T75T76.binpack * 99% of dfrc_n5000.binpack * T80 oct + nov 2022 data, no positions with castling flags, rescored with ~600gb 7p tablebases * T79 apr + may 2022 data, rescored with 12tb 7p tablebases * T60 nov + dec 2021 data, rescored with 12tb 7p tablebases These parts of the dataset were not filtered. Positions with ply <= 24 were skipped during training: * T78 aug + sep 2022 data, rescored with 12tb 7p tablebases * 84% of T77 dec 2021 data, rescored with 16tb 7p tablebases The code and exact evaluation thresholds used for data filtering can be found at: https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-eval-diff-t2/src/filter The exact training data used can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move: nn-epoch859.nnue : 3.5 +/ 1.2 Passed STC: LLR: 2.95 (-2.94,2.94) <0.00,2.00> https://tests.stockfishchess.org/tests/view/63dfeefc73223e7f52ad769f Total: 219744 W: 58572 L: 58002 D: 103170 Ptnml(0-2): 609, 24446, 59284, 24832, 701 Passed LTC: https://tests.stockfishchess.org/tests/view/63e268fc73223e7f52ade7b6 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 91256 W: 24528 L: 24121 D: 42607 Ptnml(0-2): 48, 8863, 27390, 9288, 39 closes https://github.com/official-stockfish/Stockfish/pull/4387 bench 3841998 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index f7ecaac9..cdea2ab2 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-bc24c101ada0.nnue" + #define EvalFileDefaultName "nn-1337b1adec5b.nnue" namespace NNUE { From e5f6d71b96b5149e5e1df30721e1870abdb218ce Mon Sep 17 00:00:00 2001 From: borg323 Date: Thu, 9 Feb 2023 21:14:59 +0200 Subject: [PATCH 065/192] Fix build on arm windows avoids the use of _mm_malloc on arm windows. fixes #4379 closes https://github.com/official-stockfish/Stockfish/pull/4388 No functional change --- AUTHORS | 1 + src/misc.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 42ba5930..634de4a3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -35,6 +35,7 @@ Ben Chaney (Chaneybenjamini) Ben Koshy (BKSpurgeon) Bill Henry (VoyagerOne) Bojun Guo (noobpwnftw, Nooby) +borg323 Boštjan Mejak (PedanticHacker) braich Brian Sheppard (SapphireBrand, briansheppard-toast) diff --git a/src/misc.cpp b/src/misc.cpp index 7d848d32..e65faab9 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -448,8 +448,10 @@ void* std_aligned_alloc(size_t alignment, size_t size) { #if defined(POSIXALIGNEDALLOC) void *mem; return posix_memalign(&mem, alignment, size) ? nullptr : mem; -#elif defined(_WIN32) +#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64) return _mm_malloc(size, alignment); +#elif defined(_WIN32) + return _aligned_malloc(size, alignment); #else return std::aligned_alloc(alignment, size); #endif @@ -459,8 +461,10 @@ void std_aligned_free(void* ptr) { #if defined(POSIXALIGNEDALLOC) free(ptr); -#elif defined(_WIN32) +#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64) _mm_free(ptr); +#elif defined(_WIN32) + _aligned_free(ptr); #else free(ptr); #endif From 852330ee5060e42a42c1cddd85b82e28d09f4229 Mon Sep 17 00:00:00 2001 From: disservin Date: Sat, 11 Feb 2023 17:14:16 +0100 Subject: [PATCH 066/192] update cuckoo link use webarchive to link to the cycle detection paper by Kervinck. closes https://github.com/official-stockfish/Stockfish/pull/4389 No functional change --- src/position.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/position.cpp b/src/position.cpp index cfd98f68..37aa2e9e 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -97,7 +97,7 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) { // Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition" // situations. Description of the algorithm in the following paper: -// https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf +// http://web.archive.org/web/20201107002606/https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf // First and second hash functions for indexing the cuckoo tables inline int H1(Key h) { return h & 0x1fff; } From 2c36d1e7e7374b8babb3cc503c0bc07ceb83dbf8 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Mon, 13 Feb 2023 11:54:59 +0900 Subject: [PATCH 067/192] Fix overflow in add_dpbusd_epi32x2 This patch fixes 16bit overflow in *_add_dpbusd_epi32x2 functions, that can be triggered in rare cases depending on the NNUE weights. While the code leads to some slowdown on affected architectures (most notably avx2), the fix is simpler than some of the other options discussed in https://github.com/official-stockfish/Stockfish/pull/4394 Code suggested by Sopel97. Result of "bench 4096 1 30 default depth nnue": | Architecture | master | patch (gcc) | patch (clang) | |---------------------|-----------|-------------|---------------| | x86-64-vnni512 | 762122798 | 762122798 | 762122798 | | x86-64-avx512 | 769723503 | 762122798 | 762122798 | | x86-64-bmi2 | 769723503 | 762122798 | 762122798 | | x86-64-ssse3 | 769723503 | 762122798 | 762122798 | | x86-64 | 762122798 | 762122798 | 762122798 | Following architectures will experience ~4% slowdown due to an additional instruction in the middle of hot path: * x86-64-avx512 * x86-64-bmi2 * x86-64-avx2 * x86-64-sse41-popcnt (x86-64-modern) * x86-64-ssse3 * x86-32-sse41-popcnt This patch clearly loses Elo against master with both STC and LTC. Failed non-regression STC (256bit fix only): LLR: -2.95 (-2.94,2.94) <-1.75,0.25> Total: 33528 W: 8769 L: 9049 D: 15710 Ptnml(0-2): 96, 3616, 9600, 3376, 76 https://tests.stockfishchess.org/tests/view/63e6a5b44299542b1e26a485 60+0.6 @ 30000 games: Elo: -1.67 +-1.7 (95%) LOS: 2.8% Total: 30000 W: 7848 L: 7992 D: 14160 Ptnml(0-2): 12, 2847, 9436, 2683, 22 nElo: -3.84 +-3.9 (95%) PairsRatio: 0.95 https://tests.stockfishchess.org/tests/view/63e7ac716d0e1db55f35a660 However, a test against nn-a3dc078bafc7.nnue, which is the latest "safe" network not causing the bug, passed with regular bounds. Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 160456 W: 42658 L: 42175 D: 75623 Ptnml(0-2): 487, 17638, 43469, 18173, 461 https://tests.stockfishchess.org/tests/view/63e89836d62a5d02b0fa82c8 closes https://github.com/official-stockfish/Stockfish/pull/4391 closes https://github.com/official-stockfish/Stockfish/pull/4394 No functional change --- src/nnue/layers/simd.h | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/nnue/layers/simd.h b/src/nnue/layers/simd.h index 231f7891..381e7a68 100644 --- a/src/nnue/layers/simd.h +++ b/src/nnue/layers/simd.h @@ -165,18 +165,19 @@ namespace Stockfish::Simd { __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" + "vpmaddwd %[tmp1], %[ones], %[tmp1]\n\t" + "vpaddd %[tmp0], %[tmp1], %[tmp0]\n\t" "vpaddd %[acc], %[tmp0], %[acc]\n\t" - : [acc]"+v"(acc), [tmp0]"+&v"(tmp0) - : [tmp1]"v"(tmp1), [ones]"v"(_mm512_set1_epi16(1)) + : [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); + product1 = _mm512_madd_epi16(product1, _mm512_set1_epi16(1)); + acc = _mm512_add_epi32(acc, _mm512_add_epi32(product0, product1)); # endif # endif } @@ -261,18 +262,19 @@ namespace Stockfish::Simd { __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" + "vpmaddwd %[tmp1], %[ones], %[tmp1]\n\t" + "vpaddd %[tmp0], %[tmp1], %[tmp0]\n\t" "vpaddd %[acc], %[tmp0], %[acc]\n\t" - : [acc]"+v"(acc), [tmp0]"+&v"(tmp0) - : [tmp1]"v"(tmp1), [ones]"v"(_mm256_set1_epi16(1)) + : [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); + product1 = _mm256_madd_epi16(product1, _mm256_set1_epi16(1)); + acc = _mm256_add_epi32(acc, _mm256_add_epi32(product0, product1)); # endif # endif } @@ -326,18 +328,19 @@ namespace Stockfish::Simd { __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" + "pmaddwd %[ones], %[tmp1]\n\t" + "paddd %[tmp1], %[tmp0]\n\t" "paddd %[tmp0], %[acc]\n\t" - : [acc]"+v"(acc), [tmp0]"+&v"(tmp0) - : [tmp1]"v"(tmp1), [ones]"v"(_mm_set1_epi16(1)) + : [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); + product1 = _mm_madd_epi16(product1, _mm_set1_epi16(1)); + acc = _mm_add_epi32(acc, _mm_add_epi32(product0, product1)); # endif } From 29c1e072b669c2257e4b48094391e7dc39fb31a5 Mon Sep 17 00:00:00 2001 From: mstembera Date: Sun, 12 Feb 2023 17:33:19 -0800 Subject: [PATCH 068/192] Simplify nnueComplexity calculation. further simplification after https://github.com/official-stockfish/Stockfish/pull/4377 STC https://tests.stockfishchess.org/tests/view/63e02a3773223e7f52ad8190 LLR: 2.97 (-2.94,2.94) <-1.75,0.25> Total: 359072 W: 94605 L: 94733 D: 169734 Ptnml(0-2): 994, 39874, 97958, 39686, 1024 LTC https://tests.stockfishchess.org/tests/view/63e3fd12b5f425d71f77002a LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 248424 W: 66020 L: 66030 D: 116374 Ptnml(0-2): 113, 24653, 74689, 24645, 112 closes https://github.com/official-stockfish/Stockfish/pull/4390 bench: 4098325 --- src/evaluate.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 6d5a8a0c..080d412b 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1072,8 +1072,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // Blend nnue complexity with (semi)classical complexity nnueComplexity = ( 406 * nnueComplexity - + 424 * abs(psq - nnue) - + int(optimism) * int(psq - nnue) + + (424 + optimism) * abs(psq - nnue) ) / 1024; // Return hybrid NNUE complexity to caller From 085cace4574bf561472d8d3d3afe50c2c536b4e3 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sun, 22 Jan 2023 19:45:46 -0600 Subject: [PATCH 069/192] Simplify late countermove bonus condition STC: https://tests.stockfishchess.org/tests/view/63d53ac6a67dd929a555e1e2 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 216096 W: 56862 L: 56839 D: 102395 Ptnml(0-2): 648, 24033, 58650, 24082, 635 LTC: https://tests.stockfishchess.org/tests/view/63d7f9a6a67dd929a5565991 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 808512 W: 214060 L: 214610 D: 379842 Ptnml(0-2): 301, 79448, 245293, 78928, 286 closes https://github.com/official-stockfish/Stockfish/pull/4392 Bench: 4283297 --- src/search.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 2eed74b8..eccb97fd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1371,11 +1371,10 @@ moves_loop: // When in check, search starts here quietsSearched, quietCount, capturesSearched, captureCount, depth); // Bonus for prior countermove that caused the fail low - else if ( (depth >= 5 || PvNode || bestValue < alpha - 65 * depth) - && !priorCapture) + else if (!priorCapture) { // Extra bonuses for PV/Cut nodes or bad fail lows - int bonus = 1 + (PvNode || cutNode) + (bestValue < alpha - 88 * depth); + int bonus = (depth > 4) + (PvNode || cutNode) + (bestValue < alpha - 88 * depth); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } From 037ef3e18dc7f5455cc671995ae38d5b4d1fce4a Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 14 Feb 2023 18:04:17 -0600 Subject: [PATCH 070/192] Remove one `reduction` call even though bench is unchanged to depth 28, due to adjusting depth in singular extensions this might be functional. STC: https://tests.stockfishchess.org/tests/view/63ec21affe833123fef34153 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 195712 W: 51625 L: 51581 D: 92506 Ptnml(0-2): 504, 20527, 55779, 20513, 533 LTC: https://tests.stockfishchess.org/tests/view/63ed3487fe833123fef375ed LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 32176 W: 8631 L: 8442 D: 15103 Ptnml(0-2): 5, 2794, 10309, 2967, 13 closes https://github.com/official-stockfish/Stockfish/pull/4395 Bench 4283297 --- src/search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index eccb97fd..6ca2cfa5 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -987,6 +987,8 @@ moves_loop: // When in check, search starts here Value delta = beta - alpha; + Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); + // Step 14. Pruning at shallow depth (~120 Elo). Depth conditions are important for mate finding. if ( !rootNode && pos.non_pawn_material(us) @@ -996,7 +998,7 @@ moves_loop: // When in check, search starts here moveCountPruning = moveCount >= futility_move_count(improving, depth); // Reduced depth of the next LMR search - int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount, delta, thisThread->rootDelta), 0); + int lmrDepth = std::max(newDepth - r, 0); if ( capture || givesCheck) @@ -1133,8 +1135,6 @@ moves_loop: // When in check, search starts here // Step 16. Make the move pos.do_move(move, st, givesCheck); - Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); - // Decrease reduction if position is or has been on the PV // and node is not likely to fail low. (~3 Elo) if ( ss->ttPv From b4ad3a3c4b68f9c8736f444aeb3364f833247fdc Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Tue, 21 Feb 2023 22:18:17 +0100 Subject: [PATCH 071/192] Add support for ARM dot product instructions The sdot instruction computes (and accumulates) a signed dot product, which is quite handy for Stockfish's NNUE code. The instruction is optional for Armv8.2 and Armv8.3, and mandatory for Armv8.4 and above. The commit adds a new 'arm-dotprod' architecture with enabled dot product support. It also enables dot product support for the existing 'apple-silicon' architecture, which is at least Armv8.5. The following local speed test was performed on an Apple M1 with ARCH=apple-silicon. I had to remove CPU pinning from the benchmark script. However, the results were still consistent: Checking both binaries against themselves reported a speedup of +0.0000 and +0.0005, respectively. ``` Result of 100 runs ================== base (...ish.037ef3e1) = 1917997 +/- 7152 test (...fish.dotprod) = 2159682 +/- 9066 diff = +241684 +/- 2923 speedup = +0.1260 P(speedup > 0) = 1.0000 CPU: 10 x arm Hyperthreading: off ``` Fixes #4193 closes https://github.com/official-stockfish/Stockfish/pull/4400 No functional change --- src/Makefile | 65 +++++++++++++++++++----------- src/nnue/layers/affine_transform.h | 24 +++++++++++ src/nnue/layers/simd.h | 13 ++++++ 3 files changed, 78 insertions(+), 24 deletions(-) diff --git a/src/Makefile b/src/Makefile index 775c72c3..3d6432fd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -69,32 +69,33 @@ VPATH = syzygy:nnue:nnue/features ### Section 2. High-level Configuration ### ========================================================================== # -# flag --- Comp switch --- Description +# flag --- Comp switch --- Description # ---------------------------------------------------------------------------- # -# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode +# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode # sanitize = none/ ... (-fsanitize ) -# --- ( undefined ) --- enable undefined behavior checks -# --- ( thread ) --- enable threading error checks -# --- ( address ) --- enable memory access checks -# --- ...etc... --- see compiler documentation for supported sanitizers -# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations -# arch = (name) --- (-arch) --- Target architecture -# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system -# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction -# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction -# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction -# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions -# mmx = yes/no --- -mmmx --- Use Intel MMX instructions -# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2 -# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3 -# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1 -# 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 -# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256 -# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512 -# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture +# --- ( undefined ) --- enable undefined behavior checks +# --- ( thread ) --- enable threading error checks +# --- ( address ) --- enable memory access checks +# --- ...etc... --- see compiler documentation for supported sanitizers +# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations +# arch = (name) --- (-arch) --- Target architecture +# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system +# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction +# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction +# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction +# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions +# mmx = yes/no --- -mmmx --- Use Intel MMX instructions +# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2 +# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3 +# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1 +# 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 +# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256 +# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512 +# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture +# dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions # # Note that Makefile is space sensitive, so when adding new architectures # or modifying existing flags, you have to make sure there are no extra spaces @@ -116,7 +117,7 @@ ifeq ($(ARCH), $(filter $(ARCH), \ x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-avxvnni x86-64-bmi2 \ 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 \ - armv7 armv7-neon armv8 apple-silicon general-64 general-32 riscv64)) + armv7 armv7-neon armv8 armv8-dotprod apple-silicon general-64 general-32 riscv64)) SUPPORTED_ARCH=true else SUPPORTED_ARCH=false @@ -140,6 +141,7 @@ avx512 = no vnni256 = no vnni512 = no neon = no +dotprod = no arm_version = 0 STRIP = strip @@ -308,11 +310,21 @@ ifeq ($(ARCH),armv8) arm_version = 8 endif +ifeq ($(ARCH),armv8-dotprod) + arch = armv8 + prefetch = yes + popcnt = yes + neon = yes + dotprod = yes + arm_version = 8 +endif + ifeq ($(ARCH),apple-silicon) arch = arm64 prefetch = yes popcnt = yes neon = yes + dotprod = yes arm_version = 8 endif @@ -675,6 +687,10 @@ ifeq ($(neon),yes) endif endif +ifeq ($(dotprod),yes) + CXXFLAGS += -march=armv8.2-a+dotprod -DUSE_NEON_DOTPROD +endif + ### 3.7 pext ifeq ($(pext),yes) CXXFLAGS += -DUSE_PEXT @@ -776,6 +792,7 @@ help: @echo "armv7 > ARMv7 32-bit" @echo "armv7-neon > ARMv7 32-bit with popcnt and neon" @echo "armv8 > ARMv8 64-bit with popcnt and neon" + @echo "armv8-dotprod > ARMv8 64-bit with popcnt, neon and dot product support" @echo "e2k > Elbrus 2000" @echo "apple-silicon > Apple silicon ARM64" @echo "general-64 > unspecified 64-bit" diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 363b4916..63b58af3 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -72,6 +72,10 @@ namespace Stockfish::Eval::NNUE::Layers { const __m64 Zeros = _mm_setzero_si64(); const auto inputVector = reinterpret_cast(input); +# elif defined(USE_NEON_DOTPROD) + constexpr IndexType NumChunks = ceil_to_multiple(InputDimensions, 16) / 16; + const auto inputVector = reinterpret_cast(input); + # elif defined(USE_NEON) constexpr IndexType NumChunks = ceil_to_multiple(InputDimensions, 16) / 16; const auto inputVector = reinterpret_cast(input); @@ -123,6 +127,14 @@ namespace Stockfish::Eval::NNUE::Layers { sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum)); output[i] = _mm_cvtsi64_si32(sum); +# elif defined(USE_NEON_DOTPROD) + int32x4_t sum = {biases[i]}; + const auto row = reinterpret_cast(&weights[offset]); + for (IndexType j = 0; j < NumChunks; ++j) { + sum = vdotq_s32(sum, inputVector[j], row[j]); + } + output[i] = vaddvq_s32(sum); + # elif defined(USE_NEON) int32x4_t sum = {biases[i]}; const auto row = reinterpret_cast(&weights[offset]); @@ -187,6 +199,9 @@ namespace Stockfish::Eval::NNUE::Layers { #elif defined (USE_SSSE3) static constexpr IndexType InputSimdWidth = 16; static constexpr IndexType MaxNumOutputRegs = 8; +#elif defined (USE_NEON_DOTPROD) + static constexpr IndexType InputSimdWidth = 16; + static constexpr IndexType MaxNumOutputRegs = 8; #elif defined (USE_NEON) static constexpr IndexType InputSimdWidth = 8; static constexpr IndexType MaxNumOutputRegs = 8; @@ -292,6 +307,15 @@ namespace Stockfish::Eval::NNUE::Layers { #define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2 #define vec_hadd Simd::m128_hadd #define vec_haddx4 Simd::m128_haddx4 +#elif defined (USE_NEON_DOTPROD) + using acc_vec_t = int32x4_t; + using bias_vec_t = int32x4_t; + using weight_vec_t = int8x16_t; + using in_vec_t = int8x16_t; + #define vec_zero {0} + #define vec_add_dpbusd_32x2 Simd::dotprod_m128_add_dpbusd_epi32x2 + #define vec_hadd Simd::neon_m128_hadd + #define vec_haddx4 Simd::neon_m128_haddx4 #elif defined (USE_NEON) using acc_vec_t = int32x4_t; using bias_vec_t = int32x4_t; diff --git a/src/nnue/layers/simd.h b/src/nnue/layers/simd.h index 381e7a68..22c51980 100644 --- a/src/nnue/layers/simd.h +++ b/src/nnue/layers/simd.h @@ -346,6 +346,19 @@ namespace Stockfish::Simd { #endif +#if defined (USE_NEON_DOTPROD) + + [[maybe_unused]] static void dotprod_m128_add_dpbusd_epi32x2( + int32x4_t& acc, + int8x16_t a0, int8x16_t b0, + int8x16_t a1, int8x16_t b1) { + + acc = vdotq_s32(acc, a0, b0); + acc = vdotq_s32(acc, a1, b1); + } + +#endif + #if defined (USE_NEON) [[maybe_unused]] static int neon_m128_reduce_add_epi32(int32x4_t s) { From 77dfcbedce2861b2c6c5056d49e7a8731fea4256 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sun, 19 Feb 2023 11:25:10 +0100 Subject: [PATCH 072/192] Remove unused macros closes https://github.com/official-stockfish/Stockfish/pull/4397 No functional change --- src/nnue/layers/affine_transform.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 63b58af3..313b1568 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -480,18 +480,14 @@ namespace Stockfish::Eval::NNUE::Layers { #define vec_set_32 _mm256_set1_epi32 #define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32 #define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2 - #define vec_add_dpbusd_32x4 Simd::m256_add_dpbusd_epi32x4 #define vec_hadd Simd::m256_hadd - #define vec_haddx4 Simd::m256_haddx4 #elif defined (USE_SSSE3) using vec_t = __m128i; #define vec_setzero _mm_setzero_si128 #define vec_set_32 _mm_set1_epi32 #define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32 #define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2 - #define vec_add_dpbusd_32x4 Simd::m128_add_dpbusd_epi32x4 #define vec_hadd Simd::m128_hadd - #define vec_haddx4 Simd::m128_haddx4 #endif #if defined (USE_SSSE3) @@ -542,9 +538,7 @@ namespace Stockfish::Eval::NNUE::Layers { # undef vec_set_32 # undef vec_add_dpbusd_32 # undef vec_add_dpbusd_32x2 -# undef vec_add_dpbusd_32x4 # undef vec_hadd -# undef vec_haddx4 #else // Use old implementation for the other architectures. affine_transform_non_ssse3< From 08385527dd470ece814ac85013802995a0e7f6ca Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 20 Feb 2023 20:02:55 +0100 Subject: [PATCH 073/192] Introduce a function to compute NNUE accumulator This patch introduces `hint_common_parent_position()` to signal that potentially several child nodes will require an NNUE eval. By populating explicitly the accumulator, these subsequent evaluations can be performed more efficiently. This was based on the observation that calculating the evaluation in an excluded move position yielded a significant Elo gain, even though the evaluation itself was already available (work by pb00067). Sopel wrote the code to perform just the accumulator update. This PR is based on cleaned up code that passed STC: https://tests.stockfishchess.org/tests/view/63f62f9be74a12625bcd4aa0 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 110368 W: 29607 L: 29167 D: 51594 Ptnml(0-2): 41, 10551, 33572, 10967, 53 and in an the earlier (equivalent) version passed STC: https://tests.stockfishchess.org/tests/view/63f3c3fee74a12625bcce2a6 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 47552 W: 12786 L: 12467 D: 22299 Ptnml(0-2): 120, 5107, 12997, 5438, 114 passed LTC: https://tests.stockfishchess.org/tests/view/63f45cc2e74a12625bccfa63 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 110368 W: 29607 L: 29167 D: 51594 Ptnml(0-2): 41, 10551, 33572, 10967, 53 closes https://github.com/official-stockfish/Stockfish/pull/4402 Bench: 3726250 --- src/evaluate.h | 1 + src/nnue/evaluate_nnue.cpp | 5 + src/nnue/evaluate_nnue.h | 1 + src/nnue/nnue_feature_transformer.h | 425 +++++++++++++++++----------- src/search.cpp | 8 +- 5 files changed, 266 insertions(+), 174 deletions(-) diff --git a/src/evaluate.h b/src/evaluate.h index cdea2ab2..46f20259 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -45,6 +45,7 @@ namespace Eval { std::string trace(Position& pos); Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr); + void hint_common_parent_position(const Position& pos); void init(); void verify(); diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index f132de71..f33aa3b8 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -136,6 +136,11 @@ namespace Stockfish::Eval::NNUE { return (bool)stream; } + void hint_common_parent_position(const Position& pos) { + if (Eval::useNNUE) + featureTransformer->hint_common_access(pos); + } + // Evaluation function. Perform differential calculation. Value evaluate(const Position& pos, bool adjusted, int* complexity) { diff --git a/src/nnue/evaluate_nnue.h b/src/nnue/evaluate_nnue.h index 9499f7d9..15638cae 100644 --- a/src/nnue/evaluate_nnue.h +++ b/src/nnue/evaluate_nnue.h @@ -31,6 +31,7 @@ namespace Stockfish::Eval::NNUE { constexpr std::uint32_t HashValue = FeatureTransformer::get_hash_value() ^ Network::get_hash_value(); + // Deleter for automating release of memory area template struct AlignedDeleter { diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 62f1615d..13f1604f 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -25,6 +25,7 @@ #include "nnue_architecture.h" #include // std::memset() +#include // std::pair namespace Stockfish::Eval::NNUE { @@ -332,27 +333,16 @@ namespace Stockfish::Eval::NNUE { #endif return psqt; + } // end of function transform() - } // end of function transform() - - + void hint_common_access(const Position& pos) const { + hint_common_access_for_perspective(pos); + hint_common_access_for_perspective(pos); + } private: template - void update_accumulator(const Position& pos) const { - - // The size must be enough to contain the largest possible update. - // That might depend on the feature set and generally relies on the - // feature set's update cost calculation to be correct and never - // allow updates with more added/removed features than MaxActiveDimensions. - - #ifdef VECTOR - // Gcc-10.2 unnecessarily spills AVX2 registers if this array - // is defined in the VECTOR code below, once in each branch - vec_t acc[NumRegs]; - psqt_vec_t psqt[NumPsqtRegs]; - #endif - + [[nodiscard]] std::pair try_find_computed_accumulator(const Position& pos) const { // Look for a usable accumulator of an earlier position. We keep track // of the estimated gain in terms of features to be added/subtracted. StateInfo *st = pos.state(), *next = nullptr; @@ -367,218 +357,313 @@ namespace Stockfish::Eval::NNUE { next = st; st = st->previous; } + return { st, next }; + } - if (st->accumulator.computed[Perspective]) - { - if (next == nullptr) - return; + // NOTE: The parameter states_to_update is an array of position states, ending with nullptr. + // All states must be sequential, that is states_to_update[i] must either be reachable + // by repeatedly applying ->previous from states_to_update[i+1] or states_to_update[i] == nullptr. + // computed_st must be reachable by repeatadly applying ->previous on states_to_update[0], if not nullptr. + template + void update_accumulator_incremetal(const Position& pos, StateInfo* computed_st, StateInfo* states_to_update[N]) const { + static_assert(N > 0); + assert(states_to_update[N-1] == nullptr); - // Update incrementally in two steps. First, we update the "next" - // accumulator. Then, we update the current accumulator (pos.state()). - - // Gather all features to be updated. - const Square ksq = pos.square(Perspective); - FeatureSet::IndexList removed[2], added[2]; - FeatureSet::append_changed_indices( - ksq, next->dirtyPiece, removed[0], added[0]); - for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous) - FeatureSet::append_changed_indices( - ksq, st2->dirtyPiece, removed[1], added[1]); - - // Mark the accumulators as computed. - next->accumulator.computed[Perspective] = true; - pos.state()->accumulator.computed[Perspective] = true; - - // Now update the accumulators listed in states_to_update[], where the last element is a sentinel. - StateInfo *states_to_update[3] = - { next, next == pos.state() ? nullptr : pos.state(), nullptr }; #ifdef VECTOR - for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) + // Gcc-10.2 unnecessarily spills AVX2 registers if this array + // is defined in the VECTOR code below, once in each branch + vec_t acc[NumRegs]; + psqt_vec_t psqt[NumPsqtRegs]; + #endif + + if (states_to_update[0] == nullptr) + return; + + // Update incrementally going back through states_to_update. + + // Gather all features to be updated. + const Square ksq = pos.square(Perspective); + + // The size must be enough to contain the largest possible update. + // That might depend on the feature set and generally relies on the + // feature set's update cost calculation to be correct and never + // allow updates with more added/removed features than MaxActiveDimensions. + FeatureSet::IndexList removed[N-1], added[N-1]; + + { + int i = N-2; // last potential state to update. Skip last element because it must be nullptr. + while (states_to_update[i] == nullptr) + --i; + + StateInfo *st2 = states_to_update[i]; + + for (; i >= 0; --i) { - // Load accumulator - auto accTile = reinterpret_cast( - &st->accumulator.accumulation[Perspective][j * TileHeight]); - for (IndexType k = 0; k < NumRegs; ++k) - acc[k] = vec_load(&accTile[k]); + states_to_update[i]->accumulator.computed[Perspective] = true; - for (IndexType i = 0; states_to_update[i]; ++i) - { - // Difference calculation for the deactivated features - for (const auto index : removed[i]) - { - const IndexType offset = HalfDimensions * index + j * TileHeight; - auto column = reinterpret_cast(&weights[offset]); - for (IndexType k = 0; k < NumRegs; ++k) - acc[k] = vec_sub_16(acc[k], column[k]); - } + StateInfo* end_state = i == 0 ? computed_st : states_to_update[i - 1]; - // Difference calculation for the activated features - for (const auto index : added[i]) - { - const IndexType offset = HalfDimensions * index + j * TileHeight; - auto column = reinterpret_cast(&weights[offset]); - for (IndexType k = 0; k < NumRegs; ++k) - acc[k] = vec_add_16(acc[k], column[k]); - } - - // Store accumulator - accTile = reinterpret_cast( - &states_to_update[i]->accumulator.accumulation[Perspective][j * TileHeight]); - for (IndexType k = 0; k < NumRegs; ++k) - vec_store(&accTile[k], acc[k]); - } + for (; st2 != end_state; st2 = st2->previous) + FeatureSet::append_changed_indices( + ksq, st2->dirtyPiece, removed[i], added[i]); } + } - for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j) - { - // Load accumulator - auto accTilePsqt = reinterpret_cast( - &st->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) - psqt[k] = vec_load_psqt(&accTilePsqt[k]); + StateInfo* st = computed_st; - for (IndexType i = 0; states_to_update[i]; ++i) - { - // Difference calculation for the deactivated features - for (const auto index : removed[i]) - { - const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) - psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]); - } + // Now update the accumulators listed in states_to_update[], where the last element is a sentinel. +#ifdef VECTOR + for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) + { + // Load accumulator + auto accTile = reinterpret_cast( + &st->accumulator.accumulation[Perspective][j * TileHeight]); + for (IndexType k = 0; k < NumRegs; ++k) + acc[k] = vec_load(&accTile[k]); - // Difference calculation for the activated features - for (const auto index : added[i]) - { - const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) - psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]); - } - - // Store accumulator - accTilePsqt = reinterpret_cast( - &states_to_update[i]->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) - vec_store_psqt(&accTilePsqt[k], psqt[k]); - } - } - - #else for (IndexType i = 0; states_to_update[i]; ++i) { - std::memcpy(states_to_update[i]->accumulator.accumulation[Perspective], - st->accumulator.accumulation[Perspective], - HalfDimensions * sizeof(BiasType)); - - for (std::size_t k = 0; k < PSQTBuckets; ++k) - states_to_update[i]->accumulator.psqtAccumulation[Perspective][k] = st->accumulator.psqtAccumulation[Perspective][k]; - - st = states_to_update[i]; - // Difference calculation for the deactivated features for (const auto index : removed[i]) { - const IndexType offset = HalfDimensions * index; - - for (IndexType j = 0; j < HalfDimensions; ++j) - st->accumulator.accumulation[Perspective][j] -= weights[offset + j]; - - for (std::size_t k = 0; k < PSQTBuckets; ++k) - st->accumulator.psqtAccumulation[Perspective][k] -= psqtWeights[index * PSQTBuckets + k]; + const IndexType offset = HalfDimensions * index + j * TileHeight; + auto column = reinterpret_cast(&weights[offset]); + for (IndexType k = 0; k < NumRegs; ++k) + acc[k] = vec_sub_16(acc[k], column[k]); } // Difference calculation for the activated features for (const auto index : added[i]) - { - const IndexType offset = HalfDimensions * index; - - for (IndexType j = 0; j < HalfDimensions; ++j) - st->accumulator.accumulation[Perspective][j] += weights[offset + j]; - - for (std::size_t k = 0; k < PSQTBuckets; ++k) - st->accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; - } - } - #endif - } - else - { - // Refresh the accumulator - auto& accumulator = pos.state()->accumulator; - accumulator.computed[Perspective] = true; - FeatureSet::IndexList active; - FeatureSet::append_active_indices(pos, active); - - #ifdef VECTOR - for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) - { - auto biasesTile = reinterpret_cast( - &biases[j * TileHeight]); - for (IndexType k = 0; k < NumRegs; ++k) - acc[k] = biasesTile[k]; - - for (const auto index : active) { const IndexType offset = HalfDimensions * index + j * TileHeight; auto column = reinterpret_cast(&weights[offset]); - - for (unsigned k = 0; k < NumRegs; ++k) + for (IndexType k = 0; k < NumRegs; ++k) acc[k] = vec_add_16(acc[k], column[k]); } - auto accTile = reinterpret_cast( - &accumulator.accumulation[Perspective][j * TileHeight]); - for (unsigned k = 0; k < NumRegs; k++) + // Store accumulator + accTile = reinterpret_cast( + &states_to_update[i]->accumulator.accumulation[Perspective][j * TileHeight]); + for (IndexType k = 0; k < NumRegs; ++k) vec_store(&accTile[k], acc[k]); } + } - for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j) + for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j) + { + // Load accumulator + auto accTilePsqt = reinterpret_cast( + &st->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); + for (std::size_t k = 0; k < NumPsqtRegs; ++k) + psqt[k] = vec_load_psqt(&accTilePsqt[k]); + + for (IndexType i = 0; states_to_update[i]; ++i) { - for (std::size_t k = 0; k < NumPsqtRegs; ++k) - psqt[k] = vec_zero_psqt(); - - for (const auto index : active) + // Difference calculation for the deactivated features + for (const auto index : removed[i]) { const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); + for (std::size_t k = 0; k < NumPsqtRegs; ++k) + psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]); + } + // Difference calculation for the activated features + for (const auto index : added[i]) + { + const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; + auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); for (std::size_t k = 0; k < NumPsqtRegs; ++k) psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]); } - auto accTilePsqt = reinterpret_cast( - &accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); + // Store accumulator + accTilePsqt = reinterpret_cast( + &states_to_update[i]->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); for (std::size_t k = 0; k < NumPsqtRegs; ++k) vec_store_psqt(&accTilePsqt[k], psqt[k]); } + } - #else - std::memcpy(accumulator.accumulation[Perspective], biases, +#else + for (IndexType i = 0; states_to_update[i]; ++i) + { + std::memcpy(states_to_update[i]->accumulator.accumulation[Perspective], + st->accumulator.accumulation[Perspective], HalfDimensions * sizeof(BiasType)); for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[Perspective][k] = 0; + states_to_update[i]->accumulator.psqtAccumulation[Perspective][k] = st->accumulator.psqtAccumulation[Perspective][k]; - for (const auto index : active) + st = states_to_update[i]; + + // Difference calculation for the deactivated features + for (const auto index : removed[i]) { const IndexType offset = HalfDimensions * index; for (IndexType j = 0; j < HalfDimensions; ++j) - accumulator.accumulation[Perspective][j] += weights[offset + j]; + st->accumulator.accumulation[Perspective][j] -= weights[offset + j]; for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; + st->accumulator.psqtAccumulation[Perspective][k] -= psqtWeights[index * PSQTBuckets + k]; + } + + // Difference calculation for the activated features + for (const auto index : added[i]) + { + const IndexType offset = HalfDimensions * index; + + for (IndexType j = 0; j < HalfDimensions; ++j) + st->accumulator.accumulation[Perspective][j] += weights[offset + j]; + + for (std::size_t k = 0; k < PSQTBuckets; ++k) + st->accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; } - #endif } +#endif #if defined(USE_MMX) _mm_empty(); #endif } + template + void update_accumulator_refresh(const Position& pos) const { + #ifdef VECTOR + // Gcc-10.2 unnecessarily spills AVX2 registers if this array + // is defined in the VECTOR code below, once in each branch + vec_t acc[NumRegs]; + psqt_vec_t psqt[NumPsqtRegs]; + #endif + + // Refresh the accumulator + // Could be extracted to a separate function because it's done in 2 places, + // but it's unclear if compilers would correctly handle register allocation. + auto& accumulator = pos.state()->accumulator; + accumulator.computed[Perspective] = true; + FeatureSet::IndexList active; + FeatureSet::append_active_indices(pos, active); + +#ifdef VECTOR + for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) + { + auto biasesTile = reinterpret_cast( + &biases[j * TileHeight]); + for (IndexType k = 0; k < NumRegs; ++k) + acc[k] = biasesTile[k]; + + for (const auto index : active) + { + const IndexType offset = HalfDimensions * index + j * TileHeight; + auto column = reinterpret_cast(&weights[offset]); + + for (unsigned k = 0; k < NumRegs; ++k) + acc[k] = vec_add_16(acc[k], column[k]); + } + + auto accTile = reinterpret_cast( + &accumulator.accumulation[Perspective][j * TileHeight]); + for (unsigned k = 0; k < NumRegs; k++) + vec_store(&accTile[k], acc[k]); + } + + for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j) + { + for (std::size_t k = 0; k < NumPsqtRegs; ++k) + psqt[k] = vec_zero_psqt(); + + for (const auto index : active) + { + const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; + auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); + + for (std::size_t k = 0; k < NumPsqtRegs; ++k) + psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]); + } + + auto accTilePsqt = reinterpret_cast( + &accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); + for (std::size_t k = 0; k < NumPsqtRegs; ++k) + vec_store_psqt(&accTilePsqt[k], psqt[k]); + } + +#else + std::memcpy(accumulator.accumulation[Perspective], biases, + HalfDimensions * sizeof(BiasType)); + + for (std::size_t k = 0; k < PSQTBuckets; ++k) + accumulator.psqtAccumulation[Perspective][k] = 0; + + for (const auto index : active) + { + const IndexType offset = HalfDimensions * index; + + for (IndexType j = 0; j < HalfDimensions; ++j) + accumulator.accumulation[Perspective][j] += weights[offset + j]; + + for (std::size_t k = 0; k < PSQTBuckets; ++k) + accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; + } +#endif + + #if defined(USE_MMX) + _mm_empty(); + #endif + } + + template + void hint_common_access_for_perspective(const Position& pos) const { + + // Works like update_accumulator, but performs less work. + // Updates ONLY the accumulator for pos. + + // Look for a usable accumulator of an earlier position. We keep track + // of the estimated gain in terms of features to be added/subtracted. + // Fast early exit. + if (pos.state()->accumulator.computed[Perspective]) + return; + + auto [oldest_st, _] = try_find_computed_accumulator(pos); + + if (oldest_st->accumulator.computed[Perspective]) + { + // Only update current position accumulator to minimize work. + StateInfo* states_to_update[2] = { pos.state(), nullptr }; + update_accumulator_incremetal(pos, oldest_st, states_to_update); + } + else + { + update_accumulator_refresh(pos); + } + } + + template + void update_accumulator(const Position& pos) const { + + auto [oldest_st, next] = try_find_computed_accumulator(pos); + + if (oldest_st->accumulator.computed[Perspective]) + { + if (next == nullptr) + return; + + // Now update the accumulators listed in states_to_update[], where the last element is a sentinel. + // Currently we update 2 accumulators. + // 1. for the current position + // 2. the next accumulator after the computed one + // The heuristic may change in the future. + StateInfo *states_to_update[3] = + { next, next == pos.state() ? nullptr : pos.state(), nullptr }; + + update_accumulator_incremetal(pos, oldest_st, states_to_update); + } + else + { + update_accumulator_refresh(pos); + } + } + alignas(CacheLineSize) BiasType biases[HalfDimensions]; alignas(CacheLineSize) WeightType weights[HalfDimensions * InputDimensions]; alignas(CacheLineSize) PSQTWeightType psqtWeights[InputDimensions * PSQTBuckets]; diff --git a/src/search.cpp b/src/search.cpp index 6ca2cfa5..5cb9750c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -730,10 +730,10 @@ namespace { goto moves_loop; } else if (excludedMove) { - // excludeMove implies that we had a ttHit on the containing non-excluded search with ss->staticEval filled from TT - // However static evals from the TT aren't good enough (-13 elo), presumably due to changing optimism context - // Recalculate value with current optimism (without updating thread avgComplexity) - ss->staticEval = eval = evaluate(pos, &complexity); + // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 elo) + Eval::NNUE::hint_common_parent_position(pos); + eval = ss->staticEval; + complexity = abs(ss->staticEval - pos.psq_eg_stm()); } else if (ss->ttHit) { From 69639d764bde566e524b8c2566119bf677cb2622 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Tue, 21 Feb 2023 11:17:59 -0500 Subject: [PATCH 074/192] Reintroduce nnue pawn scaling with lower lazy thresholds Params found with the nevergrad TBPSA optimizer via nevergrad4sf modified to: * use SPRT LLR with fishtest STC elo gainer bounds [0, 2] as the objective function * increase the game batch size after each new optimal point is found The params were the optimal point after TBPSA iteration 7 and 160 nevergrad evaluations with: * initial batch size of 96 games per evaluation * batch size increase of 64 games after each iteration * a budget of 512 evaluations * TC: fixed 1.5 million nodes per move, no time limit nevergrad4sf enables optimizing stockfish params with TBPSA: https://github.com/vondele/nevergrad4sf Using pentanomial game results with smaller game batch sizes was inspired by: Use of SPRT LLR calculated from pentanomial game results as the objective function was an experiment at maximizing the information from game batches to reduce the computational cost for TBPSA to converge on good parameters. For the exact code used to find the params: https://github.com/linrock/tuning-fork Passed STC: https://tests.stockfishchess.org/tests/view/63f4ef5ee74a12625bcd114a LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 66552 W: 17736 L: 17390 D: 31426 Ptnml(0-2): 164, 7229, 18166, 7531, 186 Passed LTC: https://tests.stockfishchess.org/tests/view/63f56028e74a12625bcd2550 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 71264 W: 19150 L: 18787 D: 33327 Ptnml(0-2): 23, 6728, 21771, 7083, 27 closes https://github.com/official-stockfish/Stockfish/pull/4401 bench 3687580 --- src/evaluate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 080d412b..cf6f23ea 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -193,8 +193,8 @@ using namespace Trace; namespace { // Threshold for lazy and space evaluation - constexpr Value LazyThreshold1 = Value(3631); - constexpr Value LazyThreshold2 = Value(2084); + constexpr Value LazyThreshold1 = Value(3622); + constexpr Value LazyThreshold2 = Value(1962); constexpr Value SpaceThreshold = Value(11551); // KingAttackWeights[PieceType] contains king attack weights by piece type @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { else { int nnueComplexity; - int scale = 1076 + 96 * pos.non_pawn_material() / 5120; + int scale = 1001 + 5 * pos.count() + 61 * pos.non_pawn_material() / 4096; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; From 29b5ad5deaf323f43019443b322090caec13f847 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Thu, 23 Feb 2023 19:01:51 +0100 Subject: [PATCH 075/192] Fix typo in method name closes https://github.com/official-stockfish/Stockfish/pull/4404 No functional change --- src/nnue/nnue_feature_transformer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 13f1604f..b0d5743e 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -365,7 +365,7 @@ namespace Stockfish::Eval::NNUE { // by repeatedly applying ->previous from states_to_update[i+1] or states_to_update[i] == nullptr. // computed_st must be reachable by repeatadly applying ->previous on states_to_update[0], if not nullptr. template - void update_accumulator_incremetal(const Position& pos, StateInfo* computed_st, StateInfo* states_to_update[N]) const { + void update_accumulator_incremental(const Position& pos, StateInfo* computed_st, StateInfo* states_to_update[N]) const { static_assert(N > 0); assert(states_to_update[N-1] == nullptr); @@ -630,7 +630,7 @@ namespace Stockfish::Eval::NNUE { { // Only update current position accumulator to minimize work. StateInfo* states_to_update[2] = { pos.state(), nullptr }; - update_accumulator_incremetal(pos, oldest_st, states_to_update); + update_accumulator_incremental(pos, oldest_st, states_to_update); } else { @@ -656,7 +656,7 @@ namespace Stockfish::Eval::NNUE { StateInfo *states_to_update[3] = { next, next == pos.state() ? nullptr : pos.state(), nullptr }; - update_accumulator_incremetal(pos, oldest_st, states_to_update); + update_accumulator_incremental(pos, oldest_st, states_to_update); } else { From 472e726bff0d0e496dc8359cc071726a76317a72 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 24 Feb 2023 18:25:24 +0300 Subject: [PATCH 076/192] Search tuning at very long time control This patch is a result of tuning session of approximately 100k games at 120+1.2. Biggest changes are in extensions, stat bonus and depth reduction for nodes without a tt move. Failed STC: https://tests.stockfishchess.org/tests/view/63f72c72e74a12625bcd7938 LLR: -2.94 (-2.94,2.94) <0.00,2.00> Total: 13872 W: 3535 L: 3769 D: 6568 Ptnml(0-2): 56, 1621, 3800, 1419, 40 Close to neutral at LTC: https://tests.stockfishchess.org/tests/view/63f738f5e74a12625bcd7b8a Elo: 0.80 +-1.2 (95%) LOS: 90.0% Total: 60000 W: 16213 L: 16074 D: 27713 Ptnml(0-2): 24, 5718, 18379, 5853, 26 nElo: 1.82 +-2.8 (95%) PairsRatio: 1.02 Passed 180+1.8 VLTC: https://tests.stockfishchess.org/tests/view/63f868f3e74a12625bcdb33e LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 15864 W: 4449 L: 4202 D: 7213 Ptnml(0-2): 1, 1301, 5083, 1544, 3 Passed 60+0.6 8 threads SMP VLTC: https://tests.stockfishchess.org/tests/view/63f8a5d6e74a12625bcdbdb3 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 6288 W: 1821 L: 1604 D: 2863 Ptnml(0-2): 0, 402, 2123, 619, 0 closes https://github.com/official-stockfish/Stockfish/pull/4406 bench 4705194 --- src/search.cpp | 102 ++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5cb9750c..a41ea4fd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -63,7 +63,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(158 * (d - improving)); + return Value(154 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -71,7 +71,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1460 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 937); + return (r + 1449 - int(delta) * 1032 / int(rootDelta)) / 1024 + (!i && r > 941); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min(350 * d - 400, 1650); + return std::min(340 * d - 470, 1855); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -161,7 +161,7 @@ namespace { void Search::init() { for (int i = 1; i < MAX_MOVES; ++i) - Reductions[i] = int((20.26 + std::log(Threads.size()) / 2) * std::log(i)); + Reductions[i] = int((19.47 + std::log(Threads.size()) / 2) * std::log(i)); } @@ -354,12 +354,12 @@ void Thread::search() { if (rootDepth >= 4) { Value prev = rootMoves[pvIdx].averageScore; - delta = Value(10) + int(prev) * prev / 15400; + delta = Value(10) + int(prev) * prev / 16502; alpha = std::max(prev - delta,-VALUE_INFINITE); beta = std::min(prev + delta, VALUE_INFINITE); // Adjust optimism based on root move's previousScore - int opt = 116 * prev / (std::abs(prev) + 170); + int opt = 120 * prev / (std::abs(prev) + 161); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; } @@ -462,16 +462,16 @@ void Thread::search() { && !Threads.stop && !mainThread->stopOnPonderhit) { - double fallingEval = (71 + 12 * (mainThread->bestPreviousAverageScore - bestValue) - + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 656.7; + double fallingEval = (69 + 13 * (mainThread->bestPreviousAverageScore - bestValue) + + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 619.6; fallingEval = std::clamp(fallingEval, 0.5, 1.5); // If the bestMove is stable over several iterations, reduce time accordingly - timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.37 : 0.65; - double reduction = (1.4 + mainThread->previousTimeReduction) / (2.15 * timeReduction); - double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); + timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.57 : 0.65; + double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction); + double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::min(1.0 + (complexity - 261) / 1738.7, 1.5); + double complexPosition = std::min(1.03 + (complexity - 241) / 1552.0, 1.45); double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; @@ -491,7 +491,7 @@ void Thread::search() { Threads.stop = true; } else if ( !mainThread->ponder - && Time.elapsed() > totalTime * 0.53) + && Time.elapsed() > totalTime * 0.50) Threads.increaseDepth = false; else Threads.increaseDepth = true; @@ -760,7 +760,7 @@ namespace { // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { - int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1940, 1940); + int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1920, 1920); thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus; } @@ -770,13 +770,13 @@ namespace { // margin and the improving flag are used in various pruning heuristics. improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval - : 172; + : 156; improving = improvement > 0; // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if (eval < alpha - 394 - 255 * depth * depth) + if (eval < alpha - 426 - 252 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -786,19 +786,19 @@ namespace { // Step 8. Futility pruning: child node (~40 Elo). // The depth condition is important for mate finding. if ( !ss->ttPv - && depth < 8 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 304 >= beta + && depth < 9 + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 280 >= beta && eval >= beta - && eval < 28580) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 25128) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~35 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 18200 + && (ss-1)->statScore < 18755 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 20 * depth - improvement / 14 + 235 + complexity / 24 + && ss->staticEval >= beta - 19 * depth - improvement / 13 + 253 + complexity / 25 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) @@ -806,7 +806,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 165, 6) + depth / 3 + 4 - (complexity > 800); + Depth R = std::min(int(eval - beta) / 168, 6) + depth / 3 + 4 - (complexity > 825); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -842,7 +842,7 @@ namespace { } } - probCutBeta = beta + 180 - 54 * improving; + probCutBeta = beta + 186 - 54 * improving; // Step 10. ProbCut (~10 Elo) // If we have a good enough capture and a reduced search returns a value @@ -904,14 +904,14 @@ namespace { return qsearch(pos, ss, alpha, beta); if ( cutNode - && depth >= 9 + && depth >= 7 && !ttMove) depth -= 2; moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~4 Elo) - probCutBeta = beta + 402; + probCutBeta = beta + 391; if ( ss->inCheck && !PvNode && depth >= 2 @@ -1006,14 +1006,14 @@ moves_loop: // When in check, search starts here // Futility pruning for captures (~2 Elo) if ( !givesCheck && !PvNode - && lmrDepth < 7 + && lmrDepth < 6 && !ss->inCheck - && ss->staticEval + 185 + 203 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] - + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha) + && ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, Value(-220) * depth)) + if (!pos.see_ge(move, Value(-206) * depth)) continue; } else @@ -1024,24 +1024,24 @@ moves_loop: // When in check, search starts here // Continuation history based pruning (~2 Elo) if ( lmrDepth < 5 - && history < -4180 * (depth - 1)) + && history < -4405 * (depth - 1)) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; - lmrDepth += history / 7208; + lmrDepth += history / 7278; lmrDepth = std::max(lmrDepth, -2); // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck && lmrDepth < 13 - && ss->staticEval + 103 + 136 * lmrDepth <= alpha) + && ss->staticEval + 103 + 138 * lmrDepth <= alpha) continue; lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 16 * lmrDepth))) + if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) continue; } } @@ -1056,7 +1056,7 @@ moves_loop: // When in check, search starts here // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( !rootNode - && depth >= 4 - (thisThread->completedDepth > 22) + 2 * (PvNode && tte->is_pv()) + && depth >= 4 - (thisThread->completedDepth > 21) + 2 * (PvNode && tte->is_pv()) && move == ttMove && !excludedMove // Avoid recursive singular search /* && ttValue != VALUE_NONE Already implicit in the next condition */ @@ -1064,7 +1064,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - (3 + (ss->ttPv && !PvNode)) * depth; + Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth; Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; @@ -1083,7 +1083,7 @@ moves_loop: // When in check, search starts here && ss->doubleExtensions <= 10) { extension = 2; - depth += depth < 12; + depth += depth < 13; } } @@ -1106,15 +1106,15 @@ moves_loop: // When in check, search starts here // Check extensions (~1 Elo) else if ( givesCheck - && depth > 9 - && abs(ss->staticEval) > 78) + && depth > 10 + && abs(ss->staticEval) > 88) extension = 1; // Quiet ttMove extensions (~1 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 5600) + && (*contHist[0])[movedPiece][to_sq(move)] >= 5705) extension = 1; } @@ -1155,7 +1155,7 @@ moves_loop: // When in check, search starts here // Decrease reduction for PvNodes based on depth if (PvNode) - r -= 1 + 11 / (3 + depth); + r -= 1 + 12 / (3 + depth); // Decrease reduction if ttMove has been singularly extended (~1 Elo) if (singularQuietLMR) @@ -1172,17 +1172,17 @@ moves_loop: // When in check, search starts here // Decrease reduction if move is a killer and we have a good history if (move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 3600) + && (*contHist[0])[movedPiece][to_sq(move)] >= 3722) r--; ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4467; + - 4182; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (12800 + 4410 * (depth > 7 && depth < 19)); + r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has @@ -1206,8 +1206,8 @@ moves_loop: // When in check, search starts here { // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower - const bool doDeeperSearch = value > (alpha + 66 + 11 * (newDepth - d)); - const bool doEvenDeeperSearch = value > alpha + 582 && ss->doubleExtensions <= 5; + const bool doDeeperSearch = value > (alpha + 58 + 12 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 588 && ss->doubleExtensions <= 5; const bool doShallowerSearch = value < bestValue + newDepth; ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch; @@ -1318,8 +1318,8 @@ moves_loop: // When in check, search starts here // Reduce other moves if we have found at least one score improvement if ( depth > 1 && depth < 6 - && beta < VALUE_KNOWN_WIN - && alpha > -VALUE_KNOWN_WIN) + && beta < 10534 + && alpha > -10534) depth -= 1; assert(depth > 0); @@ -1374,7 +1374,7 @@ moves_loop: // When in check, search starts here else if (!priorCapture) { // Extra bonuses for PV/Cut nodes or bad fail lows - int bonus = (depth > 4) + (PvNode || cutNode) + (bestValue < alpha - 88 * depth); + int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } @@ -1502,7 +1502,7 @@ moves_loop: // When in check, search starts here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = bestValue + 158; + futilityBase = bestValue + 168; } const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, @@ -1575,7 +1575,7 @@ moves_loop: // When in check, search starts here continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-108))) + if (!pos.see_ge(move, Value(-110))) continue; } @@ -1708,7 +1708,7 @@ moves_loop: // When in check, search starts here if (!pos.capture(bestMove)) { - int bonus2 = bestValue > beta + 146 ? bonus1 // larger bonus + int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus : stat_bonus(depth); // smaller bonus // Increase stats for the best move in case it was a quiet move From 98dafda6c8d432924821d085fd958c89bc8834c3 Mon Sep 17 00:00:00 2001 From: Alfredo Menezes Date: Mon, 27 Feb 2023 00:39:26 -0300 Subject: [PATCH 077/192] Simplify condition in step 15 Remove 'ttValue <= alpha' check for negative extension in singular search. Also apply some small code style changes. STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 127888 W: 33766 L: 33651 D: 60471 Ptnml(0-2): 303, 14082, 35089, 14137, 333 https://tests.stockfishchess.org/tests/view/63f79528e74a12625bcd8c05 LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 89048 W: 23924 L: 23782 D: 41342 Ptnml(0-2): 27, 8635, 27065, 8763, 34 https://tests.stockfishchess.org/tests/view/63f82177e74a12625bcda6f4 LTC (retest): LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 196360 W: 52514 L: 52475 D: 91371 Ptnml(0-2): 103, 19066, 59780, 19151, 80 https://tests.stockfishchess.org/tests/view/63f934bfe74a12625bcdd929 closes https://github.com/official-stockfish/Stockfish/pull/4407 Bench: 5310866 --- src/search.cpp | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index a41ea4fd..6ccc70cc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -334,7 +334,7 @@ void Thread::search() { pvLast = 0; if (!Threads.increaseDepth) - searchAgainCounter++; + searchAgainCounter++; // MultiPV loop. We perform a full root search for each PV line for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx) @@ -432,9 +432,10 @@ void Thread::search() { if (!Threads.stop) completedDepth = rootDepth; - if (rootMoves[0].pv[0] != lastBestMove) { - lastBestMove = rootMoves[0].pv[0]; - lastBestMoveDepth = rootDepth; + if (rootMoves[0].pv[0] != lastBestMove) + { + lastBestMove = rootMoves[0].pv[0]; + lastBestMoveDepth = rootDepth; } // Have we found a "mate in x"? @@ -729,7 +730,8 @@ namespace { complexity = 0; goto moves_loop; } - else if (excludedMove) { + else if (excludedMove) + { // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 elo) Eval::NNUE::hint_common_parent_position(pos); eval = ss->staticEval; @@ -755,6 +757,7 @@ namespace { // Save static evaluation into transposition table tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } + thisThread->complexityAverage.update(complexity); // Use static evaluation difference to improve quiet move ordering (~4 Elo) @@ -920,11 +923,9 @@ moves_loop: // When in check, search starts here && tte->depth() >= depth - 3 && ttValue >= probCutBeta && abs(ttValue) <= VALUE_KNOWN_WIN - && abs(beta) <= VALUE_KNOWN_WIN - ) + && abs(beta) <= VALUE_KNOWN_WIN) return probCutBeta; - const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, nullptr , (ss-4)->continuationHistory, nullptr , (ss-6)->continuationHistory }; @@ -1099,8 +1100,8 @@ moves_loop: // When in check, search starts here else if (ttValue >= beta) extension = -2; - // If the eval of ttMove is less than alpha and value, we reduce it (negative extension) - else if (ttValue <= alpha && ttValue <= value) + // If the eval of ttMove is less than value, we reduce it (negative extension) + else if (ttValue <= value) extension = -1; } @@ -1227,11 +1228,11 @@ moves_loop: // When in check, search starts here // Step 18. Full depth search when LMR is skipped. If expected reduction is high, reduce its depth by 1. else if (!PvNode || moveCount > 1) { - // Increase reduction for cut nodes and not ttMove (~1 Elo) - if (!ttMove && cutNode) - r += 2; + // Increase reduction for cut nodes and not ttMove (~1 Elo) + if (!ttMove && cutNode) + r += 2; - value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode); + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode); } // For PV nodes only, do a full PV search on the first move or after a fail @@ -1271,14 +1272,17 @@ moves_loop: // When in check, search starts here rm.selDepth = thisThread->selDepth; rm.scoreLowerbound = rm.scoreUpperbound = false; - if (value >= beta) { - rm.scoreLowerbound = true; - rm.uciScore = beta; + if (value >= beta) + { + rm.scoreLowerbound = true; + rm.uciScore = beta; } - else if (value <= alpha) { - rm.scoreUpperbound = true; - rm.uciScore = alpha; + else if (value <= alpha) + { + rm.scoreUpperbound = true; + rm.uciScore = alpha; } + rm.pv.resize(1); assert((ss+1)->pv); @@ -1447,7 +1451,8 @@ moves_loop: // When in check, search starts here // TT entry depth that we are going to use. Note that in qsearch we use // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS. ttDepth = ss->inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS - : DEPTH_QS_NO_CHECKS; + : DEPTH_QS_NO_CHECKS; + // Step 3. Transposition table lookup posKey = pos.key(); tte = TT.probe(posKey, ss->ttHit); @@ -1577,7 +1582,6 @@ moves_loop: // When in check, search starts here // Do not search moves with bad enough SEE values (~5 Elo) if (!pos.see_ge(move, Value(-110))) continue; - } // Speculative prefetch as early as possible From 728b963614a765f5cb64c44a078169cca977750f Mon Sep 17 00:00:00 2001 From: pb00067 Date: Sun, 26 Feb 2023 09:59:35 +0100 Subject: [PATCH 078/192] Use common_parent_position hint also at PVNodes TT hits. Credits to Stefan Geschwentner (locutus2) showing that the hint is useful on PvNodes. In contrast to his test, this version avoids to use the hint when in check. I believe checking positions aren't good candidates for the hint because: - evasion moves are rather few, so a checking pos. has much less childs than a normal position - if the king has to move the NNUE eval can't use incremental updates, so the child nodes have to do a full refresh anyway. Passed STC: https://tests.stockfishchess.org/tests/view/63f9c5b1e74a12625bcdf585 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 124472 W: 33268 L: 32846 D: 58358 Ptnml(0-2): 350, 12986, 35170, 13352, 378 closes https://github.com/official-stockfish/Stockfish/pull/4410 no functional change --- src/search.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 6ccc70cc..206779ed 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -744,7 +744,11 @@ namespace { if (eval == VALUE_NONE) ss->staticEval = eval = evaluate(pos, &complexity); else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost + { complexity = abs(ss->staticEval - pos.psq_eg_stm()); + if (PvNode) + Eval::NNUE::hint_common_parent_position(pos); + } // ttValue can be used as a better position evaluation (~7 Elo) if ( ttValue != VALUE_NONE From ff5a6f8df196d61a0d9b1ebe54d84eeb9af20079 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Sun, 26 Feb 2023 09:56:54 +0100 Subject: [PATCH 079/192] NNUE accumulator update in probcut. Call the recently added hint function for NNUE accumulator update after a failed probcut search. In this case we already searched at least some captures and tt move which, however, is not sufficient for a cutoff. So it seems we have a greater chance that the full search will also have no cutoff and hence all moves have to be searched. STC: https://tests.stockfishchess.org/tests/view/63fa74a4e74a12625bce1823 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 70096 W: 18770 L: 18423 D: 32903 Ptnml(0-2): 191, 7342, 19654, 7651, 210 To be sure that we have no heavy interaction retest on top of #4410. Rebased STC: https://tests.stockfishchess.org/tests/view/63fb2f62e74a12625bce3b03 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 137688 W: 36790 L: 36349 D: 64549 Ptnml(0-2): 397, 14373, 38919, 14702, 453 closes https://github.com/official-stockfish/Stockfish/pull/4411 No functional change --- src/search.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 206779ed..cfb569b9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -899,6 +899,8 @@ namespace { return value; } } + + Eval::NNUE::hint_common_parent_position(pos); } // Step 11. If the position is not in TT, decrease depth by 3. From 564456a6a824bfca26d6d9af5b35a055eb9fc6c2 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sun, 26 Feb 2023 19:42:31 +0100 Subject: [PATCH 080/192] Unify type alias declarations The commit unifies the declaration of type aliases by replacing all typedefs with corresponding using statements. closing https://github.com/official-stockfish/Stockfish/pull/4412 No functional change --- src/material.h | 2 +- src/misc.cpp | 12 ++++++------ src/misc.h | 4 ++-- src/movepick.h | 14 +++++++------- src/nnue/nnue_feature_transformer.h | 20 ++++++++++---------- src/pawns.h | 2 +- src/position.h | 2 +- src/search.h | 2 +- src/syzygy/tbprobe.cpp | 4 ++-- src/tune.h | 6 +++--- src/types.h | 6 +++--- src/uci.h | 4 ++-- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/material.h b/src/material.h index 73c83100..9acf78f5 100644 --- a/src/material.h +++ b/src/material.h @@ -62,7 +62,7 @@ struct Entry { uint8_t factor[COLOR_NB]; }; -typedef HashTable Table; +using Table = HashTable; Entry* probe(const Position& pos); diff --git a/src/misc.cpp b/src/misc.cpp index e65faab9..c22126af 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -32,12 +32,12 @@ // the calls at compile time), try to load them at runtime. To do this we need // first to define the corresponding function pointers. extern "C" { -typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP, - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); -typedef bool(*fun2_t)(USHORT, 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)(); +using fun1_t = bool(*)(LOGICAL_PROCESSOR_RELATIONSHIP, + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); +using fun2_t = bool(*)(USHORT, PGROUP_AFFINITY); +using fun3_t = bool(*)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY); +using fun4_t = bool(*)(USHORT, PGROUP_AFFINITY, USHORT, PUSHORT); +using fun5_t = WORD(*)(); } #endif diff --git a/src/misc.h b/src/misc.h index 9761da8a..c20a816e 100644 --- a/src/misc.h +++ b/src/misc.h @@ -45,7 +45,7 @@ void dbg_stdev_of(int64_t value, int slot = 0); void dbg_correl_of(int64_t value1, int64_t value2, int slot = 0); void dbg_print(); -typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds +using TimePoint = std::chrono::milliseconds::rep; // A value in milliseconds static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits"); inline TimePoint now() { return std::chrono::duration_cast @@ -165,7 +165,7 @@ public: inline uint64_t mul_hi64(uint64_t a, uint64_t b) { #if defined(__GNUC__) && defined(IS_64BIT) - __extension__ typedef unsigned __int128 uint128; + __extension__ using uint128 = unsigned __int128; return ((uint128)a * (uint128)b) >> 64; #else uint64_t aL = (uint32_t)a, aH = a >> 32; diff --git a/src/movepick.h b/src/movepick.h index 90f60b8a..b6c07378 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -62,14 +62,14 @@ public: template struct Stats : public std::array, Size> { - typedef Stats stats; + using stats = Stats; void fill(const T& v) { // For standard-layout 'this' points to first struct member assert(std::is_standard_layout::value); - typedef StatsEntry entry; + using entry = StatsEntry; entry* p = reinterpret_cast(this); std::fill(p, p + sizeof(*this) / sizeof(entry), v); } @@ -87,23 +87,23 @@ enum StatsType { NoCaptures, Captures }; /// 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 /// (~11 elo) -typedef Stats ButterflyHistory; +using ButterflyHistory = Stats; /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous /// move, see www.chessprogramming.org/Countermove_Heuristic -typedef Stats CounterMoveHistory; +using CounterMoveHistory = Stats; /// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type] -typedef Stats CapturePieceToHistory; +using CapturePieceToHistory = Stats; /// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to] -typedef Stats PieceToHistory; +using PieceToHistory = Stats; /// ContinuationHistory is the combined history of a given pair of moves, usually /// the current one given a previous one. The nested history table is based on /// PieceToHistory instead of ButterflyBoards. /// (~63 elo) -typedef Stats ContinuationHistory; +using ContinuationHistory = Stats; /// MovePicker class is used to pick one pseudo-legal move at a time from the diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index b0d5743e..8087ea55 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -42,8 +42,8 @@ namespace Stockfish::Eval::NNUE { "Per feature PSQT values cannot be processed at granularity lower than 8 at a time."); #ifdef USE_AVX512 - typedef __m512i vec_t; - typedef __m256i psqt_vec_t; + using vec_t = __m512i; + using psqt_vec_t = __m256i; #define vec_load(a) _mm512_load_si512(a) #define vec_store(a,b) _mm512_store_si512(a,b) #define vec_add_16(a,b) _mm512_add_epi16(a,b) @@ -66,8 +66,8 @@ namespace Stockfish::Eval::NNUE { #define MaxChunkSize 64 #elif USE_AVX2 - typedef __m256i vec_t; - typedef __m256i psqt_vec_t; + using vec_t = __m256i; + using psqt_vec_t = __m256i; #define vec_load(a) _mm256_load_si256(a) #define vec_store(a,b) _mm256_store_si256(a,b) #define vec_add_16(a,b) _mm256_add_epi16(a,b) @@ -90,8 +90,8 @@ namespace Stockfish::Eval::NNUE { #define MaxChunkSize 32 #elif USE_SSE2 - typedef __m128i vec_t; - typedef __m128i psqt_vec_t; + using vec_t = __m128i; + using psqt_vec_t = __m128i; #define vec_load(a) (*(a)) #define vec_store(a,b) *(a)=(b) #define vec_add_16(a,b) _mm_add_epi16(a,b) @@ -111,8 +111,8 @@ namespace Stockfish::Eval::NNUE { #define MaxChunkSize 16 #elif USE_MMX - typedef __m64 vec_t; - typedef __m64 psqt_vec_t; + using vec_t = __m64; + using psqt_vec_t = __m64; #define vec_load(a) (*(a)) #define vec_store(a,b) *(a)=(b) #define vec_add_16(a,b) _mm_add_pi16(a,b) @@ -139,8 +139,8 @@ namespace Stockfish::Eval::NNUE { #define MaxChunkSize 8 #elif USE_NEON - typedef int16x8_t vec_t; - typedef int32x4_t psqt_vec_t; + using vec_t = int16x8_t; + using psqt_vec_t = int32x4_t; #define vec_load(a) (*(a)) #define vec_store(a,b) *(a)=(b) #define vec_add_16(a,b) vaddq_s16(a,b) diff --git a/src/pawns.h b/src/pawns.h index 95c9ea3c..d20e7c2e 100644 --- a/src/pawns.h +++ b/src/pawns.h @@ -61,7 +61,7 @@ struct Entry { int blockedCount; }; -typedef HashTable Table; +using Table = HashTable; Entry* probe(const Position& pos); diff --git a/src/position.h b/src/position.h index 3de24f22..c82c7a8b 100644 --- a/src/position.h +++ b/src/position.h @@ -68,7 +68,7 @@ struct StateInfo { /// start position to the position just before the search starts). Needed by /// 'draw by repetition' detection. Use a std::deque because pointers to /// elements are not invalidated upon list resizing. -typedef std::unique_ptr> StateListPtr; +using StateListPtr = std::unique_ptr>; /// Position class stores information regarding the board representation as diff --git a/src/search.h b/src/search.h index 48a0f7ce..806e4be6 100644 --- a/src/search.h +++ b/src/search.h @@ -80,7 +80,7 @@ struct RootMove { std::vector pv; }; -typedef std::vector RootMoves; +using RootMoves = std::vector; /// LimitsType struct stores information sent by GUI about available time to diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index bbfd819d..b594ac37 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -142,7 +142,7 @@ struct SparseEntry { static_assert(sizeof(SparseEntry) == 6, "SparseEntry must be 6 bytes"); -typedef uint16_t Sym; // Huffman symbol +using Sym = uint16_t; // Huffman symbol struct LR { enum Side { Left, Right }; @@ -327,7 +327,7 @@ struct PairsData { // first access, when the corresponding file is memory mapped. template struct TBTable { - typedef typename std::conditional::type Ret; + using Ret = typename std::conditional::type; static constexpr int Sides = Type == WDL ? 2 : 1; diff --git a/src/tune.h b/src/tune.h index f5b787af..440d950a 100644 --- a/src/tune.h +++ b/src/tune.h @@ -26,8 +26,8 @@ namespace Stockfish { -typedef std::pair Range; // Option's min-max values -typedef Range (RangeFun) (int); +using Range = std::pair; // Option's min-max values +using RangeFun = Range (int); // Default Range function, to calculate Option's min-max values inline Range default_range(int v) { @@ -75,7 +75,7 @@ struct SetRange { class Tune { - typedef void (PostUpdate) (); // Post-update function + using PostUpdate = void (); // Post-update function Tune() { read_results(); } Tune(const Tune&) = delete; diff --git a/src/types.h b/src/types.h index 8a021342..37ce343a 100644 --- a/src/types.h +++ b/src/types.h @@ -103,8 +103,8 @@ constexpr bool Is64Bit = true; constexpr bool Is64Bit = false; #endif -typedef uint64_t Key; -typedef uint64_t Bitboard; +using Key = uint64_t; +using Bitboard = uint64_t; constexpr int MAX_MOVES = 256; constexpr int MAX_PLY = 246; @@ -218,7 +218,7 @@ constexpr Value PieceValue[PHASE_NB][PIECE_NB] = { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, VALUE_ZERO, VALUE_ZERO } }; -typedef int Depth; +using Depth = int; enum : int { DEPTH_QS_CHECKS = 0, diff --git a/src/uci.h b/src/uci.h index 5d8ccf1a..70e45acc 100644 --- a/src/uci.h +++ b/src/uci.h @@ -45,12 +45,12 @@ struct CaseInsensitiveLess { }; /// The options container is defined as a std::map -typedef std::map OptionsMap; +using OptionsMap = std::map; /// The Option class implements each option as specified by the UCI protocol class Option { - typedef void (*OnChange)(const Option&); + using OnChange = void (*)(const Option&); public: Option(OnChange = nullptr); From 6adbc6fa05bbd2a574a8c4c6a6ef2307280217ab Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 22 Feb 2023 05:45:43 -0600 Subject: [PATCH 081/192] Late counter bonus: boost underestimated moves The idea here is very intuitive: since we've just proven that the move is good, then if it previously had poor stats, boost those stats more than otherwise. Passed STC: https://tests.stockfishchess.org/tests/view/63fb504ce74a12625bce4154 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 21128 W: 5763 L: 5481 D: 9884 Ptnml(0-2): 52, 2212, 5759, 2484, 57 Passed LTC: https://tests.stockfishchess.org/tests/view/63fb7825e74a12625bce491b LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 91904 W: 24764 L: 24359 D: 42781 Ptnml(0-2): 45, 8735, 27984, 9146, 42 closes https://github.com/official-stockfish/Stockfish/pull/4415 bench 4318808 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index cfb569b9..6585f7bc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1383,8 +1383,7 @@ moves_loop: // When in check, search starts here // Bonus for prior countermove that caused the fail low else if (!priorCapture) { - // Extra bonuses for PV/Cut nodes or bad fail lows - int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth); + int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth) + ((ss-1)->moveCount > 10); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } From 876906965b8d552866486c0e6eda1184fdb1d636 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Fri, 24 Feb 2023 09:16:55 -0500 Subject: [PATCH 082/192] Update default net to nn-52471d67216a.nnue Created by retraining the master net with modifications to the previous best dataset: * Improving T80 oct+nov 2022 endgame lambda accuracy by rescoring with 12-16tb of syzygy 7p tablebases * Filtering T78 jun+jul+aug 2022 with d6pv2 search to remove positions with bestmove captures or one good move * Adding T80 sep 2022 data, rescored with 16tb of 7p tablebases, unfiltered Trained with max-epoch 900, end-lambda 0.7, and early-fen-skipping 28. ``` python3 easy_train.py \ --experiment-name leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p-lambda7-sk28 \ --training-dataset /data/leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/easy-train-early-fen-skipping \ --early-fen-skipping 28 \ --start-from-engine-test-net True \ --gpus "0," \ --max_epoch 900 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --gamma 0.995 \ --lr 4.375e-4 \ --tui False \ --seed $RANDOM ``` Training data was rescored and d6pv2 filtered in the same way as recent best datasets. For preparing the merged training dataset: ``` python3 interleave_binpacks.py \ leela96-eval-filt-v2.binpack \ dfrc99-eval-filt-v2.binpack \ test80-oct2022-16tb7p-eval-filt-v2-d6.binpack \ test80-nov2022-12tb7p-eval-filt-v2-d6.binpack \ T79-apr2022-12tb7p-eval-filt-v2.binpack \ T79-may2022-12tb7p-eval-filt-v2.binpack \ test78-junjulaug2022-16tb7p-eval-filt-v2-d6.binpack \ T60-nov2021-12tb7p-eval-filt-v2.binpack \ T60-dec2021-12tb7p-eval-filt-v2.binpack \ T78-sep2022-12tb7p.binpack \ test77-dec2021-16gb7p.binpack \ test80-sep2022-16tb7p.binpack \ /data/leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p.binpack ``` Links for downloading the training data components can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move: nn-epoch839.nnue : 0.6 +/- 1.4 Passed STC: https://tests.stockfishchess.org/tests/view/63f9ab4be74a12625bcdf02e LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 84656 W: 22681 L: 22302 D: 39673 Ptnml(0-2): 271, 9343, 22734, 9696, 284 Passed LTC: https://tests.stockfishchess.org/tests/view/63fa3833e74a12625bce0c0e LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 184664 W: 49933 L: 49344 D: 85387 Ptnml(0-2): 111, 17977, 55561, 18578, 105 closes https://github.com/official-stockfish/Stockfish/pull/4416 bench: 4814343 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 46f20259..5238cb81 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-1337b1adec5b.nnue" + #define EvalFileDefaultName "nn-52471d67216a.nnue" namespace NNUE { From 5c75c1c2fbb7bb4f0bf7c44fb855c415b788cbf7 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 24 Feb 2023 12:09:45 +0300 Subject: [PATCH 083/192] Fix duplicated moves generation in movepicker in a some of cases movepicker returned some moves more than once which lead to them being searched more than once. This bug was possible because of how we use queen promotions - they are generated as a captures but are not included in position function which checks if move is a capture. Thus if any refutation (killer or countermove) was a queen promotion it was searched twice - once as a capture and one as a refutation. This patch affects various things, namely stats assignments for queen promotions and other moves if best move is queen promotion, also some heuristics in search and qsearch. With this patch every queen promotion is now considered a capture. After this patch number of found duplicated moves is 0 during normal 13 depth bench run. Passed STC: https://tests.stockfishchess.org/tests/view/63f77e01e74a12625bcd87d7 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 80920 W: 21455 L: 21289 D: 38176 Ptnml(0-2): 198, 8839, 22241, 8963, 219 Passed LTC: https://tests.stockfishchess.org/tests/view/63f7e020e74a12625bcd9a76 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 89712 W: 23674 L: 23533 D: 42505 Ptnml(0-2): 24, 8737, 27202, 8860, 33 closes https://github.com/official-stockfish/Stockfish/pull/4405 bench 4681731 --- src/movepick.cpp | 6 +++--- src/position.h | 12 ++++++++---- src/search.cpp | 12 ++++++------ src/syzygy/tbprobe.cpp | 4 ++-- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 65155a73..36ee46b5 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -93,7 +93,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePiece { assert(!pos.checkers()); - stage = PROBCUT_TT + !(ttm && pos.capture(ttm) + stage = PROBCUT_TT + !(ttm && pos.capture_stage(ttm) && pos.pseudo_legal(ttm) && pos.see_ge(ttm, threshold)); } @@ -141,7 +141,7 @@ void MovePicker::score() { + bool(pos.check_squares(type_of(pos.moved_piece(m))) & to_sq(m)) * 16384; else // Type == EVASIONS { - if (pos.capture(m)) + if (pos.capture_stage(m)) m.value = PieceValue[MG][pos.piece_on(to_sq(m))] - Value(type_of(pos.moved_piece(m))) + (1 << 28); @@ -216,7 +216,7 @@ top: case REFUTATION: if (select([&](){ return *cur != MOVE_NONE - && !pos.capture(*cur) + && !pos.capture_stage(*cur) && pos.pseudo_legal(*cur); })) return *(cur - 1); ++stage; diff --git a/src/position.h b/src/position.h index c82c7a8b..485540ef 100644 --- a/src/position.h +++ b/src/position.h @@ -125,7 +125,7 @@ public: // Properties of moves bool legal(Move m) const; bool pseudo_legal(const Move m) const; - bool capture(Move m) const; + bool capture_stage(Move m) const; bool gives_check(Move m) const; Piece moved_piece(Move m) const; Piece captured_piece() const; @@ -381,10 +381,14 @@ inline bool Position::is_chess960() const { return chess960; } -inline bool Position::capture(Move m) const { +// returns true if a move is generated from the capture stage +// having also queen promotions covered, i.e. consistency with the capture stage move generation +// is needed to avoid the generation of duplicate moves. +inline bool Position::capture_stage(Move m) const { assert(is_ok(m)); - // Castling is encoded as "king captures rook" - return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == EN_PASSANT; + return (!empty(to_sq(m)) && type_of(m) != CASTLING) + || (type_of(m) == PROMOTION && promotion_type(m) == QUEEN) + || type_of(m) == EN_PASSANT; } inline Piece Position::captured_piece() const { diff --git a/src/search.cpp b/src/search.cpp index 6585f7bc..fcdb8d67 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -623,7 +623,7 @@ namespace { ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0] : ss->ttHit ? tte->move() : MOVE_NONE; - ttCapture = ttMove && pos.capture(ttMove); + ttCapture = ttMove && pos.capture_stage(ttMove); // At this point, if excluded, skip straight to step 6, static eval. However, // to save indentation, we list the condition in all code between here and there. @@ -852,7 +852,7 @@ namespace { probCutBeta = beta + 186 - 54 * improving; // Step 10. ProbCut (~10 Elo) - // If we have a good enough capture and a reduced search returns a value + // If we have a good enough capture (or queen promotion) and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode && depth > 4 @@ -873,7 +873,7 @@ namespace { while ((move = mp.next_move()) != MOVE_NONE) if (move != excludedMove && pos.legal(move)) { - assert(pos.capture(move) || promotion_type(move) == QUEEN); + assert(pos.capture_stage(move)); ss->currentMove = move; ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] @@ -985,7 +985,7 @@ moves_loop: // When in check, search starts here (ss+1)->pv = nullptr; extension = 0; - capture = pos.capture(move); + capture = pos.capture_stage(move); movedPiece = pos.moved_piece(move); givesCheck = pos.gives_check(move); @@ -1542,7 +1542,7 @@ moves_loop: // When in check, search starts here continue; givesCheck = pos.gives_check(move); - capture = pos.capture(move); + capture = pos.capture_stage(move); moveCount++; @@ -1715,7 +1715,7 @@ moves_loop: // When in check, search starts here PieceType captured = type_of(pos.piece_on(to_sq(bestMove))); int bonus1 = stat_bonus(depth + 1); - if (!pos.capture(bestMove)) + if (!pos.capture_stage(bestMove)) { int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus : stat_bonus(depth); // smaller bonus diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index b594ac37..2a9e1b68 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1203,7 +1203,7 @@ WDLScore search(Position& pos, ProbeState* result) { for (const Move move : moveList) { - if ( !pos.capture(move) + if ( !pos.capture_stage(move) && (!CheckZeroingMoves || type_of(pos.moved_piece(move)) != PAWN)) continue; @@ -1472,7 +1472,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) { for (const Move move : MoveList(pos)) { - bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN; + bool zeroing = pos.capture_stage(move) || type_of(pos.moved_piece(move)) == PAWN; pos.do_move(move, st); From 5c589142ae5714ecb9ded29bec12c591a1ba8f3f Mon Sep 17 00:00:00 2001 From: disservin Date: Sat, 4 Mar 2023 16:34:34 +0100 Subject: [PATCH 084/192] Add wiki to artifacts snapshot the wiki https://github.com/official-stockfish/stockfish/wiki as part of the artifacts generated. This will allow future release to include the wiki pages as a form of documentation closes https://github.com/official-stockfish/Stockfish/pull/4420 No functional change --- .github/workflows/stockfish_arm_binaries.yml | 7 +++++++ .github/workflows/stockfish_binaries.yml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml index a1b3cdab..e088c441 100644 --- a/.github/workflows/stockfish_arm_binaries.yml +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -99,10 +99,17 @@ jobs: - name: Remove non src files run: rm -f *.o .depend *.nnue + - name: Download wiki + run: | + git clone https://github.com/official-stockfish/Stockfish.wiki.git ../wiki + cd ../wiki + rm -rf .git + - name: Create tar archive. run: | cd .. mkdir stockfish + cp -r wiki stockfish/ cp -r src stockfish/ cp stockfish-android-$BINARY$EXT stockfish/ cp "Top CPU Contributors.txt" stockfish/ diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 06b13a9e..b22897cf 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -83,10 +83,17 @@ jobs: - name: Remove non src files run: rm -f *.o .depend *.nnue + - name: Download wiki + run: | + git clone https://github.com/official-stockfish/Stockfish.wiki.git ../wiki + cd ../wiki + rm -rf .git + - name: Create tar archive. run: | cd .. mkdir stockfish + cp -r wiki stockfish/ cp -r src stockfish/ cp stockfish-$OS-$BINARY$EXT stockfish/ cp "Top CPU Contributors.txt" stockfish/ From 3a634f5282700484445c0f66b21b35e96fcb947b Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:24:35 +0100 Subject: [PATCH 085/192] Update README.md Update and simplify the readme, removing duplicated and outdated stuff and pointing to the new wiki closes https://github.com/official-stockfish/Stockfish/pull/4421 No functional change --- README.md | 376 ++++++++++++------------------------------------------ 1 file changed, 81 insertions(+), 295 deletions(-) diff --git a/README.md b/README.md index ca90d5d4..1f462d31 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,21 @@ [![Stockfish][stockfish128-logo]][website-link] +

Stockfish

+ + A free and strong UCI chess engine. +
+ [Explore Stockfish docs »][wiki-link] +
+
+ [Report bug][issue-link] + · + [Open a discussion][discussions-link] + · + [Discord][discord-link] + · + [Blog][website-blog-link] + [![Build][build-badge]][build-link] [![License][license-badge]][license-link]
@@ -16,19 +31,16 @@ ## Overview -[Stockfish][website-link] is a free, powerful UCI chess engine derived from -Glaurung 2.1. Stockfish is not a complete chess program and requires a UCI-compatible -graphical user interface (GUI) (e.g. XBoard with PolyGlot, Scid, Cute Chess, eboard, -Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in order to be used comfortably. -Read the documentation for your GUI of choice for information about how to use +[Stockfish][website-link] is a **free and strong UCI chess engine** derived from +Glaurung 2.1 that analyzes chess positions and computes the optimal moves. + +Stockfish **does not include a graphical user interface** (GUI) that is required +to display a chessboard and to make it easy to input moves. These GUIs are +developed independently from Stockfish and are available online. **Read the +documentation for your GUI** of choice for information about how to use Stockfish with it. -The Stockfish engine features two evaluation functions for chess. The efficiently -updatable neural network (NNUE) based evaluation is the default and by far the strongest. -The classical evaluation based on handcrafted terms remains available. The strongest -network is integrated in the binary and downloaded automatically during the build process. -The NNUE evaluation benefits from the vector intrinsics available on most CPUs (sse2, -avx2, neon, or similar). +See also the Stockfish [documentation][wiki-usage-link] for further usage help. ## Files @@ -36,338 +48,112 @@ This distribution of Stockfish consists of the following files: * [README.md][readme-link], the file you are currently reading. - * [Copying.txt][license-link], a text file containing the GNU General Public License - version 3. + * [Copying.txt][license-link], a text file containing the GNU General Public + License version 3. * [AUTHORS][authors-link], a text file with the list of authors for the project. - * [src][src-link], a subdirectory containing the full source code, including a Makefile - that can be used to compile Stockfish on Unix-like systems. + * [src][src-link], a subdirectory containing the full source code, including a + Makefile that can be used to compile Stockfish on Unix-like systems. - * a file with the .nnue extension, storing the neural network for the NNUE evaluation. - Binary distributions will have this file embedded. + * a file with the .nnue extension, storing the neural network for the NNUE + evaluation. Binary distributions will have this file embedded. -## The UCI protocol and available options +## The UCI protocol -The Universal Chess Interface (UCI) is a standard protocol used to communicate with -a chess engine, and is the recommended way to do so for typical graphical user interfaces -(GUI) or chess tools. Stockfish implements the majority of its options as described -in [the UCI protocol][uci-link]. +The [Universal Chess Interface][uci-link] (UCI) is a standard text-based protocol +used to communicate with a chess engine and is the recommended way to do so for +typical graphical user interfaces (GUI) or chess tools. Stockfish implements the +majority of its options. -Developers can see the default values for UCI options available in Stockfish by typing -`./stockfish uci` in a terminal, but the majority of users will typically see them and -change them via a chess GUI. This is a list of available UCI options in Stockfish: +Developers can see the default values for the UCI options available in Stockfish +by typing `./stockfish uci` in a terminal, but most users should typically use a +chess GUI to interact with Stockfish. - * #### Threads - The number of CPU threads used for searching a position. For best performance, set - this equal to the number of CPU cores available. +For more information on UCI or debug commands, see our [documentation][wiki-commands-link]. - * #### Hash - The size of the hash table in MB. It is recommended to set Hash after setting Threads. +## Compiling Stockfish - * #### Clear Hash - Clear the hash table. +Stockfish has support for 32 or 64-bit CPUs, certain hardware instructions, +big-endian machines such as Power PC, and other platforms. - * #### Ponder - Let Stockfish ponder its next move while the opponent is thinking. - - * #### MultiPV - Output the N best lines (principal variations, PVs) when searching. - Leave at 1 for best performance. - - * #### Use NNUE - Toggle between the NNUE and classical evaluation functions. If set to "true", - the network parameters must be available to load from file (see also EvalFile), - if they are not embedded in the binary. - - * #### EvalFile - 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. Other locations, such as the directory that contains the binary and the - working directory, are also searched. - - * #### UCI_AnalyseMode - An option handled by your GUI. - - * #### UCI_Chess960 - An option handled by your GUI. If true, Stockfish will play Chess960. - - * #### UCI_ShowWDL - If enabled, show approximate WDL statistics as part of the engine output. - These WDL numbers model expected game outcomes for a given evaluation and - game ply for engine self-play at fishtest LTC conditions (60+0.6s per game). - - * #### UCI_LimitStrength - Enable weaker play aiming for an Elo rating as set by UCI_Elo. This option overrides Skill Level. - - * #### UCI_Elo - If enabled by UCI_LimitStrength, aim for an engine strength of the given Elo. - This Elo rating has been calibrated at a time control of 120s+1.0s and anchored to +- 100 Elo to CCRL Blitz. - - * #### Skill Level - Lower the Skill Level in order to make Stockfish play weaker (see also UCI_LimitStrength). - Internally, MultiPV is enabled, and with a certain probability depending on the Skill Level a - weaker move will be played. - - * #### SyzygyPath - Path to the folders/directories storing the Syzygy tablebase files. Multiple - directories are to be separated by ";" on Windows and by ":" on Unix-based - operating systems. Do not use spaces around the ";" or ":". - - 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 - 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 - lead to engine crashes. - - * #### SyzygyProbeDepth - Minimum remaining search depth for which a position is probed. Set this option - to a higher value to probe less aggressively if you experience too much slowdown - (in terms of nps) due to tablebase probing. - - * #### Syzygy50MoveRule - Disable to let fifty-move rule draws detected by Syzygy tablebase probes count - as wins or losses. This is useful for ICCF correspondence games. - - * #### SyzygyProbeLimit - Limit Syzygy tablebase probing to positions with at most this many pieces left - (including kings and pawns). - - * #### Move Overhead - Assume a time delay of x ms due to network and GUI overheads. This is useful to - avoid losses on time in those cases. - - * #### Slow Mover - Lower values will make Stockfish take less time in games, higher values will - make it think longer. - - * #### nodestime - Tells the engine to use nodes searched instead of wall time to account for - elapsed time. Useful for engine testing. - - * #### Debug Log File - Write all communication to and from the engine into a text file. - -For developers the following non-standard commands might be of interest, mainly useful for debugging: - - * #### bench *ttSize threads limit fenFile limitType evalType* - Performs a standard benchmark using various options. The signature of a version - (standard node count) is obtained using all defaults. `bench` is currently - `bench 16 1 13 default depth mixed`. - - * #### compiler - Give information about the compiler and environment used for building a binary. - - * #### d - Display the current position, with ascii art and fen. - - * #### eval - Return the evaluation of the current position. - - * #### export_net [filename] - Exports the currently loaded network to a file. - If the currently loaded network is the embedded network and the filename - is not specified then the network is saved to the file matching the name - of the embedded network, as defined in evaluate.h. - If the currently loaded network is not the embedded network (some net set - through the UCI setoption) then the filename parameter is required and the - network is saved into that file. - - * #### flip - Flips the side to move. - - -## A note on classical evaluation versus NNUE evaluation - -Both approaches assign a value to a position that is used in alpha-beta (PVS) search -to find the best move. The classical evaluation computes this value as a function -of various chess concepts, handcrafted by experts, tested and tuned using fishtest. -The NNUE evaluation computes this value with a neural network based on basic -inputs (e.g. piece positions only). The network is optimized and trained -on the evaluations of millions of positions at moderate search depth. - -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 -of the neural network need to be updated after a typical chess move. -[The nodchip repository][nodchip-link] provided the first version of the needed tools -to train and develop the NNUE networks. Today, more advanced training tools are -available in [the nnue-pytorch repository][pytorch-link], while data generation tools -are available in [a dedicated branch][tools-link]. - -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: - -1) the NNUE evaluation depends on the Stockfish binary and the network parameter file -(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 that is guaranteed to be compatible with that binary. - -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 can -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` -(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from -``` -https://tests.stockfishchess.org/api/nn/[filename] -``` -replacing `[filename]` as needed. - -## What to expect from the Syzygy tablebases? - -If the engine is searching a position that is not in the tablebases (e.g. -a position with 8 pieces), it will access the tablebases during the search. -If the engine reports a very large score (typically 153.xx), this means -it has found a winning line into a tablebase position. - -If the engine is given a position to search that is in the tablebases, it -will use the tablebases at the beginning of the search to preselect all -good moves, i.e. all moves that preserve the win or preserve the draw while -taking into account the 50-move rule. -It will then perform a search only on those moves. **The engine will not move -immediately**, unless there is only a single good move. **The engine likely -will not report a mate score, even if the position is known to be won.** - -It is therefore clear that this behaviour is not identical to what one might -be used to with Nalimov tablebases. There are technical reasons for this -difference, the main technical reason being that Nalimov tablebases use the -DTM metric (distance-to-mate), while the Syzygy tablebases use a variation of the -DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move -counter). This special metric is one of the reasons that the Syzygy tablebases are -more compact than Nalimov tablebases, while still storing all information -needed for optimal play and in addition being able to take into account -the 50-move rule. - -## Large Pages - -Stockfish supports large pages on Linux and Windows. Large pages make -the hash access more efficient, improving the engine speed, especially -on large hash sizes. Typical increases are 5..10% in terms of nodes per -second, but speed increases up to 30% have been measured. The support is -automatic. Stockfish attempts to use large pages when available and -will fall back to regular memory allocation when this is not the case. - -### Support on Linux - -Large page support on Linux is obtained by the Linux kernel -transparent huge pages functionality. Typically, transparent huge pages -are already enabled, and no configuration is needed. - -### Support on Windows - -The use of large pages requires "Lock Pages in Memory" privilege. See -[Enable the Lock Pages in Memory Option (Windows)][lockpages-link] -on how to enable this privilege, then run [RAMMap][rammap-link] -to double-check that large pages are used. We suggest that you reboot -your computer after you have enabled large pages, because long Windows -sessions suffer from memory fragmentation, which may prevent Stockfish -from getting large pages: a fresh session is better in this regard. - -## Compiling Stockfish yourself from the sources - -Stockfish has support for 32 or 64-bit CPUs, certain hardware -instructions, big-endian machines such as Power PC, and other platforms. - -On Unix-like systems, it should be easy to compile Stockfish -directly from the source code with the included Makefile in the folder -`src`. In general it is recommended to run `make help` to see a list of make -targets with corresponding descriptions. +On Unix-like systems, it should be easy to compile Stockfish directly from the +source code with the included Makefile in the folder `src`. In general, it is +recommended to run `make help` to see a list of make targets with corresponding +descriptions. ``` - cd src - make help - make net - make build ARCH=x86-64-modern +cd src +make -j build ARCH=x86-64-modern ``` -When not using the Makefile to compile (for instance, with Microsoft MSVC) you -need to manually set/unset some switches in the compiler command line; see -file *types.h* for a quick reference. +Detailed compilation instructions for all platforms can be found in our +[documentation][wiki-compile-link]. -When reporting an issue or a bug, please tell us which Stockfish version -and which compiler you used to create your executable. This information -can be found by typing the following command in a console: - -``` - ./stockfish compiler -``` - -## Understanding the code base and participating in the project - -Stockfish's improvement over the last decade has been a great community -effort. There are a few ways to help contribute to its growth. +## Contributing ### Donating hardware -Improving Stockfish requires a massive amount of testing. You can donate -your hardware resources by installing the [Fishtest Worker][worker-link] -and view the current tests on [Fishtest][fishtest-link]. +Improving Stockfish requires a massive amount of testing. You can donate your +hardware resources by installing the [Fishtest Worker][worker-link] and viewing +the current tests on [Fishtest][fishtest-link]. ### Improving the code -If you want to help improve the code, there are several valuable resources: - -* [In this wiki,][programming-link] many techniques used in +In the [chessprogramming wiki][programming-link], many techniques used in Stockfish are explained with a lot of background information. +The [section on Stockfish][programmingsf-link] describes many features +and techniques used by Stockfish. However, it is generic rather than +focused on Stockfish's precise implementation. -* [The section on Stockfish][programmingsf-link] -describes many features and techniques used by Stockfish. However, it is -generic rather than being focused on Stockfish's precise implementation. -Nevertheless, a helpful resource. - -* The latest source can always be found on [GitHub][github-link]. -Discussions about Stockfish take place these days mainly in the [FishCooking][fishcooking-link] -group and on the [Stockfish Discord channel][discord-link]. The engine testing is done on [Fishtest][fishtest-link]. If you want to help improve Stockfish, please read this [guideline][guideline-link] first, where the basics of Stockfish development are explained. +Discussions about Stockfish take place these days mainly in the Stockfish +[Discord server][discord-link]. This is also the best place to ask questions +about the codebase and how to improve it. ## Terms of use -Stockfish is free, and distributed under the **GNU General Public License version 3** -(GPL v3). Essentially, this means you are free to do almost exactly -what you want with the program, including distributing it among your -friends, making it available for download from your website, selling -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. +Stockfish is free and distributed under the +[**GNU General Public License version 3**][license-link] (GPL v3). Essentially, +this means you are free to do almost exactly what you want with the program, +including distributing it among your friends, making it available for download +from your website, selling 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. -The only real limitation is that whenever you distribute Stockfish in -some way, you MUST always include the license and the full source code -(or a pointer to where the source code can be found) to generate the -exact binary you are distributing. If you make any changes to the -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 -[*Copying.txt*][license-link]. +The only real limitation is that whenever you distribute Stockfish in some way, +you MUST always include the license and the full source code (or a pointer to +where the source code can be found) to generate the exact binary you are +distributing. If you make any changes to the source code, these changes must +also be made available under GPL v3. [authors-link]: https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS [build-link]: https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml [commits-link]: https://github.com/official-stockfish/Stockfish/commits/master [discord-link]: https://discord.gg/GWDRS3kU6R -[fishcooking-link]: https://groups.google.com/g/fishcooking +[issue-link]: https://github.com/official-stockfish/Stockfish/issues/new?assignees=&labels=&template=BUG-REPORT.yml +[discussions-link]: https://github.com/official-stockfish/Stockfish/discussions/new [fishtest-link]: https://tests.stockfishchess.org/tests -[github-link]: https://github.com/official-stockfish/Stockfish [guideline-link]: https://github.com/glinscott/fishtest/wiki/Creating-my-first-test [license-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt -[lockpages-link]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows -[nodchip-link]: https://github.com/nodchip/Stockfish [programming-link]: https://www.chessprogramming.org/Main_Page [programmingsf-link]: https://www.chessprogramming.org/Stockfish -[pytorch-link]: https://github.com/glinscott/nnue-pytorch -[rammap-link]: https://docs.microsoft.com/en-us/sysinternals/downloads/rammap [readme-link]: https://github.com/official-stockfish/Stockfish/blob/master/README.md [release-link]: https://github.com/official-stockfish/Stockfish/releases/latest [src-link]: https://github.com/official-stockfish/Stockfish/tree/master/src [stockfish128-logo]: https://stockfishchess.org/images/logo/icon_128x128.png -[tools-link]: https://github.com/official-stockfish/Stockfish/tree/tools -[uci-link]: https://www.shredderchess.com/download/div/uci.zip +[uci-link]: https://backscattering.de/chess/uci/ [website-link]: https://stockfishchess.org -[worker-link]: https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview +[website-blog-link]: https://stockfishchess.org/blog/ +[wiki-link]: https://github.com/official-stockfish/Stockfish/wiki +[wiki-usage-link]: https://github.com/official-stockfish/Stockfish/wiki/Download-and-usage +[wiki-compile-link]: https://github.com/official-stockfish/Stockfish/wiki/Compiling-from-source +[wiki-commands-link]: https://github.com/official-stockfish/Stockfish/wiki/Commands +[worker-link]: https://github.com/glinscott/fishtest/wiki/Running-the-worker [build-badge]: https://img.shields.io/github/actions/workflow/status/official-stockfish/Stockfish/stockfish.yml?branch=master&style=for-the-badge&label=stockfish&logo=github [commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge From cdec775a1555ef83cb9c878c42a11b7dde0a627b Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 4 Mar 2023 18:14:23 +0100 Subject: [PATCH 086/192] Add CITATION.cff file Make the stockfish software more easily citable, for example in academic papers. fixes https://github.com/official-stockfish/Stockfish/issues/4419 closes https://github.com/official-stockfish/Stockfish/pull/4422 No functional change --- CITATION.cff | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..bc0889a8 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,23 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: Stockfish +message: >- + Please cite this software using the metadata from this + file. +type: software +authors: + - name: The Stockfish developers (see AUTHORS file) +repository-code: 'https://github.com/official-stockfish/Stockfish' +url: 'https://stockfishchess.org/' +repository-artifact: 'https://stockfishchess.org/download/' +abstract: Stockfish is a free and strong UCI chess engine. +keywords: + - chess + - artificial intelligence (AI) + - tree search + - alpha-beta search + - neural networks (NN) + - efficiently updatable neural networks (NNUE) +license: GPL-3.0 From 70dfa141d560c18cd1aa28884b7cd8ab0f094944 Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Sun, 5 Mar 2023 17:10:52 +0200 Subject: [PATCH 087/192] Clarify the description of the x86-64-vnni256 and x86-64-avxvnni architectures Now it is clearly explained that "x86-64-vnni256" requires full support of AVX512-VNNI, but only 256-bit operands are used. closes https://github.com/official-stockfish/Stockfish/pull/4427 No functional change --- AUTHORS | 1 + src/Makefile | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 634de4a3..49f7009f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -134,6 +134,7 @@ Matt Ginsberg (mattginsberg) Matthew Lai (matthewlai) Matthew Sullivan (Matt14916) Max A. (Disservin) +Maxim Masiutin (maximmasiutin) Maxim Molchanov (Maxim) Michael An (man) Michael Byrne (MichaelB7) diff --git a/src/Makefile b/src/Makefile index 3d6432fd..774ba6ea 100644 --- a/src/Makefile +++ b/src/Makefile @@ -92,7 +92,7 @@ VPATH = syzygy:nnue:nnue/features # 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 -# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256 +# vnni256 = yes/no --- -mavx256vnni --- Use Intel Vector Neural Network Instructions 512 with 256bit operands # vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512 # neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture # dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions @@ -773,10 +773,10 @@ help: @echo "" @echo "Supported archs:" @echo "" - @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-vnni512 > x86 64-bit with vnni 512bit support" + @echo "x86-64-vnni256 > x86 64-bit with vnni 512bit support, limit operands to 256bit wide" @echo "x86-64-avx512 > x86 64-bit with avx512 support" - @echo "x86-64-avxvnni > x86 64-bit with avxvnni support" + @echo "x86-64-avxvnni > x86 64-bit with vnni 256bit support" @echo "x86-64-bmi2 > x86 64-bit with bmi2 support" @echo "x86-64-avx2 > x86 64-bit with avx2 support" @echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support" From 6ce225bb4c31298b131714eff67b56de3b8ee78d Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 5 Mar 2023 17:26:12 +0100 Subject: [PATCH 088/192] Fix TB after capture_stage fix https://github.com/official-stockfish/Stockfish/commit/5c75c1c2fbb7bb4f0bf7c44fb855c415b788cbf7 introduced a capture_stage() function, but TB usage needs a pure capture() function. closes https://github.com/official-stockfish/Stockfish/pull/4428 No functional change. --- src/position.h | 11 ++++++++--- src/syzygy/tbprobe.cpp | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/position.h b/src/position.h index 485540ef..1fc6b3b8 100644 --- a/src/position.h +++ b/src/position.h @@ -125,6 +125,7 @@ public: // Properties of moves bool legal(Move m) const; bool pseudo_legal(const Move m) const; + bool capture(Move m) const; bool capture_stage(Move m) const; bool gives_check(Move m) const; Piece moved_piece(Move m) const; @@ -381,14 +382,18 @@ inline bool Position::is_chess960() const { return chess960; } +inline bool Position::capture(Move m) const { + assert(is_ok(m)); + return (!empty(to_sq(m)) && type_of(m) != CASTLING) + || type_of(m) == EN_PASSANT; +} + // returns true if a move is generated from the capture stage // having also queen promotions covered, i.e. consistency with the capture stage move generation // is needed to avoid the generation of duplicate moves. inline bool Position::capture_stage(Move m) const { assert(is_ok(m)); - return (!empty(to_sq(m)) && type_of(m) != CASTLING) - || (type_of(m) == PROMOTION && promotion_type(m) == QUEEN) - || type_of(m) == EN_PASSANT; + return capture(m) || (type_of(m) == PROMOTION && promotion_type(m) == QUEEN); } inline Piece Position::captured_piece() const { diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 2a9e1b68..b594ac37 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1203,7 +1203,7 @@ WDLScore search(Position& pos, ProbeState* result) { for (const Move move : moveList) { - if ( !pos.capture_stage(move) + if ( !pos.capture(move) && (!CheckZeroingMoves || type_of(pos.moved_piece(move)) != PAWN)) continue; @@ -1472,7 +1472,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) { for (const Move move : MoveList(pos)) { - bool zeroing = pos.capture_stage(move) || type_of(pos.moved_piece(move)) == PAWN; + bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN; pos.do_move(move, st); From 39da50ed23ee3f1bd32a58c8f02471faa9a9fd63 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Tue, 7 Mar 2023 01:54:20 +0300 Subject: [PATCH 089/192] Do more negative extensions This patch does negatively extend transposition table move if singular search failed and tt value is not bigger than alpha. Logic is close to what we had before recent simplification of negative extensions but uses or condition instead of and condition. Passed STC: https://tests.stockfishchess.org/tests/view/6404c8102644b62c33934607 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 119040 W: 31841 L: 31416 D: 55783 Ptnml(0-2): 356, 13070, 32292, 13397, 405 Passed LTC: https://tests.stockfishchess.org/tests/view/6405abda2644b62c33937119 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 47216 W: 12816 L: 12496 D: 21904 Ptnml(0-2): 12, 4500, 14286, 4776, 34 closes https://github.com/official-stockfish/Stockfish/pull/4430 bench 4747020 --- src/search.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index fcdb8d67..349d4389 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1109,6 +1109,10 @@ moves_loop: // When in check, search starts here // If the eval of ttMove is less than value, we reduce it (negative extension) else if (ttValue <= value) extension = -1; + + // If the eval of ttMove is less than alpha, we reduce it (negative extension) + else if (ttValue <= alpha) + extension = -1; } // Check extensions (~1 Elo) From a48573e15fbd18fecb087c9fc02c38a07cece68b Mon Sep 17 00:00:00 2001 From: Dubslow Date: Thu, 9 Mar 2023 18:33:13 -0600 Subject: [PATCH 090/192] More negative extensions on nonsingular nonpv nodes. Following up the previous gainer also in this nonsingular node section of code. Credit shared with @FauziAkram for realizing this nonsingular node stuff had some potential, and @XInTheDark for reminding us that !PvNodes better handle extensions/reductions than Pv. Passed STC: https://tests.stockfishchess.org/tests/view/640a7bb32644b62c339457c3 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 136776 W: 36598 L: 36149 D: 64029 Ptnml(0-2): 439, 14834, 37384, 15301, 430 Passed LTC: https://tests.stockfishchess.org/tests/view/640c43a02644b62c3394b23c LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 79536 W: 21363 L: 20984 D: 37189 Ptnml(0-2): 28, 7525, 24285, 7900, 30 closes https://github.com/official-stockfish/Stockfish/pull/4441 Bench: 4444953 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 349d4389..582e4457 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1104,7 +1104,7 @@ moves_loop: // When in check, search starts here // If the eval of ttMove is greater than beta, we reduce it (negative extension) else if (ttValue >= beta) - extension = -2; + extension = -2 - !PvNode; // If the eval of ttMove is less than value, we reduce it (negative extension) else if (ttValue <= value) From 78532af9dc585a81730d5d28763cc9d5273f96d1 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Mon, 13 Mar 2023 15:57:58 +0300 Subject: [PATCH 091/192] Do more singular extensions This patch continues trend of last VLTC tuning - as measured by dubslow most of it gains was in lowering marging in calculation of singularBeta. This patch is a manual adjustment on top of it - it lowers multiplier of depth in calculation of singularBeta even further, from 2/3 to 1,5/2,5. Was negative at STC: https://tests.stockfishchess.org/tests/view/64089c632644b62c3393fc12 Elo: -2.49 +-1.7 (95%) LOS: 0.2% Total: 40000 W: 10601 L: 10888 D: 18511 Ptnml(0-2): 123, 4580, 10875, 4305, 117 nElo: -5.03 +-3.4 (95%) PairsRatio: 0.94 Passed 180+1.8 SPRT: https://tests.stockfishchess.org/tests/view/640096dae74a12625bcf3b33 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 160952 W: 43753 L: 43342 D: 73857 Ptnml(0-2): 25, 13984, 52039, 14411, 17 Passed 60+0.6 8 threads SPRT: https://tests.stockfishchess.org/tests/view/640dca8e65775d3b539cb7f6 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 38824 W: 10825 L: 10554 D: 17445 Ptnml(0-2): 0, 2939, 13268, 3200, 5 closes https://github.com/official-stockfish/Stockfish/pull/4443 bench 4776866 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 582e4457..7eb4a0c5 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1071,7 +1071,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth; + Value singularBeta = ttValue - (3 + 2 * (ss->ttPv && !PvNode)) * depth / 2; Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; From 55896a1384b022624a8c33b9f7f51b6b551eed50 Mon Sep 17 00:00:00 2001 From: Alfredo Menezes Date: Sun, 12 Mar 2023 22:29:07 -0300 Subject: [PATCH 092/192] Change mode of incbin.h Keep incbin.h with the same mode as the other source files. A mode diff might show up when working with patch files or sending the source code between devices. This patch should fix such behaviour. closes https://github.com/official-stockfish/Stockfish/pull/4442 No functional change --- src/incbin/incbin.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/incbin/incbin.h diff --git a/src/incbin/incbin.h b/src/incbin/incbin.h old mode 100755 new mode 100644 From d1e17989b51f220629e4e81a4bf413974f4b18e2 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Sat, 11 Mar 2023 22:08:35 +0100 Subject: [PATCH 093/192] Fix Makefile for clang 16 The clang 16 release will remove the -fexperimental-new-pass-manager flag (see https://github.com/llvm/llvm-project/commit/69b2b7282e92a1b576b7bd26f3b16716a5027e8e). Thus, the commit adapts the Makefile to use this flag only for older clang versions. closes https://github.com/official-stockfish/Stockfish/pull/4437 No functional change --- src/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 774ba6ea..e257bc63 100644 --- a/src/Makefile +++ b/src/Makefile @@ -584,7 +584,10 @@ ifeq ($(optimize),yes) endif ifeq ($(comp),clang) - CXXFLAGS += -fexperimental-new-pass-manager + clangmajorversion = $(shell $(CXX) -dumpversion 2>/dev/null | cut -f1 -d.) + ifeq ($(shell expr $(clangmajorversion) \< 16),1) + CXXFLAGS += -fexperimental-new-pass-manager + endif endif endif From 7077fbdd1481829a0a20b6975c4245609118b938 Mon Sep 17 00:00:00 2001 From: mstembera Date: Sat, 11 Mar 2023 11:51:08 -0800 Subject: [PATCH 094/192] Remove redundant condition from capture_stage() Change a non functional promotion check to an assert. closes https://github.com/official-stockfish/Stockfish/pull/4436 No functional change --- src/position.cpp | 3 +-- src/position.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 37aa2e9e..632a40b5 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -569,8 +569,7 @@ bool Position::pseudo_legal(const Move m) const { : MoveList(*this).contains(m); // Is not a promotion, so promotion piece must be empty - if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE) - return false; + assert(promotion_type(m) - KNIGHT == NO_PIECE_TYPE); // If the 'from' square is not occupied by a piece belonging to the side to // move, the move is obviously not legal. diff --git a/src/position.h b/src/position.h index 1fc6b3b8..cc606a5a 100644 --- a/src/position.h +++ b/src/position.h @@ -393,7 +393,7 @@ inline bool Position::capture(Move m) const { // is needed to avoid the generation of duplicate moves. inline bool Position::capture_stage(Move m) const { assert(is_ok(m)); - return capture(m) || (type_of(m) == PROMOTION && promotion_type(m) == QUEEN); + return capture(m) || promotion_type(m) == QUEEN; } inline Piece Position::captured_piece() const { From f0556dcbe3ba2fc804ab26d4552446602a75f064 Mon Sep 17 00:00:00 2001 From: pb00067 Date: Wed, 1 Mar 2023 10:29:51 +0100 Subject: [PATCH 095/192] Small cleanups remove some unneeded assignments, typos, incorrect comments, add authors entry. closes https://github.com/official-stockfish/Stockfish/pull/4417 no functional change --- AUTHORS | 1 + src/nnue/nnue_feature_transformer.h | 2 +- src/position.cpp | 3 --- src/search.cpp | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index 49f7009f..9b36111e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -190,6 +190,7 @@ Sergei Antonov (saproj) Sergei Ivanov (svivanov72) Sergio Vieri (sergiovieri) sf-x +Shahin M. Shahin (peregrine) Shane Booth (shane31) Shawn Varghese (xXH4CKST3RXx) Siad Daboul (Topologist) diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 8087ea55..a1888c7a 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -363,7 +363,7 @@ namespace Stockfish::Eval::NNUE { // NOTE: The parameter states_to_update is an array of position states, ending with nullptr. // All states must be sequential, that is states_to_update[i] must either be reachable // by repeatedly applying ->previous from states_to_update[i+1] or states_to_update[i] == nullptr. - // computed_st must be reachable by repeatadly applying ->previous on states_to_update[0], if not nullptr. + // computed_st must be reachable by repeatedly applying ->previous on states_to_update[0], if not nullptr. template void update_accumulator_incremental(const Position& pos, StateInfo* computed_st, StateInfo* states_to_update[N]) const { static_assert(N > 0); diff --git a/src/position.cpp b/src/position.cpp index 632a40b5..aeac23a3 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -765,9 +765,6 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { // Update board and piece lists remove_piece(capsq); - if (type_of(m) == EN_PASSANT) - board[capsq] = NO_PIECE; - // Update material hash key and prefetch access to materialTable k ^= Zobrist::psq[captured][capsq]; st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]]; diff --git a/src/search.cpp b/src/search.cpp index 7eb4a0c5..d6571a14 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -601,7 +601,6 @@ namespace { assert(0 <= ss->ply && ss->ply < MAX_PLY); - (ss+1)->ttPv = false; (ss+1)->excludedMove = bestMove = MOVE_NONE; (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; (ss+2)->cutoffCnt = 0; @@ -1075,7 +1074,6 @@ moves_loop: // When in check, search starts here Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; - // the search with excludedMove will update ss->staticEval value = search(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode); ss->excludedMove = MOVE_NONE; From 515b66f18833ed87e97313d2ec4dfa4e2329d3df Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Sun, 12 Mar 2023 01:22:55 +0300 Subject: [PATCH 096/192] Fix null move issue Fix altering for stats landing on B1 Square after a null move and fix considering counter-moves on A1 for root node. fixes https://github.com/official-stockfish/Stockfish/issues/4333 by preventing calls to from_sq and to_sq functions over null-moves and none-moves. closes https://github.com/official-stockfish/Stockfish/pull/4448 bench: 4980082 --- src/search.cpp | 19 ++++++++++++------- src/types.h | 10 ++++++---- src/uci.cpp | 6 +++--- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index d6571a14..466e0d6f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -605,7 +605,7 @@ namespace { (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; (ss+2)->cutoffCnt = 0; ss->doubleExtensions = (ss-1)->doubleExtensions; - Square prevSq = to_sq((ss-1)->currentMove); + Square prevSq = is_ok((ss-1)->currentMove) ? to_sq((ss-1)->currentMove) : SQ_NONE; // Initialize statScore to zero for the grandchildren of the current position. // So statScore is shared between all grandchildren and only the first grandchild @@ -647,7 +647,7 @@ namespace { update_quiet_stats(pos, ss, ttMove, stat_bonus(depth)); // Extra penalty for early quiet moves of the previous ply (~0 Elo on STC, ~2 Elo on LTC) - if ((ss-1)->moveCount <= 2 && !priorCapture) + if (prevSq != SQ_NONE && (ss-1)->moveCount <= 2 && !priorCapture) update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + 1)); } // Penalty for a quiet ttMove that fails low (~1 Elo) @@ -935,7 +935,7 @@ moves_loop: // When in check, search starts here nullptr , (ss-4)->continuationHistory, nullptr , (ss-6)->continuationHistory }; - Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq]; + Move countermove = prevSq != SQ_NONE ? thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] : MOVE_NONE; MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &captureHistory, @@ -1383,7 +1383,7 @@ moves_loop: // When in check, search starts here quietsSearched, quietCount, capturesSearched, captureCount, depth); // Bonus for prior countermove that caused the fail low - else if (!priorCapture) + else if (!priorCapture && prevSq != SQ_NONE) { int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth) + ((ss-1)->moveCount > 10); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); @@ -1525,7 +1525,7 @@ moves_loop: // When in check, search starts here // to search the moves. Because the depth is <= 0 here, only captures, // queen promotions, and other checks (only if depth >= DEPTH_QS_CHECKS) // will be generated. - Square prevSq = to_sq((ss-1)->currentMove); + Square prevSq = (ss-1)->currentMove != MOVE_NULL ? to_sq((ss-1)->currentMove) : SQ_NONE; MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &thisThread->captureHistory, contHist, @@ -1714,7 +1714,8 @@ moves_loop: // When in check, search starts here Thread* thisThread = pos.this_thread(); CapturePieceToHistory& captureHistory = thisThread->captureHistory; Piece moved_piece = pos.moved_piece(bestMove); - PieceType captured = type_of(pos.piece_on(to_sq(bestMove))); + PieceType captured; + int bonus1 = stat_bonus(depth + 1); if (!pos.capture_stage(bestMove)) @@ -1733,12 +1734,16 @@ moves_loop: // When in check, search starts here } } else + { // Increase stats for the best move in case it was a capture move + captured = type_of(pos.piece_on(to_sq(bestMove))); captureHistory[moved_piece][to_sq(bestMove)][captured] << bonus1; + } // Extra penalty for a quiet early move that was not a TT move or // main killer move in previous ply when it gets refuted. - if ( ((ss-1)->moveCount == 1 + (ss-1)->ttHit || ((ss-1)->currentMove == (ss-1)->killers[0])) + if ( prevSq != SQ_NONE + && ((ss-1)->moveCount == 1 + (ss-1)->ttHit || ((ss-1)->currentMove == (ss-1)->killers[0])) && !pos.captured_piece()) update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -bonus1); diff --git a/src/types.h b/src/types.h index 37ce343a..06b0a059 100644 --- a/src/types.h +++ b/src/types.h @@ -416,6 +416,10 @@ inline Color color_of(Piece pc) { return Color(pc >> 3); } +constexpr bool is_ok(Move m) { + return m != MOVE_NONE && m != MOVE_NULL; +} + constexpr bool is_ok(Square s) { return s >= SQ_A1 && s <= SQ_H8; } @@ -445,10 +449,12 @@ constexpr Direction pawn_push(Color c) { } constexpr Square from_sq(Move m) { + assert(is_ok(m)); return Square((m >> 6) & 0x3F); } constexpr Square to_sq(Move m) { + assert(is_ok(m)); return Square(m & 0x3F); } @@ -473,10 +479,6 @@ constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) { return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to); } -constexpr bool is_ok(Move m) { - return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE -} - /// Based on a congruential pseudo random number generator constexpr Key make_key(uint64_t seed) { return seed * 6364136223846793005ULL + 1442695040888963407ULL; diff --git a/src/uci.cpp b/src/uci.cpp index 3883b3d3..d3d99243 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -358,15 +358,15 @@ std::string UCI::square(Square s) { string UCI::move(Move m, bool chess960) { - Square from = from_sq(m); - Square to = to_sq(m); - if (m == MOVE_NONE) return "(none)"; if (m == MOVE_NULL) return "0000"; + Square from = from_sq(m); + Square to = to_sq(m); + if (type_of(m) == CASTLING && !chess960) to = make_square(to > from ? FILE_G : FILE_C, rank_of(from)); From af4b62a593cc4fa6d7d34110c41301028a5c9695 Mon Sep 17 00:00:00 2001 From: disservin Date: Mon, 13 Mar 2023 19:35:27 +0100 Subject: [PATCH 097/192] NNUE namespace cleanup This patch moves the nnue namespace in the appropiate header that correspondes with the definition. It also makes navigation a bit easier. closes https://github.com/official-stockfish/Stockfish/pull/4445 No functional change --- src/evaluate.cpp | 6 +++--- src/evaluate.h | 8 -------- src/nnue/evaluate_nnue.h | 8 ++++++++ src/search.cpp | 1 + src/uci.cpp | 1 + 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index cf6f23ea..99b87300 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -36,7 +36,7 @@ #include "timeman.h" #include "uci.h" #include "incbin/incbin.h" - +#include "nnue/evaluate_nnue.h" // Macro to embed the default efficiently updatable neural network (NNUE) file // data in the engine binary (using incbin.h, by Dale Weiler). @@ -95,7 +95,7 @@ namespace Eval { if (directory != "") { ifstream stream(directory + eval_file, ios::binary); - if (load_eval(eval_file, stream)) + if (NNUE::load_eval(eval_file, stream)) currentEvalFileName = eval_file; } @@ -111,7 +111,7 @@ namespace Eval { (void) gEmbeddedNNUEEnd; // Silence warning on unused variable istream stream(&buffer); - if (load_eval(eval_file, stream)) + if (NNUE::load_eval(eval_file, stream)) currentEvalFileName = eval_file; } } diff --git a/src/evaluate.h b/src/evaluate.h index 5238cb81..3615fe6d 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -43,17 +43,9 @@ namespace Eval { namespace NNUE { - std::string trace(Position& pos); - Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr); - void hint_common_parent_position(const Position& pos); - void init(); void verify(); - bool load_eval(std::string name, std::istream& stream); - bool save_eval(std::ostream& stream); - bool save_eval(const std::optional& filename); - } // namespace NNUE } // namespace Eval diff --git a/src/nnue/evaluate_nnue.h b/src/nnue/evaluate_nnue.h index 15638cae..b84bed8b 100644 --- a/src/nnue/evaluate_nnue.h +++ b/src/nnue/evaluate_nnue.h @@ -55,6 +55,14 @@ namespace Stockfish::Eval::NNUE { template using LargePagePtr = std::unique_ptr>; + std::string trace(Position& pos); + Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr); + void hint_common_parent_position(const Position& pos); + + bool load_eval(std::string name, std::istream& stream); + bool save_eval(std::ostream& stream); + bool save_eval(const std::optional& filename); + } // namespace Stockfish::Eval::NNUE #endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED diff --git a/src/search.cpp b/src/search.cpp index 466e0d6f..17c1c28b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -34,6 +34,7 @@ #include "tt.h" #include "uci.h" #include "syzygy/tbprobe.h" +#include "nnue/evaluate_nnue.h" namespace Stockfish { diff --git a/src/uci.cpp b/src/uci.cpp index d3d99243..8f9684ee 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -32,6 +32,7 @@ #include "tt.h" #include "uci.h" #include "syzygy/tbprobe.h" +#include "nnue/evaluate_nnue.h" using namespace std; From 02e4697055519ed206fa76e4ef9abb9f156cd1a0 Mon Sep 17 00:00:00 2001 From: pb00067 Date: Mon, 13 Mar 2023 18:32:40 +0100 Subject: [PATCH 098/192] Remove 'si' StateInfo variable/parameter. Since st is a member of position we don't need to pass it separately as parameter. While being there also remove some line in pos_is_ok, where a copy of StateInfo was made by using default copy constructor and then verified it's correctedness by doing a memcmp. There is no point in doing that. Passed non-regression test https://tests.stockfishchess.org/tests/view/64098d562644b62c33942b35 LLR: 3.24 (-2.94,2.94) <-1.75,0.25> Total: 548960 W: 145834 L: 146134 D: 256992 Ptnml(0-2): 1617, 57652, 156261, 57314, 1636 closes https://github.com/official-stockfish/Stockfish/pull/4444 No functional change --- src/position.cpp | 58 ++++++++++++++++++++++-------------------------- src/position.h | 4 ++-- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index aeac23a3..171193ec 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -282,7 +282,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th chess960 = isChess960; thisThread = th; - set_state(st); + set_state(); assert(pos_is_ok()); @@ -313,19 +313,19 @@ void Position::set_castling_right(Color c, Square rfrom) { /// Position::set_check_info() sets king attacks to detect if a move gives check -void Position::set_check_info(StateInfo* si) const { +void Position::set_check_info() const { - si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE), si->pinners[BLACK]); - si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK), si->pinners[WHITE]); + st->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE), st->pinners[BLACK]); + st->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK), st->pinners[WHITE]); Square ksq = square(~sideToMove); - si->checkSquares[PAWN] = pawn_attacks_bb(~sideToMove, ksq); - si->checkSquares[KNIGHT] = attacks_bb(ksq); - si->checkSquares[BISHOP] = attacks_bb(ksq, pieces()); - si->checkSquares[ROOK] = attacks_bb(ksq, pieces()); - si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK]; - si->checkSquares[KING] = 0; + st->checkSquares[PAWN] = pawn_attacks_bb(~sideToMove, ksq); + st->checkSquares[KNIGHT] = attacks_bb(ksq); + st->checkSquares[BISHOP] = attacks_bb(ksq, pieces()); + st->checkSquares[ROOK] = attacks_bb(ksq, pieces()); + st->checkSquares[QUEEN] = st->checkSquares[BISHOP] | st->checkSquares[ROOK]; + st->checkSquares[KING] = 0; } @@ -334,39 +334,39 @@ void Position::set_check_info(StateInfo* si) const { /// The function is only used when a new position is set up, and to verify /// the correctness of the StateInfo data when running in debug mode. -void Position::set_state(StateInfo* si) const { +void Position::set_state() const { - si->key = si->materialKey = 0; - si->pawnKey = Zobrist::noPawns; - si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; - si->checkersBB = attackers_to(square(sideToMove)) & pieces(~sideToMove); + st->key = st->materialKey = 0; + st->pawnKey = Zobrist::noPawns; + st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO; + st->checkersBB = attackers_to(square(sideToMove)) & pieces(~sideToMove); - set_check_info(si); + set_check_info(); for (Bitboard b = pieces(); b; ) { Square s = pop_lsb(b); Piece pc = piece_on(s); - si->key ^= Zobrist::psq[pc][s]; + st->key ^= Zobrist::psq[pc][s]; if (type_of(pc) == PAWN) - si->pawnKey ^= Zobrist::psq[pc][s]; + st->pawnKey ^= Zobrist::psq[pc][s]; else if (type_of(pc) != KING) - si->nonPawnMaterial[color_of(pc)] += PieceValue[MG][pc]; + st->nonPawnMaterial[color_of(pc)] += PieceValue[MG][pc]; } - if (si->epSquare != SQ_NONE) - si->key ^= Zobrist::enpassant[file_of(si->epSquare)]; + if (st->epSquare != SQ_NONE) + st->key ^= Zobrist::enpassant[file_of(st->epSquare)]; if (sideToMove == BLACK) - si->key ^= Zobrist::side; + st->key ^= Zobrist::side; - si->key ^= Zobrist::castling[si->castlingRights]; + st->key ^= Zobrist::castling[st->castlingRights]; for (Piece pc : Pieces) for (int cnt = 0; cnt < pieceCount[pc]; ++cnt) - si->materialKey ^= Zobrist::psq[pc][cnt]; + st->materialKey ^= Zobrist::psq[pc][cnt]; } @@ -865,7 +865,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { sideToMove = ~sideToMove; // Update king attacks used for fast check detection - set_check_info(st); + set_check_info(); // Calculate the repetition info. It is the ply distance from the previous // occurrence of the same position, negative in the 3-fold case, or zero @@ -1017,7 +1017,7 @@ void Position::do_null_move(StateInfo& newSt) { sideToMove = ~sideToMove; - set_check_info(st); + set_check_info(); st->repetition = 0; @@ -1320,12 +1320,6 @@ bool Position::pos_is_ok() const { if (p1 != p2 && (pieces(p1) & pieces(p2))) assert(0 && "pos_is_ok: Bitboards"); - StateInfo si = *st; - ASSERT_ALIGNED(&si, Eval::NNUE::CacheLineSize); - - set_state(&si); - if (std::memcmp(&si, st, sizeof(StateInfo))) - assert(0 && "pos_is_ok: State"); for (Piece pc : Pieces) if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))) diff --git a/src/position.h b/src/position.h index cc606a5a..d3483bcf 100644 --- a/src/position.h +++ b/src/position.h @@ -179,8 +179,8 @@ public: private: // Initialization helpers (used while setting up a position) void set_castling_right(Color c, Square rfrom); - void set_state(StateInfo* si) const; - void set_check_info(StateInfo* si) const; + void set_state() const; + void set_check_info() const; // Other helpers void move_piece(Square from, Square to); From 24b37e4586ba610d331048446bd036bec5544c4f Mon Sep 17 00:00:00 2001 From: pb00067 Date: Mon, 20 Mar 2023 08:56:44 +0100 Subject: [PATCH 099/192] Verified SEE pruning for capturing and checking moves. Patch analyzes field after SEE exchanges concluded with a recapture by the opponent: if opponent Queen/Rook/King results under attack after the exchanges, we consider the move sharp and don't prune it. Important note: By accident I forgot to adjust 'occupied' when the king takes part in the exchanges. As result of this a move is considered sharp too, when opponent king apparently can evade check by recapturing. Surprisingly this seems contribute to patch's strength. STC: https://tests.stockfishchess.org/tests/view/640b16132644b62c33947397 LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 116400 W: 31239 L: 30817 D: 54344 Ptnml(0-2): 350, 12742, 31618, 13116, 374 LTC: https://tests.stockfishchess.org/tests/view/640c88092644b62c3394c1c5 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 177600 W: 47988 L: 47421 D: 82191 Ptnml(0-2): 62, 16905, 54317, 17436, 80 closes https://github.com/official-stockfish/Stockfish/pull/4453 bench: 5012145 --- src/movepick.cpp | 6 +++--- src/movepick.h | 1 + src/position.cpp | 15 +++++++-------- src/position.h | 2 +- src/search.cpp | 30 +++++++++++++++++++++++++----- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 36ee46b5..855f2b1d 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -95,7 +95,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePiece stage = PROBCUT_TT + !(ttm && pos.capture_stage(ttm) && pos.pseudo_legal(ttm) - && pos.see_ge(ttm, threshold)); + && pos.see_ge(ttm, occupied, threshold)); } /// MovePicker::score() assigns a numerical value to each move in a list, used @@ -197,7 +197,7 @@ top: case GOOD_CAPTURE: if (select([&](){ - return pos.see_ge(*cur, Value(-cur->value)) ? + return pos.see_ge(*cur, occupied, Value(-cur->value)) ? // Move losing capture to endBadCaptures to be tried later true : (*endBadCaptures++ = *cur, false); })) return *(cur - 1); @@ -264,7 +264,7 @@ top: return select([](){ return true; }); case PROBCUT: - return select([&](){ return pos.see_ge(*cur, threshold); }); + return select([&](){ return pos.see_ge(*cur, occupied, threshold); }); case QCAPTURE: if (select([&](){ return depth > DEPTH_QS_RECAPTURES diff --git a/src/movepick.h b/src/movepick.h index b6c07378..725607b8 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -150,6 +150,7 @@ private: Value threshold; Depth depth; ExtMove moves[MAX_MOVES]; + Bitboard occupied; }; } // namespace Stockfish diff --git a/src/position.cpp b/src/position.cpp index 171193ec..ba6888eb 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1062,7 +1062,7 @@ Key Position::key_after(Move m) const { /// SEE value of move is greater or equal to the given threshold. We'll use an /// algorithm similar to alpha-beta pruning with a null window. -bool Position::see_ge(Move m, Value threshold) const { +bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { assert(is_ok(m)); @@ -1081,7 +1081,7 @@ bool Position::see_ge(Move m, Value threshold) const { return true; assert(color_of(piece_on(from)) == sideToMove); - Bitboard occupied = pieces() ^ from ^ to; + occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic Color stm = sideToMove; Bitboard attackers = attackers_to(to, occupied); Bitboard stmAttackers, bb; @@ -1112,45 +1112,44 @@ bool Position::see_ge(Move m, Value threshold) const { // the bitboard 'attackers' any X-ray attackers behind it. if ((bb = stmAttackers & pieces(PAWN))) { + occupied ^= least_significant_square_bb(bb); if ((swap = PawnValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(KNIGHT))) { + occupied ^= least_significant_square_bb(bb); if ((swap = KnightValueMg - swap) < res) break; - - occupied ^= least_significant_square_bb(bb); } else if ((bb = stmAttackers & pieces(BISHOP))) { + occupied ^= least_significant_square_bb(bb); if ((swap = BishopValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(ROOK))) { + occupied ^= least_significant_square_bb(bb); if ((swap = RookValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(ROOK, QUEEN); } else if ((bb = stmAttackers & pieces(QUEEN))) { + occupied ^= least_significant_square_bb(bb); if ((swap = QueenValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= (attacks_bb(to, occupied) & pieces(BISHOP, QUEEN)) | (attacks_bb(to, occupied) & pieces(ROOK , QUEEN)); } diff --git a/src/position.h b/src/position.h index d3483bcf..670b621c 100644 --- a/src/position.h +++ b/src/position.h @@ -144,7 +144,7 @@ public: void undo_null_move(); // Static Exchange Evaluation - bool see_ge(Move m, Value threshold = VALUE_ZERO) const; + bool see_ge(Move m, Bitboard& occupied, Value threshold = VALUE_ZERO) const; // Accessing hash keys Key key() const; diff --git a/src/search.cpp b/src/search.cpp index 17c1c28b..7564c109 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1019,9 +1019,27 @@ moves_loop: // When in check, search starts here + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; + Bitboard occupied; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, Value(-206) * depth)) - continue; + if (!pos.see_ge(move, occupied, Value(-206) * depth)) + { + if (depth < 2 - capture) + continue; + // don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges + Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & occupied; + Bitboard attacks = 0; + occupied |= to_sq(move); + while (leftEnemies && !attacks) + { + Square sq = pop_lsb(leftEnemies); + attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; + // exclude Queen/Rook(s) which were already threatened before SEE + if (attacks && (sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))) + attacks = 0; + } + if (!attacks) + continue; + } } else { @@ -1047,8 +1065,9 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); + Bitboard occupied; // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) + if (!pos.see_ge(move, occupied, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) continue; } } @@ -1533,6 +1552,7 @@ moves_loop: // When in check, search starts here prevSq); int quietCheckEvasions = 0; + Bitboard occupied; // Step 5. Loop through all pseudo-legal moves until no moves remain // or a beta cutoff occurs. @@ -1569,7 +1589,7 @@ moves_loop: // When in check, search starts here continue; } - if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1)) + if (futilityBase <= alpha && !pos.see_ge(move, occupied, VALUE_ZERO + 1)) { bestValue = std::max(bestValue, futilityBase); continue; @@ -1588,7 +1608,7 @@ moves_loop: // When in check, search starts here continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-110))) + if (!pos.see_ge(move, occupied, Value(-110))) continue; } From b973e40e45d75c3b3391141d149d4186494d4652 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Tue, 21 Mar 2023 23:58:25 +0300 Subject: [PATCH 100/192] Update Elo estimates for terms in search Setting the Elo value of some functions which were not set before. All tests run at 10+0.1 (STC), 25000 games (Same as #4294). Book used: UHO_XXL_+0.90_+1.19.epd Values are rounded to the nearest non-negative integer. Test links: https://tests.stockfishchess.org/tests/view/6419ab5b65775d3b539f46c6 https://tests.stockfishchess.org/tests/view/6419adb465775d3b539f4730 https://tests.stockfishchess.org/tests/view/6419ae9c65775d3b539f4756 https://tests.stockfishchess.org/tests/view/6419b03f65775d3b539f47a8 https://tests.stockfishchess.org/tests/view/6419b35d65775d3b539f4860 https://tests.stockfishchess.org/tests/view/6419b6b965775d3b539f48e6 https://tests.stockfishchess.org/tests/view/6419cade65775d3b539f4cd5 https://tests.stockfishchess.org/tests/view/6419cbb565775d3b539f4d01 https://tests.stockfishchess.org/tests/view/6419cc6965775d3b539f4d1e closes https://github.com/official-stockfish/Stockfish/pull/4459 No functional change --- src/search.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 7564c109..b2983f66 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -732,7 +732,7 @@ namespace { } else if (excludedMove) { - // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 elo) + // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 Elo) Eval::NNUE::hint_common_parent_position(pos); eval = ss->staticEval; complexity = abs(ss->staticEval - pos.psq_eg_stm()); @@ -1120,15 +1120,15 @@ moves_loop: // When in check, search starts here else if (singularBeta >= beta) return singularBeta; - // If the eval of ttMove is greater than beta, we reduce it (negative extension) + // If the eval of ttMove is greater than beta, we reduce it (negative extension) (~7 Elo) else if (ttValue >= beta) extension = -2 - !PvNode; - // If the eval of ttMove is less than value, we reduce it (negative extension) + // If the eval of ttMove is less than value, we reduce it (negative extension) (~1 Elo) else if (ttValue <= value) extension = -1; - // If the eval of ttMove is less than alpha, we reduce it (negative extension) + // If the eval of ttMove is less than alpha, we reduce it (negative extension) (~1 Elo) else if (ttValue <= alpha) extension = -1; } @@ -1182,7 +1182,7 @@ moves_loop: // When in check, search starts here if (ttCapture) r++; - // Decrease reduction for PvNodes based on depth + // Decrease reduction for PvNodes based on depth (~2 Elo) if (PvNode) r -= 1 + 12 / (3 + depth); @@ -1195,11 +1195,11 @@ moves_loop: // When in check, search starts here && (mp.threatenedPieces & from_sq(move))) r--; - // Increase reduction if next ply has a lot of fail high + // Increase reduction if next ply has a lot of fail high (~5 Elo) if ((ss+1)->cutoffCnt > 3) r++; - // Decrease reduction if move is a killer and we have a good history + // Decrease reduction if move is a killer and we have a good history (~1 Elo) if (move == ss->killers[0] && (*contHist[0])[movedPiece][to_sq(move)] >= 3722) r--; @@ -1210,7 +1210,7 @@ moves_loop: // When in check, search starts here + (*contHist[3])[movedPiece][to_sq(move)] - 4182; - // Decrease/increase reduction for moves with a good/bad history (~30 Elo) + // Decrease/increase reduction for moves with a good/bad history (~25 Elo) r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) @@ -1347,7 +1347,7 @@ moves_loop: // When in check, search starts here { alpha = value; - // Reduce other moves if we have found at least one score improvement + // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 && depth < 6 && beta < 10534 @@ -1413,7 +1413,7 @@ moves_loop: // When in check, search starts here bestValue = std::min(bestValue, maxValue); // If no good move is found and the previous position was ttPv, then the previous - // opponent move is probably good and the new position is added to the search tree. + // opponent move is probably good and the new position is added to the search tree. (~7 Elo) if (bestValue <= alpha) ss->ttPv = ss->ttPv || ((ss-1)->ttPv && depth > 3); @@ -1432,7 +1432,7 @@ moves_loop: // When in check, search starts here // qsearch() is the quiescence search function, which is called by the main search // function with zero depth, or recursively with further decreasing depth per call. - // (~155 elo) + // (~155 Elo) template Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { From 1b5738e0c958ac8d3d140a3d182b85f8c0c0cd2c Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 24 Mar 2023 07:45:22 +0300 Subject: [PATCH 101/192] Simplify statScore initialization This patch simplifies initialization of statScore to "always set it up to 0" instead of setting it up to 0 two plies deeper. Reason for why it was done in previous way partially was because of LMR usage of previous statScore which was simplified long time ago so it makes sense to make in more simple there. Passed STC: https://tests.stockfishchess.org/tests/view/641a86d1db43ab2ba6f7b31d LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 115648 W: 30895 L: 30764 D: 53989 Ptnml(0-2): 368, 12741, 31473, 12876, 366 Passed LTC: https://tests.stockfishchess.org/tests/view/641b1c31db43ab2ba6f7d17a LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 175576 W: 47122 L: 47062 D: 81392 Ptnml(0-2): 91, 17077, 53390, 17141, 89 closes https://github.com/official-stockfish/Stockfish/pull/4460 bench 5081969 --- src/search.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index b2983f66..d2358ea2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -607,14 +607,7 @@ namespace { (ss+2)->cutoffCnt = 0; ss->doubleExtensions = (ss-1)->doubleExtensions; Square prevSq = is_ok((ss-1)->currentMove) ? to_sq((ss-1)->currentMove) : SQ_NONE; - - // Initialize statScore to zero for the grandchildren of the current position. - // So statScore is shared between all grandchildren and only the first grandchild - // starts with statScore = 0. Later grandchildren start with the last calculated - // statScore of the previous grandchild. This influences the reduction rules in - // LMR which are based on the statScore of parent position. - if (!rootNode) - (ss+2)->statScore = 0; + ss->statScore = 0; // Step 4. Transposition table lookup. excludedMove = ss->excludedMove; From 587bc647d7d14b53d8625c4446006e23a4acd82a Mon Sep 17 00:00:00 2001 From: MinetaS Date: Wed, 22 Mar 2023 16:50:55 +0900 Subject: [PATCH 102/192] Remove non_pawn_material in NNUE::evaluate After "Use NNUE complexity in search, retune related parameters" commit, the effect of non-pawn material adjustment has been nearly diminished. This patch removes pos.non_pawn_material as a simplification, which passed non-regression tests with both STC and LTC. Passed non-regression STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 75152 W: 20030 L: 19856 D: 35266 Ptnml(0-2): 215, 8281, 20459, 8357, 264 https://tests.stockfishchess.org/tests/view/641ab471db43ab2ba6f7bc58 Passed non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 193864 W: 51870 L: 51829 D: 90165 Ptnml(0-2): 86, 18968, 58794, 18987, 97 https://tests.stockfishchess.org/tests/view/641b4fe6db43ab2ba6f7db96 closes https://github.com/official-stockfish/Stockfish/pull/4461 Bench: 5020718 --- src/nnue/evaluate_nnue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index f33aa3b8..329adfda 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -148,7 +148,7 @@ namespace Stockfish::Eval::NNUE { // overaligning stack variables with alignas() doesn't work correctly. constexpr uint64_t alignment = CacheLineSize; - int delta = 24 - pos.non_pawn_material() / 9560; + constexpr int delta = 24; #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType transformedFeaturesUnaligned[ From 43108a619899af084e45224e8744ca668a9efed2 Mon Sep 17 00:00:00 2001 From: Sebastian Buchwald Date: Tue, 28 Mar 2023 19:53:43 +0200 Subject: [PATCH 103/192] Reuse existing functions to read/write array of network parameters closes https://github.com/official-stockfish/Stockfish/pull/4463 No functional change --- src/nnue/layers/affine_transform.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 313b1568..f84f054e 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -256,8 +256,7 @@ namespace Stockfish::Eval::NNUE::Layers { // Read network parameters bool read_parameters(std::istream& stream) { - for (IndexType i = 0; i < OutputDimensions; ++i) - biases[i] = read_little_endian(stream); + read_little_endian(stream, biases, OutputDimensions); for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) weights[get_weight_index(i)] = read_little_endian(stream); @@ -267,8 +266,7 @@ namespace Stockfish::Eval::NNUE::Layers { // Write network parameters bool write_parameters(std::ostream& stream) const { - for (IndexType i = 0; i < OutputDimensions; ++i) - write_little_endian(stream, biases[i]); + write_little_endian(stream, biases, OutputDimensions); for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) write_little_endian(stream, weights[get_weight_index(i)]); @@ -452,8 +450,7 @@ namespace Stockfish::Eval::NNUE::Layers { // Read network parameters bool read_parameters(std::istream& stream) { - for (IndexType i = 0; i < OutputDimensions; ++i) - biases[i] = read_little_endian(stream); + read_little_endian(stream, biases, OutputDimensions); for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) weights[get_weight_index(i)] = read_little_endian(stream); @@ -462,8 +459,7 @@ namespace Stockfish::Eval::NNUE::Layers { // Write network parameters bool write_parameters(std::ostream& stream) const { - for (IndexType i = 0; i < OutputDimensions; ++i) - write_little_endian(stream, biases[i]); + write_little_endian(stream, biases, OutputDimensions); for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) write_little_endian(stream, weights[get_weight_index(i)]); From 37160c4b1632245d46d86cec7bd22b76f5a87531 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Mon, 27 Mar 2023 01:00:54 -0400 Subject: [PATCH 104/192] Update default net to nn-dabb1ed23026.nnue Created by retraining the master net with these modifications: * New filtering methods for existing data from T80 sep+oct2022, T79 apr2022, T78 jun+jul+aug+sep2022, T77 dec2021 * Adding new filtered data from T80 aug2022 and T78 apr+may2022 * Increasing early-fen-skipping from 28 to 30 ``` python3 easy_train.py \ --experiment-name leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3-sk30 \ --training-dataset /data/leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \ --start-from-engine-test-net True \ --early-fen-skipping 30 \ --max_epoch 900 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --lr 4.375e-4 \ --gamma 0.995 \ --tui False \ --gpus "0," \ --seed $RANDOM ``` The v3 filtering used for data from T77dec 2021 differs from v2 filtering in that: * To improve binpack compression, positions after ply 28 were skipped during training by setting position scores to VALUE_NONE (32002) instead of removing them entirely * All early-game positions with ply <= 28 were removed to maximize binpack compression * Only bestmove captures at d6pv2 search were skipped, not 2nd bestmove captures * Binpack compression was repaired for the remaining positions by effectively replacing bestmoves with "played moves" to maintain contiguous sequences of positions in the training game data After improving binpack compression, The T77 dec2021 data size was reduced from 95G to 19G. The v6 filtering used for data from T80augsepoctT79aprT78aprtosep 2022 differs from v2 in that: * All positions with only one legal move were removed * Tighter score differences at d6pv2 search were used to remove more positions with only one good move than before * d6pv2 search was not used to remove positions where the best 2 moves were captures ``` python3 interleave_binpacks.py \ nn-547-dataset/leela96-eval-filt-v2.binpack \ nn-547-dataset/dfrc99-eval-filt-v2.binpack \ nn-547-dataset/test80-nov2022-12tb7p-eval-filt-v2-d6.binpack \ nn-547-dataset/T79-may2022-12tb7p-eval-filt-v2.binpack \ nn-547-dataset/T60-nov2021-12tb7p-eval-filt-v2.binpack \ nn-547-dataset/T60-dec2021-12tb7p-eval-filt-v2.binpack \ filt-v6/test80-aug2022-16tb7p-filter-v6.binpack \ filt-v6/test80-sep2022-16tb7p-filter-v6.binpack \ filt-v6/test80-oct2022-16tb7p-filter-v6.binpack \ filt-v6/test79-apr2022-16tb7p-filter-v6.binpack \ filt-v6/test78-aprmay2022-16tb7p-filter-v6.binpack \ filt-v6/test78-junjulaug2022-16tb7p-filter-v6.binpack \ filt-v6/test78-sep2022-16tb7p-filter-v6.binpack \ filt-v3/test77-dec2021-16tb7p-filt-v3.binpack \ /data/leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3.binpack ``` The code for the new data filtering methods is available at: https://github.com/linrock/Stockfish/tree/nnue-data-v3/nnue-data The code for giving hexword names to .nnue files is at: https://github.com/linrock/nnue-namer Links for downloading the training data components can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move: nn-epoch779.nnue : 0.6 +/- 3.1 Passed STC: https://tests.stockfishchess.org/tests/view/64212412db43ab2ba6f8efb0 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 82256 W: 22185 L: 21809 D: 38262 Ptnml(0-2): 286, 9065, 22067, 9407, 303 Passed LTC: https://tests.stockfishchess.org/tests/view/64223726db43ab2ba6f91d6c LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 30840 W: 8437 L: 8149 D: 14254 Ptnml(0-2): 14, 2891, 9323, 3177, 15 closes https://github.com/official-stockfish/Stockfish/pull/4465 bench 5101970 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 3615fe6d..61846073 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-52471d67216a.nnue" + #define EvalFileDefaultName "nn-dabb1ed23026.nnue" namespace NNUE { From a9c26357deb01c764cd16ef4e61acb4f687cbd77 Mon Sep 17 00:00:00 2001 From: Miguel Lahoz Date: Tue, 28 Mar 2023 00:06:24 +0800 Subject: [PATCH 105/192] Clean up repetitive declarations for see_ge The occupied bitboard is only used in one place and is otherwise thrown away. To simplify use, see_ge function can instead be overloaded. Repetitive declarations for occupied bitboard can be removed. Passed non-regression test https://tests.stockfishchess.org/tests/view/6421c286db43ab2ba6f908eb LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 48912 W: 13196 L: 13001 D: 22715 Ptnml(0-2): 146, 5003, 13967, 5190, 150 closes https://github.com/official-stockfish/Stockfish/pull/4469 No functional change. --- src/movepick.cpp | 6 +++--- src/movepick.h | 1 - src/position.cpp | 5 +++++ src/position.h | 1 + src/search.cpp | 8 +++----- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 855f2b1d..36ee46b5 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -95,7 +95,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePiece stage = PROBCUT_TT + !(ttm && pos.capture_stage(ttm) && pos.pseudo_legal(ttm) - && pos.see_ge(ttm, occupied, threshold)); + && pos.see_ge(ttm, threshold)); } /// MovePicker::score() assigns a numerical value to each move in a list, used @@ -197,7 +197,7 @@ top: case GOOD_CAPTURE: if (select([&](){ - return pos.see_ge(*cur, occupied, Value(-cur->value)) ? + return pos.see_ge(*cur, Value(-cur->value)) ? // Move losing capture to endBadCaptures to be tried later true : (*endBadCaptures++ = *cur, false); })) return *(cur - 1); @@ -264,7 +264,7 @@ top: return select([](){ return true; }); case PROBCUT: - return select([&](){ return pos.see_ge(*cur, occupied, threshold); }); + return select([&](){ return pos.see_ge(*cur, threshold); }); case QCAPTURE: if (select([&](){ return depth > DEPTH_QS_RECAPTURES diff --git a/src/movepick.h b/src/movepick.h index 725607b8..b6c07378 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -150,7 +150,6 @@ private: Value threshold; Depth depth; ExtMove moves[MAX_MOVES]; - Bitboard occupied; }; } // namespace Stockfish diff --git a/src/position.cpp b/src/position.cpp index ba6888eb..e6fdb511 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1163,6 +1163,11 @@ bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { return bool(res); } +bool Position::see_ge(Move m, Value threshold) const { + Bitboard occupied; + return see_ge(m, occupied, threshold); +} + /// Position::is_draw() tests whether the position is drawn by 50-move rule /// or by repetition. It does not detect stalemates. diff --git a/src/position.h b/src/position.h index 670b621c..bb45c44a 100644 --- a/src/position.h +++ b/src/position.h @@ -145,6 +145,7 @@ public: // Static Exchange Evaluation bool see_ge(Move m, Bitboard& occupied, Value threshold = VALUE_ZERO) const; + bool see_ge(Move m, Value threshold = VALUE_ZERO) const; // Accessing hash keys Key key() const; diff --git a/src/search.cpp b/src/search.cpp index d2358ea2..ac74cdaf 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1058,9 +1058,8 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); - Bitboard occupied; // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, occupied, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) + if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) continue; } } @@ -1545,7 +1544,6 @@ moves_loop: // When in check, search starts here prevSq); int quietCheckEvasions = 0; - Bitboard occupied; // Step 5. Loop through all pseudo-legal moves until no moves remain // or a beta cutoff occurs. @@ -1582,7 +1580,7 @@ moves_loop: // When in check, search starts here continue; } - if (futilityBase <= alpha && !pos.see_ge(move, occupied, VALUE_ZERO + 1)) + if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1)) { bestValue = std::max(bestValue, futilityBase); continue; @@ -1601,7 +1599,7 @@ moves_loop: // When in check, search starts here continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, occupied, Value(-110))) + if (!pos.see_ge(move, Value(-110))) continue; } From 3f01e3f41f11aa66befec2307a32ee023c699a2a Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Thu, 23 Mar 2023 13:35:34 +0300 Subject: [PATCH 106/192] Allow PvNode in futility pruning for captures. Passed non-regression STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 148128 W: 39428 L: 39333 D: 69367 Ptnml(0-2): 492, 16326, 40315, 16457, 474 https://tests.stockfishchess.org/tests/view/641c2dbfdb43ab2ba6f804e8 Passed non-regression LTC: LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 376256 W: 100906 L: 101039 D: 174311 Ptnml(0-2): 186, 36697, 114494, 36566, 185 https://tests.stockfishchess.org/tests/view/641d33b2db43ab2ba6f83338 closes https://github.com/official-stockfish/Stockfish/pull/4470 bench: 4935616 --- src/search.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index ac74cdaf..5f95a1bd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1005,7 +1005,6 @@ moves_loop: // When in check, search starts here { // Futility pruning for captures (~2 Elo) if ( !givesCheck - && !PvNode && lmrDepth < 6 && !ss->inCheck && ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] From 7a6fa34f5f9f0f193d9350cd58c82a8f98a6505d Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Sun, 12 Mar 2023 15:16:51 +0200 Subject: [PATCH 107/192] Improve compatibility this makes it easier to compile under MSVC, even though we recommend gcc/clang for production compiles at the moment. In Win32 API, by default, most null-terminated character strings arguments are of wchar_t (UTF16, formerly UCS16-LE) type, i.e. 2 bytes (at least) per character. So, src/misc.cpp should have proper type. Respectively, for src/syzygy/tbprobe.cpp, in Widows, file paths should be std::wstring rather than std::string. However, this requires a very big number of changes, since the config files are also keeping the 8-bit-per-character std::string strings. Therefore, just one change of using 8-byte-per-character CreateFileA make it compile under MSVC. closes https://github.com/official-stockfish/Stockfish/pull/4438 No functional change --- src/misc.cpp | 4 ++-- src/syzygy/tbprobe.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index c22126af..6469c5cf 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -605,7 +605,7 @@ static int best_node(size_t idx) { DWORD byteOffset = 0; // Early exit if the needed API is not available at runtime - HMODULE k32 = GetModuleHandle("Kernel32.dll"); + HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll")); auto fun1 = (fun1_t)(void(*)())GetProcAddress(k32, "GetLogicalProcessorInformationEx"); if (!fun1) return -1; @@ -675,7 +675,7 @@ void bindThisThread(size_t idx) { return; // Early exit if the needed API are not available at runtime - HMODULE k32 = GetModuleHandle("Kernel32.dll"); + HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll")); auto fun2 = (fun2_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMaskEx"); auto fun3 = (fun3_t)(void(*)())GetProcAddress(k32, "SetThreadGroupAffinity"); auto fun4 = (fun4_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMask2"); diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index b594ac37..9cb0bfdb 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -234,7 +234,7 @@ public: } #else // Note FILE_FLAG_RANDOM_ACCESS is only a hint to Windows and as such may get ignored. - HANDLE fd = CreateFile(fname.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, + HANDLE fd = CreateFileA(fname.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr); if (fd == INVALID_HANDLE_VALUE) From e8742bdab35c63253b5110d1861f27337e18f9fc Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Wed, 29 Mar 2023 12:43:36 +0300 Subject: [PATCH 108/192] Made advanced Windows API calls dynamically linked Made advanced Windows API calls (those from Advapi32.dll) dynamically linked to avoid link errors when compiling using Intel icx compiler for Windows. https://github.com/official-stockfish/Stockfish/pull/4467 No functional change --- src/misc.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index 6469c5cf..cac9dd94 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -38,6 +38,9 @@ using fun2_t = bool(*)(USHORT, PGROUP_AFFINITY); using fun3_t = bool(*)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY); using fun4_t = bool(*)(USHORT, PGROUP_AFFINITY, USHORT, PUSHORT); using fun5_t = WORD(*)(); +using fun6_t = bool(*)(HANDLE, DWORD, PHANDLE); +using fun7_t = bool(*)(LPCSTR, LPCSTR, PLUID); +using fun8_t = bool(*)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD); } #endif @@ -488,11 +491,26 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize if (!largePageSize) return nullptr; + // Dynamically link OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges + HMODULE k32 = GetModuleHandle("Advapi32.dll"); + auto fun6 = (fun6_t)(void(*)())GetProcAddress(k32, "OpenProcessToken"); + if (!fun6) + return nullptr; + auto fun7 = (fun7_t)(void(*)())GetProcAddress(k32, "LookupPrivilegeValueA"); + if (!fun7) + return nullptr; + auto fun8 = (fun8_t)(void(*)())GetProcAddress(k32, "AdjustTokenPrivileges"); + if (!fun8) + return nullptr; + + // We need SeLockMemoryPrivilege, so try to enable it for the process - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken)) + // OpenProcessToken() + if (!fun6(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken)) return nullptr; - if (LookupPrivilegeValue(nullptr, SE_LOCK_MEMORY_NAME, &luid)) + // LookupPrivilegeValueA() + if (fun7(nullptr, SE_LOCK_MEMORY_NAME, &luid)) { TOKEN_PRIVILEGES tp { }; TOKEN_PRIVILEGES prevTp { }; @@ -504,7 +522,8 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds, // we still need to query GetLastError() to ensure that the privileges were actually obtained. - if (AdjustTokenPrivileges( + // AdjustTokenPrivileges() + if (fun8( hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) && GetLastError() == ERROR_SUCCESS) { @@ -514,7 +533,8 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); // Privilege no longer needed, restore previous state - AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr); + // AdjustTokenPrivileges () + fun8(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr); } } From c3c46feebba470dcbaa0a5a6ef83534091dffe6a Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Thu, 30 Mar 2023 17:46:15 +0800 Subject: [PATCH 109/192] Remove reduction for moving threatened piece Simplify away "Decrease reduction if we move a threatened piece". Running a dbg_hit_on() shows that this line is only called ~0.12% of the time. Simplification STC: https://tests.stockfishchess.org/tests/view/641ec2dcdb43ab2ba6f88103 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 146128 W: 39168 L: 39070 D: 67890 Ptnml(0-2): 466, 16117, 39830, 16155, 496 Simplification LTC: https://tests.stockfishchess.org/tests/view/64200689db43ab2ba6f8bca8 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 248016 W: 66703 L: 66714 D: 114599 Ptnml(0-2): 105, 24202, 75406, 24189, 106 closes https://github.com/official-stockfish/Stockfish/pull/4471 Bench: 4961236 --- src/search.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5f95a1bd..2fcbc7df 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1181,11 +1181,6 @@ moves_loop: // When in check, search starts here if (singularQuietLMR) r--; - // Decrease reduction if we move a threatened piece (~1 Elo) - if ( depth > 9 - && (mp.threatenedPieces & from_sq(move))) - r--; - // Increase reduction if next ply has a lot of fail high (~5 Elo) if ((ss+1)->cutoffCnt > 3) r++; From 66bf45b99e2061c1ba74f9975bc5059ac0121dfd Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 1 Apr 2023 11:56:49 +0200 Subject: [PATCH 110/192] Stringify the git info passed avoid escaping the string in the Makefile. Alternative to https://github.com/official-stockfish/Stockfish/pull/4476 closes https://github.com/official-stockfish/Stockfish/pull/4481 No functional change. --- src/Makefile | 4 ++-- src/evaluate.cpp | 2 -- src/misc.cpp | 6 ++---- src/misc.h | 3 +++ 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Makefile b/src/Makefile index e257bc63..0b22fb4e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -705,13 +705,13 @@ endif ### 3.7.1 Try to include git commit sha for versioning GIT_SHA = $(shell git rev-parse --short HEAD 2>/dev/null) ifneq ($(GIT_SHA), ) - CXXFLAGS += -DGIT_SHA=\"$(GIT_SHA)\" + CXXFLAGS += -DGIT_SHA=$(GIT_SHA) endif ### 3.7.2 Try to include git commit date for versioning GIT_DATE = $(shell git show -s --date=format:'%Y%m%d' --format=%cd HEAD 2>/dev/null) ifneq ($(GIT_DATE), ) - CXXFLAGS += -DGIT_DATE=\"$(GIT_DATE)\" + CXXFLAGS += -DGIT_DATE=$(GIT_DATE) endif ### 3.8 Link Time Optimization diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 99b87300..12883fcc 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -82,8 +82,6 @@ namespace Eval { eval_file = EvalFileDefaultName; #if defined(DEFAULT_NNUE_DIRECTORY) - #define stringify2(x) #x - #define stringify(x) stringify2(x) vector dirs = { "" , "" , CommandLine::binaryDirectory , stringify(DEFAULT_NNUE_DIRECTORY) }; #else vector dirs = { "" , "" , CommandLine::binaryDirectory }; diff --git a/src/misc.cpp b/src/misc.cpp index cac9dd94..e36a04bc 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -160,7 +160,7 @@ string engine_info(bool to_uci) { { ss << "-"; #ifdef GIT_DATE - ss << GIT_DATE; + ss << stringify(GIT_DATE); #else constexpr string_view months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); string month, day, year; @@ -173,7 +173,7 @@ string engine_info(bool to_uci) { ss << "-"; #ifdef GIT_SHA - ss << GIT_SHA; + ss << stringify(GIT_SHA); #else ss << "nogit"; #endif @@ -190,8 +190,6 @@ string engine_info(bool to_uci) { std::string compiler_info() { - #define stringify2(x) #x - #define stringify(x) stringify2(x) #define make_version_string(major, minor, patch) stringify(major) "." stringify(minor) "." stringify(patch) /// Predefined macros hell: diff --git a/src/misc.h b/src/misc.h index c20a816e..d4965156 100644 --- a/src/misc.h +++ b/src/misc.h @@ -28,6 +28,9 @@ #include "types.h" +#define stringify2(x) #x +#define stringify(x) stringify2(x) + namespace Stockfish { std::string engine_info(bool to_uci = false); From 38a80c0b47397dbdd9167ec1476dfd3c033020d6 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Thu, 30 Mar 2023 11:14:30 +0000 Subject: [PATCH 111/192] Simplify away complexityAverage Instead of tracking the average of complexity values, calculate complexity of root position at the beginning of the search and use it as a scaling factor in time management. Passed non-regression STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 58752 W: 15738 L: 15551 D: 27463 Ptnml(0-2): 164, 6194, 16478, 6371, 169 https://tests.stockfishchess.org/tests/view/6423010edb43ab2ba6f9424a Passed non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 92872 W: 24865 L: 24729 D: 43278 Ptnml(0-2): 38, 8652, 28929, 8770, 47 https://tests.stockfishchess.org/tests/view/6423c1f0db43ab2ba6f9644f closes https://github.com/official-stockfish/Stockfish/pull/4472 No functional change --- src/misc.h | 26 -------------------------- src/search.cpp | 17 ++++++++++------- src/thread.h | 2 +- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/misc.h b/src/misc.h index d4965156..69d470c2 100644 --- a/src/misc.h +++ b/src/misc.h @@ -89,32 +89,6 @@ static inline const union { uint32_t i; char c[4]; } Le = { 0x01020304 }; static inline const bool IsLittleEndian = (Le.c[0] == 4); -// RunningAverage : a class to calculate a running average of a series of values. -// For efficiency, all computations are done with integers. -class RunningAverage { - public: - - // Reset the running average to rational value p / q - void set(int64_t p, int64_t q) - { average = p * PERIOD * RESOLUTION / q; } - - // Update average with value v - void update(int64_t v) - { average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; } - - // Test if average is strictly greater than rational a / b - bool is_greater(int64_t a, int64_t b) const - { return b * average > a * (PERIOD * RESOLUTION); } - - int64_t value() const - { return average / (PERIOD * RESOLUTION); } - - private : - static constexpr int64_t PERIOD = 4096; - static constexpr int64_t RESOLUTION = 1024; - int64_t average; -}; - template class ValueList { diff --git a/src/search.cpp b/src/search.cpp index 2fcbc7df..3136046d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -293,6 +293,15 @@ void Thread::search() { if (mainThread) { + + int rootComplexity; + if (Eval::useNNUE) + Eval::NNUE::evaluate(rootPos, true, &rootComplexity); + else + Eval::evaluate(rootPos, &rootComplexity); + + mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); + if (mainThread->bestPreviousScore == VALUE_INFINITE) for (int i = 0; i < 4; ++i) mainThread->iterValue[i] = VALUE_ZERO; @@ -311,8 +320,6 @@ void Thread::search() { multiPV = std::min(multiPV, rootMoves.size()); - complexityAverage.set(153, 1); - optimism[us] = optimism[~us] = VALUE_ZERO; int searchAgainCounter = 0; @@ -472,10 +479,8 @@ void Thread::search() { timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.57 : 0.65; double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction); double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size(); - int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::min(1.03 + (complexity - 241) / 1552.0, 1.45); - double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; + double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * mainThread->complexity; // Cap used time in case of a single legal move for a better viewer experience in tournaments // yielding correct scores and sufficiently fast moves. @@ -755,8 +760,6 @@ namespace { tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } - thisThread->complexityAverage.update(complexity); - // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { diff --git a/src/thread.h b/src/thread.h index 46cdb11c..d6a48eca 100644 --- a/src/thread.h +++ b/src/thread.h @@ -60,7 +60,6 @@ public: Pawns::Table pawnsTable; Material::Table materialTable; size_t pvIdx, pvLast; - RunningAverage complexityAverage; std::atomic nodes, tbHits, bestMoveChanges; int selDepth, nmpMinPly; Color nmpColor; @@ -87,6 +86,7 @@ struct MainThread : public Thread { void search() override; void check_time(); + double complexity; double previousTimeReduction; Value bestPreviousScore; Value bestPreviousAverageScore; From bc50378ff1915a8ad6ac3e4946193c65e4cacb56 Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Fri, 31 Mar 2023 18:16:50 +0300 Subject: [PATCH 112/192] Replace deprecated icc with icx Replace the deprecated Intel compiler icc with its newer icx variant. This newer compiler is based on clang, and yields good performance. As before, currently only linux is supported. closes https://github.com/official-stockfish/Stockfish/pull/4478 No functional change --- src/Makefile | 70 +++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0b22fb4e..abcf11b0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -425,10 +425,11 @@ ifeq ($(COMP),mingw) CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations endif -ifeq ($(COMP),icc) - comp=icc - CXX=icpc - CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi +ifeq ($(COMP),icx) + comp=icx + CXX=icpx + CXXFLAGS += --intel -pedantic -Wextra -Wshadow -Wmissing-prototypes \ + -Wconditional-uninitialized -Wabi -Wdeprecated endif ifeq ($(COMP),clang) @@ -499,9 +500,9 @@ ifeq ($(COMP),ndk) LDFLAGS += -static-libstdc++ -pie -lm -latomic endif -ifeq ($(comp),icc) - profile_make = icc-profile-make - profile_use = icc-profile-use +ifeq ($(comp),icx) + profile_make = icx-profile-make + profile_use = icx-profile-use else ifeq ($(comp),clang) profile_make = clang-profile-make profile_use = clang-profile-use @@ -572,7 +573,7 @@ ifeq ($(optimize),yes) endif ifeq ($(KERNEL),Darwin) - ifeq ($(comp),$(filter $(comp),clang icc)) + ifeq ($(comp),$(filter $(comp),clang icx)) CXXFLAGS += -mdynamic-no-pic endif @@ -608,8 +609,6 @@ endif ifeq ($(popcnt),yes) ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64)) CXXFLAGS += -DUSE_POPCNT - else ifeq ($(comp),icc) - CXXFLAGS += -msse3 -DUSE_POPCNT else CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT endif @@ -618,63 +617,63 @@ endif ### 3.6 SIMD architectures ifeq ($(avx2),yes) CXXFLAGS += -DUSE_AVX2 - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mavx2 -mbmi endif endif ifeq ($(avxvnni),yes) CXXFLAGS += -DUSE_VNNI -DUSE_AVXVNNI - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mavxvnni endif endif ifeq ($(avx512),yes) CXXFLAGS += -DUSE_AVX512 - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mavx512f -mavx512bw endif endif ifeq ($(vnni256),yes) CXXFLAGS += -DUSE_VNNI - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256 endif endif ifeq ($(vnni512),yes) CXXFLAGS += -DUSE_VNNI - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) - CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) + CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=512 endif endif ifeq ($(sse41),yes) CXXFLAGS += -DUSE_SSE41 - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -msse4.1 endif endif ifeq ($(ssse3),yes) CXXFLAGS += -DUSE_SSSE3 - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mssse3 endif endif ifeq ($(sse2),yes) CXXFLAGS += -DUSE_SSE2 - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -msse2 endif endif ifeq ($(mmx),yes) CXXFLAGS += -DUSE_MMX - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mmmx endif endif @@ -697,7 +696,7 @@ endif ### 3.7 pext ifeq ($(pext),yes) CXXFLAGS += -DUSE_PEXT - ifeq ($(comp),$(filter $(comp),gcc clang mingw)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw icx)) CXXFLAGS += -mbmi2 endif endif @@ -719,8 +718,11 @@ endif ### needs access to the optimization flags. ifeq ($(optimize),yes) ifeq ($(debug), no) - ifeq ($(comp),clang) + ifeq ($(comp),$(filter $(comp),clang icx)) CXXFLAGS += -flto=full + ifeq ($(comp),icx) + CXXFLAGS += -fwhole-program-vtables + endif ifeq ($(target_windows),yes) CXXFLAGS += -fuse-ld=lld endif @@ -807,7 +809,7 @@ help: @echo "gcc > Gnu compiler (default)" @echo "mingw > Gnu compiler with MinGW under Windows" @echo "clang > LLVM Clang compiler" - @echo "icc > Intel compiler" + @echo "icx > Intel oneAPI DPC++/C++ Compiler" @echo "ndk > Google NDK to cross-compile for Android" @echo "" @echo "Simple examples. If you don't know what to do, you likely want to run one of: " @@ -833,8 +835,10 @@ endif .PHONY: help build profile-build strip install clean net objclean profileclean \ - config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \ - clang-profile-use clang-profile-make FORCE + config-sanity \ + icx-profile-use icx-profile-make \ + gcc-profile-use gcc-profile-make \ + clang-profile-use clang-profile-make FORCE build: net config-sanity $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all @@ -949,7 +953,9 @@ config-sanity: net @echo "vnni256: '$(vnni256)'" @echo "vnni512: '$(vnni512)'" @echo "neon: '$(neon)'" + @echo "dotprod: '$(dotprod)'" @echo "arm_version: '$(arm_version)'" + @echo "target_windows: '$(target_windows)'" @echo "" @echo "Flags:" @echo "CXX: $(CXX)" @@ -978,7 +984,7 @@ config-sanity: net @test "$(vnni256)" = "yes" || test "$(vnni256)" = "no" @test "$(vnni512)" = "yes" || test "$(vnni512)" = "no" @test "$(neon)" = "yes" || test "$(neon)" = "no" - @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \ + @test "$(comp)" = "gcc" || test "$(comp)" = "icx" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \ || test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang" $(EXE): $(OBJS) @@ -1016,15 +1022,17 @@ gcc-profile-use: EXTRALDFLAGS='-lgcov' \ all -icc-profile-make: - @mkdir -p profdir +icx-profile-make: $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ - EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \ + EXTRACXXFLAGS='-fprofile-instr-generate ' \ + EXTRALDFLAGS=' -fprofile-instr-generate' \ all -icc-profile-use: +icx-profile-use: + $(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ - EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \ + EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \ + EXTRALDFLAGS='-fprofile-use ' \ all .depend: $(SRCS) From 6a6e32dfc80488dfdcd6c23e601063b47729e890 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Sat, 1 Apr 2023 15:22:53 +0300 Subject: [PATCH 113/192] Decrease Depth more for positions not in TT. If the position is not in TT, decrease depth by 2 or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth. Many thanks to Vizvezdenec as the main idea was his. Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 70664 W: 18995 L: 18639 D: 33030 Ptnml(0-2): 228, 7712, 19090, 8080, 222 https://tests.stockfishchess.org/tests/view/64258a8bdb43ab2ba6f9b682 Passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 85040 W: 23227 L: 22836 D: 38977 Ptnml(0-2): 26, 8115, 25867, 8466, 46 https://tests.stockfishchess.org/tests/view/64262057db43ab2ba6f9d0e7 closes https://github.com/official-stockfish/Stockfish/pull/4482 bench: 4380438 --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 3136046d..46cca50f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -899,11 +899,11 @@ namespace { Eval::NNUE::hint_common_parent_position(pos); } - // Step 11. If the position is not in TT, decrease depth by 3. + // Step 11. If the position is not in TT, decrease depth by 2 (or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth). // Use qsearch if depth is equal or below zero (~9 Elo) if ( PvNode && !ttMove) - depth -= 3; + depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth); if (depth <= 0) return qsearch(pos, ss, alpha, beta); From 1fee996999364bedbd9ca4c29649d5c7321947c5 Mon Sep 17 00:00:00 2001 From: Miguel Lahoz Date: Sun, 2 Apr 2023 17:28:39 +0800 Subject: [PATCH 114/192] Remove unneeded bitboard from MP Recent simplification has removed the need for an extra bitboard in MP struct. Use a local variable instead. STC: Passed Non-regression test https://tests.stockfishchess.org/tests/view/64294ae677ff3301150cba16 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 64872 W: 17383 L: 17203 D: 30286 Ptnml(0-2): 179, 6675, 18546, 6859, 177 closes https://github.com/official-stockfish/Stockfish/pull/4490 No functional change. --- src/movepick.cpp | 3 +-- src/movepick.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 36ee46b5..6fbcb2c3 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -69,7 +69,6 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist stage = (pos.checkers() ? EVASION_TT : MAIN_TT) + !(ttm && pos.pseudo_legal(ttm)); - threatenedPieces = 0; } /// MovePicker constructor for quiescence search @@ -106,7 +105,7 @@ void MovePicker::score() { static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); - [[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook; + [[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook, threatenedPieces; if constexpr (Type == QUIETS) { Color us = pos.side_to_move(); diff --git a/src/movepick.h b/src/movepick.h index b6c07378..0b44557f 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -131,8 +131,6 @@ public: MovePicker(const Position&, Move, Value, const CapturePieceToHistory*); Move next_move(bool skipQuiets = false); - Bitboard threatenedPieces; - private: template Move select(Pred); template void score(); From 77e2b915e1e4f2469a414712e52b469633fb3273 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sat, 1 Apr 2023 18:48:31 -0500 Subject: [PATCH 115/192] Simplifiy TM's root complexity Also requires moving optimism initialization, this is a very early `evaluate()` call. STC: https://tests.stockfishchess.org/tests/view/6428c39677ff3301150ca0d7 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 51256 W: 13805 L: 13612 D: 23839 Ptnml(0-2): 145, 5283, 14592, 5450, 158 LTC: https://tests.stockfishchess.org/tests/view/64296ff377ff3301150cc519 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 106968 W: 28951 L: 28830 D: 49187 Ptnml(0-2): 47, 9746, 33789, 9843, 59 closes https://github.com/official-stockfish/Stockfish/pull/4492 no functional change --- src/search.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 46cca50f..becaee3a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -290,15 +290,13 @@ void Thread::search() { bestValue = delta = alpha = -VALUE_INFINITE; beta = VALUE_INFINITE; + optimism[us] = optimism[~us] = VALUE_ZERO; if (mainThread) { int rootComplexity; - if (Eval::useNNUE) - Eval::NNUE::evaluate(rootPos, true, &rootComplexity); - else - Eval::evaluate(rootPos, &rootComplexity); + Eval::evaluate(rootPos, &rootComplexity); mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); @@ -320,8 +318,6 @@ void Thread::search() { multiPV = std::min(multiPV, rootMoves.size()); - optimism[us] = optimism[~us] = VALUE_ZERO; - int searchAgainCounter = 0; // Iterative deepening loop until requested to stop or the target depth is reached From 9a42bbdf3163222db5e0fa764d48ca0a09a0dec2 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Tue, 4 Apr 2023 14:26:29 +0300 Subject: [PATCH 116/192] Parameters Tweak Passed STC LLR: 3.22 (-2.94,2.94) <0.00,2.00> Total: 664048 W: 177526 L: 176301 D: 310221 Ptnml(0-2): 2002, 72968, 180891, 74129, 2034 https://tests.stockfishchess.org/tests/view/64219901db43ab2ba6f901fa Passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 77576 W: 21125 L: 20750 D: 35701 Ptnml(0-2): 24, 7350, 23669, 7717, 28 https://tests.stockfishchess.org/tests/view/642abe3377ff3301150d3a16 closes https://github.com/official-stockfish/Stockfish/pull/4493 bench: 4522076 --- src/search.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index becaee3a..749de792 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -72,7 +72,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1449 - int(delta) * 1032 / int(rootDelta)) / 1024 + (!i && r > 941); + return (r + 1449 - int(delta) * 1001 / int(rootDelta)) / 1024 + (!i && r > 941); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -82,7 +82,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min(340 * d - 470, 1855); + return std::min(341 * d - 470, 1855); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -1057,7 +1057,7 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) + if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 16 * lmrDepth))) continue; } } @@ -1193,10 +1193,10 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4182; + - 4082; // Decrease/increase reduction for moves with a good/bad history (~25 Elo) - r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19)); + r -= ss->statScore / (11079 + 4626 * (depth > 6 && depth < 19)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has From a2737d8bb5e480563823820fb12a8887d61c991e Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Wed, 5 Apr 2023 07:25:00 +0800 Subject: [PATCH 117/192] Simplify away piece count condition for useClassical Simplify away the piece count condition for useClassical. In compensation, the psq requirement is increased by 15%. Also updated the Elo estimate for useClassical, based on recent testing. Simplification STC: https://tests.stockfishchess.org/tests/view/642acbb577ff3301150d3ef5 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 51984 W: 13906 L: 13707 D: 24371 Ptnml(0-2): 150, 5638, 14227, 5817, 160 Simplification LTC: https://tests.stockfishchess.org/tests/view/642b9c5777ff3301150d778a LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 119696 W: 32412 L: 32300 D: 54984 Ptnml(0-2): 53, 11529, 36567, 11651, 48 closes https://github.com/official-stockfish/Stockfish/pull/4494 Bench: 5089321 --- src/evaluate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 12883fcc..703cf869 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1053,8 +1053,8 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // We use the much less accurate but faster Classical eval when the NNUE // option is set to false. Otherwise we use the NNUE eval unless the - // PSQ advantage is decisive and several pieces remain. (~3 Elo) - bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1781); + // PSQ advantage is decisive. (~4 Elo at STC, 1 Elo at LTC) + bool useClassical = !useNNUE || abs(psq) > 2048; if (useClassical) v = Evaluation(pos).value(); From 510aca1ef62279dc35941fa45ed61fb9d3796f10 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 5 Apr 2023 05:48:34 +0300 Subject: [PATCH 118/192] Assign negative stat bonuses for quiet moves at Pv nodes This patch assigns negative stat bonuses for quiet moves at pv nodes which are searched at depth greater than this node assumes, so are extended. Passed STC: https://tests.stockfishchess.org/tests/view/6426198bdb43ab2ba6f9cfa2 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 548944 W: 147287 L: 146254 D: 255403 Ptnml(0-2): 1662, 59772, 150671, 60605, 1762 Passed LTC: https://tests.stockfishchess.org/tests/view/642be4f177ff3301150d892d LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 93352 W: 25400 L: 24994 D: 42958 Ptnml(0-2): 44, 8817, 28547, 9225, 43 closes https://github.com/official-stockfish/Stockfish/pull/4495 bench 5044536 --- src/search.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 749de792..aa1a3e8c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -290,7 +290,7 @@ void Thread::search() { bestValue = delta = alpha = -VALUE_INFINITE; beta = VALUE_INFINITE; - optimism[us] = optimism[~us] = VALUE_ZERO; + optimism[WHITE] = optimism[BLACK] = VALUE_ZERO; if (mainThread) { @@ -1257,6 +1257,9 @@ moves_loop: // When in check, search starts here (ss+1)->pv[0] = MOVE_NONE; value = -search(pos, ss+1, -beta, -alpha, newDepth, false); + + if (moveCount > 1 && newDepth >= depth && !capture) + update_continuation_histories(ss, movedPiece, to_sq(move), -stat_bonus(newDepth)); } // Step 19. Undo move From 59f2085469a7dd96146905a5d8d0c1a5d987187d Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Thu, 6 Apr 2023 00:35:05 +0300 Subject: [PATCH 119/192] Depth Tweak and tuning tunes reduction related parameters, and introduces more reduction on found good moves. credit for this patch goes also to candirufish Yoshie2000 dubslow peregrineshahin Vizvezdenec Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 38424 W: 10346 L: 10040 D: 18038 Ptnml(0-2): 103, 4111, 10473, 4427, 98 https://tests.stockfishchess.org/tests/view/642ca74277ff3301150db511 Passed LTC: LLR: 2.97 (-2.94,2.94) <0.50,2.50> Total: 136968 W: 37151 L: 36660 D: 63157 Ptnml(0-2): 43, 13052, 41808, 13533, 48 https://tests.stockfishchess.org/tests/view/642d632377ff3301150dddbe closes https://github.com/official-stockfish/Stockfish/pull/4499 bench: 3672914 --- src/search.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index aa1a3e8c..fba9685b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -72,7 +72,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1449 - int(delta) * 1001 / int(rootDelta)) / 1024 + (!i && r > 941); + return (r + 1449 - int(delta) * 937 / int(rootDelta)) / 1024 + (!i && r > 941); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -82,7 +82,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min(341 * d - 470, 1855); + return std::min(341 * d - 470, 1710); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -775,7 +775,7 @@ namespace { // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if (eval < alpha - 426 - 252 * depth * depth) + if (eval < alpha - 426 - 256 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -797,7 +797,7 @@ namespace { && (ss-1)->statScore < 18755 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 19 * depth - improvement / 13 + 253 + complexity / 25 + && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + complexity / 25 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) @@ -805,7 +805,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 168, 6) + depth / 3 + 4 - (complexity > 825); + Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4 - (complexity > 825); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -1333,16 +1333,18 @@ moves_loop: // When in check, search starts here if (PvNode && value < beta) // Update alpha! Always alpha < beta { - alpha = value; // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 - && depth < 6 - && beta < 10534 - && alpha > -10534) - depth -= 1; + && ((improving && complexity > 971) || (value < (5 * alpha + 75 * beta) / 87) || depth < 6) + && beta < 12535 + && value > -12535) { + bool extraReduction = depth > 2 && alpha > -12535 && bestValue != -VALUE_INFINITE && (value - bestValue) > (7 * (beta - alpha)) / 8; + depth -= 1 + extraReduction; + } assert(depth > 0); + alpha = value; } else { From b36d39de3d61b8f31c11d85233631aafaf760ee1 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 9 Apr 2023 09:18:29 +0200 Subject: [PATCH 120/192] Fix rootComplexity calculation The calculation of rootComplexity can't call eval when in check. Doing so triggers an assert if compiled in debug mode when the rootpos is evaluated using classical eval. Fixes https://github.com/official-stockfish/Stockfish/issues/4512 Passed STC: https://tests.stockfishchess.org/tests/view/6432697431feee5c6d306876 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 41096 W: 11017 L: 10815 D: 19264 Ptnml(0-2): 113, 4172, 11780, 4366, 117 Running LTC: https://tests.stockfishchess.org/tests/view/6432974d31feee5c6d306fc0 LLR: 1.76 (-2.94,2.94) <-1.75,0.25> Total: 73200 W: 19792 L: 19728 D: 33680 Ptnml(0-2): 24, 6659, 23182, 6699, 36 closes https://github.com/official-stockfish/Stockfish/pull/4515 No functional change --- src/evaluate.cpp | 2 ++ src/search.cpp | 10 ++++++---- src/thread.cpp | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 703cf869..2d0df89c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1048,6 +1048,8 @@ make_v: Value Eval::evaluate(const Position& pos, int* complexity) { + assert(!pos.checkers()); + Value v; Value psq = pos.psq_eg_stm(); diff --git a/src/search.cpp b/src/search.cpp index fba9685b..5d54a15d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -295,10 +295,12 @@ void Thread::search() { if (mainThread) { - int rootComplexity; - Eval::evaluate(rootPos, &rootComplexity); - - mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); + if (!rootPos.checkers()) + { + int rootComplexity; + Eval::evaluate(rootPos, &rootComplexity); + mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); + } if (mainThread->bestPreviousScore == VALUE_INFINITE) for (int i = 0; i < 4; ++i) diff --git a/src/thread.cpp b/src/thread.cpp index c680393e..202768c8 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -160,6 +160,7 @@ void ThreadPool::clear() { main()->bestPreviousScore = VALUE_INFINITE; main()->bestPreviousAverageScore = VALUE_INFINITE; main()->previousTimeReduction = 1.0; + main()->complexity = 1.0; } From 5d258e168f7ea9019ed640ae2e56f04b26aea6a2 Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Sat, 1 Apr 2023 20:14:41 +0300 Subject: [PATCH 121/192] Fix linking / character types of windows API calls ensures large pages can be allocated again. closes https://github.com/official-stockfish/Stockfish/pull/4509 No functional change --- src/misc.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index e36a04bc..f1554060 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -490,25 +490,29 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize return nullptr; // Dynamically link OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges - HMODULE k32 = GetModuleHandle("Advapi32.dll"); - auto fun6 = (fun6_t)(void(*)())GetProcAddress(k32, "OpenProcessToken"); + + HMODULE hAdvapi32 = GetModuleHandle(TEXT("advapi32.dll")); + + if (!hAdvapi32) + hAdvapi32 = LoadLibrary(TEXT("advapi32.dll")); + + auto fun6 = (fun6_t)(void(*)())GetProcAddress(hAdvapi32, "OpenProcessToken"); if (!fun6) return nullptr; - auto fun7 = (fun7_t)(void(*)())GetProcAddress(k32, "LookupPrivilegeValueA"); + auto fun7 = (fun7_t)(void(*)())GetProcAddress(hAdvapi32, "LookupPrivilegeValueA"); if (!fun7) return nullptr; - auto fun8 = (fun8_t)(void(*)())GetProcAddress(k32, "AdjustTokenPrivileges"); + auto fun8 = (fun8_t)(void(*)())GetProcAddress(hAdvapi32, "AdjustTokenPrivileges"); if (!fun8) return nullptr; - // We need SeLockMemoryPrivilege, so try to enable it for the process - // OpenProcessToken() - if (!fun6(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken)) - return nullptr; + if (!fun6( // OpenProcessToken() + GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken)) + return nullptr; - // LookupPrivilegeValueA() - if (fun7(nullptr, SE_LOCK_MEMORY_NAME, &luid)) + if (fun7( // LookupPrivilegeValue(nullptr, SE_LOCK_MEMORY_NAME, &luid) + nullptr, "SeLockMemoryPrivilege", &luid)) { TOKEN_PRIVILEGES tp { }; TOKEN_PRIVILEGES prevTp { }; @@ -520,8 +524,7 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds, // we still need to query GetLastError() to ensure that the privileges were actually obtained. - // AdjustTokenPrivileges() - if (fun8( + if (fun8( // AdjustTokenPrivileges() hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) && GetLastError() == ERROR_SUCCESS) { @@ -531,8 +534,8 @@ static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); // Privilege no longer needed, restore previous state - // AdjustTokenPrivileges () - fun8(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr); + fun8( // AdjustTokenPrivileges () + hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr); } } From 6e63dd63a4f1e3074a9f5a8d7f64fdd0eba19c7e Mon Sep 17 00:00:00 2001 From: MinetaS Date: Fri, 7 Apr 2023 15:23:04 +0000 Subject: [PATCH 122/192] Use int conversion for Option class The current implementation generates warnings on MSVC. However, we have no real use cases for double-typed UCI option values now. Also parameter tuning only accepts following three types: int, Value, Score closes https://github.com/official-stockfish/Stockfish/pull/4505 No functional change --- src/tt.cpp | 4 ++-- src/uci.h | 2 +- src/ucioption.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tt.cpp b/src/tt.cpp index 39f18d3d..3339c993 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -87,7 +87,7 @@ void TranspositionTable::clear() { std::vector threads; - for (size_t idx = 0; idx < Options["Threads"]; ++idx) + for (size_t idx = 0; idx < size_t(Options["Threads"]); ++idx) { threads.emplace_back([this, idx]() { @@ -98,7 +98,7 @@ void TranspositionTable::clear() { // Each thread will zero its part of the hash table const size_t stride = size_t(clusterCount / Options["Threads"]), start = size_t(stride * idx), - len = idx != Options["Threads"] - 1 ? + len = idx != size_t(Options["Threads"]) - 1 ? stride : clusterCount - start; std::memset(&table[start], 0, len * sizeof(Cluster)); diff --git a/src/uci.h b/src/uci.h index 70e45acc..9ca0ed36 100644 --- a/src/uci.h +++ b/src/uci.h @@ -61,7 +61,7 @@ public: Option& operator=(const std::string&); void operator<<(const Option&); - operator double() const; + operator int() const; operator std::string() const; bool operator==(const char*) const; diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 39933ea5..f6342e5c 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -128,9 +128,9 @@ Option::Option(double v, int minv, int maxv, OnChange f) : type("spin"), min(min Option::Option(const char* v, const char* cur, OnChange f) : type("combo"), min(0), max(0), on_change(f) { defaultValue = v; currentValue = cur; } -Option::operator double() const { +Option::operator int() const { assert(type == "check" || type == "spin"); - return (type == "spin" ? stof(currentValue) : currentValue == "true"); + return (type == "spin" ? std::stoi(currentValue) : currentValue == "true"); } Option::operator std::string() const { From a5643b89fda5060d4b40dff54afe02816c899dd4 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Fri, 7 Apr 2023 14:30:59 +0000 Subject: [PATCH 123/192] Remove extraReduction Since bestValue becomes value and beta - alpha is always non-negative, extraReduction is always false, hence it has no effect. This patch includes small changes to improve readability. closes https://github.com/official-stockfish/Stockfish/pull/4505 No functional change --- src/search.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5d54a15d..4463b42a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1335,15 +1335,14 @@ moves_loop: // When in check, search starts here if (PvNode && value < beta) // Update alpha! Always alpha < beta { - // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 - && ((improving && complexity > 971) || (value < (5 * alpha + 75 * beta) / 87) || depth < 6) + && ( (improving && complexity > 971) + || value < (5 * alpha + 75 * beta) / 87 + || depth < 6) && beta < 12535 - && value > -12535) { - bool extraReduction = depth > 2 && alpha > -12535 && bestValue != -VALUE_INFINITE && (value - bestValue) > (7 * (beta - alpha)) / 8; - depth -= 1 + extraReduction; - } + && value > -12535) + depth -= 1; assert(depth > 0); alpha = value; From 2f2f45f9f47c1212f3229c22304456c9bad8f843 Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Thu, 6 Apr 2023 14:08:50 +0300 Subject: [PATCH 124/192] Made two specializations for affine transform easier to understand. Added AVX-512 for the specialization for small inputs closes https://github.com/official-stockfish/Stockfish/pull/4502 No functional change --- src/nnue/layers/affine_transform.h | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index f84f054e..9e2f2f97 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -31,7 +31,7 @@ This file contains the definition for a fully connected layer (aka affine transform). Two approaches are employed, depending on the sizes of the transform. - Approach 1: + Approach 1 (a specialization for large inputs): - used when the PaddedInputDimensions >= 128 - uses AVX512 if possible - processes inputs in batches of 2*InputSimdWidth @@ -42,9 +42,8 @@ depends on the architecture (the amount of registers) - accumulate + hadd is used - Approach 2: + Approach 2 (a specialization for small inputs): - used when the PaddedInputDimensions < 128 - - does not use AVX512 - expected use-case is for when PaddedInputDimensions == 32 and InputDimensions <= 32. - that's why AVX512 is hard to implement - expected use-case is small layers @@ -169,7 +168,7 @@ namespace Stockfish::Eval::NNUE::Layers { constexpr IndexType LargeInputSize = std::numeric_limits::max(); #endif - // A specialization for large inputs. + // A specialization for large inputs template class AffineTransform(InDims, MaxSimdWidth) >= LargeInputSize)>> { public: @@ -188,7 +187,7 @@ namespace Stockfish::Eval::NNUE::Layers { using OutputBuffer = OutputType[PaddedOutputDimensions]; - static_assert(PaddedInputDimensions >= LargeInputSize, "Something went wrong. This specialization should not have been chosen."); + static_assert(PaddedInputDimensions >= LargeInputSize, "Something went wrong. This specialization (for large inputs) should not have been chosen."); #if defined (USE_AVX512) static constexpr IndexType InputSimdWidth = 64; @@ -396,6 +395,7 @@ namespace Stockfish::Eval::NNUE::Layers { alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions]; }; + // A specialization for small inputs template class AffineTransform(InDims, MaxSimdWidth) < LargeInputSize)>> { public: @@ -415,12 +415,7 @@ namespace Stockfish::Eval::NNUE::Layers { using OutputBuffer = OutputType[PaddedOutputDimensions]; - static_assert(PaddedInputDimensions < LargeInputSize, "Something went wrong. This specialization should not have been chosen."); - -#if defined (USE_SSSE3) - static constexpr IndexType OutputSimdWidth = SimdWidth / 4; - static constexpr IndexType InputSimdWidth = SimdWidth; -#endif + static_assert(PaddedInputDimensions < LargeInputSize, "Something went wrong. This specialization (for small inputs) should not have been chosen."); // Hash value embedded in the evaluation file static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) { @@ -470,7 +465,14 @@ namespace Stockfish::Eval::NNUE::Layers { const OutputType* propagate( const InputType* input, OutputType* output) const { -#if defined (USE_AVX2) +#if defined (USE_AVX512) + using vec_t = __m512i; + #define vec_setzero _mm512_setzero_si512 + #define vec_set_32 _mm512_set1_epi32 + #define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32 + #define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2 + #define vec_hadd Simd::m512_hadd +#elif defined (USE_AVX2) using vec_t = __m256i; #define vec_setzero _mm256_setzero_si256 #define vec_set_32 _mm256_set1_epi32 @@ -489,6 +491,8 @@ namespace Stockfish::Eval::NNUE::Layers { #if defined (USE_SSSE3) const auto inputVector = reinterpret_cast(input); + static constexpr IndexType OutputSimdWidth = sizeof(vec_t) / sizeof(OutputType); + static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1); if constexpr (OutputDimensions % OutputSimdWidth == 0) From 7a9f67747f23e837a8691ba9e6e4f0d1fdafff73 Mon Sep 17 00:00:00 2001 From: mstembera Date: Tue, 4 Apr 2023 19:44:09 -0700 Subject: [PATCH 125/192] Reduce Position::pieces() overloads Reduce the number of overloads for pieces() by using a more general template implementation. Secondly simplify some code in search.cpp using the new general functionality. TC https://tests.stockfishchess.org/tests/view/642ce27877ff3301150dc193 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 269640 W: 71775 L: 71809 D: 126056 Ptnml(0-2): 687, 27294, 78885, 27274, 680 closes https://github.com/official-stockfish/Stockfish/pull/4501 No functional change. --- src/position.h | 19 ++++++++----------- src/search.cpp | 12 +++++++----- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/position.h b/src/position.h index bb45c44a..a736f3e6 100644 --- a/src/position.h +++ b/src/position.h @@ -92,10 +92,9 @@ public: // Position representation Bitboard pieces(PieceType pt) const; - Bitboard pieces(PieceType pt1, PieceType pt2) const; + template Bitboard pieces(PieceType pt, PieceTypes... pts) const; Bitboard pieces(Color c) const; - Bitboard pieces(Color c, PieceType pt) const; - Bitboard pieces(Color c, PieceType pt1, PieceType pt2) const; + template Bitboard pieces(Color c, PieceTypes... pts) const; Piece piece_on(Square s) const; Square ep_square() const; bool empty(Square s) const; @@ -229,20 +228,18 @@ inline Bitboard Position::pieces(PieceType pt = ALL_PIECES) const { return byTypeBB[pt]; } -inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const { - return pieces(pt1) | pieces(pt2); +template +inline Bitboard Position::pieces(PieceType pt, PieceTypes... pts) const { + return pieces(pt) | pieces(pts...); } inline Bitboard Position::pieces(Color c) const { return byColorBB[c]; } -inline Bitboard Position::pieces(Color c, PieceType pt) const { - return pieces(c) & pieces(pt); -} - -inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const { - return pieces(c) & (pieces(pt1) | pieces(pt2)); +template +inline Bitboard Position::pieces(Color c, PieceTypes... pts) const { + return pieces(c) & pieces(pts...); } template inline int Position::count(Color c) const { diff --git a/src/search.cpp b/src/search.cpp index 4463b42a..4187117b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1018,16 +1018,18 @@ moves_loop: // When in check, search starts here { if (depth < 2 - capture) continue; - // don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges - Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & occupied; + // Don't prune the move if opp. King/Queen/Rook is attacked by a slider after the exchanges. + // Since in see_ge we don't update occupied when the king recaptures, we also don't prune the + // move when the opp. King gets a discovered slider attack DURING the exchanges. + Bitboard leftEnemies = pos.pieces(~us, ROOK, QUEEN, KING) & occupied; Bitboard attacks = 0; occupied |= to_sq(move); while (leftEnemies && !attacks) { Square sq = pop_lsb(leftEnemies); - attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; - // exclude Queen/Rook(s) which were already threatened before SEE - if (attacks && (sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))) + attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; + // Exclude Queen/Rook(s) which were already threatened before SEE + if (attacks && sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))) attacks = 0; } if (!attacks) From 1a64afb1c65591ccd374504c791eb27b762f6c8f Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Sat, 1 Apr 2023 23:49:03 +0300 Subject: [PATCH 126/192] Do no initialize TM in all cases Avoid doing full TM initialization if it won't be used, avoids division by zero. closes https://github.com/official-stockfish/Stockfish/pull/4484 No functional change --- src/timeman.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index 5c826b4f..061de018 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -36,6 +36,12 @@ TimeManagement Time; // Our global time management object void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { + // if we have no time, no need to initialize TM, except for the start time, + // which is used by movetime. + startTime = limits.startTime; + if (limits.time[us] == 0) + return; + TimePoint moveOverhead = TimePoint(Options["Move Overhead"]); TimePoint slowMover = TimePoint(Options["Slow Mover"]); TimePoint npmsec = TimePoint(Options["nodestime"]); @@ -59,8 +65,6 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { limits.npmsec = npmsec; } - startTime = limits.startTime; - // Maximum move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; From 7bd23d4d04d6644b6ccae8ea63cfc6646e4248dd Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Fri, 7 Apr 2023 12:33:28 -0400 Subject: [PATCH 127/192] Simplify away nnue scale pawn count multiplier Removes 2x multipliers in nnue scale calculation along with the pawn count term that was recently reintroduced. Passed non-regression STC: https://tests.stockfishchess.org/tests/view/64305bc720eb941419bdf72e LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 38008 W: 10234 L: 10021 D: 17753 Ptnml(0-2): 96, 4151, 10323, 4312, 122 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/6430b76a028b029b01ac9bfd LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 91232 W: 24686 L: 24547 D: 41999 Ptnml(0-2): 30, 8721, 27986, 8838, 41 closes https://github.com/official-stockfish/Stockfish/pull/4510 bench 4017320 --- src/evaluate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 2d0df89c..873dc5d2 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { else { int nnueComplexity; - int scale = 1001 + 5 * pos.count() + 61 * pos.non_pawn_material() / 4096; + int scale = 1001 + pos.non_pawn_material() / 64; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; From 4ad2713e19cbf8db1e588c4d24d1fe4af5c6e917 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Fri, 17 Mar 2023 00:04:41 +0300 Subject: [PATCH 128/192] Fix capturing underpromotions issue Fix underpromotion captures are generated amongst quiets although dealt with as a capture_stage in search, this makes not skipping them when move count pruning kicks-in consistent with updating their histories amongst captures. Passed STC: https://tests.stockfishchess.org/tests/view/6415579f65775d3b539e7537 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 118896 W: 31678 L: 31553 D: 55665 Ptnml(0-2): 356, 12911, 32793, 13028, 360 Passed LTC: https://tests.stockfishchess.org/tests/view/641633b965775d3b539e9e95 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 126800 W: 34255 L: 34148 D: 58397 Ptnml(0-2): 57, 12216, 38763, 12291, 73 see also discussion in https://github.com/official-stockfish/Stockfish/pull/4436 closes https://github.com/official-stockfish/Stockfish/pull/4452 bench: 3979409 --- src/movegen.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/movegen.cpp b/src/movegen.cpp index 255dce04..6b28a52e 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -25,13 +25,21 @@ namespace Stockfish { namespace { - template + template ExtMove* make_promotions(ExtMove* moveList, [[maybe_unused]] Square to) { if constexpr (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) + { *moveList++ = make(to - D, to, QUEEN); + if constexpr (Enemy && Type == CAPTURES) + { + *moveList++ = make(to - D, to, ROOK); + *moveList++ = make(to - D, to, BISHOP); + *moveList++ = make(to - D, to, KNIGHT); + } + } - if constexpr (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS) + if constexpr ((Type == QUIETS && !Enemy) || Type == EVASIONS || Type == NON_EVASIONS) { *moveList++ = make(to - D, to, ROOK); *moveList++ = make(to - D, to, BISHOP); @@ -106,13 +114,13 @@ namespace { b3 &= target; while (b1) - moveList = make_promotions(moveList, pop_lsb(b1)); + moveList = make_promotions(moveList, pop_lsb(b1)); while (b2) - moveList = make_promotions(moveList, pop_lsb(b2)); + moveList = make_promotions(moveList, pop_lsb(b2)); while (b3) - moveList = make_promotions(moveList, pop_lsb(b3)); + moveList = make_promotions(moveList, pop_lsb(b3)); } // Standard and en passant captures From f66c36277fe57d0ce4f10a4aeb5b41eb0cb9ebd1 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 5 Apr 2023 20:30:01 -0500 Subject: [PATCH 129/192] Remove nmpColor no benefit seen, neither in game play nor for zugzwang test positions STC: https://tests.stockfishchess.org/tests/view/642e293977ff3301150e9b55 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 161848 W: 43332 L: 43254 D: 75262 Ptnml(0-2): 418, 16987, 46058, 17021, 440 LTC: https://tests.stockfishchess.org/tests/view/642fea9420eb941419bde296 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 120208 W: 32529 L: 32418 D: 55261 Ptnml(0-2): 35, 11424, 37080, 11525, 40 closes https://github.com/official-stockfish/Stockfish/pull/4511 bench 3979409 --- src/search.cpp | 5 ++--- src/thread.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4187117b..04299dbd 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -802,7 +802,7 @@ namespace { && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + complexity / 25 && !excludedMove && pos.non_pawn_material(us) - && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) + && (ss->ply >= thisThread->nmpMinPly)) { assert(eval - beta >= 0); @@ -830,9 +830,8 @@ namespace { assert(!thisThread->nmpMinPly); // Recursive verification is not allowed // Do verification search at high depths, with null move pruning disabled - // for us, until ply exceeds nmpMinPly. + // until ply exceeds nmpMinPly. thisThread->nmpMinPly = ss->ply + 3 * (depth-R) / 4; - thisThread->nmpColor = us; Value v = search(pos, ss, beta-1, beta, depth-R, false); diff --git a/src/thread.h b/src/thread.h index d6a48eca..3a114c79 100644 --- a/src/thread.h +++ b/src/thread.h @@ -62,7 +62,6 @@ public: size_t pvIdx, pvLast; std::atomic nodes, tbHits, bestMoveChanges; int selDepth, nmpMinPly; - Color nmpColor; Value bestValue, optimism[COLOR_NB]; Position rootPos; From 9829bceda90d025a5f5d7c04457902413e367041 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Tue, 11 Apr 2023 01:20:29 +0200 Subject: [PATCH 130/192] Remove good killer reduction rule. STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 246544 W: 65646 L: 65657 D: 115241 Ptnml(0-2): 706, 27350, 67138, 27405, 673 https://tests.stockfishchess.org/tests/view/642e253277ff3301150e9aa2 LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 165136 W: 44878 L: 44809 D: 75449 Ptnml(0-2): 64, 15991, 50378, 16082, 53 https://tests.stockfishchess.org/tests/view/6430db07028b029b01acd87f closes https://github.com/official-stockfish/Stockfish/pull/4519 Bench: 3746080 --- src/search.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 04299dbd..411befde 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1187,11 +1187,6 @@ moves_loop: // When in check, search starts here if ((ss+1)->cutoffCnt > 3) r++; - // Decrease reduction if move is a killer and we have a good history (~1 Elo) - if (move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 3722) - r--; - ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] From acb0d204d56e16398c58822df2cc60b90ef1ae85 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Tue, 11 Apr 2023 19:53:36 +0300 Subject: [PATCH 131/192] Simplify stats assignment for Pv nodes This patch is a simplification of my recent elo gainer. Logically the Elo gainer didn't make much sense and this patch simplifies it into smth more logical. Instead of assigning negative bonuses to all non-first moves that enter PV nodes we assign positive bonuses in full depth search after LMR only for moves that will result in a fail high - thus not assigning positive bonuses for moves that will go to pv search - so doing "almost" the same as we do in master now for them. Logic differs for some other moves, though, but this removes some lines of code. Passed STC: https://tests.stockfishchess.org/tests/view/642cf5cf77ff3301150dc5ec LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 409320 W: 109124 L: 109308 D: 190888 Ptnml(0-2): 1149, 45385, 111751, 45251, 1124 Passed LTC: https://tests.stockfishchess.org/tests/view/642fe75d20eb941419bde200 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 260336 W: 70280 L: 70303 D: 119753 Ptnml(0-2): 99, 25236, 79528, 25199, 106 closes https://github.com/official-stockfish/Stockfish/pull/4522 Bench: 4286815 --- src/search.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 411befde..390c6b1c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1229,8 +1229,9 @@ moves_loop: // When in check, search starts here if (newDepth > d) value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); - int bonus = value > alpha ? stat_bonus(newDepth) - : -stat_bonus(newDepth); + int bonus = value <= alpha ? -stat_bonus(newDepth) + : value >= beta ? stat_bonus(newDepth) + : 0; update_continuation_histories(ss, movedPiece, to_sq(move), bonus); } @@ -1255,9 +1256,6 @@ moves_loop: // When in check, search starts here (ss+1)->pv[0] = MOVE_NONE; value = -search(pos, ss+1, -beta, -alpha, newDepth, false); - - if (moveCount > 1 && newDepth >= depth && !capture) - update_continuation_histories(ss, movedPiece, to_sq(move), -stat_bonus(newDepth)); } // Step 19. Undo move From 96b6c0b36f28f0ef5fa58f48405db710542521df Mon Sep 17 00:00:00 2001 From: MinetaS Date: Fri, 7 Apr 2023 14:49:05 +0000 Subject: [PATCH 132/192] Remove some conditions at PV improvement reduction Non-regression STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 63664 W: 17007 L: 16823 D: 29834 Ptnml(0-2): 163, 6998, 17336, 7162, 173 https://tests.stockfishchess.org/tests/view/6430b124028b029b01ac99f2 Non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 90016 W: 24399 L: 24258 D: 41359 Ptnml(0-2): 52, 8672, 27405, 8841, 38 https://tests.stockfishchess.org/tests/view/64310e74028b029b01ad3131 closes https://github.com/official-stockfish/Stockfish/pull/4526 Bench: 3661938 --- src/search.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 390c6b1c..ed81263a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1331,9 +1331,6 @@ moves_loop: // When in check, search starts here { // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 - && ( (improving && complexity > 971) - || value < (5 * alpha + 75 * beta) / 87 - || depth < 6) && beta < 12535 && value > -12535) depth -= 1; From f9d9c69bc33dc7a17c28cd586d7e67c1bfff66f6 Mon Sep 17 00:00:00 2001 From: Torom Date: Thu, 13 Apr 2023 21:55:13 +0200 Subject: [PATCH 133/192] Set the length of GIT_SHA to 8 characters Previously, the length of git commit hashes could vary depending on the git environment. closes https://github.com/official-stockfish/Stockfish/pull/4527 No functional change --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index abcf11b0..82664618 100644 --- a/src/Makefile +++ b/src/Makefile @@ -702,7 +702,7 @@ ifeq ($(pext),yes) endif ### 3.7.1 Try to include git commit sha for versioning -GIT_SHA = $(shell git rev-parse --short HEAD 2>/dev/null) +GIT_SHA = $(shell git rev-parse HEAD 2>/dev/null | cut -c 1-8) ifneq ($(GIT_SHA), ) CXXFLAGS += -DGIT_SHA=$(GIT_SHA) endif From c90dd38903206ede56fa73c15d7d2b366d56ebdb Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Fri, 14 Apr 2023 20:48:22 +0800 Subject: [PATCH 134/192] Simplify away complexity in evaluation Simplification STC: https://tests.stockfishchess.org/tests/view/64394bc0605991a801b4f6f0 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 72360 W: 19313 L: 19138 D: 33909 Ptnml(0-2): 206, 7883, 19800, 8112, 179 Simplification LTC: https://tests.stockfishchess.org/tests/view/6439e788c233ce943b6bdac1 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 224992 W: 60665 L: 60654 D: 103673 Ptnml(0-2): 96, 21875, 68526, 21920, 79 closes https://github.com/official-stockfish/Stockfish/pull/4530 Bench: 3709369 --- src/evaluate.cpp | 10 +--------- src/evaluate.h | 2 +- src/search.cpp | 27 ++++++++------------------- src/thread.cpp | 1 - src/thread.h | 1 - 5 files changed, 10 insertions(+), 31 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 873dc5d2..851ccfe1 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1046,7 +1046,7 @@ make_v: /// evaluate() is the evaluator for the outer world. It returns a static /// evaluation of the position from the point of view of the side to move. -Value Eval::evaluate(const Position& pos, int* complexity) { +Value Eval::evaluate(const Position& pos) { assert(!pos.checkers()); @@ -1075,10 +1075,6 @@ Value Eval::evaluate(const Position& pos, int* complexity) { + (424 + optimism) * abs(psq - nnue) ) / 1024; - // Return hybrid NNUE complexity to caller - if (complexity) - *complexity = nnueComplexity; - optimism = optimism * (272 + nnueComplexity) / 256; v = (nnue * scale + optimism * (scale - 748)) / 1024; } @@ -1089,10 +1085,6 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // 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); - // When not using NNUE, return classical complexity to caller - if (complexity && useClassical) - *complexity = abs(v - psq); - return v; } diff --git a/src/evaluate.h b/src/evaluate.h index 61846073..48076670 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -31,7 +31,7 @@ class Position; namespace Eval { std::string trace(Position& pos); - Value evaluate(const Position& pos, int* complexity = nullptr); + Value evaluate(const Position& pos); extern bool useNNUE; extern std::string currentEvalFileName; diff --git a/src/search.cpp b/src/search.cpp index ed81263a..3a7f85a8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -294,14 +294,6 @@ void Thread::search() { if (mainThread) { - - if (!rootPos.checkers()) - { - int rootComplexity; - Eval::evaluate(rootPos, &rootComplexity); - mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); - } - if (mainThread->bestPreviousScore == VALUE_INFINITE) for (int i = 0; i < 4; ++i) mainThread->iterValue[i] = VALUE_ZERO; @@ -478,7 +470,7 @@ void Thread::search() { double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction); double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size(); - double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * mainThread->complexity; + double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability; // Cap used time in case of a single legal move for a better viewer experience in tournaments // yielding correct scores and sufficiently fast moves. @@ -561,7 +553,7 @@ namespace { bool givesCheck, improving, priorCapture, singularQuietLMR; bool capture, moveCountPruning, ttCapture; Piece movedPiece; - int moveCount, captureCount, quietCount, improvement, complexity; + int moveCount, captureCount, quietCount, improvement; // Step 1. Initialize node Thread* thisThread = pos.this_thread(); @@ -723,7 +715,6 @@ namespace { ss->staticEval = eval = VALUE_NONE; improving = false; improvement = 0; - complexity = 0; goto moves_loop; } else if (excludedMove) @@ -731,17 +722,15 @@ namespace { // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 Elo) Eval::NNUE::hint_common_parent_position(pos); eval = ss->staticEval; - complexity = abs(ss->staticEval - pos.psq_eg_stm()); } else if (ss->ttHit) { // Never assume anything about values stored in TT ss->staticEval = eval = tte->eval(); if (eval == VALUE_NONE) - ss->staticEval = eval = evaluate(pos, &complexity); - else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost + ss->staticEval = eval = evaluate(pos); + else { - complexity = abs(ss->staticEval - pos.psq_eg_stm()); if (PvNode) Eval::NNUE::hint_common_parent_position(pos); } @@ -753,7 +742,7 @@ namespace { } else { - ss->staticEval = eval = evaluate(pos, &complexity); + ss->staticEval = eval = evaluate(pos); // Save static evaluation into transposition table tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } @@ -799,15 +788,15 @@ namespace { && (ss-1)->statScore < 18755 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + complexity / 25 + && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly)) { assert(eval - beta >= 0); - // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4 - (complexity > 825); + // Null move dynamic reduction based on depth and eval + Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4; ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; diff --git a/src/thread.cpp b/src/thread.cpp index 202768c8..c680393e 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -160,7 +160,6 @@ void ThreadPool::clear() { main()->bestPreviousScore = VALUE_INFINITE; main()->bestPreviousAverageScore = VALUE_INFINITE; main()->previousTimeReduction = 1.0; - main()->complexity = 1.0; } diff --git a/src/thread.h b/src/thread.h index 3a114c79..09bdb470 100644 --- a/src/thread.h +++ b/src/thread.h @@ -85,7 +85,6 @@ struct MainThread : public Thread { void search() override; void check_time(); - double complexity; double previousTimeReduction; Value bestPreviousScore; Value bestPreviousAverageScore; From 7b9b793fd544aa7a599b113a40533cde16de640b Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Mon, 17 Apr 2023 11:38:26 +0200 Subject: [PATCH 135/192] Simplification of SEE verification logic Use same logic for all handled pieces. Don't prune the move if opponent King, Queen, Rook gets a discovered attack while or after the exchanges. remove an obsolete comment in position.cpp Passed STC non regression: https://tests.stockfishchess.org/tests/view/6437907594daa91835c290d0 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 107432 W: 28359 L: 28221 D: 50852 Ptnml(0-2): 298, 11724, 29524, 11882, 288 Passed LTC non-regression: https://tests.stockfishchess.org/tests/view/6438ed2ebd1a5470263c51e8 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 236288 W: 63656 L: 63656 D: 108976 Ptnml(0-2): 99, 22960, 72011, 22990, 84 closes https://github.com/official-stockfish/Stockfish/pull/4533 bench: 3741125 --- src/position.cpp | 3 +-- src/search.cpp | 8 +++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index e6fdb511..2a9d798f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -331,8 +331,7 @@ void Position::set_check_info() const { /// Position::set_state() computes the hash keys of the position, and other /// data that once computed is updated incrementally as moves are made. -/// The function is only used when a new position is set up, and to verify -/// the correctness of the StateInfo data when running in debug mode. +/// The function is only used when a new position is set up void Position::set_state() const { diff --git a/src/search.cpp b/src/search.cpp index 3a7f85a8..5205fb57 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1006,17 +1006,15 @@ moves_loop: // When in check, search starts here { if (depth < 2 - capture) continue; - // Don't prune the move if opp. King/Queen/Rook is attacked by a slider after the exchanges. - // Since in see_ge we don't update occupied when the king recaptures, we also don't prune the - // move when the opp. King gets a discovered slider attack DURING the exchanges. - Bitboard leftEnemies = pos.pieces(~us, ROOK, QUEEN, KING) & occupied; + // Don't prune the move if opp. King/Queen/Rook gets a discovered attack during or after the exchanges + Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK); Bitboard attacks = 0; occupied |= to_sq(move); while (leftEnemies && !attacks) { Square sq = pop_lsb(leftEnemies); attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; - // Exclude Queen/Rook(s) which were already threatened before SEE + // Exclude Queen/Rook(s) which were already threatened before SEE (opp King can't be in check when it's our turn) if (attacks && sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))) attacks = 0; } From d64d4ac426e06cdd52249b0464d22f3cdb7fcf79 Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Fri, 14 Apr 2023 20:33:33 +0800 Subject: [PATCH 136/192] Simplify away depth condition for aspiration window adjust Simplification STC: https://tests.stockfishchess.org/tests/view/64351654596a20f264276ded LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 374664 W: 98942 L: 99089 D: 176633 Ptnml(0-2): 1049, 41767, 101878, 41558, 1080 Simplification LTC: https://tests.stockfishchess.org/tests/view/6439499f605991a801b4f684 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 457880 W: 123021 L: 123233 D: 211626 Ptnml(0-2): 166, 44739, 139335, 44541, 159 closes https://github.com/official-stockfish/Stockfish/pull/4534 Bench: 3879281 --- src/search.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5205fb57..e322a1c9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -288,9 +288,7 @@ void Thread::search() { ss->pv = pv; - bestValue = delta = alpha = -VALUE_INFINITE; - beta = VALUE_INFINITE; - optimism[WHITE] = optimism[BLACK] = VALUE_ZERO; + bestValue = -VALUE_INFINITE; if (mainThread) { @@ -349,18 +347,15 @@ void Thread::search() { selDepth = 0; // Reset aspiration window starting size - if (rootDepth >= 4) - { - Value prev = rootMoves[pvIdx].averageScore; - delta = Value(10) + int(prev) * prev / 16502; - alpha = std::max(prev - delta,-VALUE_INFINITE); - beta = std::min(prev + delta, VALUE_INFINITE); + Value prev = rootMoves[pvIdx].averageScore; + delta = Value(10) + int(prev) * prev / 16502; + alpha = std::max(prev - delta,-VALUE_INFINITE); + beta = std::min(prev + delta, VALUE_INFINITE); - // Adjust optimism based on root move's previousScore - int opt = 120 * prev / (std::abs(prev) + 161); - optimism[ us] = Value(opt); - optimism[~us] = -optimism[us]; - } + // Adjust optimism based on root move's previousScore + int opt = 120 * prev / (std::abs(prev) + 161); + optimism[ us] = Value(opt); + optimism[~us] = -optimism[us]; // Start with a small aspiration window and, in the case of a fail // high/low, re-search with a bigger window until we don't fail From ba06c480a752458a8159db0c9110bd3b7e34145a Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Fri, 21 Apr 2023 16:22:55 +0200 Subject: [PATCH 137/192] Less reduction for tt move. This idea is a result of my second condition combination tuning for reductions: https://tests.stockfishchess.org/tests/view/643ed5573806eca398f06d61 There were used two parameters per combination: one for the 'sign' of the first and the second condition in a combination. Values >= 50 indicate using a condition directly and values <= -50 means use the negation of a condition. Each condition pair (X,Y) had two occurances dependent of the order of the two conditions: - if X < Y the parameters used for more reduction - if X > Y the parameters used for less reduction - if X = Y then only one condition is present and A[X][X][0]/A[X][X][1] stands for using more/less reduction for only this condition. The parameter pair A[7][2][0] (value = -94.70) and A[7][2][1] (value = 93.60) was one of the strongest signals with values near 100/-100. Here condition nr. 7 was '(ss+1)->cutoffCnt > 3' and condition nr. 2 'move == ttMove'. For condition nr. 7 the negation is used because A[7][2][0] is negative. This translates finally to less reduction (because 7 > 2) for tt moves if child cutoffs <= 3. STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 65728 W: 17704 L: 17358 D: 30666 Ptnml(0-2): 184, 7092, 18008, 7354, 226 https://tests.stockfishchess.org/tests/view/643ff767ef2529086a7ed042 LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 139200 W: 37776 L: 37282 D: 64142 Ptnml(0-2): 58, 13241, 42509, 13733, 59 https://tests.stockfishchess.org/tests/view/6440bfa9ef2529086a7edbc7 closes https://github.com/official-stockfish/Stockfish/pull/4538 Bench: 3548023 --- src/search.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index e322a1c9..366065b8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1169,6 +1169,9 @@ moves_loop: // When in check, search starts here if ((ss+1)->cutoffCnt > 3) r++; + else if (move == ttMove) + r--; + ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] From b22a1b10bbae2bb773afb50eba23dbf15e426365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=C5=A1tjan=20Mejak?= Date: Tue, 11 Apr 2023 13:55:14 +0200 Subject: [PATCH 138/192] Update AUTHORS Improved some comments in the AUTHORS file, sort contributors closes https://github.com/official-stockfish/Stockfish/pull/4520 No functional change --- AUTHORS | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/AUTHORS b/AUTHORS index 9b36111e..b6723246 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,17 +1,15 @@ -# List of authors for Stockfish - -# Founders of the Stockfish project and fishtest infrastructure +# Founders of the Stockfish project and Fishtest infrastructure Tord Romstad (romstad) Marco Costalba (mcostalba) Joona Kiiski (zamar) Gary Linscott (glinscott) -# Authors and inventors of NNUE, training, NNUE port +# Authors and inventors of NNUE, training, and NNUE port Yu Nasu (ynasu87) Motohiro Isozaki (yaneurao) Hisayori Noda (nodchip) -# all other authors of the code in alphabetical order +# All other authors of Stockfish code (in alphabetical order) Aditya (absimaldata) Adrian Petrescu (apetresc) Ajith Chandy Jose (ajithcj) @@ -47,12 +45,12 @@ Chess13234 Chris Cain (ceebo) clefrks Dale Weiler (graphitemaster) -Dan Schmidt (dfannius) Daniel Axtens (daxtens) Daniel Dugovic (ddugovic) +Dan Schmidt (dfannius) Dariusz Orzechowski (dorzechowski) -David Zar David (dav1312) +David Zar Daylen Yang (daylen) Deshawn Mohan-Smith (GoldenRare) Dieter Dobbelaere (ddobbelaere) @@ -66,7 +64,6 @@ Eelco de Groot (KingDefender) Elvin Liu (solarlight2) erbsenzaehler Ernesto Gatti -Linmiao Xu (linrock) Fabian Beuke (madnight) Fabian Fichter (ianfab) Fanael Linithien (Fanael) @@ -83,30 +80,30 @@ Gontran Lemaire (gonlem) Goodkov Vasiliy Aleksandrovich (goodkov) Gregor Cramer GuardianRM -Günther Demetz (pb00067, pb00068) Guy Vreuls (gvreuls) +Günther Demetz (pb00067, pb00068) Henri Wiechers Hiraoka Takuya (HiraokaTakuya) homoSapiensSapiens Hongzhi Cheng Ivan Ivec (IIvec) Jacques B. (Timshel) +Jake Senne (w1wwwwww) Jan Ondruš (hxim) Jared Kish (Kurtbusch, kurt22i) -Jake Senne (w1wwwwww) Jarrod Torriero (DU-jdto) -Jean Gauthier (OuaisBla) Jean-Francois Romang (jromang) +Jean Gauthier (OuaisBla) Jekaa Jerry Donald Watson (jerrydonaldwatson) jjoshua2 -Jonathan Calovski (Mysseno) Jonathan Buladas Dumale (SFisGOD) +Jonathan Calovski (Mysseno) Jonathan McDermid (jonathanmcdermid) Joost VandeVondele (vondele) -Jörg Oster (joergoster) Joseph Ellis (jhellis3) Joseph R. Prostko +Jörg Oster (joergoster) Julian Willemer (NightlyKing) jundery Justin Blanchard (UncombedCoconut) @@ -120,6 +117,7 @@ Krystian Kuzniarek (kuzkry) Leonardo Ljubičić (ICCF World Champion) Leonid Pechenik (lp--) Liam Keegan (lkeegan) +Linmiao Xu (linrock) Linus Arver (listx) loco-loco Lub van den Berg (ElbertoOne) @@ -151,11 +149,11 @@ Moez Jellouli (MJZ1977) Mohammed Li (tthsqe12) Muzhen J (XInTheDark) Nathan Rugg (nmrugg) -Nick Pelling (nickpelling) +Nguyen Pham (nguyenpham) Nicklas Persson (NicklasPersson) +Nick Pelling (nickpelling) Niklas Fiekas (niklasf) Nikolay Kostov (NikolayIT) -Nguyen Pham (nguyenpham) Norman Schmidt (FireFather) notruck Ofek Shochat (OfekShochat, ghostway) @@ -170,6 +168,7 @@ Peter Schneider (pschneider1968) Peter Zsifkovits (CoffeeOne) PikaCat Praveen Kumar Tummala (praveentml) +Prokop Randáček (ProkopRandacek) Rahul Dsilva (silversolver1) Ralph Stößer (Ralph Stoesser) Raminder Singh @@ -178,8 +177,8 @@ Reuven Peleg (R-Peleg) Richard Lloyd (Richard-Lloyd) Rodrigo Exterckötter Tjäder Rodrigo Roim (roim) -Ron Britvich (Britvich) Ronald de Man (syzygy1, syzygy) +Ron Britvich (Britvich) rqs Rui Coelho (ruicoelhopedro) Ryan Schmitt @@ -200,13 +199,12 @@ Stefano Di Martino (StefanoD) Steinar Gunderson (sesse) Stéphane Nicolet (snicolet) Syine Mineta (MinetaS) -Prokop Randáček (ProkopRandacek) Thanar2 thaspel theo77186 +Tomasz Sobczyk (Sopel97) Tom Truscott Tom Vijlbrief (tomtor) -Tomasz Sobczyk (Sopel97) Torsten Franz (torfranz, tfranzer) Torsten Hellwig (Torom) Tracey Emery (basepr1me) @@ -217,8 +215,7 @@ Vince Negri (cuddlestmonkey) xefoci7612 zz4032 - # Additionally, we acknowledge the authors and maintainers of fishtest, -# an amazing and essential framework for the development of Stockfish! +# an amazing and essential framework for Stockfish development! # # https://github.com/glinscott/fishtest/blob/master/AUTHORS From c3ce2204083400267592dc088b8ad9e88aed56b1 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sat, 15 Apr 2023 09:51:01 -0400 Subject: [PATCH 139/192] Created by retraining the master net with these changes to the dataset: * Extending v6 filtering to data from T77 dec2021, T79 may2022, and T80 nov2022 * Reducing the number of duplicate positions, prioritizing position scores seen later in time * Using a binpack minimizer to reduce the overall data size Trained the same way as the previous master net, aside from the dataset changes: ``` python3 easy_train.py \ --experiment-name leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd \ --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \ --start-from-engine-test-net True \ --early-fen-skipping 30 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --max_epoch 900 \ --lr 4.375e-4 \ --gamma 0.995 \ --tui False \ --gpus "0," \ --seed $RANDOM ``` The new v6-dd filtering reduces duplicate positions by iterating over hourly data files within leela test runs, starting with the most recent, then keeping positions the first time they're seen and ignoring positions that are seen again. This ordering was done with the assumption that position scores seen later in time are generally more accurate than scores seen earlier in the test run. Positions are de-duplicated based on piece orientations, the first token in fen strings. The binpack minimizer was run with default settings after first merging monthly data into single binpacks. ``` python3 interleave_binpacks.py \ leela96-filt-v2.binpack \ dfrc99-filt-v2.binpack \ T60-nov2021-12tb7p-eval-filt-v2.binpack \ T60-dec2021-12tb7p-eval-filt-v2.binpack \ filt-v6/test80-aug2022-16tb7p-filter-v6.min-mar2023.binpack \ filt-v6/test80-sep2022-16tb7p-filter-v6.min-mar2023.binpack \ filt-v6-dd/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \ /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd.binpack ``` The code for v6-dd filtering is available along with training data preparation scripts at: https://github.com/linrock/nnue-data Links for downloading the training data components: https://robotmoon.com/nnue-training-data/ The binpack minimizer is from: #4447 Local elo at 25k nodes per move: nn-epoch859.nnue : 1.2 +/- 2.6 Passed STC: https://tests.stockfishchess.org/tests/view/643aad7db08900ff1bc5a832 LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 565040 W: 150225 L: 149162 D: 265653 Ptnml(0-2): 1875, 62137, 153229, 63608, 1671 Passed LTC: https://tests.stockfishchess.org/tests/view/643ecf2fa43cf30e719d2042 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 1014840 W: 274645 L: 272456 D: 467739 Ptnml(0-2): 515, 98565, 306970, 100956, 414 closes https://github.com/official-stockfish/Stockfish/pull/4545 bench 3476305 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 48076670..9dc45371 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-dabb1ed23026.nnue" + #define EvalFileDefaultName "nn-1ceb1a57d117.nnue" namespace NNUE { From 41f50b2c83a0ba36a2b9c507c1783e57c9b13485 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Fri, 21 Apr 2023 09:37:29 -0400 Subject: [PATCH 140/192] Update default net to nn-e1fb1ade4432.nnue Created by retraining nn-dabb1ed23026.nnue with a dataset composed of: * The previous best dataset (nn-1ceb1a57d117.nnue dataset) * Adding de-duplicated T80 data from feb2023 and the last 10 days of jan2023, filtered with v6-dd Initially trained with the same options as the recent master net (nn-1ceb1a57d117.nnue). Around epoch 890, training was manually stopped and max epoch increased to 1000. ``` python3 easy_train.py \ --experiment-name leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd \ --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \ --start-from-engine-test-net True \ --early-fen-skipping 30 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --max_epoch 900 \ --lr 4.375e-4 \ --gamma 0.995 \ --tui False \ --gpus "0," \ --seed $RANDOM ``` The same v6-dd filtering and binpack minimizer was used for preparing the recent nn-1ceb1a57d117.nnue dataset. ``` python3 interleave_binpacks.py \ leela96-filt-v2.binpack \ dfrc99-filt-v2.binpack \ T60-nov2021-12tb7p-eval-filt-v2.binpack \ T60-dec2021-12tb7p-eval-filt-v2.binpack \ filt-v6/test80-aug2022-16tb7p-filter-v6.min-mar2023.binpack \ filt-v6/test80-sep2022-16tb7p-filter-v6.min-mar2023.binpack \ filt-v6-dd/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-jan2022-3of3-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.binpack \ filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \ /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack ``` Links for downloading the training data components can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move: nn-epoch919.nnue : 2.6 +/- 2.8 Passed STC vs. nn-dabb1ed23026.nnue https://tests.stockfishchess.org/tests/view/644420df94ff3db5625f2af5 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 125960 W: 33898 L: 33464 D: 58598 Ptnml(0-2): 351, 13920, 34021, 14320, 368 Passed LTC vs. nn-1ceb1a57d117.nnue https://tests.stockfishchess.org/tests/view/64469f128d30316529b3dc46 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 24544 W: 6817 L: 6542 D: 11185 Ptnml(0-2): 8, 2252, 7488, 2505, 19 closes https://github.com/official-stockfish/Stockfish/pull/4546 bench 3714847 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 9dc45371..f5db1c1e 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-1ceb1a57d117.nnue" + #define EvalFileDefaultName "nn-e1fb1ade4432.nnue" namespace NNUE { From 21d6b69f7c8d0c0a71fe627714913a59d39a3b57 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sat, 29 Apr 2023 15:45:22 -0400 Subject: [PATCH 141/192] Update 7 eval and optimism params Params found using spsa at 30+0.3 with this tuning config: ``` // evaluate.cpp int nnueOptScaleBase = 1001; int nnueComplexityMult = 406; int nnueComplexityOptOffset = 424; int evalOptComplexityOffset = 272; int evalOptScaleOffset = 748; TUNE(SetRange(801, 1201), nnueOptScaleBase); TUNE(SetRange(306, 506), nnueComplexityMult); TUNE(SetRange(324, 524), nnueComplexityOptOffset); TUNE(SetRange(172, 372), evalOptComplexityOffset); TUNE(SetRange(648, 848), evalOptScaleOffset); // search.cpp int searchOptBase = 120; int searchOptDenom = 161; TUNE(SetRange(20, 220), searchOptBase); TUNE(SetRange(111, 211), searchOptDenom); ``` Passed STC: https://tests.stockfishchess.org/tests/view/644dda8accf5e93df5e50cbe LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 136800 W: 36682 L: 36237 D: 63881 Ptnml(0-2): 353, 14910, 37492, 15229, 416 Passed LTC: https://tests.stockfishchess.org/tests/view/644eaedb3f31c3bbe4a3d345 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 64548 W: 17624 L: 17272 D: 29652 Ptnml(0-2): 33, 6112, 19631, 6466, 32 closes https://github.com/official-stockfish/Stockfish/pull/4550 bench 3670343 --- src/evaluate.cpp | 10 +++++----- src/search.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 851ccfe1..d8f4e2e1 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos) { else { int nnueComplexity; - int scale = 1001 + pos.non_pawn_material() / 64; + int scale = 967 + pos.non_pawn_material() / 64; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; @@ -1071,12 +1071,12 @@ Value Eval::evaluate(const Position& pos) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 406 * nnueComplexity - + (424 + optimism) * abs(psq - nnue) + nnueComplexity = ( 402 * nnueComplexity + + (454 + optimism) * abs(psq - nnue) ) / 1024; - optimism = optimism * (272 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 748)) / 1024; + optimism = optimism * (274 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 791)) / 1024; } // Damp down the evaluation linearly when shuffling diff --git a/src/search.cpp b/src/search.cpp index 366065b8..8ce9c56e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -353,7 +353,7 @@ void Thread::search() { beta = std::min(prev + delta, VALUE_INFINITE); // Adjust optimism based on root move's previousScore - int opt = 120 * prev / (std::abs(prev) + 161); + int opt = 102 * prev / (std::abs(prev) + 147); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; From 72d542f00026fd8437e6033c95802714e4cd45d1 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Fri, 28 Apr 2023 19:05:56 +0200 Subject: [PATCH 142/192] Adjust reductions Decrease further on cutNodes with tte->depth() >= depth + 3 condition. LTC: https://tests.stockfishchess.org/tests/view/644dc84bccf5e93df5e50c13 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 155346 W: 42184 L: 41660 D: 71502 Ptnml(0-2): 59, 14765, 47504, 15283, 62 STC: https://tests.stockfishchess.org/tests/view/644d05de68e01d8194cd9bbb LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 121888 W: 32868 L: 32444 D: 56576 Ptnml(0-2): 332, 13273, 33343, 13631, 365 closes https://github.com/official-stockfish/Stockfish/pull/4552 bench: 3739675 --- src/search.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 8ce9c56e..a6618c5b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -884,7 +884,7 @@ namespace { // Use qsearch if depth is equal or below zero (~9 Elo) if ( PvNode && !ttMove) - depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth); + depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth); if (depth <= 0) return qsearch(pos, ss, alpha, beta); @@ -1141,9 +1141,10 @@ moves_loop: // When in check, search starts here // Decrease reduction if position is or has been on the PV // and node is not likely to fail low. (~3 Elo) + // Decrease further on cutNodes. (~1 Elo) if ( ss->ttPv && !likelyFailLow) - r -= 2; + r -= cutNode && tte->depth() >= depth + 3 ? 3 : 2; // Decrease reduction if opponent's move count is high (~1 Elo) if ((ss-1)->moveCount > 7) From 2429e162890478a48ab9b1cf0c431de9ebaf9429 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 5 May 2023 07:54:12 +0300 Subject: [PATCH 143/192] Reduce more if current node has a lot of refuted moves. This patch refines idea of cutoff count - in master we reduce more if current node has at least 4 moves that are refuted by search, this patch increases this count by 1 if refutation happened without having a tt move. Passed STC: https://tests.stockfishchess.org/tests/view/645363c36206ee34ebf8191d LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 67616 W: 18220 L: 17874 D: 31522 Ptnml(0-2): 142, 7346, 18504, 7656, 160 Passed LTC: https://tests.stockfishchess.org/tests/view/6453a0ea6206ee34ebf82796 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 195228 W: 52741 L: 52140 D: 90347 Ptnml(0-2): 53, 18718, 59482, 19297, 64 closes https://github.com/official-stockfish/Stockfish/pull/4556 bench 3448916 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index a6618c5b..a1f916d0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1326,7 +1326,7 @@ moves_loop: // When in check, search starts here } else { - ss->cutoffCnt++; + ss->cutoffCnt += 1 + !ttMove; assert(value >= beta); // Fail high break; } From 28442195c7d168a87221c6f1ae9ac51893427250 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Wed, 3 May 2023 14:11:55 +0300 Subject: [PATCH 144/192] Clean up after "Simplify away complexity in evaluation" closes https://github.com/official-stockfish/Stockfish/pull/4555 No functional change. --- src/search.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index a1f916d0..8d9dc04f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -724,11 +724,8 @@ namespace { ss->staticEval = eval = tte->eval(); if (eval == VALUE_NONE) ss->staticEval = eval = evaluate(pos); - else - { - if (PvNode) - Eval::NNUE::hint_common_parent_position(pos); - } + else if (PvNode) + Eval::NNUE::hint_common_parent_position(pos); // ttValue can be used as a better position evaluation (~7 Elo) if ( ttValue != VALUE_NONE From 464ebdf127273db0ccb0084c881b255b880e922e Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 5 May 2023 23:32:56 +0300 Subject: [PATCH 145/192] Small cleanup In search remove one condition check and reorder conditions. Removes some code. Passed non-regression test: https://tests.stockfishchess.org/tests/view/64548fa06206ee34ebf853ad LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 282976 W: 75327 L: 75374 D: 132275 Ptnml(0-2): 604, 29673, 80995, 29598, 618 closes https://github.com/official-stockfish/Stockfish/pull/4557 No functional change --- src/search.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 8d9dc04f..45fc1a7e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1310,7 +1310,13 @@ moves_loop: // When in check, search starts here if (PvNode && !rootNode) // Update pv even in fail-high case update_pv(ss->pv, move, (ss+1)->pv); - if (PvNode && value < beta) // Update alpha! Always alpha < beta + if (value >= beta) + { + ss->cutoffCnt += 1 + !ttMove; + assert(value >= beta); // Fail high + break; + } + else { // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 @@ -1319,13 +1325,7 @@ moves_loop: // When in check, search starts here depth -= 1; assert(depth > 0); - alpha = value; - } - else - { - ss->cutoffCnt += 1 + !ttMove; - assert(value >= beta); // Fail high - break; + alpha = value; // Update alpha! Always alpha < beta } } } From 65e2150501b87e6ce00fae4e3f056444f39462fd Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sun, 7 May 2023 23:33:04 +0300 Subject: [PATCH 146/192] Refine deeper post-lmr searches This patch improves logic conditions for performing deeper searches after passed LMR. Instead of exceeding alpha by some margin now it requires to exceed the current best value - which may be lower than alpha (but never bigger since we update alpha with bestvalue if it exceeds alpha). Passed STC: https://tests.stockfishchess.org/tests/view/6455f78008858de8313775b6 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 209344 W: 55993 L: 55448 D: 97903 Ptnml(0-2): 507, 22798, 57526, 23325, 516 Passed LTC: https://tests.stockfishchess.org/tests/view/64572d46eb75932ccfebff97 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 66288 W: 17867 L: 17514 D: 30907 Ptnml(0-2): 21, 6240, 20269, 6593, 21 closes https://github.com/official-stockfish/Stockfish/pull/4559 bench 3808503 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 45fc1a7e..bc495c0e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1201,7 +1201,7 @@ moves_loop: // When in check, search starts here { // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower - const bool doDeeperSearch = value > (alpha + 58 + 12 * (newDepth - d)); + const bool doDeeperSearch = value > (bestValue + 68 + 12 * (newDepth - d)); const bool doEvenDeeperSearch = value > alpha + 588 && ss->doubleExtensions <= 5; const bool doShallowerSearch = value < bestValue + newDepth; From 5f7b26aaa0d0bbdeb50ea6b17f049f167c1eb996 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 19 May 2023 23:02:27 +0200 Subject: [PATCH 147/192] Update WLD model using data of May, recalibrate the WLD model. closes https://github.com/official-stockfish/Stockfish/pull/4577 No functional change --- src/uci.cpp | 4 ++-- src/uci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index 8f9684ee..523d551e 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -207,8 +207,8 @@ namespace { // The coefficients of a third-order polynomial fit is based on the fishtest data // for two parameters that need to transform eval to the argument of a logistic // function. - constexpr double as[] = { 0.33677609, -4.30175627, 33.08810557, 365.60223431}; - constexpr double bs[] = { -2.50471102, 14.23235405, -14.33066859, 71.42705250 }; + constexpr double as[] = { 1.07390458, -6.94334517, 31.95090161, 317.75424048}; + constexpr double bs[] = { -2.82843814, 16.64518180, -19.74439200, 68.39499088 }; // Enforce that NormalizeToPawnValue corresponds to a 50% win rate at ply 64 static_assert(UCI::NormalizeToPawnValue == int(as[0] + as[1] + as[2] + as[3])); diff --git a/src/uci.h b/src/uci.h index 9ca0ed36..680d2d2c 100644 --- a/src/uci.h +++ b/src/uci.h @@ -35,7 +35,7 @@ namespace UCI { // the win_rate_model() such that Stockfish outputs an advantage of // "100 centipawns" for a position if the engine has a 50% probability to win // from this position in selfplay at fishtest LTC time control. -const int NormalizeToPawnValue = 394; +const int NormalizeToPawnValue = 343; class Option; From f030a1c592eabfa602ff8560d365e516298363ce Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Tue, 16 May 2023 21:30:53 +0800 Subject: [PATCH 148/192] Search tuning at very long time control Many search parameter changes, tuned (https://tests.stockfishchess.org/tests/view/645e4c67d55cccb2e64220ff) at ~300k games @ VLTC (120+1.2). Failed STC: https://tests.stockfishchess.org/tests/view/6465fcd77968ca827c1410c2 LLR: -2.95 (-2.94,2.94) <0.00,2.00> Total: 33824 W: 8863 L: 9067 D: 15894 Ptnml(0-2): 89, 3833, 9266, 3641, 83 Neutral LTC: https://tests.stockfishchess.org/tests/view/646385ce87f6567dd4df4e37 Elo: -0.48 +-1.2 (95%) LOS: 22.2% Total: 60000 W: 16235 L: 16318 D: 27447 Ptnml(0-2): 27, 5831, 18366, 5750, 26 nElo: -1.08 +-2.8 (95%) PairsRatio: 0.99 Passed VLTC 180+1.8: https://tests.stockfishchess.org/tests/view/646385f787f6567dd4df4e3e LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 126448 W: 34704 L: 34258 D: 57486 Ptnml(0-2): 9, 10970, 40825, 11406, 14 Passed VLTC SMP 60+0.6 8thread: https://tests.stockfishchess.org/tests/view/646628de884ce93b65df2ac9 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 59456 W: 16791 L: 16487 D: 26178 Ptnml(0-2): 5, 4473, 20467, 4779, 4 closes https://github.com/official-stockfish/Stockfish/pull/4574 Bench: 3347573 --- src/search.cpp | 94 +++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index bc495c0e..429db9a5 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -64,7 +64,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(154 * (d - improving)); + return Value(148 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -72,7 +72,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1449 - int(delta) * 937 / int(rootDelta)) / 1024 + (!i && r > 941); + return (r + 1356 - int(delta) * 983 / int(rootDelta)) / 1024 + (!i && r > 901); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -82,7 +82,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min(341 * d - 470, 1710); + return std::min(337 * d - 497, 1632); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -162,7 +162,7 @@ namespace { void Search::init() { for (int i = 1; i < MAX_MOVES; ++i) - Reductions[i] = int((19.47 + std::log(Threads.size()) / 2) * std::log(i)); + Reductions[i] = int((20.89 + std::log(Threads.size()) / 2) * std::log(i)); } @@ -348,12 +348,12 @@ void Thread::search() { // Reset aspiration window starting size Value prev = rootMoves[pvIdx].averageScore; - delta = Value(10) + int(prev) * prev / 16502; + delta = Value(11) + int(prev) * prev / 15368; alpha = std::max(prev - delta,-VALUE_INFINITE); beta = std::min(prev + delta, VALUE_INFINITE); // Adjust optimism based on root move's previousScore - int opt = 102 * prev / (std::abs(prev) + 147); + int opt = 116 * prev / (std::abs(prev) + 143); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; @@ -742,7 +742,7 @@ namespace { // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { - int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1920, 1920); + int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1717, 1717); thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus; } @@ -752,13 +752,13 @@ namespace { // margin and the improving flag are used in various pruning heuristics. improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval - : 156; + : 163; improving = improvement > 0; // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if (eval < alpha - 426 - 256 * depth * depth) + if (eval < alpha - 467 - 266 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -769,18 +769,18 @@ namespace { // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 9 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 280 >= beta + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 306 >= beta && eval >= beta - && eval < 25128) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 22761) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~35 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 18755 + && (ss-1)->statScore < 18404 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + && ss->staticEval >= beta - 19 * depth - improvement / 13 + 257 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly)) @@ -823,13 +823,13 @@ namespace { } } - probCutBeta = beta + 186 - 54 * improving; + probCutBeta = beta + 174 - 60 * improving; // Step 10. ProbCut (~10 Elo) // If we have a good enough capture (or queen promotion) and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode - && depth > 4 + && depth > 3 && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY // if value from transposition table is lower than probCutBeta, don't attempt probCut // there and in further interactions with transposition table cutoff depth is set to depth - 3 @@ -887,20 +887,20 @@ namespace { return qsearch(pos, ss, alpha, beta); if ( cutNode - && depth >= 7 + && depth >= 8 && !ttMove) depth -= 2; moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~4 Elo) - probCutBeta = beta + 391; + probCutBeta = beta + 430; if ( ss->inCheck && !PvNode && depth >= 2 && ttCapture && (tte->bound() & BOUND_LOWER) - && tte->depth() >= depth - 3 + && tte->depth() >= depth - 4 && ttValue >= probCutBeta && abs(ttValue) <= VALUE_KNOWN_WIN && abs(beta) <= VALUE_KNOWN_WIN) @@ -986,15 +986,15 @@ moves_loop: // When in check, search starts here { // Futility pruning for captures (~2 Elo) if ( !givesCheck - && lmrDepth < 6 + && lmrDepth < 7 && !ss->inCheck - && ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] - + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) + && ss->staticEval + 207 + 223 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] * 1078 / 7000 < alpha) continue; Bitboard occupied; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, occupied, Value(-206) * depth)) + if (!pos.see_ge(move, occupied, Value(-205) * depth)) { if (depth < 2 - capture) continue; @@ -1022,24 +1022,24 @@ moves_loop: // When in check, search starts here // Continuation history based pruning (~2 Elo) if ( lmrDepth < 5 - && history < -4405 * (depth - 1)) + && history < -3792 * (depth - 1)) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; - lmrDepth += history / 7278; + lmrDepth += history / 7019; lmrDepth = std::max(lmrDepth, -2); // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck - && lmrDepth < 13 - && ss->staticEval + 103 + 138 * lmrDepth <= alpha) + && lmrDepth < 12 + && ss->staticEval + 111 + 136 * lmrDepth <= alpha) continue; lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 16 * lmrDepth))) + if (!pos.see_ge(move, Value(-27 * lmrDepth * lmrDepth - 33 * lmrDepth / 2))) continue; } } @@ -1054,7 +1054,7 @@ moves_loop: // When in check, search starts here // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( !rootNode - && depth >= 4 - (thisThread->completedDepth > 21) + 2 * (PvNode && tte->is_pv()) + && depth >= 4 - (thisThread->completedDepth > 22) + 2 * (PvNode && tte->is_pv()) && move == ttMove && !excludedMove // Avoid recursive singular search /* && ttValue != VALUE_NONE Already implicit in the next condition */ @@ -1062,7 +1062,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - (3 + 2 * (ss->ttPv && !PvNode)) * depth / 2; + Value singularBeta = ttValue - (99 + 65 * (ss->ttPv && !PvNode)) * depth / 64; Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; @@ -1076,8 +1076,8 @@ moves_loop: // When in check, search starts here // Avoid search explosion by limiting the number of double extensions if ( !PvNode - && value < singularBeta - 25 - && ss->doubleExtensions <= 10) + && value < singularBeta - 22 + && ss->doubleExtensions <= 11) { extension = 2; depth += depth < 13; @@ -1107,15 +1107,15 @@ moves_loop: // When in check, search starts here // Check extensions (~1 Elo) else if ( givesCheck - && depth > 10 - && abs(ss->staticEval) > 88) + && depth > 9 + && abs(ss->staticEval) > 87) extension = 1; // Quiet ttMove extensions (~1 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 5705) + && (*contHist[0])[movedPiece][to_sq(move)] >= 5480) extension = 1; } @@ -1144,7 +1144,7 @@ moves_loop: // When in check, search starts here r -= cutNode && tte->depth() >= depth + 3 ? 3 : 2; // Decrease reduction if opponent's move count is high (~1 Elo) - if ((ss-1)->moveCount > 7) + if ((ss-1)->moveCount > 8) r--; // Increase reduction for cut nodes (~3 Elo) @@ -1157,7 +1157,7 @@ moves_loop: // When in check, search starts here // Decrease reduction for PvNodes based on depth (~2 Elo) if (PvNode) - r -= 1 + 12 / (3 + depth); + r -= 1 + 11 / (3 + depth); // Decrease reduction if ttMove has been singularly extended (~1 Elo) if (singularQuietLMR) @@ -1174,10 +1174,10 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4082; + - 3755; // Decrease/increase reduction for moves with a good/bad history (~25 Elo) - r -= ss->statScore / (11079 + 4626 * (depth > 6 && depth < 19)); + r -= ss->statScore / (10445 + 4762 * (depth > 6 && depth < 21)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has @@ -1201,8 +1201,8 @@ moves_loop: // When in check, search starts here { // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower - const bool doDeeperSearch = value > (bestValue + 68 + 12 * (newDepth - d)); - const bool doEvenDeeperSearch = value > alpha + 588 && ss->doubleExtensions <= 5; + const bool doDeeperSearch = value > (bestValue + 63 + 11 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 662 && ss->doubleExtensions <= 6; const bool doShallowerSearch = value < bestValue + newDepth; ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch; @@ -1227,7 +1227,7 @@ moves_loop: // When in check, search starts here if (!ttMove && cutNode) r += 2; - value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode); + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 3), !cutNode); } // For PV nodes only, do a full PV search on the first move or after a fail @@ -1320,8 +1320,8 @@ moves_loop: // When in check, search starts here { // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 - && beta < 12535 - && value > -12535) + && beta < 14001 + && value > -12754) depth -= 1; assert(depth > 0); @@ -1370,7 +1370,7 @@ moves_loop: // When in check, search starts here // Bonus for prior countermove that caused the fail low else if (!priorCapture && prevSq != SQ_NONE) { - int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth) + ((ss-1)->moveCount > 10); + int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 100 * depth) + ((ss-1)->moveCount > 11); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } @@ -1499,7 +1499,7 @@ moves_loop: // When in check, search starts here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = bestValue + 168; + futilityBase = bestValue + 190; } const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, @@ -1572,7 +1572,7 @@ moves_loop: // When in check, search starts here continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-110))) + if (!pos.see_ge(move, Value(-94))) continue; } @@ -1705,7 +1705,7 @@ moves_loop: // When in check, search starts here if (!pos.capture_stage(bestMove)) { - int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus + int bonus2 = bestValue > beta + 143 ? bonus1 // larger bonus : stat_bonus(depth); // smaller bonus // Increase stats for the best move in case it was a quiet move From 4f24ee086828e28df7d0b2dce5c13732139e7c19 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Fri, 19 May 2023 23:16:48 +0200 Subject: [PATCH 149/192] Small simplification in history pruning. Remove the constant term of the history threshold which lowers the chance that pruning occurs. As compensation allow pruning at a slightly higher depth. Passed STC: https://tests.stockfishchess.org/tests/view/64634c9a87f6567dd4df4901 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 101536 W: 27156 L: 27012 D: 47368 Ptnml(0-2): 266, 11165, 27772, 11289, 276 Passed LTC: https://tests.stockfishchess.org/tests/view/6463d68b17982fde89d2bc2b LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 32154 W: 8741 L: 8543 D: 14870 Ptnml(0-2): 8, 3093, 9687, 3271, 18 Passed LTC: retest on top of VLTC tuning PR 4571 because this changes the history depth factor (use this new factor here) https://tests.stockfishchess.org/tests/view/6467300e165c4b29ec0afd3f LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 99270 W: 26840 L: 26707 D: 45723 Ptnml(0-2): 36, 9753, 29928, 9878, 40 closes https://github.com/official-stockfish/Stockfish/pull/4578 Bench: 2984341 --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 429db9a5..10844746 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1021,8 +1021,8 @@ moves_loop: // When in check, search starts here + (*contHist[3])[movedPiece][to_sq(move)]; // Continuation history based pruning (~2 Elo) - if ( lmrDepth < 5 - && history < -3792 * (depth - 1)) + if ( lmrDepth < 6 + && history < -3792 * depth) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; From 4b085c4777c36939bd0a598f4bc3e0c04606e31b Mon Sep 17 00:00:00 2001 From: xoto10 <23479932+xoto10@users.noreply.github.com> Date: Fri, 19 May 2023 19:58:18 +0100 Subject: [PATCH 150/192] Simplify optimism calculation This change removes one of the constants in the calculation of optimism. It also changes the 2 constants used with the scale value so that they are independent, instead of applying a constant to the scale and then adjusting it again when it is applied to the optimism. This might make the tuning of these constants cleaner and more reliable in the future. STC 10+0.1 (accidentally run as an Elo gainer: LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 154080 W: 41119 L: 40651 D: 72310 Ptnml(0-2): 375, 16840, 42190, 17212, 423 https://tests.stockfishchess.org/tests/live_elo/64653eabf3b1a4e86c317f77 LTC 60+0.6: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 217434 W: 58382 L: 58363 D: 100689 Ptnml(0-2): 66, 21075, 66419, 21088, 69 https://tests.stockfishchess.org/tests/live_elo/6465d077f3b1a4e86c318d6c closes https://github.com/official-stockfish/Stockfish/pull/4576 bench: 3190961 --- src/evaluate.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index d8f4e2e1..cc789e35 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1063,7 +1063,7 @@ Value Eval::evaluate(const Position& pos) { else { int nnueComplexity; - int scale = 967 + pos.non_pawn_material() / 64; + int npm = pos.non_pawn_material() / 64; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; @@ -1071,12 +1071,12 @@ Value Eval::evaluate(const Position& pos) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 402 * nnueComplexity - + (454 + optimism) * abs(psq - nnue) + nnueComplexity = ( 397 * nnueComplexity + + (477 + optimism) * abs(psq - nnue) ) / 1024; - optimism = optimism * (274 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 791)) / 1024; + optimism += optimism * nnueComplexity / 256; + v = (nnue * (945 + npm) + optimism * (174 + npm)) / 1024; } // Damp down the evaluation linearly when shuffling From 7cd650f435715f73550d1f8031315e65b701d631 Mon Sep 17 00:00:00 2001 From: pb00067 Date: Wed, 17 May 2023 09:22:02 +0200 Subject: [PATCH 151/192] Simplify SEE verfication logic Passed STC https://tests.stockfishchess.org/tests/view/6461d51887f6567dd4df27d0 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 177056 W: 47181 L: 47118 D: 82757 Ptnml(0-2): 456, 19381, 48792, 19442, 457 Passed LTC https://tests.stockfishchess.org/tests/view/64631a9287f6567dd4df4502 2.94 (-2.94,2.94) <-1.75,0.25> Total: 104346 W: 28062 L: 27935 D: 48349 Ptnml(0-2): 25, 10190, 31631, 10287, 40 closes https://github.com/official-stockfish/Stockfish/pull/4578 bench: 2903251 --- src/search.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 10844746..653cbf33 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -996,9 +996,7 @@ moves_loop: // When in check, search starts here // SEE based pruning (~11 Elo) if (!pos.see_ge(move, occupied, Value(-205) * depth)) { - if (depth < 2 - capture) - continue; - // Don't prune the move if opp. King/Queen/Rook gets a discovered attack during or after the exchanges + // Don't prune the move if opponent King/Queen/Rook gets a discovered attack during or after the exchanges Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK); Bitboard attacks = 0; occupied |= to_sq(move); @@ -1006,7 +1004,7 @@ moves_loop: // When in check, search starts here { Square sq = pop_lsb(leftEnemies); attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; - // Exclude Queen/Rook(s) which were already threatened before SEE (opp King can't be in check when it's our turn) + // Exclude Queen/Rook(s) which were already threatened before SEE (opponent King can't be in check when it's our turn) if (attacks && sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))) attacks = 0; } From df0fb8471e5015bb4ba0b398c203b7faad45840e Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sun, 14 May 2023 00:30:35 +0300 Subject: [PATCH 152/192] Small simplification in low depth pruning Uncap low depth pruning lmr depth. It's anyway capped for most cases apart from futility pruning for captures - removes one std::min call. Passed STC: https://tests.stockfishchess.org/tests/view/645e8fa6d55cccb2e64225a1 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 184064 W: 49039 L: 48982 D: 86043 Ptnml(0-2): 462, 20353, 50349, 20402, 466 Passed LTC: https://tests.stockfishchess.org/tests/view/645f4d48d55cccb2e6423335 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 83886 W: 22613 L: 22465 D: 38808 Ptnml(0-2): 31, 8090, 25546, 8252, 24 closes https://github.com/official-stockfish/Stockfish/pull/4566 bench 3201883 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 653cbf33..f58def60 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -979,7 +979,7 @@ moves_loop: // When in check, search starts here moveCountPruning = moveCount >= futility_move_count(improving, depth); // Reduced depth of the next LMR search - int lmrDepth = std::max(newDepth - r, 0); + int lmrDepth = newDepth - r; if ( capture || givesCheck) From d7e72d801fd68f2ee3c7d6b814bbc82916c30041 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Mon, 22 May 2023 00:14:55 +0200 Subject: [PATCH 153/192] More Depth Reduction Reduce more for depth > 3 and depth < 12 LTC: https://tests.stockfishchess.org/tests/view/646c5abbd1f14fd69a6f2fab LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 197280 W: 53405 L: 52797 D: 91078 Ptnml(0-2): 62, 19025, 59886, 19577, 90 STC: https://tests.stockfishchess.org/tests/view/646bee71d1f14fd69a6f259d LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 100832 W: 26861 L: 26466 D: 47505 Ptnml(0-2): 240, 10985, 27622, 11278, 291 https://github.com/official-stockfish/Stockfish/pull/4585 bench: 2276617 --- src/search.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index f58def60..130855c1 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1317,10 +1317,11 @@ moves_loop: // When in check, search starts here else { // Reduce other moves if we have found at least one score improvement (~1 Elo) + // Reduce more for depth > 3 and depth < 12 (~1 Elo) if ( depth > 1 && beta < 14001 && value > -12754) - depth -= 1; + depth -= depth > 3 && depth < 12 ? 2 : 1; assert(depth > 0); alpha = value; // Update alpha! Always alpha < beta From b64c97825eb473d9b5cbdb67afe65a8ac0d5ec9f Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Sat, 20 May 2023 21:28:54 +0800 Subject: [PATCH 154/192] Simplify delta calculation in aspiration window Simplification STC: https://tests.stockfishchess.org/tests/view/6468cb200db5177f2b76ecbb LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 220416 W: 58503 L: 58487 D: 103426 Ptnml(0-2): 596, 24384, 60188, 24488, 552 Simplification LTC: https://tests.stockfishchess.org/tests/view/646a15840db5177f2b770704 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 177756 W: 47882 L: 47825 D: 82049 Ptnml(0-2): 55, 17430, 53858, 17473, 62 closes https://github.com/official-stockfish/Stockfish/pull/4581 Bench: 2304063 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 130855c1..3632a469 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -409,7 +409,7 @@ void Thread::search() { else break; - delta += delta / 4 + 2; + delta += delta / 3; assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE); } From a989aa1825503ab39e6b2cf77bba2f1f022f367c Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Sun, 21 May 2023 16:22:28 +0300 Subject: [PATCH 155/192] Simplify Prune moves with negative SEE Passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 57760 W: 15472 L: 15286 D: 27002 Ptnml(0-2): 123, 6025, 16430, 6147, 155 https://tests.stockfishchess.org/tests/view/6468eb6b0db5177f2b76ef62 Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 93966 W: 25274 L: 25141 D: 43551 Ptnml(0-2): 33, 8498, 29792, 8623, 37 https://tests.stockfishchess.org/tests/view/6469570b0db5177f2b76f81b closes: https://github.com/official-stockfish/Stockfish/pull/4579 Bench: 2304063 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 3632a469..270c5e7c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1037,7 +1037,7 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-27 * lmrDepth * lmrDepth - 33 * lmrDepth / 2))) + if (!pos.see_ge(move, Value(-27 * lmrDepth * lmrDepth - 16 * lmrDepth))) continue; } } From cedd73f4aa9f83c2891105695ac11e743e6ceab7 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Tue, 23 May 2023 20:36:47 +0300 Subject: [PATCH 156/192] Simplify Futility pruning for captures Passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 412928 W: 109433 L: 109620 D: 193875 Ptnml(0-2): 1071, 45929, 112650, 45744, 1070 https://tests.stockfishchess.org/tests/view/6468eac40db5177f2b76ef4d Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 190200 W: 51465 L: 51420 D: 87315 Ptnml(0-2): 58, 18585, 57788, 18592, 77 https://tests.stockfishchess.org/tests/view/646b66520db5177f2b772a84 closes https://github.com/official-stockfish/Stockfish/pull/4583 bench: 2486604 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 270c5e7c..32eeedab 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -989,7 +989,7 @@ moves_loop: // When in check, search starts here && lmrDepth < 7 && !ss->inCheck && ss->staticEval + 207 + 223 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] - + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] * 1078 / 7000 < alpha) + + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; Bitboard occupied; From c701745cf243f4816754167e85bf5fabf5b34e47 Mon Sep 17 00:00:00 2001 From: cj5716 <125858804+cj5716@users.noreply.github.com> Date: Thu, 25 May 2023 14:34:52 +0800 Subject: [PATCH 157/192] Remove ss->ttHit condition where ttValue != VALUE_NONE Simplification is done at 3 separate places in the code. Thanks to peregrineshahin for helping me find 2 of such places. (See original PR #4584) Passed non-regression test LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 120256 W: 32204 L: 32085 D: 55967 Ptnml(0-2): 292, 12473, 34483, 12584, 296 https://tests.stockfishchess.org/tests/view/646f045968661bfd984325e3 closes https://github.com/official-stockfish/Stockfish/pull/4587 No functional change --- AUTHORS | 1 + src/search.cpp | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index b6723246..884bffab 100644 --- a/AUTHORS +++ b/AUTHORS @@ -76,6 +76,7 @@ George Sobala (gsobala) gguliash Giacomo Lorenzetti (G-Lorenz) Gian-Carlo Pascutto (gcp) +Goh CJ (cj5716) Gontran Lemaire (gonlem) Goodkov Vasiliy Aleksandrovich (goodkov) Gregor Cramer diff --git a/src/search.cpp b/src/search.cpp index 32eeedab..93212e23 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -615,10 +615,9 @@ namespace { // At non-PV nodes we check for an early TT cutoff if ( !PvNode - && ss->ttHit && !excludedMove && tte->depth() > depth - (tte->bound() == BOUND_EXACT) - && ttValue != VALUE_NONE // Possible in case of TT access race + && ttValue != VALUE_NONE // Possible in case of TT access race or if !ttHit && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) { // If ttMove is quiet, update move sorting heuristics on TT hit (~2 Elo) @@ -835,8 +834,7 @@ namespace { // there and in further interactions with transposition table cutoff depth is set to depth - 3 // because probCut search has depth set to depth - 4 but we also do a move before it // so effective depth is equal to depth - 3 - && !( ss->ttHit - && tte->depth() >= depth - 3 + && !( tte->depth() >= depth - 3 && ttValue != VALUE_NONE && ttValue < probCutBeta)) { @@ -1453,9 +1451,8 @@ moves_loop: // When in check, search starts here // At non-PV nodes we check for an early TT cutoff if ( !PvNode - && ss->ttHit && tte->depth() >= ttDepth - && ttValue != VALUE_NONE // Only in case of TT access race + && ttValue != VALUE_NONE // Only in case of TT access race or if !ttHit && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) return ttValue; From 7f0b19dedf7bff7dbe2dd42e73788826486b36b6 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 27 May 2023 18:01:08 +0200 Subject: [PATCH 158/192] Update CPU contributors list update CPU contributors list, the previous update was a couple of months ago, and unfortunately, was not quite accurate for the number of games played. This version is based clean calculation from the DB and an updated script that tracks things (see https://github.com/glinscott/fishtest/pull/1702). closes https://github.com/official-stockfish/Stockfish/pull/4589 No functional change --- Top CPU Contributors.txt | 196 ++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 95 deletions(-) diff --git a/Top CPU Contributors.txt b/Top CPU Contributors.txt index 30c963d7..7b279590 100644 --- a/Top CPU Contributors.txt +++ b/Top CPU Contributors.txt @@ -1,212 +1,218 @@ -Contributors to Fishtest with >10,000 CPU hours, as of 2022-11-19. +Contributors to Fishtest with >10,000 CPU hours, as of 2023-05-27. Thank you! Username CPU Hours Games played ------------------------------------------------------------------ -noobpwnftw 36475307 2748033975 -technologov 14570711 760073590 +noobpwnftw 37304027 2833556221 +technologov 13508659 714674674 +linrock 4121386 280027751 mlang 3026000 200065824 -dew 1689222 100034318 -grandphish2 1442171 86798057 -okrout 1439985 133471766 -pemo 1405374 44189811 -linrock 1299003 28382783 -TueRens 1163420 71159522 -JojoM 897158 55177114 +dew 1689162 100033738 +okrout 1541122 145085726 +pemo 1481818 47546583 +grandphish2 1459364 91364265 +TueRens 1178700 69951886 +JojoM 937875 60821044 tvijlbrief 796125 51897690 mibere 703840 46867607 -gvreuls 635982 40652394 -oz 590763 41201352 -sebastronomy 581517 23307132 -cw 517915 34865769 -fastgm 504266 30264740 -CSU_Dynasty 479901 31846710 -ctoks 433503 28180725 +sebastronomy 687502 35585318 +gvreuls 645570 42437926 +oz 541224 39133532 +cw 517856 34869499 +fastgm 503862 30260818 +CSU_Dynasty 464691 31166478 +leszek 460426 32840277 +ctoks 434323 28497451 crunchy 427035 27344275 -leszek 416883 27493447 -bcross 409982 28062127 -velislav 345954 22232274 +maximmasiutin 424154 26534660 +bcross 415722 29060963 +rpngn 344368 24218047 +velislav 342559 22138408 Fisherman 327231 21829379 +mgrabiak 297057 20260882 Dantist 296386 18031762 -mgrabiak 288928 18869896 -rpngn 259965 16281463 -robal 237653 15148350 -ncfish1 231764 15275003 -nordlandia 226923 14624832 +nordlandia 242642 15922516 +robal 240199 15544104 +marrco 234581 17714473 +ncfish1 227517 15233777 glinscott 208125 13277240 drabel 204167 13930674 mhoram 202894 12601997 bking_US 198894 11876016 -thirdlife 198844 5453268 +olafm 192342 14968698 Thanar 179852 12365359 vdv 175544 9904472 -armo9494 168201 11136452 spams 157128 10319326 -marrco 151599 9551115 sqrt2 147963 9724586 -vdbergh 137690 8971569 +DesolatedDodo 144759 9408038 +Calis007 143165 9478764 +vdbergh 138436 9042073 CoffeeOne 137100 5024116 malala 136182 8002293 -DesolatedDodo 135276 8657464 +armo9494 136010 9447548 xoto 133759 9159372 davar 129023 8376525 +DMBK 122960 8980062 dsmith 122059 7570238 amicic 119661 7938029 Data 113305 8220352 BrunoBanani 112960 7436849 CypressChess 108331 7759788 -skiminki 106518 7062598 +skiminki 107583 7218170 MaZePallas 102823 6633619 sterni1971 100532 5880772 +jcAEie 100392 7788270 sunu 100167 7040199 zeryl 99331 6221261 +thirdlife 99124 2242380 ElbertoOne 99028 7023771 -DMBK 97572 6950312 -Calis007 96779 5611552 -cuistot 93111 5536500 +cuistot 98360 6017102 +bigpen0r 94809 6529203 brabos 92118 6186135 -Wolfgang 91769 5720158 +Wolfgang 90855 5998076 psk 89957 5984901 racerschmacer 85805 6122790 -jcAEie 85527 5630616 +Dubslow 84986 6042456 Vizvezdenec 83761 5344740 -sschnee 83557 4853690 +sschnee 83564 4853834 0x3C33 82614 5271253 BRAVONE 81239 5054681 -Dubslow 78461 5042980 +Fifis 77355 5158211 nssy 76497 5259388 jromang 76106 5236025 teddybaer 75125 5407666 -yurikvelo 73933 5031096 -tolkki963 73885 4721430 +Wencey 74181 4711488 +megaman7de 73866 4894960 Pking_cda 73776 5293873 -Bobo1239 71675 4860987 +tolkki963 73531 5020500 +yurikvelo 72847 4972808 +Bobo1239 70579 4794999 solarlight 70517 5028306 dv8silencer 70287 3883992 -Gelma 69304 3980932 +markkulix 70278 5068326 manap 66273 4121774 -megaman7de 65419 4120200 -markkulix 65331 4114860 -bigpen0r 64932 4683883 tinker 64333 4268790 qurashee 61208 3429862 -AGI 58325 4258646 +Mineta 58759 4399960 +AGI 58147 4325994 +Spprtr 58106 3858759 robnjr 57262 4053117 Freja 56938 3733019 MaxKlaxxMiner 56879 3423958 +MarcusTullius 56746 3762951 ttruscott 56010 3680085 rkl 55132 4164467 renouve 53811 3501516 -Spprtr 52736 3410019 finfish 51360 3370515 eva42 51272 3599691 eastorwest 51117 3454811 rap 49985 3219146 -unixwizard 49734 2536230 -pb00067 49727 3298270 +pb00067 49733 3298934 +javran 49178 4190632 +OuaisBla 48606 3442958 ronaldjerum 47654 3240695 biffhero 46564 3111352 -GPUex 45861 2926502 -Fifis 45843 3088497 -oryx 45578 3493978 VoyagerOne 45476 3452465 -Wencey 44943 2654490 +oryx 44532 3450170 +jmdana 43849 2955821 speedycpu 43842 3003273 jbwiebe 43305 2805433 Antihistamine 41788 2761312 mhunt 41735 2691355 -olafm 41277 3284344 +maposora 41534 3733078 +GPUex 41061 2998356 homyur 39893 2850481 gri 39871 2515779 -MarcusTullius 38303 2251097 Garf 37741 2999686 -kdave 37424 2557406 SC 37299 2731694 csnodgrass 36207 2688994 -jmdana 36157 2210661 strelock 34716 2074055 EthanOConnor 33370 2090311 slakovv 32915 2021889 -gopeto 31669 2060958 +Gelma 31771 1551204 +gopeto 31671 2060990 +szupaw 31248 2594920 +kdave 31157 2198362 manapbk 30987 1810399 Prcuvu 30377 2170122 anst 30301 2190091 jkiiski 30136 1904470 -spcc 30135 1903728 +spcc 29925 1901692 hyperbolic.tom 29840 2017394 -xwziegtm 29763 2347412 chuckstablers 29659 2093438 Pyafue 29650 1902349 belzedar94 28846 1811530 -OuaisBla 27636 1578800 chriswk 26902 1868317 +xwziegtm 26897 2124586 achambord 26582 1767323 Patrick_G 26276 1801617 yorkman 26193 1992080 -Ulysses 25289 1674274 +Ulysses 25285 1689346 SFTUser 25182 1675689 nabildanial 24942 1519409 Sharaf_DG 24765 1786697 rodneyc 24376 1416402 agg177 23890 1395014 -Ente 23747 1674582 -Karpovbot 23629 1313186 +Ente 23639 1671638 JanErik 23408 1703875 Isidor 23388 1680691 Norabor 23371 1603244 -cisco2015 22934 1763773 +Goatminola 23338 1910634 +cisco2015 22920 1763301 +Jopo12321 22890 1424926 Zirie 22542 1472937 team-oh 22272 1636708 Roady 22220 1465606 MazeOfGalious 21978 1629593 sg4032 21947 1643353 +jsys14 21935 1499128 ianh2105 21725 1632562 xor12 21628 1680365 dex 21612 1467203 nesoneg 21494 1463031 user213718 21454 1404128 -AndreasKrug 21227 1577833 sphinx 21211 1384728 jjoshua2 21001 1423089 +Zake9298 20938 1565848 +AndreasKrug 20911 1615673 horst.prack 20878 1465656 -jsys14 20729 1221010 0xB00B1ES 20590 1208666 j3corre 20405 941444 Adrian.Schmidt123 20316 1281436 -bonsi 20022 1300682 wei 19973 1745989 -dapper 19754 1167758 -Zake9298 19745 1458416 +Serpensin 19840 1697528 fishtester 19617 1257388 rstoesser 19569 1293588 eudhan 19274 1283717 +Gaster319 18934 1596772 vulcan 18871 1729392 -Jopo12321 18803 1036284 +Karpovbot 18766 1053178 jundery 18445 1115855 +votoanthuan 18012 1508836 ville 17883 1384026 -5t0ckf15hTr4in3r 17809 1105858 chris 17698 1487385 -dju 17697 994333 purplefishies 17595 1092533 +qoo_charly_cai 17494 1182667 +dju 17414 981289 iisiraider 17275 1049015 DragonLord 17014 1162790 -Karby 16457 1010138 -Goatminola 16278 1145026 +redstone59 16842 1461780 +Alb11747 16787 1213926 IgorLeMasson 16064 1147232 -Gaster319 16056 1109070 -redstone59 15953 1161664 +Karby 15982 979610 +notchris 15818 1426762 scuzzi 15757 968735 ako027ako 15671 1173203 Nikolay.IT 15154 1068349 Andrew Grant 15114 895539 Naven94 15054 834762 OssumOpossum 14857 1007129 -qoo_charly_cai 14490 847865 +ZacHFX 14783 1021842 enedene 14476 905279 -szupaw 14252 929130 bpfliegel 14233 882523 mpx86 14019 759568 jpulman 13982 870599 +Skiff84 13826 721996 crocogoat 13803 1117422 Nesa92 13786 1114691 joster 13710 946160 @@ -214,47 +220,47 @@ mbeier 13650 1044928 Hjax 13535 915487 Dark_wizzie 13422 1007152 Rudolphous 13244 883140 +pirt 13100 1009897 Machariel 13010 863104 infinigon 12991 943216 -pirt 12925 985437 -Skiff84 12923 649994 +Maxim 12963 985594 mabichito 12903 749391 thijsk 12886 722107 AdrianSA 12860 804972 Flopzee 12698 894821 +korposzczur 12606 838168 +Nullvalue 12583 1048502 fatmurphy 12547 853210 -woutboat 12419 836696 SapphireBrand 12416 969604 -Oakwen 12406 840961 +Oakwen 12399 844109 deflectooor 12386 579392 modolief 12386 896470 Farseer 12249 694108 +Jackfish 12180 801372 pgontarz 12151 848794 +dbernier 12103 860824 +getraideBFF 12072 1024966 stocky 11954 699440 mschmidt 11941 803401 -MooTheCow 11871 773654 -Jackfish 11867 773550 -dbernier 11705 821780 +MooTheCow 11870 773598 +FormazChar 11689 877727 whelanh 11557 245188 -Maxim 11543 836024 -Nullvalue 11534 731410 -icewulf 11528 650470 -FormazChar 11523 861599 infinity 11470 727027 aga 11412 695127 torbjo 11395 729145 Thomas A. Anderson 11372 732094 savage84 11358 670860 -ali-al-zhrani 11272 781310 d64 11263 789184 -Bourbaki 11108 709144 +ali-al-zhrani 11245 779246 snicolet 11106 869170 -Alb11747 10855 696920 +dapper 11032 771402 +Karmatron 10828 677458 basepi 10637 744851 Cubox 10621 826448 -Karmatron 10616 674818 michaelrpg 10509 739239 OIVAS7572 10420 995586 -Garruk 10348 704905 +jojo2357 10419 929708 +WoodMan777 10380 873720 +Garruk 10365 706465 dzjp 10343 732529 ols 10259 570669 From 7e9b131efb832339ee6cd9e22b7c837c3e69a1b5 Mon Sep 17 00:00:00 2001 From: windfishballad Date: Mon, 22 May 2023 20:13:44 -0400 Subject: [PATCH 159/192] Removed quadratic term in optimism Remove term which is quadratic in optimism in the eval. Simplifies and should also remove the bias towards side to move making the eval better for analysis. STC: https://tests.stockfishchess.org/tests/view/6470a9d8c29e0d4352b0bca5 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 154432 W: 41127 L: 41040 D: 72265 Ptnml(0-2): 380, 17094, 42190, 17163, 389 LTC: https://tests.stockfishchess.org/tests/view/6471e9b3e549d9cf2fb219ef LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 127926 W: 34474 L: 34369 D: 59083 Ptnml(0-2): 43, 12505, 38776, 12582, 57 closes https://github.com/official-stockfish/Stockfish/pull/4590 Bench: 2541211 --- AUTHORS | 1 + src/evaluate.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 884bffab..d01d23cd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -213,6 +213,7 @@ tttak Unai Corzo (unaiic) Uri Blass (uriblass) Vince Negri (cuddlestmonkey) +windfishballad xefoci7612 zz4032 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index cc789e35..7239fd1e 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1072,7 +1072,7 @@ Value Eval::evaluate(const Position& pos) { // Blend nnue complexity with (semi)classical complexity nnueComplexity = ( 397 * nnueComplexity - + (477 + optimism) * abs(psq - nnue) + + 477 * abs(psq - nnue) ) / 1024; optimism += optimism * nnueComplexity / 256; From c1fff71650e2f8bf5a2d63bdc043161cdfe8e460 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Fri, 12 May 2023 18:07:20 -0400 Subject: [PATCH 160/192] Update NNUE architecture to SFNNv6 with larger L1 size of 1536 Created by training a new net from scratch with L1 size increased from 1024 to 1536. Thanks to Vizvezdenec for the idea of exploring larger net sizes after recent training data improvements. A new net was first trained with lambda 1.0 and constant LR 8.75e-4. Then a strong net from a later epoch in the training run was chosen for retraining with start-lambda 1.0 and initial LR 4.375e-4 decaying with gamma 0.995. Retraining was performed a total of 3 times, for this 4-step process: 1. 400 epochs, lambda 1.0 on filtered T77+T79 v6 deduplicated data 2. 800 epochs, end-lambda 0.75 on T60T70wIsRightFarseerT60T74T75T76.binpack 3. 800 epochs, end-lambda 0.75 and early-fen-skipping 28 on the master dataset 4. 800 epochs, end-lambda 0.7 and early-fen-skipping 28 on the master dataset In the training sequence that reached the new nn-8d69132723e2.nnue net, the epochs used for the 3x retraining runs were: 1. epoch 379 trained on T77T79-filter-v6-dd.min.binpack 2. epoch 679 trained on T60T70wIsRightFarseerT60T74T75T76.binpack 3. epoch 799 trained on the master dataset For training from scratch: python3 easy_train.py \ --experiment-name new-L1-1536-T77T79-filter-v6dd \ --training-dataset /data/T77T79-filter-v6-dd.min.binpack \ --max_epoch 400 \ --lambda 1.0 \ --start-from-engine-test-net False \ --engine-test-branch linrock/Stockfish/L1-1536 \ --nnue-pytorch-branch linrock/Stockfish/misc-fixes-L1-1536 \ --tui False \ --gpus "0," \ --seed $RANDOM Retraining commands were similar to each other. For the 3rd retraining run: python3 easy_train.py \ --experiment-name L1-1536-T77T79-v6dd-Re1-LeelaFarseer-Re2-masterDataset-Re3-sameData \ --training-dataset /data/leela96-dfrc99-v2-T60novdecT80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack \ --early-fen-skipping 28 \ --max_epoch 800 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --lr 4.375e-4 \ --gamma 0.995 \ --start-from-engine-test-net False \ --start-from-model /data/L1-1536-T77T79-v6dd-Re1-LeelaFarseer-Re2-masterDataset-nn-epoch799.nnue \ --engine-test-branch linrock/Stockfish/L1-1536 \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \ --tui False \ --gpus "0," \ --seed $RANDOM The T77+T79 data used is a subset of the master dataset available at: https://robotmoon.com/nnue-training-data/ T60T70wIsRightFarseerT60T74T75T76.binpack is available at: https://drive.google.com/drive/folders/1S9-ZiQa_3ApmjBtl2e8SyHxj4zG4V8gG Local elo at 25k nodes per move vs. nn-e1fb1ade4432.nnue (L1 size 1024): nn-epoch759.nnue : 26.9 +/- 1.6 Failed STC https://tests.stockfishchess.org/tests/view/64742485d29264e4cfa75f97 LLR: -2.94 (-2.94,2.94) <0.00,2.00> Total: 13728 W: 3588 L: 3829 D: 6311 Ptnml(0-2): 71, 1661, 3610, 1482, 40 Failing LTC https://tests.stockfishchess.org/tests/view/64752d7c4a36543c4c9f3618 LLR: -1.91 (-2.94,2.94) <0.50,2.50> Total: 35424 W: 9522 L: 9603 D: 16299 Ptnml(0-2): 24, 3579, 10585, 3502, 22 Passed VLTC 180+1.8 https://tests.stockfishchess.org/tests/view/64752df04a36543c4c9f3638 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 47616 W: 13174 L: 12863 D: 21579 Ptnml(0-2): 13, 4261, 14952, 4566, 16 Passed VLTC SMP 60+0.6 th 8 https://tests.stockfishchess.org/tests/view/647446ced29264e4cfa761e5 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 19942 W: 5694 L: 5451 D: 8797 Ptnml(0-2): 6, 1504, 6707, 1749, 5 closes https://github.com/official-stockfish/Stockfish/pull/4593 bench 2222567 --- src/evaluate.h | 2 +- src/nnue/nnue_architecture.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evaluate.h b/src/evaluate.h index f5db1c1e..0990111c 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-e1fb1ade4432.nnue" + #define EvalFileDefaultName "nn-8d69132723e2.nnue" namespace NNUE { diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index 508f3aae..d10434f3 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -39,7 +39,7 @@ namespace Stockfish::Eval::NNUE { using FeatureSet = Features::HalfKAv2_hm; // Number of input feature dimensions after conversion -constexpr IndexType TransformedFeatureDimensions = 1024; +constexpr IndexType TransformedFeatureDimensions = 1536; constexpr IndexType PSQTBuckets = 8; constexpr IndexType LayerStacks = 8; From 07bd8adcbce41f076c36f4b65c7f9a786de0b02d Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sun, 28 May 2023 14:45:24 -0400 Subject: [PATCH 161/192] Simplify nnue eval complexity calculation Remove a multiplier when blending nnue complexity with semi-classical complexity. Passed non-regression STC: https://tests.stockfishchess.org/tests/view/6473a71dd29264e4cfa75839 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 124768 W: 33180 L: 33060 D: 58528 Ptnml(0-2): 314, 13797, 34030, 13941, 302 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/6474af3dd29264e4cfa768f4 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 108180 W: 29008 L: 28884 D: 50288 Ptnml(0-2): 29, 10420, 33075, 10530, 36 closes https://github.com/official-stockfish/Stockfish/pull/4592 bench 2316827 --- src/evaluate.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 7239fd1e..40c43d23 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1071,9 +1071,7 @@ Value Eval::evaluate(const Position& pos) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend nnue complexity with (semi)classical complexity - nnueComplexity = ( 397 * nnueComplexity - + 477 * abs(psq - nnue) - ) / 1024; + nnueComplexity = 25 * (nnueComplexity + abs(psq - nnue)) / 64; optimism += optimism * nnueComplexity / 256; v = (nnue * (945 + npm) + optimism * (174 + npm)) / 1024; From d99942f25449789de78c9d36e3dcb67d4eb04e98 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 31 May 2023 09:22:26 +0300 Subject: [PATCH 162/192] Small simplification for probcut in check Remove depth condition from there as not longer needed. Passed STC: https://tests.stockfishchess.org/tests/view/647367cad29264e4cfa753e6 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 254336 W: 67830 L: 67847 D: 118659 Ptnml(0-2): 580, 28181, 69697, 28096, 614 Passed LTC: https://tests.stockfishchess.org/tests/view/647576184a36543c4c9f3af7 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 80706 W: 22048 L: 21898 D: 36760 Ptnml(0-2): 28, 7721, 24712, 7857, 35 closes https://github.com/official-stockfish/Stockfish/pull/4594 bench 2381945 --- src/search.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 93212e23..41116eb2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -895,7 +895,6 @@ moves_loop: // When in check, search starts here probCutBeta = beta + 430; if ( ss->inCheck && !PvNode - && depth >= 2 && ttCapture && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 4 From 06186b786e4a73a29d6f0eef80fa7e20084a1e85 Mon Sep 17 00:00:00 2001 From: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com> Date: Fri, 2 Jun 2023 19:55:25 +0800 Subject: [PATCH 163/192] Search tuning at very long time control with new net MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The most significant change would be the singularBeta formula. It was first tested by cj5716 (see https://tests.stockfishchess.org/tests/view/647317c9d29264e4cfa74ec7), and I took much inspiration from that idea. LTC (fixed games): https://tests.stockfishchess.org/tests/view/6479d8da54dd118e1d990b12 Elo: 0.61 ± 1.2 (95%) LOS: 83.4% Total: 60000 W: 16278 L: 16172 D: 27550 Ptnml(0-2): 16, 5845, 18179, 5937, 23 nElo: 1.38 ± 2.8 (95%) PairsRatio: 1.02 VLTC 180+1.8: https://tests.stockfishchess.org/tests/view/6479da1454dd118e1d990b2b LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 33224 W: 9261 L: 8984 D: 14979 Ptnml(0-2): 5, 2809, 10710, 3080, 8 SMP VLTC 8-thread: https://tests.stockfishchess.org/tests/view/647b0fe354dd118e1d992425 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 61398 W: 17386 L: 17081 D: 26931 Ptnml(0-2): 7, 4571, 21232, 4888, 1 closes https://github.com/official-stockfish/Stockfish/pull/4603 Bench: 2805878 --- src/search.cpp | 72 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 41116eb2..16122315 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -64,7 +64,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(148 * (d - improving)); + return Value(140 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -72,7 +72,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1356 - int(delta) * 983 / int(rootDelta)) / 1024 + (!i && r > 901); + return (r + 1372 - int(delta) * 1073 / int(rootDelta)) / 1024 + (!i && r > 936); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -82,7 +82,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min(337 * d - 497, 1632); + return std::min(336 * d - 547, 1561); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -162,7 +162,7 @@ namespace { void Search::init() { for (int i = 1; i < MAX_MOVES; ++i) - Reductions[i] = int((20.89 + std::log(Threads.size()) / 2) * std::log(i)); + Reductions[i] = int((20.57 + std::log(Threads.size()) / 2) * std::log(i)); } @@ -348,12 +348,12 @@ void Thread::search() { // Reset aspiration window starting size Value prev = rootMoves[pvIdx].averageScore; - delta = Value(11) + int(prev) * prev / 15368; + delta = Value(10) + int(prev) * prev / 15799; alpha = std::max(prev - delta,-VALUE_INFINITE); beta = std::min(prev + delta, VALUE_INFINITE); // Adjust optimism based on root move's previousScore - int opt = 116 * prev / (std::abs(prev) + 143); + int opt = 109 * prev / (std::abs(prev) + 141); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; @@ -741,7 +741,7 @@ namespace { // Use static evaluation difference to improve quiet move ordering (~4 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { - int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1717, 1717); + int bonus = std::clamp(-18 * int((ss-1)->staticEval + ss->staticEval), -1817, 1817); thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus; } @@ -751,13 +751,13 @@ namespace { // margin and the improving flag are used in various pruning heuristics. improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval - : 163; + : 173; improving = improvement > 0; // Step 7. Razoring (~1 Elo). // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if (eval < alpha - 467 - 266 * depth * depth) + if (eval < alpha - 456 - 252 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -770,16 +770,16 @@ namespace { && depth < 9 && eval - futility_margin(depth, improving) - (ss-1)->statScore / 306 >= beta && eval >= beta - && eval < 22761) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 24923) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~35 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 18404 + && (ss-1)->statScore < 17329 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 19 * depth - improvement / 13 + 257 + && ss->staticEval >= beta - 21 * depth - improvement * 99 / 1300 + 258 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly)) @@ -787,7 +787,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth and eval - Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4; + Depth R = std::min(int(eval - beta) / 173, 6) + depth / 3 + 4; ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -822,7 +822,7 @@ namespace { } } - probCutBeta = beta + 174 - 60 * improving; + probCutBeta = beta + 168 - 61 * improving; // Step 10. ProbCut (~10 Elo) // If we have a good enough capture (or queen promotion) and a reduced search returns a value @@ -892,7 +892,7 @@ namespace { moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~4 Elo) - probCutBeta = beta + 430; + probCutBeta = beta + 413; if ( ss->inCheck && !PvNode && ttCapture @@ -985,13 +985,13 @@ moves_loop: // When in check, search starts here if ( !givesCheck && lmrDepth < 7 && !ss->inCheck - && ss->staticEval + 207 + 223 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + && ss->staticEval + 197 + 248 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; Bitboard occupied; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, occupied, Value(-205) * depth)) + if (!pos.see_ge(move, occupied, Value(-212) * depth)) { // Don't prune the move if opponent King/Queen/Rook gets a discovered attack during or after the exchanges Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK); @@ -1017,18 +1017,18 @@ moves_loop: // When in check, search starts here // Continuation history based pruning (~2 Elo) if ( lmrDepth < 6 - && history < -3792 * depth) + && history < -3832 * depth) continue; history += 2 * thisThread->mainHistory[us][from_to(move)]; - lmrDepth += history / 7019; + lmrDepth += history / 7011; lmrDepth = std::max(lmrDepth, -2); // Futility pruning: parent node (~13 Elo) if ( !ss->inCheck && lmrDepth < 12 - && ss->staticEval + 111 + 136 * lmrDepth <= alpha) + && ss->staticEval + 112 + 138 * lmrDepth <= alpha) continue; lmrDepth = std::max(lmrDepth, 0); @@ -1057,7 +1057,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - (99 + 65 * (ss->ttPv && !PvNode)) * depth / 64; + Value singularBeta = ttValue - (82 + 65 * (ss->ttPv && !PvNode)) * depth / 64; Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; @@ -1071,7 +1071,7 @@ moves_loop: // When in check, search starts here // Avoid search explosion by limiting the number of double extensions if ( !PvNode - && value < singularBeta - 22 + && value < singularBeta - 21 && ss->doubleExtensions <= 11) { extension = 2; @@ -1101,16 +1101,14 @@ moves_loop: // When in check, search starts here } // Check extensions (~1 Elo) - else if ( givesCheck - && depth > 9 - && abs(ss->staticEval) > 87) + else if ( givesCheck && depth > 8) extension = 1; // Quiet ttMove extensions (~1 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 5480) + && (*contHist[0])[movedPiece][to_sq(move)] >= 5168) extension = 1; } @@ -1152,7 +1150,7 @@ moves_loop: // When in check, search starts here // Decrease reduction for PvNodes based on depth (~2 Elo) if (PvNode) - r -= 1 + 11 / (3 + depth); + r -= 1 + 12 / (3 + depth); // Decrease reduction if ttMove has been singularly extended (~1 Elo) if (singularQuietLMR) @@ -1169,10 +1167,10 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 3755; + - 4006; // Decrease/increase reduction for moves with a good/bad history (~25 Elo) - r -= ss->statScore / (10445 + 4762 * (depth > 6 && depth < 21)); + r -= ss->statScore / (11124 + 4740 * (depth > 5 && depth < 22)); // Step 17. Late moves reduction / extension (LMR, ~117 Elo) // We use various heuristics for the sons of a node after the first son has @@ -1196,8 +1194,8 @@ moves_loop: // When in check, search starts here { // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower - const bool doDeeperSearch = value > (bestValue + 63 + 11 * (newDepth - d)); - const bool doEvenDeeperSearch = value > alpha + 662 && ss->doubleExtensions <= 6; + const bool doDeeperSearch = value > (bestValue + 64 + 11 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 711 && ss->doubleExtensions <= 6; const bool doShallowerSearch = value < bestValue + newDepth; ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch; @@ -1316,8 +1314,8 @@ moves_loop: // When in check, search starts here // Reduce other moves if we have found at least one score improvement (~1 Elo) // Reduce more for depth > 3 and depth < 12 (~1 Elo) if ( depth > 1 - && beta < 14001 - && value > -12754) + && beta < 14362 + && value > -12393) depth -= depth > 3 && depth < 12 ? 2 : 1; assert(depth > 0); @@ -1366,7 +1364,7 @@ moves_loop: // When in check, search starts here // Bonus for prior countermove that caused the fail low else if (!priorCapture && prevSq != SQ_NONE) { - int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 100 * depth) + ((ss-1)->moveCount > 11); + int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 113 * depth) + ((ss-1)->moveCount > 12); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); } @@ -1494,7 +1492,7 @@ moves_loop: // When in check, search starts here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = bestValue + 190; + futilityBase = bestValue + 200; } const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, @@ -1567,7 +1565,7 @@ moves_loop: // When in check, search starts here continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-94))) + if (!pos.see_ge(move, Value(-95))) continue; } @@ -1700,7 +1698,7 @@ moves_loop: // When in check, search starts here if (!pos.capture_stage(bestMove)) { - int bonus2 = bestValue > beta + 143 ? bonus1 // larger bonus + int bonus2 = bestValue > beta + 145 ? bonus1 // larger bonus : stat_bonus(depth); // smaller bonus // Increase stats for the best move in case it was a quiet move From 6cf8d938c5950ddedb8a92cdea4712f7d507c614 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Thu, 1 Jun 2023 09:50:19 -0400 Subject: [PATCH 164/192] Simplify blending nnue complexity with optimism Passed non-regression STC: https://tests.stockfishchess.org/tests/view/6478a26d54dd118e1d98f21c LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 241248 W: 64058 L: 64063 D: 113127 Ptnml(0-2): 644, 26679, 65960, 26720, 621 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/647b464854dd118e1d9928b2 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 24336 W: 6658 L: 6451 D: 11227 Ptnml(0-2): 8, 2316, 7312, 2525, 7 closes https://github.com/official-stockfish/Stockfish/pull/4602 bench 2425813 --- src/evaluate.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 40c43d23..bf6dd69a 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1070,10 +1070,8 @@ Value Eval::evaluate(const Position& pos) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); - // Blend nnue complexity with (semi)classical complexity - nnueComplexity = 25 * (nnueComplexity + abs(psq - nnue)) / 64; - - optimism += optimism * nnueComplexity / 256; + // Blend optimism with nnue complexity and (semi)classical complexity + optimism += 25 * optimism * (nnueComplexity + abs(psq - nnue)) / 16384; v = (nnue * (945 + npm) + optimism * (174 + npm)) / 1024; } From 5930c0defbe01576315d7d081447f94a01daf337 Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Wed, 31 May 2023 11:48:18 +0200 Subject: [PATCH 165/192] Simplify away SEE verification After 4 simplificatons over PR#4453 the idea does not yield significant improvement anymore. Maybe also https://tests.stockfishchess.org/tests/view/640c88092644b62c3394c1c5 was a fluke. Passed non-regression bounds: STC: https://tests.stockfishchess.org/tests/view/64705389c079b6583146d873 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 131936 W: 35040 L: 34930 D: 61966 Ptnml(0-2): 336, 14559, 36035, 14735, 303 LTC: https://tests.stockfishchess.org/tests/view/6471a2ade549d9cf2fb213cd LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 407700 W: 109999 L: 110164 D: 187537 Ptnml(0-2): 279, 39913, 123689, 39632, 337 closes https://github.com/official-stockfish/Stockfish/pull/4595 bench: 2675974 --- src/position.cpp | 19 +++++++------------ src/position.h | 1 - src/search.cpp | 18 +----------------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 2a9d798f..af274d3f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1061,7 +1061,7 @@ Key Position::key_after(Move m) const { /// SEE value of move is greater or equal to the given threshold. We'll use an /// algorithm similar to alpha-beta pruning with a null window. -bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { +bool Position::see_ge(Move m, Value threshold) const { assert(is_ok(m)); @@ -1080,7 +1080,7 @@ bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { return true; assert(color_of(piece_on(from)) == sideToMove); - occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic + Bitboard occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic Color stm = sideToMove; Bitboard attackers = attackers_to(to, occupied); Bitboard stmAttackers, bb; @@ -1111,43 +1111,43 @@ bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { // the bitboard 'attackers' any X-ray attackers behind it. if ((bb = stmAttackers & pieces(PAWN))) { - occupied ^= least_significant_square_bb(bb); if ((swap = PawnValueMg - swap) < res) break; + occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(KNIGHT))) { - occupied ^= least_significant_square_bb(bb); if ((swap = KnightValueMg - swap) < res) break; + occupied ^= least_significant_square_bb(bb); } else if ((bb = stmAttackers & pieces(BISHOP))) { - occupied ^= least_significant_square_bb(bb); if ((swap = BishopValueMg - swap) < res) break; + occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(ROOK))) { - occupied ^= least_significant_square_bb(bb); if ((swap = RookValueMg - swap) < res) break; + occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(ROOK, QUEEN); } else if ((bb = stmAttackers & pieces(QUEEN))) { - occupied ^= least_significant_square_bb(bb); if ((swap = QueenValueMg - swap) < res) break; + occupied ^= least_significant_square_bb(bb); attackers |= (attacks_bb(to, occupied) & pieces(BISHOP, QUEEN)) | (attacks_bb(to, occupied) & pieces(ROOK , QUEEN)); @@ -1162,11 +1162,6 @@ bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { return bool(res); } -bool Position::see_ge(Move m, Value threshold) const { - Bitboard occupied; - return see_ge(m, occupied, threshold); -} - /// Position::is_draw() tests whether the position is drawn by 50-move rule /// or by repetition. It does not detect stalemates. diff --git a/src/position.h b/src/position.h index a736f3e6..780d463c 100644 --- a/src/position.h +++ b/src/position.h @@ -143,7 +143,6 @@ public: void undo_null_move(); // Static Exchange Evaluation - bool see_ge(Move m, Bitboard& occupied, Value threshold = VALUE_ZERO) const; bool see_ge(Move m, Value threshold = VALUE_ZERO) const; // Accessing hash keys diff --git a/src/search.cpp b/src/search.cpp index 16122315..1e82203a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -989,25 +989,9 @@ moves_loop: // When in check, search starts here + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; - Bitboard occupied; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, occupied, Value(-212) * depth)) - { - // Don't prune the move if opponent King/Queen/Rook gets a discovered attack during or after the exchanges - Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK); - Bitboard attacks = 0; - occupied |= to_sq(move); - while (leftEnemies && !attacks) - { - Square sq = pop_lsb(leftEnemies); - attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; - // Exclude Queen/Rook(s) which were already threatened before SEE (opponent King can't be in check when it's our turn) - if (attacks && sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))) - attacks = 0; - } - if (!attacks) + if (!pos.see_ge(move, Value(-205) * depth)) continue; - } } else { From ced0311890add58ab516b9c19608cbd1e1f295ed Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Tue, 30 May 2023 18:24:54 -0400 Subject: [PATCH 166/192] Remove static eval threshold for extensions when giving check Passed non-regression STC: https://tests.stockfishchess.org/tests/view/647685d54a36543c4c9f4f2a LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 114688 W: 30701 L: 30571 D: 53416 Ptnml(0-2): 336, 12708, 31136, 12818, 346 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/64774b02b81f005b572de770 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 107310 W: 28920 L: 28796 D: 49594 Ptnml(0-2): 33, 10427, 32621, 10531, 43 closes https://github.com/official-stockfish/Stockfish/pull/4599 bench 2597974 --- src/search.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 1e82203a..4365b215 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1085,7 +1085,8 @@ moves_loop: // When in check, search starts here } // Check extensions (~1 Elo) - else if ( givesCheck && depth > 8) + else if ( givesCheck + && depth > 9) extension = 1; // Quiet ttMove extensions (~1 Elo) From 8dea070538dcad790de3c5b9720bdbb836a32440 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Thu, 1 Jun 2023 15:24:13 +0300 Subject: [PATCH 167/192] Move internal iterative reduction before probcut This patch moves IIR before probcut which allows probcut to be produced at lower depths. Comments in IIR are also slightly updated. Passed STC: https://tests.stockfishchess.org/tests/view/6472d604d29264e4cfa749fd LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 387616 W: 103295 L: 102498 D: 181823 Ptnml(0-2): 976, 42322, 106381, 43187, 942 Passed LTC: https://tests.stockfishchess.org/tests/view/6475eb8c4a36543c4c9f42e8 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 202836 W: 54901 L: 54281 D: 93654 Ptnml(0-2): 85, 19609, 61422, 20205, 97 closes https://github.com/official-stockfish/Stockfish/pull/4597 bench 2551691 --- src/search.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4365b215..0e82f04e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -822,9 +822,24 @@ namespace { } } + // Step 10. If the position doesn't a have ttMove, decrease depth by 2 + // (or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth). + // Use qsearch if depth is equal or below zero (~9 Elo) + if ( PvNode + && !ttMove) + depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth); + + if (depth <= 0) + return qsearch(pos, ss, alpha, beta); + + if ( cutNode + && depth >= 8 + && !ttMove) + depth -= 2; + probCutBeta = beta + 168 - 61 * improving; - // Step 10. ProbCut (~10 Elo) + // Step 11. ProbCut (~10 Elo) // If we have a good enough capture (or queen promotion) and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode @@ -875,20 +890,6 @@ namespace { Eval::NNUE::hint_common_parent_position(pos); } - // Step 11. If the position is not in TT, decrease depth by 2 (or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth). - // Use qsearch if depth is equal or below zero (~9 Elo) - if ( PvNode - && !ttMove) - depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth); - - if (depth <= 0) - return qsearch(pos, ss, alpha, beta); - - if ( cutNode - && depth >= 8 - && !ttMove) - depth -= 2; - moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~4 Elo) From b60738e01b5393e6f85bc10d2f257dd0cd26a2f9 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Mon, 5 Jun 2023 00:59:31 +0300 Subject: [PATCH 168/192] Fix no previous moves on root. guards against no previous move existing if qSearch is called on the root node (i.e. when razoring). Passed Non-regression STC: https://tests.stockfishchess.org/tests/view/647d242d726f6b400e408143 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 53120 W: 14167 L: 13976 D: 24977 Ptnml(0-2): 109, 5597, 14981, 5740, 133 closes https://github.com/official-stockfish/Stockfish/pull/4604 Bench: 2551691 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 0e82f04e..c7b00766 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1489,7 +1489,7 @@ moves_loop: // When in check, search starts here // to search the moves. Because the depth is <= 0 here, only captures, // queen promotions, and other checks (only if depth >= DEPTH_QS_CHECKS) // will be generated. - Square prevSq = (ss-1)->currentMove != MOVE_NULL ? to_sq((ss-1)->currentMove) : SQ_NONE; + Square prevSq = is_ok((ss-1)->currentMove) ? to_sq((ss-1)->currentMove) : SQ_NONE; MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &thisThread->captureHistory, contHist, From 295f57829ea189248c8b4afa8d11222d170f78da Mon Sep 17 00:00:00 2001 From: disservin Date: Mon, 17 Apr 2023 22:16:22 +0200 Subject: [PATCH 169/192] Add binaries to releases with github actions when a release is made with a tag matching sf_* the binaries will also be uploaded to the release as assets. closes https://github.com/official-stockfish/Stockfish/pull/4596 No functional change. --- .github/workflows/stockfish.yml | 6 +++-- .github/workflows/stockfish_arm_binaries.yml | 8 ++++++ .github/workflows/stockfish_binaries.yml | 27 +++++++++++++------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index 6345b27c..082c65de 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -1,6 +1,8 @@ name: Stockfish on: push: + tags: + - '*' branches: - master - tools @@ -17,8 +19,8 @@ jobs: Compiles: uses: ./.github/workflows/stockfish_compile_test.yml Binaries: - if: github.ref == 'refs/heads/master' + if: github.ref == 'refs/heads/master' || (startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag') uses: ./.github/workflows/stockfish_binaries.yml ARM_Binaries: - if: github.ref == 'refs/heads/master' + if: github.ref == 'refs/heads/master' || (startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag') uses: ./.github/workflows/stockfish_arm_binaries.yml diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml index e088c441..9a4734ee 100644 --- a/.github/workflows/stockfish_arm_binaries.yml +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -115,6 +115,8 @@ jobs: cp "Top CPU Contributors.txt" stockfish/ cp Copying.txt stockfish/ cp AUTHORS stockfish/ + cp CITATION.cff stockfish/ + cp README.md stockfish/ tar -cvf stockfish-android-$BINARY.tar stockfish - name: Upload binaries @@ -122,3 +124,9 @@ jobs: with: name: stockfish-android-${{ matrix.binaries }} path: stockfish-android-${{ matrix.binaries }}.tar + + - name: Release + if: startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag' + uses: softprops/action-gh-release@v1 + with: + files: stockfish-android-${{ matrix.binaries }}.tar \ No newline at end of file diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index b22897cf..86449b97 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -9,23 +9,26 @@ jobs: COMPILER: ${{ matrix.config.compiler }} COMP: ${{ matrix.config.comp }} EXT: ${{ matrix.config.ext }} - OS: ${{ matrix.config.os }} + NAME: ${{ matrix.config.simple_name }} BINARY: ${{ matrix.binaries }} strategy: matrix: config: - name: Ubuntu 20.04 GCC os: ubuntu-20.04 + simple_name: ubuntu compiler: g++ comp: gcc shell: bash {0} - name: MacOS 12 Apple Clang os: macos-12 + simple_name: macos compiler: clang++ comp: clang shell: bash {0} - name: Windows 2022 Mingw-w64 GCC x86_64 os: windows-2022 + simple_name: windows compiler: g++ comp: mingw msys_sys: mingw64 @@ -75,19 +78,17 @@ jobs: - name: Compile ${{ matrix.binaries }} build run: | - make clean make -j2 profile-build ARCH=$BINARY COMP=$COMP make strip ARCH=$BINARY COMP=$COMP - mv ./stockfish$EXT ../stockfish-$OS-$BINARY$EXT + mv ./stockfish$EXT ../stockfish-$NAME-$BINARY$EXT - name: Remove non src files - run: rm -f *.o .depend *.nnue + run: git clean -fx - name: Download wiki run: | git clone https://github.com/official-stockfish/Stockfish.wiki.git ../wiki - cd ../wiki - rm -rf .git + rm -rf ../wiki/.git - name: Create tar archive. run: | @@ -95,14 +96,22 @@ jobs: mkdir stockfish cp -r wiki stockfish/ cp -r src stockfish/ - cp stockfish-$OS-$BINARY$EXT stockfish/ + cp stockfish-$NAME-$BINARY$EXT stockfish/ cp "Top CPU Contributors.txt" stockfish/ cp Copying.txt stockfish/ cp AUTHORS stockfish/ - tar -cvf stockfish-$OS-$BINARY.tar stockfish + cp CITATION.cff stockfish/ + cp README.md stockfish/ + tar -cvf stockfish-$NAME-$BINARY.tar stockfish - name: Upload binaries uses: actions/upload-artifact@v3 with: name: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }} - path: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }}.tar + path: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.tar + + - name: Release + if: startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag' + uses: softprops/action-gh-release@v1 + with: + files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.tar From 373359b44d0947cce2628a9a8c9b432a458615a8 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Sun, 4 Jun 2023 01:56:11 -0400 Subject: [PATCH 170/192] Update default net to nn-0dd1cebea573.nnue Created by retraining an earlier epoch of the experiment leading to the first SFNNv6 net on a more-randomized version of the nn-e1fb1ade4432.nnue dataset mixed with unfiltered T80 apr2023 data. Trained using early-fen-skipping 28 and max-epoch 960. The trainer settings and epochs used in the 5-step training sequence leading here were: 1. train from scratch for 400 epochs, lambda 1.0, constant LR 9.75e-4, T79T77-filter-v6-dd.min.binpack 2. retrain ep379, max-epoch 800, end-lambda 0.75, T60T70wIsRightFarseerT60T74T75T76.binpack 3. retrain ep679, max-epoch 800, end-lambda 0.75, skip 28, nn-e1fb1ade4432 dataset 4. retrain ep799, max-epoch 800, end-lambda 0.7, skip 28, nn-e1fb1ade4432 dataset 5. retrain ep439, max-epoch 960, end-lambda 0.7, skip 28, shuffled nn-e1fb1ade4432 + T80 apr2023 This net was epoch 559 of the final (step 5) retraining: ```bash python3 easy_train.py \ --experiment-name L1-1536-Re4-leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr-shuffled-sk28 \ --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \ --early-fen-skipping 28 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --max_epoch 960 \ --start-from-engine-test-net False \ --start-from-model /data/L1-1536-Re3-nn-epoch439.nnue \ --engine-test-branch linrock/Stockfish/L1-1536 \ --lr 4.375e-4 \ --gamma 0.995 \ --tui False \ --seed $RANDOM \ --gpus "0," ``` During data preparation, most binpacks were unminimized by removing positions with score 32002 (`VALUE_NONE`). This makes the tradeoff of increasing dataset filesize on disk to increase the randomness of positions in interleaved datasets. The code used for unminimizing is at: https://github.com/linrock/Stockfish/tree/tools-unminify For preparing the dataset used in this experiment: ```bash python3 interleave_binpacks.py \ leela96-filt-v2.binpack \ dfrc99-16tb7p-eval-filt-v2.binpack \ filt-v6-dd-min/test60-novdec2021-12tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd-min/test80-aug2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd-min/test80-sep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd-min/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd-min/test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd-min/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd-min/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \ filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \ filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \ test80-apr2023-2tb7p.binpack \ /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack ``` T80 apr2023 data was converted using lc0-rescorer with ~2tb of tablebases and can be found at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move vs. nn-e1fb1ade4432.nnue (L1 size 1024): nn-epoch559.nnue : 25.7 +/- 1.6 Passed STC: https://tests.stockfishchess.org/tests/view/647cd3b87cf638f0f53f9cbb LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 59200 W: 16000 L: 15660 D: 27540 Ptnml(0-2): 159, 6488, 15996, 6768, 189 Passed LTC: https://tests.stockfishchess.org/tests/view/647d58de726f6b400e4085d8 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 58800 W: 16002 L: 15657 D: 27141 Ptnml(0-2): 44, 5607, 17748, 5962, 39 closes https://github.com/official-stockfish/Stockfish/pull/4606 bench 2141197 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 0990111c..dcbe6b3c 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-8d69132723e2.nnue" + #define EvalFileDefaultName "nn-0dd1cebea573.nnue" namespace NNUE { From 54ad986768eec524aeab721713ea2009931b51b3 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Mon, 5 Jun 2023 01:08:38 -0400 Subject: [PATCH 171/192] Remove optimism multiplier in nnue eval calculation The same formula had passed SPRT against an earlier version of master. Passed non-regression STC vs. d99942f: https://tests.stockfishchess.org/tests/view/6478e76654dd118e1d98f72e LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 118720 W: 31402 L: 31277 D: 56041 Ptnml(0-2): 301, 13148, 32344, 13259, 308 Passed non-regression LTC vs. d99942f: https://tests.stockfishchess.org/tests/view/647a22c154dd118e1d991146 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 74286 W: 20019 L: 19863 D: 34404 Ptnml(0-2): 31, 7189, 22540, 7359, 24 The earlier patch had conflicted with a faster SPRT passer, so this was tested again after rebasing on latest master. Passed non-regression STC: https://tests.stockfishchess.org/tests/view/647d6e46726f6b400e408790 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 166176 W: 44309 L: 44234 D: 77633 Ptnml(0-2): 461, 18252, 45557, 18387, 431 Passed non-regression LTC: https://tests.stockfishchess.org/tests/view/647eb00ba268d1bc11255e7b LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 28170 W: 7713 L: 7513 D: 12944 Ptnml(0-2): 14, 2609, 8635, 2817, 10 closes https://github.com/official-stockfish/Stockfish/pull/4607 bench 2503095 --- src/evaluate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index bf6dd69a..35d05427 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1071,8 +1071,8 @@ Value Eval::evaluate(const Position& pos) { Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); // Blend optimism with nnue complexity and (semi)classical complexity - optimism += 25 * optimism * (nnueComplexity + abs(psq - nnue)) / 16384; - v = (nnue * (945 + npm) + optimism * (174 + npm)) / 1024; + optimism += optimism * (nnueComplexity + abs(psq - nnue)) / 512; + v = (nnue * (945 + npm) + optimism * (150 + npm)) / 1024; } // Damp down the evaluation linearly when shuffling From a9a6915e0839d3f3f54659c86f15868a7db0e386 Mon Sep 17 00:00:00 2001 From: cj5716 <125858804+cj5716@users.noreply.github.com> Date: Mon, 5 Jun 2023 07:59:56 +0800 Subject: [PATCH 172/192] Simplify multiplier for improvement This simplifies a `* 99 / 1300` term into just `/ 13`. Passed non-regression STC: LLR: 2.92 (-2.94,2.94) <-1.75,0.25> Total: 58816 W: 15727 L: 15540 D: 27549 Ptnml(0-2): 149, 6370, 16203, 6517, 169 https://tests.stockfishchess.org/tests/view/647d25e4726f6b400e408165 Passed non-regression LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 154386 W: 41749 L: 41669 D: 70968 Ptnml(0-2): 94, 14992, 46956, 15042, 109 https://tests.stockfishchess.org/tests/view/647d9b3c726f6b400e408b2a closes https://github.com/official-stockfish/Stockfish/pull/4608 Bench: 2511327 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index c7b00766..593fdc72 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -779,7 +779,7 @@ namespace { && (ss-1)->statScore < 17329 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 21 * depth - improvement * 99 / 1300 + 258 + && ss->staticEval >= beta - 21 * depth - improvement / 13 + 258 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly)) From e1dd005583bd6c2aaf58468efc5de86a3936380a Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Wed, 7 Jun 2023 09:01:05 +0200 Subject: [PATCH 173/192] Reintroduce SEE verification against discovered attacks Reintroduces https://github.com/official-stockfish/Stockfish/pull/4453 along with https://github.com/official-stockfish/Stockfish/pull/4469 Leaving out https://github.com/official-stockfish/Stockfish/pull/4533 https://github.com/official-stockfish/Stockfish/pull/4572 Passed STC: https://tests.stockfishchess.org/tests/view/647d8c37726f6b400e408a0a LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 143168 W: 38346 L: 37892 D: 66930 Ptnml(0-2): 352, 15672, 39164, 15962, 434 Passed LTC: https://tests.stockfishchess.org/tests/view/647ee8c528c4431bcb58e432 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 71538 W: 19560 L: 19190 D: 32788 Ptnml(0-2): 49, 6905, 21499, 7259, 57 closes https://github.com/official-stockfish/Stockfish/pull/4609 bench: 2595430 --- src/position.cpp | 19 ++++++++++++------- src/position.h | 1 + src/search.cpp | 23 +++++++++++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index af274d3f..2a9d798f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1061,7 +1061,7 @@ Key Position::key_after(Move m) const { /// SEE value of move is greater or equal to the given threshold. We'll use an /// algorithm similar to alpha-beta pruning with a null window. -bool Position::see_ge(Move m, Value threshold) const { +bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const { assert(is_ok(m)); @@ -1080,7 +1080,7 @@ bool Position::see_ge(Move m, Value threshold) const { return true; assert(color_of(piece_on(from)) == sideToMove); - Bitboard occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic + occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic Color stm = sideToMove; Bitboard attackers = attackers_to(to, occupied); Bitboard stmAttackers, bb; @@ -1111,43 +1111,43 @@ bool Position::see_ge(Move m, Value threshold) const { // the bitboard 'attackers' any X-ray attackers behind it. if ((bb = stmAttackers & pieces(PAWN))) { + occupied ^= least_significant_square_bb(bb); if ((swap = PawnValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(KNIGHT))) { + occupied ^= least_significant_square_bb(bb); if ((swap = KnightValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); } else if ((bb = stmAttackers & pieces(BISHOP))) { + occupied ^= least_significant_square_bb(bb); if ((swap = BishopValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(BISHOP, QUEEN); } else if ((bb = stmAttackers & pieces(ROOK))) { + occupied ^= least_significant_square_bb(bb); if ((swap = RookValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= attacks_bb(to, occupied) & pieces(ROOK, QUEEN); } else if ((bb = stmAttackers & pieces(QUEEN))) { + occupied ^= least_significant_square_bb(bb); if ((swap = QueenValueMg - swap) < res) break; - occupied ^= least_significant_square_bb(bb); attackers |= (attacks_bb(to, occupied) & pieces(BISHOP, QUEEN)) | (attacks_bb(to, occupied) & pieces(ROOK , QUEEN)); @@ -1162,6 +1162,11 @@ bool Position::see_ge(Move m, Value threshold) const { return bool(res); } +bool Position::see_ge(Move m, Value threshold) const { + Bitboard occupied; + return see_ge(m, occupied, threshold); +} + /// Position::is_draw() tests whether the position is drawn by 50-move rule /// or by repetition. It does not detect stalemates. diff --git a/src/position.h b/src/position.h index 780d463c..2e6014db 100644 --- a/src/position.h +++ b/src/position.h @@ -144,6 +144,7 @@ public: // Static Exchange Evaluation bool see_ge(Move m, Value threshold = VALUE_ZERO) const; + bool see_ge(Move m, Bitboard& occupied, Value threshold = VALUE_ZERO) const; // Accessing hash keys Key key() const; diff --git a/src/search.cpp b/src/search.cpp index 593fdc72..b2c2344a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -990,9 +990,28 @@ moves_loop: // When in check, search starts here + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha) continue; + Bitboard occupied; // SEE based pruning (~11 Elo) - if (!pos.see_ge(move, Value(-205) * depth)) - continue; + if (!pos.see_ge(move, occupied, Value(-205) * depth)) + { + if (depth < 2 - capture) + continue; + // Don't prune the move if opponent Queen/Rook is under discovered attack after the exchanges + // Don't prune the move if opponent King is under discovered attack after or during the exchanges + Bitboard leftEnemies = (pos.pieces(~us, KING, QUEEN, ROOK)) & occupied; + Bitboard attacks = 0; + occupied |= to_sq(move); + while (leftEnemies && !attacks) + { + Square sq = pop_lsb(leftEnemies); + attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; + // don't consider pieces which were already threatened/hanging before SEE exchanges + if (attacks && (sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))) + attacks = 0; + } + if (!attacks) + continue; + } } else { From 932f5a2d657c846c282adcf2051faef7ca17ae15 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Wed, 7 Jun 2023 14:57:17 -0400 Subject: [PATCH 174/192] Update default net to nn-ea57bea57e32.nnue Created by retraining an earlier epoch (ep659) of the experiment that led to the first SFNNv6 net: - First retrained on the nn-0dd1cebea573 dataset - Then retrained with skip 20 on a smaller dataset containing unfiltered Leela data - And then retrained again with skip 27 on the nn-0dd1cebea573 dataset The equivalent 7-step training sequence from scratch that led here was: 1. max-epoch 400, lambda 1.0, constant LR 9.75e-4, T79T77-filter-v6-dd.min.binpack ep379 chosen for retraining in step2 2. max-epoch 800, end-lambda 0.75, T60T70wIsRightFarseerT60T74T75T76.binpack ep679 chosen for retraining in step3 3. max-epoch 800, end-lambda 0.75, skip 28, nn-e1fb1ade4432 dataset ep799 chosen for retraining in step4 4. max-epoch 800, end-lambda 0.7, skip 28, nn-e1fb1ade4432 dataset ep759 became nn-8d69132723e2.nnue (first SFNNv6 net) ep659 chosen for retraining in step5 5. max-epoch 800, end-lambda 0.7, skip 28, nn-0dd1cebea573 dataset ep759 chosen for retraining in step6 6. max-epoch 800, end-lambda 0.7, skip 20, leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack ep639 chosen for retraining in step7 7. max-epoch 800, end-lambda 0.7, skip 27, nn-0dd1cebea573 dataset ep619 became nn-ea57bea57e32.nnue For the last retraining (step7): python3 easy_train.py --experiment-name L1-1536-Re6-masterShuffled-ep639-sk27-Re5-leela-dfrc-v2-T77toT80small-Re4-masterShuffled-ep659-Re3-sameAs-Re2-leela96-dfrc99-16t-v2-T60novdecT80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-Re1-LeelaFarseer-new-T77T79 \ --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack \ --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \ --early-fen-skipping 27 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --max_epoch 800 \ --start-from-engine-test-net False \ --start-from-model /data/L1-1536-Re5-leela-dfrc-v2-T77toT80small-epoch639.nnue \ --lr 4.375e-4 \ --gamma 0.995 \ --tui False \ --seed $RANDOM \ --gpus "0," For preparing the step6 leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack dataset: python3 interleave_binpacks.py \ leela96-filt-v2.binpack \ dfrc99-16tb7p-eval-filt-v2.binpack \ test77-dec2021-16tb7p.no-db.min-mar2023.binpack \ test78-janfeb2022-16tb7p.no-db.min-mar2023.binpack \ test79-apr2022-16tb7p-filter-v6-dd.binpack \ test80-apr2022-16tb7p.no-db.min-mar2023.binpack \ /data/leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack The unfiltered Leela data used for the step6 dataset can be found at: https://robotmoon.com/nnue-training-data Local elo at 25k nodes per move: nn-epoch619.nnue : 2.3 +/- 1.9 Passed STC: https://tests.stockfishchess.org/tests/view/6480d43c6e6ce8d9fc6d7cc8 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 40992 W: 11017 L: 10706 D: 19269 Ptnml(0-2): 113, 4400, 11170, 4689, 124 Passed LTC: https://tests.stockfishchess.org/tests/view/648119ac6e6ce8d9fc6d8208 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 129174 W: 35059 L: 34579 D: 59536 Ptnml(0-2): 66, 12548, 38868, 13050, 55 closes https://github.com/official-stockfish/Stockfish/pull/4611 bench: 2370027 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index dcbe6b3c..fc852c8d 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-0dd1cebea573.nnue" + #define EvalFileDefaultName "nn-ea57bea57e32.nnue" namespace NNUE { From b7ee7290b552b21352491ec7f390565ff4748647 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 12 Jun 2023 09:51:28 +0200 Subject: [PATCH 175/192] Add network export to CI verify the network written by export_net matches the original closes https://github.com/official-stockfish/Stockfish/pull/4613 No functional change --- tests/instrumented.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/instrumented.sh b/tests/instrumented.sh index e9455eab..1b37c7a8 100755 --- a/tests/instrumented.sh +++ b/tests/instrumented.sh @@ -70,7 +70,8 @@ for args in "eval" \ "go depth 10" \ "go movetime 1000" \ "go wtime 8000 btime 8000 winc 500 binc 500" \ - "bench 128 $threads 8 default depth" + "bench 128 $threads 8 default depth" \ + "export_net verify.nnue" do echo "$prefix $exeprefix ./stockfish $args $postfix" @@ -78,6 +79,11 @@ do done +# verify the generated net equals the base net +network=`./stockfish uci | grep 'option name EvalFile type string default' | awk '{print $NF}'` +echo "Comparing $network to the written verify.nnue" +diff $network verify.nnue + # more general testing, following an uci protocol exchange cat << EOF > game.exp set timeout 240 From 38e61663d836e062af0bc002814ad5149c4b7729 Mon Sep 17 00:00:00 2001 From: AndrovT <31534597+AndrovT@users.noreply.github.com> Date: Sun, 11 Jun 2023 03:24:04 +0200 Subject: [PATCH 176/192] Use block sparse input for the first layer. Use block sparse input for the first fully connected layer on architectures with at least SSSE3. Depending on the CPU architecture, this yields a speedup of up to 10%, e.g. ``` Result of 100 runs of 'bench 16 1 13 default depth NNUE' base (...ockfish-base) = 959345 +/- 7477 test (...ckfish-patch) = 1054340 +/- 9640 diff = +94995 +/- 3999 speedup = +0.0990 P(speedup > 0) = 1.0000 CPU: 8 x AMD Ryzen 7 5700U with Radeon Graphics Hyperthreading: on ``` Passed STC: https://tests.stockfishchess.org/tests/view/6485aa0965ffe077ca12409c LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 8864 W: 2479 L: 2223 D: 4162 Ptnml(0-2): 13, 829, 2504, 1061, 25 This commit includes a net with reordered weights, to increase the likelihood of block sparse inputs, but otherwise equivalent to the previous master net (nn-ea57bea57e32.nnue). Activation data collected with https://github.com/AndrovT/Stockfish/tree/log-activations, running bench 16 1 13 varied_1000.epd depth NNUE on this data. Net parameters permuted with https://gist.github.com/AndrovT/9e3fbaebb7082734dc84d27e02094cb3. closes https://github.com/official-stockfish/Stockfish/pull/4612 No functional change --- AUTHORS | 1 + src/evaluate.h | 2 +- .../layers/affine_transform_sparse_input.h | 286 ++++++++++++++++++ src/nnue/nnue_architecture.h | 3 +- 4 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/nnue/layers/affine_transform_sparse_input.h diff --git a/AUTHORS b/AUTHORS index d01d23cd..63b862ce 100644 --- a/AUTHORS +++ b/AUTHORS @@ -159,6 +159,7 @@ Norman Schmidt (FireFather) notruck Ofek Shochat (OfekShochat, ghostway) Ondrej Mosnáček (WOnder93) +Ondřej Mišina (AndrovT) Oskar Werkelin Ahlin Pablo Vazquez Panthee diff --git a/src/evaluate.h b/src/evaluate.h index fc852c8d..94cd42cc 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-ea57bea57e32.nnue" + #define EvalFileDefaultName "nn-fdc1d0fe6455.nnue" namespace NNUE { diff --git a/src/nnue/layers/affine_transform_sparse_input.h b/src/nnue/layers/affine_transform_sparse_input.h new file mode 100644 index 00000000..00b17c19 --- /dev/null +++ b/src/nnue/layers/affine_transform_sparse_input.h @@ -0,0 +1,286 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2023 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 . +*/ + +// Definition of layer AffineTransformSparseInput of NNUE evaluation function + +#ifndef NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED +#define NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED + +#include +#include +#include +#include +#include "../nnue_common.h" +#include "affine_transform.h" +#include "simd.h" + +/* + This file contains the definition for a fully connected layer (aka affine transform) with block sparse input. +*/ + +namespace Stockfish::Eval::NNUE::Layers { +#if defined(__GNUC__) // GCC, Clang, ICC + + static inline IndexType lsb_(std::uint32_t b) { + assert(b); + return IndexType(__builtin_ctzl(b)); + } + +#elif defined(_MSC_VER) // MSVC + + static inline IndexType lsb_(std::uint32_t b) { + assert(b); + unsigned long idx; + _BitScanForward(&idx, b); + return (IndexType) idx; + } + +#else // Compiler is neither GCC nor MSVC compatible + +#error "Compiler not supported." + +#endif + + +#if defined(USE_SSSE3) + alignas(CacheLineSize) static inline const std::array, 256> lookup_indices = [](){ + std::array, 256> v{}; + for (int i = 0; i < 256; ++i) + { + int j = i; + int k = 0; + while(j) + { + const IndexType lsbIndex = lsb_(std::uint32_t(j)); + j &= j - 1; + v[i][k] = lsbIndex; + ++k; + } + } + return v; + }(); + alignas(CacheLineSize) static inline const std::array lookup_count = [](){ + std::array v; + for (int i = 0; i < 256; ++i) + { + int j = i; + int k = 0; + while(j) + { + j &= j - 1; + ++k; + } + v[i] = k; + } + return v; + }(); + + // Find indices of nonzero numbers in an int32_t array + template + void find_nnz(const std::int32_t* input, std::uint16_t* out, IndexType& count_out) { +#if defined (USE_AVX512) + using vec_t = __m512i; + #define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512()) +#elif defined (USE_AVX2) + using vec_t = __m256i; + #define vec_nnz(a) _mm256_movemask_ps((__m256)_mm256_cmpgt_epi32(a, _mm256_setzero_si256())) +#elif defined (USE_SSSE3) + using vec_t = __m128i; + #define vec_nnz(a) _mm_movemask_ps((__m128)_mm_cmpgt_epi32(a, _mm_setzero_si128())) +#endif + constexpr IndexType InputSimdWidth = sizeof(vec_t) / sizeof(std::int32_t); + // Inputs are processed InputSimdWidth at a time and outputs are processed 8 at a time so we process in chunks of max(InputSimdWidth, 8) + constexpr IndexType ChunkSize = std::max(InputSimdWidth, 8); + constexpr IndexType NumChunks = InputDimensions / ChunkSize; + constexpr IndexType InputsPerChunk = ChunkSize / InputSimdWidth; + constexpr IndexType OutputsPerChunk = ChunkSize / 8; + + const auto inputVector = reinterpret_cast(input); + IndexType count = 0; + __m128i base = _mm_set1_epi16(0); + __m128i increment = _mm_set1_epi16(8); + for (IndexType i = 0; i < NumChunks; ++i) + { + // bitmask of nonzero values in this chunk + unsigned nnz = 0; + for (IndexType j = 0; j < InputsPerChunk; ++j) + { + const vec_t inputChunk = inputVector[i * InputsPerChunk + j]; + nnz |= (unsigned)vec_nnz(inputChunk) << (j * InputSimdWidth); + } + for (IndexType j = 0; j < OutputsPerChunk; ++j) + { + const auto lookup = (nnz >> (j * 8)) & 0xFF; + const auto offsets = _mm_loadu_si128(reinterpret_cast(&lookup_indices[lookup])); + _mm_storeu_si128(reinterpret_cast<__m128i*>(out + count), _mm_add_epi16(base, offsets)); + count += lookup_count[lookup]; + base = _mm_add_epi16(base, increment); + } + } + count_out = count; + } +# undef vec_nnz +#endif + + // Sparse input implementation + template + class AffineTransformSparseInput { + public: + // Input/output type + // Input/output type + using InputType = std::uint8_t; + using OutputType = std::int32_t; + + // Number of input/output dimensions + static constexpr IndexType InputDimensions = InDims; + static constexpr IndexType OutputDimensions = OutDims; + + static_assert(OutputDimensions % 16 == 0, "Only implemented for OutputDimensions divisible by 16."); + + static constexpr IndexType PaddedInputDimensions = + ceil_to_multiple(InputDimensions, MaxSimdWidth); + static constexpr IndexType PaddedOutputDimensions = + ceil_to_multiple(OutputDimensions, MaxSimdWidth); + +#if defined (USE_SSSE3) + static constexpr IndexType ChunkSize = 4; +#else + static constexpr IndexType ChunkSize = 1; +#endif + + 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 = 0xCC03DAE4u; + hashValue += OutputDimensions; + hashValue ^= prevHash >> 1; + hashValue ^= prevHash << 31; + return hashValue; + } + + static IndexType get_weight_index_scrambled(IndexType i) + { + return + (i / ChunkSize) % (PaddedInputDimensions / ChunkSize) * OutputDimensions * ChunkSize + + i / PaddedInputDimensions * ChunkSize + + i % ChunkSize; + } + + static IndexType get_weight_index(IndexType i) + { +#if defined (USE_SSSE3) + return get_weight_index_scrambled(i); +#else + return i; +#endif + } + + // Read network parameters + bool read_parameters(std::istream& stream) { + read_little_endian(stream, biases, OutputDimensions); + for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) + weights[get_weight_index(i)] = read_little_endian(stream); + + return !stream.fail(); + } + + // Write network parameters + bool write_parameters(std::ostream& stream) const { + write_little_endian(stream, biases, OutputDimensions); + + for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) + write_little_endian(stream, weights[get_weight_index(i)]); + + return !stream.fail(); + } + // Forward propagation + const OutputType* propagate( + const InputType* input, OutputType* output) const { + +#if defined (USE_SSSE3) +#if defined (USE_AVX512) + using vec_t = __m512i; + #define vec_setzero _mm512_setzero_si512 + #define vec_set_32 _mm512_set1_epi32 + #define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32 +#elif defined (USE_AVX2) + using vec_t = __m256i; + #define vec_setzero _mm256_setzero_si256 + #define vec_set_32 _mm256_set1_epi32 + #define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32 +#elif defined (USE_SSSE3) + using vec_t = __m128i; + #define vec_setzero _mm_setzero_si128 + #define vec_set_32 _mm_set1_epi32 + #define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32 +#endif + static constexpr IndexType OutputSimdWidth = sizeof(vec_t) / sizeof(OutputType); + + constexpr IndexType NumChunks = ceil_to_multiple(InputDimensions, 8) / ChunkSize; + constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth; + std::uint16_t nnz[NumChunks]; + IndexType count; + + const auto input32 = reinterpret_cast(input); + + // Find indices of nonzero 32bit blocks + find_nnz(input32, nnz, count); + + const vec_t* biasvec = reinterpret_cast(biases); + vec_t acc[NumRegs]; + for (IndexType k = 0; k < NumRegs; ++k) + acc[k] = biasvec[k]; + + for (IndexType j = 0; j < count; ++j) + { + const auto i = nnz[j]; + const vec_t in = vec_set_32(input32[i]); + const auto col = reinterpret_cast(&weights[i * OutputDimensions * ChunkSize]); + for (IndexType k = 0; k < NumRegs; ++k) + vec_add_dpbusd_32(acc[k], in, col[k]); + } + + vec_t* outptr = reinterpret_cast(output); + for (IndexType k = 0; k < NumRegs; ++k) + outptr[k] = acc[k]; +# undef vec_setzero +# undef vec_set_32 +# undef vec_add_dpbusd_32 +#else + // Use dense implementation for the other architectures. + affine_transform_non_ssse3< + InputDimensions, + PaddedInputDimensions, + OutputDimensions>(output, weights, biases, input); +#endif + + return output; + } + + private: + using BiasType = OutputType; + using WeightType = std::int8_t; + + alignas(CacheLineSize) BiasType biases[OutputDimensions]; + alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions]; + }; + +} // namespace Stockfish::Eval::NNUE::Layers + +#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index d10434f3..413dbb3d 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -27,6 +27,7 @@ #include "features/half_ka_v2_hm.h" +#include "layers/affine_transform_sparse_input.h" #include "layers/affine_transform.h" #include "layers/clipped_relu.h" #include "layers/sqr_clipped_relu.h" @@ -48,7 +49,7 @@ struct Network static constexpr int FC_0_OUTPUTS = 15; static constexpr int FC_1_OUTPUTS = 32; - Layers::AffineTransform fc_0; + Layers::AffineTransformSparseInput fc_0; Layers::SqrClippedReLU ac_sqr_0; Layers::ClippedReLU ac_0; Layers::AffineTransform fc_1; From ece90bca9c513fe7b252da1521fc5ff701396f61 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Mon, 12 Jun 2023 22:13:08 +0300 Subject: [PATCH 177/192] Improve comments Fix comments for IIR, also document non-linear scaling in extensions. Also add explicitly the bench, to fix an issue after the last commit. closes https://github.com/official-stockfish/Stockfish/pull/4614 bench 2370027 --- src/search.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index b2c2344a..7ee6d439 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -822,7 +822,7 @@ namespace { } } - // Step 10. If the position doesn't a have ttMove, decrease depth by 2 + // Step 10. If the position doesn't have a ttMove, decrease depth by 2 // (or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth). // Use qsearch if depth is equal or below zero (~9 Elo) if ( PvNode @@ -1052,6 +1052,9 @@ moves_loop: // When in check, search starts here // then that move is singular and should be extended. To verify this we do // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. + // Depth margin and singularBeta margin are known for having non-linear scaling. + // Their values are optimized to time controls of 180+1.8 and longer + // so changing them requires tests at this type of time controls. if ( !rootNode && depth >= 4 - (thisThread->completedDepth > 22) + 2 * (PvNode && tte->is_pv()) && move == ttMove From 92c949e12e028cb4556de2786a77f2aec178d59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicolet?= Date: Mon, 12 Jun 2023 23:26:42 +0200 Subject: [PATCH 178/192] Clean-up code indentation in qsearch closes https://github.com/official-stockfish/Stockfish/pull/4615 No functional change --- src/search.cpp | 152 +++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 75 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 7ee6d439..d3b5642a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1481,10 +1481,11 @@ moves_loop: // When in check, search starts here bestValue = ttValue; } else + { // In case of null move search use previous static eval with a different sign - ss->staticEval = bestValue = - (ss-1)->currentMove != MOVE_NULL ? evaluate(pos) - : -(ss-1)->staticEval; + ss->staticEval = bestValue = (ss-1)->currentMove != MOVE_NULL ? evaluate(pos) + : -(ss-1)->staticEval; + } // Stand pat. Return immediately if static value is at least beta if (bestValue >= beta) @@ -1523,97 +1524,98 @@ moves_loop: // When in check, search starts here // or a beta cutoff occurs. while ((move = mp.next_move()) != MOVE_NONE) { - assert(is_ok(move)); + assert(is_ok(move)); - // Check for legality - if (!pos.legal(move)) - continue; + // Check for legality + if (!pos.legal(move)) + continue; - givesCheck = pos.gives_check(move); - capture = pos.capture_stage(move); + givesCheck = pos.gives_check(move); + capture = pos.capture_stage(move); - moveCount++; + moveCount++; - // Step 6. Pruning. - if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY) - { - // Futility pruning and moveCount pruning (~10 Elo) - if ( !givesCheck - && to_sq(move) != prevSq - && futilityBase > -VALUE_KNOWN_WIN - && type_of(move) != PROMOTION) - { - if (moveCount > 2) - continue; + // Step 6. Pruning. + if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY) + { + // Futility pruning and moveCount pruning (~10 Elo) + if ( !givesCheck + && to_sq(move) != prevSq + && futilityBase > -VALUE_KNOWN_WIN + && type_of(move) != PROMOTION) + { + if (moveCount > 2) + continue; - futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))]; + futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))]; - if (futilityValue <= alpha) - { - bestValue = std::max(bestValue, futilityValue); - continue; - } + if (futilityValue <= alpha) + { + bestValue = std::max(bestValue, futilityValue); + continue; + } - if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1)) - { - bestValue = std::max(bestValue, futilityBase); - continue; - } - } + if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1)) + { + bestValue = std::max(bestValue, futilityBase); + continue; + } + } - // We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter - // and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead. - if (quietCheckEvasions > 1) - break; + // We prune after the second quiet check evasion move, where being 'in check' is + // implicitly checked through the counter, and being a 'quiet move' apart from + // being a tt move is assumed after an increment because captures are pushed ahead. + if (quietCheckEvasions > 1) + break; - // Continuation history based pruning (~3 Elo) - if ( !capture - && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 - && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) - continue; + // Continuation history based pruning (~3 Elo) + if ( !capture + && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 + && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) + continue; - // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-95))) - continue; - } + // Do not search moves with bad enough SEE values (~5 Elo) + if (!pos.see_ge(move, Value(-95))) + continue; + } - // Speculative prefetch as early as possible - prefetch(TT.first_entry(pos.key_after(move))); + // Speculative prefetch as early as possible + prefetch(TT.first_entry(pos.key_after(move))); - // Update the current move - ss->currentMove = move; - ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] - [capture] - [pos.moved_piece(move)] - [to_sq(move)]; + // Update the current move + ss->currentMove = move; + ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] + [capture] + [pos.moved_piece(move)] + [to_sq(move)]; - quietCheckEvasions += !capture && ss->inCheck; + quietCheckEvasions += !capture && ss->inCheck; - // Step 7. Make and search the move - pos.do_move(move, st, givesCheck); - value = -qsearch(pos, ss+1, -beta, -alpha, depth - 1); - pos.undo_move(move); + // Step 7. Make and search the move + pos.do_move(move, st, givesCheck); + value = -qsearch(pos, ss+1, -beta, -alpha, depth - 1); + pos.undo_move(move); - assert(value > -VALUE_INFINITE && value < VALUE_INFINITE); + assert(value > -VALUE_INFINITE && value < VALUE_INFINITE); - // Step 8. Check for a new best move - if (value > bestValue) - { - bestValue = value; + // Step 8. Check for a new best move + if (value > bestValue) + { + bestValue = value; - if (value > alpha) - { - bestMove = move; + if (value > alpha) + { + bestMove = move; - if (PvNode) // Update pv even in fail-high case - update_pv(ss->pv, move, (ss+1)->pv); + if (PvNode) // Update pv even in fail-high case + update_pv(ss->pv, move, (ss+1)->pv); - if (PvNode && value < beta) // Update alpha here! - alpha = value; - else - break; // Fail high - } - } + if (PvNode && value < beta) // Update alpha here! + alpha = value; + else + break; // Fail high + } + } } // Step 9. Check for mate From 7922e07af83dd472da6e5b38fb84214cfe46a630 Mon Sep 17 00:00:00 2001 From: Andreas Matthies Date: Tue, 13 Jun 2023 06:24:04 +0200 Subject: [PATCH 179/192] Fix for MSVC compilation. MSVC needs two more explicit casts to compile new affine_transform_sparse_input. See https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_castsi256_ps and https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castsi128_ps closes https://github.com/official-stockfish/Stockfish/pull/4616 No functional change --- AUTHORS | 1 + src/nnue/layers/affine_transform_sparse_input.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 63b862ce..a89dc130 100644 --- a/AUTHORS +++ b/AUTHORS @@ -19,6 +19,7 @@ Alexander Kure Alexander Pagel (Lolligerhans) Alfredo Menezes (lonfom169) Ali AlZhrani (Cooffe) +Andreas Matthies (Matthies) Andrei Vetrov (proukornew) Andrew Grant (AndyGrant) Andrey Neporada (nepal) diff --git a/src/nnue/layers/affine_transform_sparse_input.h b/src/nnue/layers/affine_transform_sparse_input.h index 00b17c19..e0c3a8a0 100644 --- a/src/nnue/layers/affine_transform_sparse_input.h +++ b/src/nnue/layers/affine_transform_sparse_input.h @@ -98,10 +98,10 @@ namespace Stockfish::Eval::NNUE::Layers { #define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512()) #elif defined (USE_AVX2) using vec_t = __m256i; - #define vec_nnz(a) _mm256_movemask_ps((__m256)_mm256_cmpgt_epi32(a, _mm256_setzero_si256())) + #define vec_nnz(a) _mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256()))) #elif defined (USE_SSSE3) using vec_t = __m128i; - #define vec_nnz(a) _mm_movemask_ps((__m128)_mm_cmpgt_epi32(a, _mm_setzero_si128())) + #define vec_nnz(a) _mm_movemask_ps(_mm_castsi128_ps(_mm_cmpgt_epi32(a, _mm_setzero_si128()))) #endif constexpr IndexType InputSimdWidth = sizeof(vec_t) / sizeof(std::int32_t); // Inputs are processed InputSimdWidth at a time and outputs are processed 8 at a time so we process in chunks of max(InputSimdWidth, 8) From 887bbd8b3df8a01307a38bfe529a49842f810a9c Mon Sep 17 00:00:00 2001 From: Viren6 <94880762+Viren6@users.noreply.github.com> Date: Tue, 13 Jun 2023 22:26:20 +0100 Subject: [PATCH 180/192] Remove setting of static to none if in check in qsearch Small simplification Passed non-regression STC: https://tests.stockfishchess.org/tests/view/6487924d713491385c8034ae LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 59616 W: 15885 L: 15703 D: 28028 Ptnml(0-2): 144, 6130, 17086, 6296, 152 closes https://github.com/official-stockfish/Stockfish/pull/4618 No functional change. --- AUTHORS | 1 + src/search.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index a89dc130..ff224954 100644 --- a/AUTHORS +++ b/AUTHORS @@ -215,6 +215,7 @@ tttak Unai Corzo (unaiic) Uri Blass (uriblass) Vince Negri (cuddlestmonkey) +Viren windfishballad xefoci7612 zz4032 diff --git a/src/search.cpp b/src/search.cpp index d3b5642a..5de950eb 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1464,7 +1464,6 @@ moves_loop: // When in check, search starts here // Step 4. Static evaluation of the position if (ss->inCheck) { - ss->staticEval = VALUE_NONE; bestValue = futilityBase = -VALUE_INFINITE; } else From 14bfec2a981e906d1bfc08331a2e15bddd07ffe4 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Wed, 14 Jun 2023 15:57:36 +0300 Subject: [PATCH 181/192] Consistent bench extraction with fishtest. Consistent with recent fishtest commit https://github.com/glinscott/fishtest/commit/c0d174396f7fb1c0b3243aaa6cc73769079f3ff9 closes https://github.com/official-stockfish/Stockfish/pull/4619 No functional change --- .github/workflows/stockfish_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stockfish_test.yml b/.github/workflows/stockfish_test.yml index 8c383fe7..28218402 100644 --- a/.github/workflows/stockfish_test.yml +++ b/.github/workflows/stockfish_test.yml @@ -115,7 +115,7 @@ jobs: - name: Extract the bench number from the commit history run: | - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig + git log HEAD | grep -o "\b[Bb]ench[ :]\+[1-9][0-9]\{5,9\}\b" | head -n 1 | sed "s/[^0-9]//g" > git_sig [ -s git_sig ] && echo "benchref=$(cat git_sig)" >> $GITHUB_ENV && echo "Reference bench:" $(cat git_sig) || echo "No bench found" - name: Check compiler From 32d3284df5b2fd395504efa5319d64856902fef1 Mon Sep 17 00:00:00 2001 From: AndrovT <31534597+AndrovT@users.noreply.github.com> Date: Tue, 13 Jun 2023 03:00:04 +0200 Subject: [PATCH 182/192] Permute master net weights to increase sparsity Activation data collection using https://github.com/AndrovT/Stockfish/commit/ac468039ab544b03ad9a22c859a4217729c10a77 run as bench 16 1 13 varied_1000.epd depth NNUE log.bin on FENs from https://gist.github.com/AndrovT/7eae6918eb50764227e2bafe7938953c. Permutation found using https://gist.github.com/AndrovT/359c831b7223c637e9156b01eb96949e. Uses a greedy algorithm that goes sequentially through the output positions and chooses a neuron for that position such that the number of nonzero quartets is the smallest. Net weights permuted using https://gist.github.com/AndrovT/9e3fbaebb7082734dc84d27e02094cb3. Benchmark: Result of 100 runs of 'bench 16 1 13 default depth NNUE' ======================================================== base (...kfish-master) = 885869 +/- 7395 test (./stockfish ) = 895885 +/- 7368 diff = +10016 +/- 2984 speedup = +0.0113 P(speedup > 0) = 1.0000 Passed STC: https://tests.stockfishchess.org/tests/view/648866c4713491385c804728 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 126784 W: 34003 L: 33586 D: 59195 Ptnml(0-2): 283, 13001, 36437, 13358, 313 closes https://github.com/official-stockfish/Stockfish/pull/4620 No functional change. --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 94cd42cc..c35b2f07 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-fdc1d0fe6455.nnue" + #define EvalFileDefaultName "nn-cd2ff4716c34.nnue" namespace NNUE { From 0187546275cb015d42a7d99789f2f6a650b03651 Mon Sep 17 00:00:00 2001 From: cj5716 <125858804+cj5716@users.noreply.github.com> Date: Thu, 15 Jun 2023 21:05:01 +0800 Subject: [PATCH 183/192] Small cleanup This non-functional change keeps formatting consistent. closes https://github.com/official-stockfish/Stockfish/pull/4623 Bench 2370027 --- src/search.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5de950eb..8ace674d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1463,9 +1463,7 @@ moves_loop: // When in check, search starts here // Step 4. Static evaluation of the position if (ss->inCheck) - { bestValue = futilityBase = -VALUE_INFINITE; - } else { if (ss->ttHit) @@ -1480,11 +1478,9 @@ moves_loop: // When in check, search starts here bestValue = ttValue; } else - { // In case of null move search use previous static eval with a different sign ss->staticEval = bestValue = (ss-1)->currentMove != MOVE_NULL ? evaluate(pos) : -(ss-1)->staticEval; - } // Stand pat. Return immediately if static value is at least beta if (bestValue >= beta) From a46087ee30ace00e1edd8963ee33b0a1b87031b6 Mon Sep 17 00:00:00 2001 From: maxim Date: Tue, 13 Jun 2023 23:09:05 +0300 Subject: [PATCH 184/192] Compressed network parameters Implemented LEB128 (de)compression for the feature transformer. Reduces embedded network size from 70 MiB to 39 Mib. The new nn-78bacfcee510.nnue corresponds to the master net compressed. closes https://github.com/official-stockfish/Stockfish/pull/4617 No functional change --- src/evaluate.h | 2 +- src/nnue/nnue_common.h | 77 +++++++++++++++++++++++++++++ src/nnue/nnue_feature_transformer.h | 12 ++--- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/evaluate.h b/src/evaluate.h index c35b2f07..33effb1c 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-cd2ff4716c34.nnue" + #define EvalFileDefaultName "nn-78bacfcee510.nnue" namespace NNUE { diff --git a/src/nnue/nnue_common.h b/src/nnue/nnue_common.h index 12309d26..d338527d 100644 --- a/src/nnue/nnue_common.h +++ b/src/nnue/nnue_common.h @@ -57,6 +57,9 @@ namespace Stockfish::Eval::NNUE { // Size of cache line (in bytes) constexpr std::size_t CacheLineSize = 64; + constexpr const char Leb128MagicString[] = "COMPRESSED_LEB128"; + constexpr const std::size_t Leb128MagicStringSize = sizeof(Leb128MagicString) - 1; + // SIMD width (in bytes) #if defined(USE_AVX2) constexpr std::size_t SimdWidth = 32; @@ -159,6 +162,80 @@ namespace Stockfish::Eval::NNUE { write_little_endian(stream, values[i]); } + template + inline void read_leb_128(std::istream& stream, IntType* out, std::size_t count) { + static_assert(std::is_signed_v, "Not implemented for unsigned types"); + char leb128MagicString[Leb128MagicStringSize]; + stream.read(leb128MagicString, Leb128MagicStringSize); + assert(strncmp(Leb128MagicString, leb128MagicString, Leb128MagicStringSize) == 0); + const std::uint32_t BUF_SIZE = 4096; + std::uint8_t buf[BUF_SIZE]; + auto bytes_left = read_little_endian(stream); + std::uint32_t buf_pos = BUF_SIZE; + for (std::size_t i = 0; i < count; ++i) { + IntType result = 0; + size_t shift = 0; + do { + if (buf_pos == BUF_SIZE) { + stream.read(reinterpret_cast(buf), std::min(bytes_left, BUF_SIZE)); + buf_pos = 0; + } + std::uint8_t byte = buf[buf_pos++]; + --bytes_left; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) { + out[i] = sizeof(IntType) * 8 <= shift || (byte & 0x40) == 0 ? result : result | ~((1 << shift) - 1); + break; + } + } while (shift < sizeof(IntType) * 8); + } + assert(bytes_left == 0); + } + + template + inline void write_leb_128(std::ostream& stream, const IntType* values, std::size_t count) { + static_assert(std::is_signed_v, "Not implemented for unsigned types"); + stream.write(Leb128MagicString, Leb128MagicStringSize); + std::uint32_t byte_count = 0; + for (std::size_t i = 0; i < count; ++i) { + IntType value = values[i]; + std::uint8_t byte; + do { + byte = value & 0x7f; + value >>= 7; + ++byte_count; + } while ((byte & 0x40) == 0 ? value != 0 : value != -1); + } + write_little_endian(stream, byte_count); + const std::uint32_t BUF_SIZE = 4096; + std::uint8_t buf[BUF_SIZE]; + std::uint32_t buf_pos = 0; + auto flush = [&]() { + if (buf_pos > 0) { + stream.write(reinterpret_cast(buf), buf_pos); + buf_pos = 0; + } + }; + auto write = [&](std::uint8_t byte) { + buf[buf_pos++] = byte; + if (buf_pos == BUF_SIZE) flush(); + }; + for (std::size_t i = 0; i < count; ++i) { + IntType value = values[i]; + while (true) { + std::uint8_t byte = value & 0x7f; + value >>= 7; + if ((byte & 0x40) == 0 ? value == 0 : value == -1) { + write(byte); + break; + } + write(byte | 0x80); + } + } + flush(); + } + } // namespace Stockfish::Eval::NNUE #endif // #ifndef NNUE_COMMON_H_INCLUDED diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index a1888c7a..7571f398 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -253,9 +253,9 @@ namespace Stockfish::Eval::NNUE { // Read network parameters bool read_parameters(std::istream& stream) { - read_little_endian(stream, biases , HalfDimensions ); - read_little_endian(stream, weights , HalfDimensions * InputDimensions); - read_little_endian(stream, psqtWeights, PSQTBuckets * InputDimensions); + read_leb_128(stream, biases , HalfDimensions ); + read_leb_128(stream, weights , HalfDimensions * InputDimensions); + read_leb_128(stream, psqtWeights, PSQTBuckets * InputDimensions); return !stream.fail(); } @@ -263,9 +263,9 @@ namespace Stockfish::Eval::NNUE { // Write network parameters bool write_parameters(std::ostream& stream) const { - write_little_endian(stream, biases , HalfDimensions ); - write_little_endian(stream, weights , HalfDimensions * InputDimensions); - write_little_endian(stream, psqtWeights, PSQTBuckets * InputDimensions); + write_leb_128(stream, biases , HalfDimensions ); + write_leb_128(stream, weights , HalfDimensions * InputDimensions); + write_leb_128(stream, psqtWeights, PSQTBuckets * InputDimensions); return !stream.fail(); } From a68a1c11543eef6808181c92e0e7e5fb3f826f21 Mon Sep 17 00:00:00 2001 From: disservin Date: Tue, 13 Jun 2023 19:30:01 +0200 Subject: [PATCH 185/192] create prereleases upon push to master using github actions, create a prerelease for the latest commit to master. As such a development version will be available on github, in addition to the latest release. closes https://github.com/official-stockfish/Stockfish/pull/4622 No functional change --- .github/workflows/stockfish.yml | 24 +++++++++ .github/workflows/stockfish_arm_binaries.yml | 26 +++++++++ .github/workflows/stockfish_binaries.yml | 57 ++++++++++++++++++-- 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index 082c65de..ca52ffe0 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -12,6 +12,30 @@ on: - master - tools jobs: + Prerelease: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + # returns null if no pre-release exists + - name: Get Commit SHA of Latest Pre-release + run: | + # Install required packages + sudo apt-get update + sudo apt-get install -y curl jq + + echo "COMMIT_SHA=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/${{ github.repository_owner }}/Stockfish/releases))" >> $GITHUB_ENV + + # delete old previous pre-release and tag + - uses: dev-drprasad/delete-tag-and-release@v0.2.1 + if: env.COMMIT_SHA != 'null' + with: + tag_name: ${{ env.COMMIT_SHA }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + Sanitizers: uses: ./.github/workflows/stockfish_sanitizers.yml Tests: diff --git a/.github/workflows/stockfish_arm_binaries.yml b/.github/workflows/stockfish_arm_binaries.yml index 9a4734ee..52105eb6 100644 --- a/.github/workflows/stockfish_arm_binaries.yml +++ b/.github/workflows/stockfish_arm_binaries.yml @@ -129,4 +129,30 @@ jobs: if: startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag' uses: softprops/action-gh-release@v1 with: + files: stockfish-android-${{ matrix.binaries }}.tar + + - name: Get last commit sha + id: last_commit + run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV + + - name: Get commit date + id: commit_date + run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV + + # Make sure that an old ci which still runs on master doesn't recreate a prerelease + - name: Check Pullable Commits + id: check_commits + run: | + git fetch + CHANGES=$(git rev-list HEAD..origin/master --count) + echo "CHANGES=$CHANGES" >> $GITHUB_ENV + + - name: Prerelease + if: github.ref_name == 'master' && env.CHANGES == '0' + continue-on-error: true + uses: softprops/action-gh-release@v1 + with: + name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }} + tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }} + prerelease: true files: stockfish-android-${{ matrix.binaries }}.tar \ No newline at end of file diff --git a/.github/workflows/stockfish_binaries.yml b/.github/workflows/stockfish_binaries.yml index 86449b97..0a53cb03 100644 --- a/.github/workflows/stockfish_binaries.yml +++ b/.github/workflows/stockfish_binaries.yml @@ -20,12 +20,14 @@ jobs: compiler: g++ comp: gcc shell: bash {0} + archive_ext: tar - name: MacOS 12 Apple Clang os: macos-12 simple_name: macos compiler: clang++ comp: clang shell: bash {0} + archive_ext: tar - name: Windows 2022 Mingw-w64 GCC x86_64 os: windows-2022 simple_name: windows @@ -35,6 +37,7 @@ jobs: msys_env: x86_64-gcc shell: msys2 {0} ext: .exe + archive_ext: zip binaries: - x86-64 - x86-64-modern @@ -60,7 +63,7 @@ jobs: uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.config.msys_sys }} - install: mingw-w64-${{ matrix.config.msys_env }} make git + install: mingw-w64-${{ matrix.config.msys_env }} make git zip - name: Download the used network from the fishtest framework run: make net @@ -90,7 +93,7 @@ jobs: git clone https://github.com/official-stockfish/Stockfish.wiki.git ../wiki rm -rf ../wiki/.git - - name: Create tar archive. + - name: Create directory. run: | cd .. mkdir stockfish @@ -102,16 +105,64 @@ jobs: cp AUTHORS stockfish/ cp CITATION.cff stockfish/ cp README.md stockfish/ + + - name: Create tar + if: runner.os != 'Windows' + run: | + cd .. tar -cvf stockfish-$NAME-$BINARY.tar stockfish + - name: Create zip + if: runner.os == 'Windows' + run: | + cd .. + zip -r stockfish-$NAME-$BINARY.zip stockfish + - name: Upload binaries + if: runner.os != 'Windows' uses: actions/upload-artifact@v3 with: name: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }} path: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.tar + # Artifacts automatically get zipped + # to avoid double zipping, we use the unzipped directory + - name: Upload binaries + if: runner.os == 'Windows' + uses: actions/upload-artifact@v3 + with: + name: stockfish-${{ matrix.config.os }}-${{ matrix.binaries }} + path: stockfish + - name: Release if: startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag' uses: softprops/action-gh-release@v1 with: - files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.tar + files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }} + + - name: Get last commit sha + id: last_commit + run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV + + - name: Get commit date + id: commit_date + run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV + + # Make sure that an old ci which still runs on master doesn't recreate a prerelease + - name: Check Pullable Commits + id: check_commits + run: | + git fetch + CHANGES=$(git rev-list HEAD..origin/master --count) + echo "CHANGES=$CHANGES" >> $GITHUB_ENV + + - name: Prerelease + if: github.ref_name == 'master' && env.CHANGES == '0' + continue-on-error: true + uses: softprops/action-gh-release@v1 + with: + name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }} + tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }} + prerelease: true + files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }} + From 6eaa1c3ecd297404b28f9e80cddf81c4c6926a51 Mon Sep 17 00:00:00 2001 From: Joerg Oster Date: Tue, 20 Jun 2023 10:40:31 +0200 Subject: [PATCH 186/192] Fix indentation in qsearch. https://github.com/official-stockfish/Stockfish/pull/4630 No functional change. --- src/search.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 8ace674d..9b686a52 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1555,23 +1555,23 @@ moves_loop: // When in check, search starts here bestValue = std::max(bestValue, futilityBase); continue; } - } + } - // We prune after the second quiet check evasion move, where being 'in check' is - // implicitly checked through the counter, and being a 'quiet move' apart from - // being a tt move is assumed after an increment because captures are pushed ahead. - if (quietCheckEvasions > 1) - break; + // We prune after the second quiet check evasion move, where being 'in check' is + // implicitly checked through the counter, and being a 'quiet move' apart from + // being a tt move is assumed after an increment because captures are pushed ahead. + if (quietCheckEvasions > 1) + break; - // Continuation history based pruning (~3 Elo) - if ( !capture - && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 - && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) - continue; + // Continuation history based pruning (~3 Elo) + if ( !capture + && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 + && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) + continue; - // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-95))) - continue; + // Do not search moves with bad enough SEE values (~5 Elo) + if (!pos.see_ge(move, Value(-95))) + continue; } // Speculative prefetch as early as possible From aec8fb3fdec8309a0cc78222a4f674ea6fea9411 Mon Sep 17 00:00:00 2001 From: disservin Date: Tue, 20 Jun 2023 18:27:20 +0200 Subject: [PATCH 187/192] Fix failing CI of pull requests adds a guard to prevent pull requests from trying to delete the previous pre-release closing https://github.com/official-stockfish/Stockfish/pull/4631 No functional change. --- .github/workflows/stockfish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index ca52ffe0..99c4259a 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -13,6 +13,7 @@ on: - tools jobs: Prerelease: + if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 02728736edd5915fc0abc8698635e633a3cba201 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Tue, 20 Jun 2023 09:46:02 +0200 Subject: [PATCH 188/192] Update top CPU contributors closes https://github.com/official-stockfish/Stockfish/pull/4629 No functional change --- Top CPU Contributors.txt | 117 ++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/Top CPU Contributors.txt b/Top CPU Contributors.txt index 7b279590..74c471b7 100644 --- a/Top CPU Contributors.txt +++ b/Top CPU Contributors.txt @@ -1,55 +1,55 @@ -Contributors to Fishtest with >10,000 CPU hours, as of 2023-05-27. +Contributors to Fishtest with >10,000 CPU hours, as of 2023-06-20. Thank you! Username CPU Hours Games played ------------------------------------------------------------------ -noobpwnftw 37304027 2833556221 -technologov 13508659 714674674 -linrock 4121386 280027751 +noobpwnftw 37457426 2850540907 +technologov 14135647 742892808 +linrock 4423514 303254809 mlang 3026000 200065824 dew 1689162 100033738 -okrout 1541122 145085726 -pemo 1481818 47546583 -grandphish2 1459364 91364265 -TueRens 1178700 69951886 -JojoM 937875 60821044 +okrout 1578136 148855886 +pemo 1508508 48814305 +grandphish2 1461406 91540343 +TueRens 1194790 70400852 +JojoM 947612 61773190 tvijlbrief 796125 51897690 +sebastronomy 742434 38218524 mibere 703840 46867607 -sebastronomy 687502 35585318 -gvreuls 645570 42437926 -oz 541224 39133532 -cw 517856 34869499 +gvreuls 651026 42988582 +oz 543438 39314736 +cw 517858 34869755 fastgm 503862 30260818 -CSU_Dynasty 464691 31166478 -leszek 460426 32840277 -ctoks 434323 28497451 +leszek 467278 33514883 +CSU_Dynasty 464940 31177118 +ctoks 434416 28506889 crunchy 427035 27344275 -maximmasiutin 424154 26534660 +maximmasiutin 424795 26577722 bcross 415722 29060963 -rpngn 344368 24218047 -velislav 342559 22138408 +olafm 395922 32268020 +rpngn 348378 24560289 +velislav 342567 22138992 Fisherman 327231 21829379 -mgrabiak 297057 20260882 +mgrabiak 300612 20608380 Dantist 296386 18031762 -nordlandia 242642 15922516 -robal 240199 15544104 +nordlandia 246201 16189678 +robal 241300 15656382 marrco 234581 17714473 ncfish1 227517 15233777 glinscott 208125 13277240 drabel 204167 13930674 mhoram 202894 12601997 bking_US 198894 11876016 -olafm 192342 14968698 Thanar 179852 12365359 vdv 175544 9904472 spams 157128 10319326 sqrt2 147963 9724586 -DesolatedDodo 144759 9408038 +DesolatedDodo 146350 9536172 Calis007 143165 9478764 -vdbergh 138436 9042073 +vdbergh 138650 9064413 CoffeeOne 137100 5024116 +armo9494 136191 9460264 malala 136182 8002293 -armo9494 136010 9447548 xoto 133759 9159372 davar 129023 8376525 DMBK 122960 8980062 @@ -59,43 +59,43 @@ Data 113305 8220352 BrunoBanani 112960 7436849 CypressChess 108331 7759788 skiminki 107583 7218170 +jcAEie 105675 8238962 MaZePallas 102823 6633619 sterni1971 100532 5880772 -jcAEie 100392 7788270 sunu 100167 7040199 zeryl 99331 6221261 thirdlife 99124 2242380 ElbertoOne 99028 7023771 -cuistot 98360 6017102 +cuistot 98853 6069816 bigpen0r 94809 6529203 brabos 92118 6186135 -Wolfgang 90855 5998076 +Wolfgang 91939 6105872 psk 89957 5984901 +sschnee 88235 5268000 racerschmacer 85805 6122790 +Fifis 85722 5709729 Dubslow 84986 6042456 Vizvezdenec 83761 5344740 -sschnee 83564 4853834 0x3C33 82614 5271253 BRAVONE 81239 5054681 -Fifis 77355 5158211 nssy 76497 5259388 jromang 76106 5236025 teddybaer 75125 5407666 +tolkki963 74762 5149662 +megaman7de 74351 4940352 Wencey 74181 4711488 -megaman7de 73866 4894960 Pking_cda 73776 5293873 -tolkki963 73531 5020500 -yurikvelo 72847 4972808 +yurikvelo 73150 5004382 +markkulix 72607 5304642 Bobo1239 70579 4794999 solarlight 70517 5028306 dv8silencer 70287 3883992 -markkulix 70278 5068326 manap 66273 4121774 tinker 64333 4268790 qurashee 61208 3429862 -Mineta 58759 4399960 +Mineta 59357 4418202 +Spprtr 58723 3911011 AGI 58147 4325994 -Spprtr 58106 3858759 robnjr 57262 4053117 Freja 56938 3733019 MaxKlaxxMiner 56879 3423958 @@ -103,35 +103,35 @@ MarcusTullius 56746 3762951 ttruscott 56010 3680085 rkl 55132 4164467 renouve 53811 3501516 +javran 53785 4627608 finfish 51360 3370515 eva42 51272 3599691 eastorwest 51117 3454811 rap 49985 3219146 pb00067 49733 3298934 -javran 49178 4190632 -OuaisBla 48606 3442958 +OuaisBla 48626 3445134 ronaldjerum 47654 3240695 biffhero 46564 3111352 VoyagerOne 45476 3452465 -oryx 44532 3450170 -jmdana 43849 2955821 +jmdana 44893 3065205 +maposora 44597 4039578 +oryx 44570 3454238 speedycpu 43842 3003273 jbwiebe 43305 2805433 +GPUex 42378 3133332 Antihistamine 41788 2761312 mhunt 41735 2691355 -maposora 41534 3733078 -GPUex 41061 2998356 homyur 39893 2850481 gri 39871 2515779 Garf 37741 2999686 SC 37299 2731694 csnodgrass 36207 2688994 strelock 34716 2074055 +szupaw 34102 2880346 EthanOConnor 33370 2090311 slakovv 32915 2021889 Gelma 31771 1551204 gopeto 31671 2060990 -szupaw 31248 2594920 kdave 31157 2198362 manapbk 30987 1810399 Prcuvu 30377 2170122 @@ -147,52 +147,54 @@ xwziegtm 26897 2124586 achambord 26582 1767323 Patrick_G 26276 1801617 yorkman 26193 1992080 -Ulysses 25285 1689346 +Ulysses 25288 1689730 SFTUser 25182 1675689 nabildanial 24942 1519409 Sharaf_DG 24765 1786697 +Maxim 24705 1502062 rodneyc 24376 1416402 agg177 23890 1395014 +Goatminola 23763 1956036 Ente 23639 1671638 +Jopo12321 23467 1483172 JanErik 23408 1703875 Isidor 23388 1680691 Norabor 23371 1603244 -Goatminola 23338 1910634 cisco2015 22920 1763301 -Jopo12321 22890 1424926 +jsys14 22824 1591906 Zirie 22542 1472937 team-oh 22272 1636708 Roady 22220 1465606 MazeOfGalious 21978 1629593 sg4032 21947 1643353 -jsys14 21935 1499128 ianh2105 21725 1632562 xor12 21628 1680365 dex 21612 1467203 nesoneg 21494 1463031 user213718 21454 1404128 sphinx 21211 1384728 +AndreasKrug 21097 1634811 jjoshua2 21001 1423089 Zake9298 20938 1565848 -AndreasKrug 20911 1615673 horst.prack 20878 1465656 0xB00B1ES 20590 1208666 j3corre 20405 941444 Adrian.Schmidt123 20316 1281436 wei 19973 1745989 +notchris 19958 1800128 Serpensin 19840 1697528 +Gaster319 19712 1677310 fishtester 19617 1257388 rstoesser 19569 1293588 eudhan 19274 1283717 -Gaster319 18934 1596772 +votoanthuan 19108 1609992 vulcan 18871 1729392 Karpovbot 18766 1053178 +qoo_charly_cai 18543 1284937 jundery 18445 1115855 -votoanthuan 18012 1508836 ville 17883 1384026 chris 17698 1487385 purplefishies 17595 1092533 -qoo_charly_cai 17494 1182667 dju 17414 981289 iisiraider 17275 1049015 DragonLord 17014 1162790 @@ -200,7 +202,6 @@ redstone59 16842 1461780 Alb11747 16787 1213926 IgorLeMasson 16064 1147232 Karby 15982 979610 -notchris 15818 1426762 scuzzi 15757 968735 ako027ako 15671 1173203 Nikolay.IT 15154 1068349 @@ -218,33 +219,33 @@ Nesa92 13786 1114691 joster 13710 946160 mbeier 13650 1044928 Hjax 13535 915487 +Nullvalue 13468 1140498 Dark_wizzie 13422 1007152 Rudolphous 13244 883140 pirt 13100 1009897 Machariel 13010 863104 infinigon 12991 943216 -Maxim 12963 985594 mabichito 12903 749391 thijsk 12886 722107 AdrianSA 12860 804972 Flopzee 12698 894821 korposzczur 12606 838168 -Nullvalue 12583 1048502 fatmurphy 12547 853210 SapphireBrand 12416 969604 Oakwen 12399 844109 deflectooor 12386 579392 modolief 12386 896470 Farseer 12249 694108 -Jackfish 12180 801372 +Jackfish 12213 805008 pgontarz 12151 848794 dbernier 12103 860824 getraideBFF 12072 1024966 stocky 11954 699440 mschmidt 11941 803401 MooTheCow 11870 773598 -FormazChar 11689 877727 +FormazChar 11766 885707 whelanh 11557 245188 +3cho 11494 1031076 infinity 11470 727027 aga 11412 695127 torbjo 11395 729145 @@ -254,6 +255,7 @@ d64 11263 789184 ali-al-zhrani 11245 779246 snicolet 11106 869170 dapper 11032 771402 +ols 10947 624903 Karmatron 10828 677458 basepi 10637 744851 Cubox 10621 826448 @@ -263,4 +265,3 @@ jojo2357 10419 929708 WoodMan777 10380 873720 Garruk 10365 706465 dzjp 10343 732529 -ols 10259 570669 From 52e84e4b4675aae52a619c309479684dc5478bf5 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Thu, 22 Jun 2023 09:59:03 +0200 Subject: [PATCH 189/192] Update winrate model with June data Retained 748191776 scored positions for analysis const int NormalizeToPawnValue = 328; Corresponding spread = 60; Corresponding normalized spread = 0.18337766691628035; Draw rate at 0.0 eval at move 32 = 0.9914715947898592; closes https://github.com/official-stockfish/Stockfish/pull/4636 No functional change --- src/uci.cpp | 4 ++-- src/uci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index 523d551e..ed16f24c 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -207,8 +207,8 @@ namespace { // The coefficients of a third-order polynomial fit is based on the fishtest data // for two parameters that need to transform eval to the argument of a logistic // function. - constexpr double as[] = { 1.07390458, -6.94334517, 31.95090161, 317.75424048}; - constexpr double bs[] = { -2.82843814, 16.64518180, -19.74439200, 68.39499088 }; + constexpr double as[] = { 0.38036525, -2.82015070, 23.17882135, 307.36768407}; + constexpr double bs[] = { -2.29434733, 13.27689788, -14.26828904, 63.45318330 }; // Enforce that NormalizeToPawnValue corresponds to a 50% win rate at ply 64 static_assert(UCI::NormalizeToPawnValue == int(as[0] + as[1] + as[2] + as[3])); diff --git a/src/uci.h b/src/uci.h index 680d2d2c..8f1be00c 100644 --- a/src/uci.h +++ b/src/uci.h @@ -35,7 +35,7 @@ namespace UCI { // the win_rate_model() such that Stockfish outputs an advantage of // "100 centipawns" for a position if the engine has a 50% probability to win // from this position in selfplay at fishtest LTC time control. -const int NormalizeToPawnValue = 343; +const int NormalizeToPawnValue = 328; class Option; From 48f7c74f15f4cae4b77596cd468802054314d701 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Mon, 12 Jun 2023 12:57:41 +0300 Subject: [PATCH 190/192] Fix Potential in TB cutoffs for NMP. Removes the second dependency on beta and caps the return value to VALUE_TB_WIN_IN_MAX_PLY - 1 Earlier tests: STC: LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 193632 W: 51372 L: 51326 D: 90934 Ptnml(0-2): 447, 20111, 55687, 20091, 480 https://tests.stockfishchess.org/tests/view/6486ee4465ffe077ca125bc1 LTC: LLR: 2.97 (-2.94,2.94) <-1.75,0.25> Total: 331758 W: 89538 L: 89624 D: 152596 Ptnml(0-2): 114, 30121, 105516, 29993, 135 https://tests.stockfishchess.org/tests/view/6489401af42a44347ed7be42 updated constant: LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 100260 W: 27143 L: 27017 D: 46100 Ptnml(0-2): 34, 8842, 32248, 8976, 30 https://tests.stockfishchess.org/tests/view/6492fcafdc7002ce609c818c closes: https://github.com/official-stockfish/Stockfish/pull/4632 fixes: https://github.com/official-stockfish/Stockfish/issues/4598 bench: 2370027 --- src/search.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 9b686a52..740ad71e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -801,10 +801,9 @@ namespace { if (nullValue >= beta) { // Do not return unproven mate or TB scores - if (nullValue >= VALUE_TB_WIN_IN_MAX_PLY) - nullValue = beta; + nullValue = std::min(nullValue, VALUE_TB_WIN_IN_MAX_PLY-1); - if (thisThread->nmpMinPly || (abs(beta) < VALUE_KNOWN_WIN && depth < 14)) + if (thisThread->nmpMinPly || depth < 14) return nullValue; assert(!thisThread->nmpMinPly); // Recursive verification is not allowed From a49b3ba7ed5d9be9151c8ceb5eed40efe3387c75 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Wed, 21 Jun 2023 00:43:46 -0400 Subject: [PATCH 191/192] Update default net to nn-5af11540bbfe.nnue Created by retraining the sparsified master net (nn-cd2ff4716c34.nnue) on a 100% minified dataset including Leela transformers data from T80 may2023. Weights permuted with the exact methods and code in: https://github.com/official-stockfish/Stockfish/pull/4620 LEB128 compression done with the new serialize.py param in: https://github.com/glinscott/nnue-pytorch/pull/251 Initially trained with max epoch 800. Around epoch 780, training was paused and max epoch raised to 960. python3 easy_train.py \ --experiment-name L1-1536-sparse-master-retrain \ --training-dataset /data/leela96-dfrc99-v2-T60novdecT77decT78jantosepT79aprmayT80juntonovjan-v6dd-T80febtomay2023.min.binpack \ --early-fen-skipping 27 \ --start-from-engine-test-net True \ --max_epoch 960 \ --lr 4.375e-4 \ --gamma 0.995 \ --start-lambda 1.0 \ --end-lambda 0.7 \ --tui False \ --seed $RANDOM \ --gpus 0 For preparing the training dataset (interleaved size 328G): python3 interleave_binpacks.py \ leela96-filt-v2.min.binpack \ dfrc99-16tb7p-eval-filt-v2.min.binpack \ filt-v6-dd-min/test60-novdec2021-12tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test77-dec2021-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test78-jantomay2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test78-juntosep2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test79-apr2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test79-may2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-jun2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-jul2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-aug2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-sep2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-oct2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-nov2022-16tb7p-filter-v6-dd.min.binpack \ filt-v6-dd-min/test80-jan2023-16tb7p-filter-v6-dd.min.binpack \ test80-2023/test80-feb2023-16tb7p-no-db.min.binpack \ test80-2023/test80-mar2023-2tb7p-no-db.min.binpack \ test80-2023/test80-apr2023-2tb7p-no-db.min.binpack \ test80-2023/test80-may2023-2tb7p-no-db.min.binpack \ /data/leela96-dfrc99-v2-T60novdecT77decT78jantosepT79aprmayT80juntonovjan-v6dd-T80febtomay2023.min.binpack Minified binpacks and Leela T80 training data from 2023 available at: https://robotmoon.com/nnue-training-data/ Local elo at 25k nodes per move: nn-epoch879.nnue : 3.9 +/- 5.7 Passed STC: https://tests.stockfishchess.org/tests/view/64928c1bdc7002ce609c7690 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 72000 W: 19242 L: 18889 D: 33869 Ptnml(0-2): 182, 7787, 19716, 8126, 189 Passed LTC: https://tests.stockfishchess.org/tests/view/64930a37dc7002ce609c82e3 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 54552 W: 14978 L: 14647 D: 24927 Ptnml(0-2): 23, 5123, 16650, 5460, 20 closes https://github.com/official-stockfish/Stockfish/pull/4635 bench 2593605 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 33effb1c..b9d7231d 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // 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 // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-78bacfcee510.nnue" + #define EvalFileDefaultName "nn-5af11540bbfe.nnue" namespace NNUE { From 68e1e9b3811e16cad014b590d7443b9063b3eb52 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 24 Jun 2023 08:58:17 +0200 Subject: [PATCH 192/192] Stockfish 16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Official release version of Stockfish 16 Bench: 2593605 --- Stockfish 16 A new major release of Stockfish is now available at https://stockfishchess.org/download/ *Quality of chess play* Stockfish continues to demonstrate its ability to discover superior moves with remarkable speed. In self-play against Stockfish 15, this new release gains up to 50 Elo[1] and wins up to 12 times more game pairs[2] than it loses. In major chess engine tournaments, Stockfish reliably tops the rankings[3] winning the TCEC season 24 Superfinal, Swiss, Fischer Random, and Double Random Chess tournaments and the CCC 19 Bullet, 20 Blitz, and 20 Rapid competitions. Leela Chess Zero[4] was the challenger in most finals, putting top-engine chess now firmly in the hands of teams embracing free and open-source software. *Progress made* This updated version of Stockfish introduces several enhancements, including an upgraded neural net architecture (SFNNv6)[5], improved implementation, and refined parameterization. The ongoing utilization of Leela’s data combined with a novel inference approach exploiting sparsity[6], and network compression[7] ensure a speedy evaluation and modest binary sizes while allowing for more weights and higher accuracy. The search has undergone more optimization, leading to improved performance, particularly in longer analyses[8]. Additionally, the Fishtest framework has been improved and is now able to run the tests needed to validate new ideas with 10000s of CPU cores. *Usability improvements* Stockfish now comes with documentation, found in the wiki folder when downloading it or on GitHub[9]. Additionally, Stockfish now includes a clear and consistent forced tablebase win score, displaying a value of 200 minus the number of plies required to reach a tablebase win[10]. Furthermore, the UCI_Elo option, to reduce its strength, has been calibrated[11]. It is worth noting that the evaluation system remains consistent with Stockfish 15.1[12], maintaining the choice that 100cp means a 50% chance of winning the game against an equal opponent[13]. Finally, binaries of our latest development version are now provided continuously as pre-releases on GitHub making it easier for enthusiasts to download the latest and strongest version of the program[14], we thank Roman Korba for having provided a similar service for a long time. *Thank you* The success of the Stockfish project relies on the vibrant community of passionate enthusiasts (we appreciate each and every one of you!) who generously contribute their knowledge, time, and resources. Together, this dedicated community works towards the common goal of developing a powerful, freely accessible, and open-source chess engine. We invite all chess enthusiasts to join the Fishtest testing framework and contribute to the project[15]. The Stockfish team [1] https://tests.stockfishchess.org/tests/view/649409f0dc7002ce609c99cc [2] https://tests.stockfishchess.org/tests/view/649409d7dc7002ce609c99c6 [3] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results [4] https://lczero.org/ [5] https://github.com/official-stockfish/Stockfish/commit/c1fff71 [6] https://github.com/official-stockfish/Stockfish/commit/38e6166 [7] https://github.com/official-stockfish/Stockfish/commit/a46087e [8] https://github.com/official-stockfish/Stockfish/commit/472e726 [9] https://github.com/official-stockfish/Stockfish/wiki/ [10] https://github.com/official-stockfish/Stockfish/commit/def2966 [11] https://github.com/official-stockfish/Stockfish/commit/a08b8d4 [12] https://github.com/official-stockfish/Stockfish/commit/52e84e4 [13] https://github.com/official-stockfish/Stockfish/wiki/Stockfish-FAQ#interpretation-of-the-stockfish-evaluation [14] https://github.com/official-stockfish/Stockfish/releases?q=prerelease%3Atrue [15] https://stockfishchess.org/get-involved/ --- src/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.cpp b/src/misc.cpp index f1554060..bbfa4061 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -73,7 +73,7 @@ namespace Stockfish { namespace { /// Version number or dev. -constexpr string_view version = "dev"; +constexpr string_view version = "16"; /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We