From 9d61822b5dda7f99d46ed9ad346afa8c34c302a8 Mon Sep 17 00:00:00 2001 From: Gahtan Nahdi <155860115+gahtan-syarif@users.noreply.github.com> Date: Sat, 10 Feb 2024 03:51:05 +0700 Subject: [PATCH 1/8] Remove penalty for quiet ttMove that fails low Passed STC non-reg: https://tests.stockfishchess.org/tests/view/65c691a7c865510db0286e6e LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 234336 W: 60258 L: 60255 D: 113823 Ptnml(0-2): 966, 28141, 58918, 28210, 933 Passed LTC non-reg: https://tests.stockfishchess.org/tests/view/65c8d0d31d8e83c78bfcd4a6 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 235206 W: 59134 L: 59132 D: 116940 Ptnml(0-2): 135, 26908, 63517, 26906, 137 https://github.com/official-stockfish/Stockfish/pull/5054 Bench: 1287996 --- src/search.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 9574465388e..cb71acbaa5b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -621,13 +621,6 @@ Value Search::Worker::search( update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -stat_malus(depth + 1)); } - // Penalty for a quiet ttMove that fails low (~1 Elo) - else if (!ttCapture) - { - int penalty = -stat_malus(depth); - thisThread->mainHistory[us][ttMove.from_to()] << penalty; - update_continuation_histories(ss, pos.moved_piece(ttMove), ttMove.to_sq(), penalty); - } } // Partial workaround for the graph history interaction problem From f3df0cfb84250f03662a6fd50ea20c9677a0a1d0 Mon Sep 17 00:00:00 2001 From: cj5716 <125858804+cj5716@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:50:16 +0800 Subject: [PATCH 2/8] Simplify TT PV reduction This also removes some incorrect fail-high logic. Passed STC: https://tests.stockfishchess.org/tests/view/65cb3b641d8e83c78bfd04a9 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 87968 W: 22634 L: 22468 D: 42866 Ptnml(0-2): 315, 10436, 22323, 10588, 322 Passed LTC: https://tests.stockfishchess.org/tests/view/65cccee21d8e83c78bfd222c LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 70794 W: 17846 L: 17672 D: 35276 Ptnml(0-2): 44, 7980, 19189, 8126, 58 closes https://github.com/official-stockfish/Stockfish/pull/5055 Bench: 1474424 --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index cb71acbaa5b..c407ae6ba6e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1098,9 +1098,9 @@ Value Search::Worker::search( thisThread->nodes.fetch_add(1, std::memory_order_relaxed); pos.do_move(move, st, givesCheck); - // Decrease reduction if position is or has been on the PV (~5 Elo) + // Decrease reduction if position is or has been on the PV (~7 Elo) if (ss->ttPv) - r -= 1 + (ttValue > alpha) + (ttValue > beta && tte->depth() >= depth); + r -= 1 + (ttValue > alpha) + (tte->depth() >= depth); // Increase reduction for cut nodes (~4 Elo) if (cutNode) From 8e75548f2a10969c1c9211056999efbcebe63f9a Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Tue, 6 Feb 2024 11:21:15 -0500 Subject: [PATCH 3/8] Update default main net to nn-b1a57edbea57.nnue Created by retraining the previous main net `nn-baff1edbea57.nnue` with: - some of the same options as before: ranger21, more WDL skipping - the addition of T80 nov+dec 2023 data - increasing loss by 15% when prediction is too high, up from 10% - use of torch.compile to speed up training by over 25% ```yaml experiment-name: 2560--S9-514G-T80-augtodec2023-more-wdl-skip-15p-more-loss-high-q-sk28 training-dataset: # https://github.com/official-stockfish/Stockfish/pull/4782 - /data/S6-514G-1ee1aba5ed.binpack - /data/test80-aug2023-2tb7p.v6.min.binpack - /data/test80-sep2023-2tb7p.binpack - /data/test80-oct2023-2tb7p.binpack - /data/test80-nov2023-2tb7p.binpack - /data/test80-dec2023-2tb7p.binpack early-fen-skipping: 28 start-from-engine-test-net: True nnue-pytorch-branch: linrock/nnue-pytorch/r21-more-wdl-skip-15p-more-loss-high-q-torch-compile num-epochs: 1000 lr: 4.375e-4 gamma: 0.995 start-lambda: 1.0 end-lambda: 0.7 ``` Epoch 819 trained with the above config led to this PR. Use of torch.compile decorators in nnue-pytorch model.py was found to speed up training by at least 25% on Ampere gpus when using recent pytorch compiled with cuda 12: https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch See recent main net PRs for more info on - ranger21 and more WDL skipping: https://github.com/official-stockfish/Stockfish/pull/4942 - increasing loss when Q is too high: https://github.com/official-stockfish/Stockfish/pull/4972 Training data can be found at: https://robotmoon.com/nnue-training-data/ Passed STC: https://tests.stockfishchess.org/tests/view/65cd76151d8e83c78bfd2f52 LLR: 2.98 (-2.94,2.94) <0.00,2.00> Total: 78336 W: 20504 L: 20115 D: 37717 Ptnml(0-2): 317, 9225, 19721, 9562, 343 Passed LTC: https://tests.stockfishchess.org/tests/view/65ce5be61d8e83c78bfd43e9 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 41016 W: 10492 L: 10159 D: 20365 Ptnml(0-2): 22, 4533, 11071, 4854, 28 closes https://github.com/official-stockfish/Stockfish/pull/5056 Bench: 1351997 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 729baa6bcb8..53928bf6494 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ Value evaluate(const Position& pos, int optimism); // 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 EvalFileDefaultNameBig "nn-baff1edbea57.nnue" +#define EvalFileDefaultNameBig "nn-b1a57edbea57.nnue" #define EvalFileDefaultNameSmall "nn-baff1ede1f90.nnue" struct EvalFile { From fc41f64dfd8a61d0e275ddbecec292833458b86a Mon Sep 17 00:00:00 2001 From: cj5716 <125858804+cj5716@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:46:37 +0800 Subject: [PATCH 4/8] Simplify PV node reduction Reduce less on PV nodes even with an upperbound TT entry. Passed STC: https://tests.stockfishchess.org/tests/view/65cb3a861d8e83c78bfd0497 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 118752 W: 30441 L: 30307 D: 58004 Ptnml(0-2): 476, 14179, 29921, 14335, 465 Passed LTC: https://tests.stockfishchess.org/tests/view/65cd3b951d8e83c78bfd2b0d LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 155058 W: 38549 L: 38464 D: 78045 Ptnml(0-2): 85, 17521, 42219, 17632, 72 closes https://github.com/official-stockfish/Stockfish/pull/5057 Bench: 1303971 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index c407ae6ba6e..55a92947d32 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1111,7 +1111,7 @@ Value Search::Worker::search( r++; // Decrease reduction for PvNodes (~3 Elo) - if (PvNode && tte->bound() != BOUND_UPPER) + if (PvNode) r--; // Increase reduction on repetition (~1 Elo) From de4a3c47a666b5ddc8d469b62bf858a6ea71d03c Mon Sep 17 00:00:00 2001 From: Tierynn Byrnes Date: Mon, 19 Feb 2024 07:32:09 +1000 Subject: [PATCH 5/8] make timeLeft a double, timepoint seemed unecessary since it was always casting back to double anyway. --- src/timeman.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index 286072848b3..ce738e96b82 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -84,10 +84,10 @@ void TimeManagement::init(Search::LimitsType& limits, // Maximum move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; - // Make sure timeLeft is > 0 since we may use it as a divisor + // Make sure timeLeft is > 0 since we use it as a divisor // If there is a healthy increment and low mtg, timeLeft can exceed actual available - TimePoint timeLeft = std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - - moveOverhead * (2 + mtg)); + double timeLeft = + std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * mtg); // x basetime (+ z increment) // game time for the current move, so also cap to 20% of available game time. @@ -102,7 +102,7 @@ void TimeManagement::init(Search::LimitsType& limits, double maxConstant = std::max(3.4 + 3.0 * std::log10(limits.time[us] / 1000.0), 2.76); optScale = std::min(0.0120 + std::pow(ply + 3.1, 0.44) * optConstant, - 0.21 * limits.time[us] / double(timeLeft)) + 0.21 * limits.time[us] / timeLeft) * optExtra; maxScale = std::min(6.9, maxConstant + ply / 12.2); } @@ -110,7 +110,7 @@ void TimeManagement::init(Search::LimitsType& limits, // x moves in y seconds (+ z increment) else { - optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft)); + optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / timeLeft); maxScale = std::min(6.3, 1.5 + 0.11 * mtg); } From 8afec41fb973ed236c125c518f33e2bc920bc8c1 Mon Sep 17 00:00:00 2001 From: Tierynn Byrnes Date: Mon, 19 Feb 2024 07:50:30 +1000 Subject: [PATCH 6/8] fixed comments --- src/timeman.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index ce738e96b82..657962663ad 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -81,15 +81,15 @@ void TimeManagement::init(Search::LimitsType& limits, limits.npmsec = npmsec; } - // Maximum move horizon of 50 moves + // Maximum and default move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; // Make sure timeLeft is > 0 since we use it as a divisor - // If there is a healthy increment and low mtg, timeLeft can exceed actual available double timeLeft = std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * mtg); // x basetime (+ z increment) + // If there is a healthy increment and low mtg, timeLeft can exceed actual available // game time for the current move, so also cap to 20% of available game time. if (limits.movestogo == 0) { From 5cf3f49d4ea7ffaa46bca70e41f819f1c3881633 Mon Sep 17 00:00:00 2001 From: Tierynn Byrnes Date: Mon, 19 Feb 2024 07:13:26 +1000 Subject: [PATCH 7/8] use current time instead of '1' for timeLeft formula. make timeLeft a double, timepoint seemed unecessary since it was always casting back to double anyway. --- src/timeman.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index 72a447af5b8..657962663ad 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -81,15 +81,15 @@ void TimeManagement::init(Search::LimitsType& limits, limits.npmsec = npmsec; } - // Maximum move horizon of 50 moves + // Maximum and default move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; - // Make sure timeLeft is > 0 since we may use it as a divisor - TimePoint timeLeft = std::max(TimePoint(1), limits.time[us] + limits.inc[us] * (mtg - 1) - - moveOverhead * (2 + mtg)); + // Make sure timeLeft is > 0 since we use it as a divisor + double timeLeft = + std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * mtg); // x basetime (+ z increment) - // If there is a healthy increment, timeLeft can exceed actual available + // If there is a healthy increment and low mtg, timeLeft can exceed actual available // game time for the current move, so also cap to 20% of available game time. if (limits.movestogo == 0) { @@ -102,7 +102,7 @@ void TimeManagement::init(Search::LimitsType& limits, double maxConstant = std::max(3.4 + 3.0 * std::log10(limits.time[us] / 1000.0), 2.76); optScale = std::min(0.0120 + std::pow(ply + 3.1, 0.44) * optConstant, - 0.21 * limits.time[us] / double(timeLeft)) + 0.21 * limits.time[us] / timeLeft) * optExtra; maxScale = std::min(6.9, maxConstant + ply / 12.2); } @@ -110,7 +110,7 @@ void TimeManagement::init(Search::LimitsType& limits, // x moves in y seconds (+ z increment) else { - optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft)); + optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / timeLeft); maxScale = std::min(6.3, 1.5 + 0.11 * mtg); } From 76c50a0df3e19b85f27721c0e90226fe4a1f47ff Mon Sep 17 00:00:00 2001 From: Tierynn Byrnes Date: Mon, 19 Feb 2024 07:13:26 +1000 Subject: [PATCH 8/8] use current time instead of '1' for timeLeft formula. make timeLeft a double, timepoint seemed unecessary since it was always casting back to double anyway. fixed comments --- src/timeman.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index 286072848b3..657962663ad 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -81,15 +81,15 @@ void TimeManagement::init(Search::LimitsType& limits, limits.npmsec = npmsec; } - // Maximum move horizon of 50 moves + // Maximum and default move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; - // Make sure timeLeft is > 0 since we may use it as a divisor - // If there is a healthy increment and low mtg, timeLeft can exceed actual available - TimePoint timeLeft = std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - - moveOverhead * (2 + mtg)); + // Make sure timeLeft is > 0 since we use it as a divisor + double timeLeft = + std::max(limits.time[us], limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * mtg); // x basetime (+ z increment) + // If there is a healthy increment and low mtg, timeLeft can exceed actual available // game time for the current move, so also cap to 20% of available game time. if (limits.movestogo == 0) { @@ -102,7 +102,7 @@ void TimeManagement::init(Search::LimitsType& limits, double maxConstant = std::max(3.4 + 3.0 * std::log10(limits.time[us] / 1000.0), 2.76); optScale = std::min(0.0120 + std::pow(ply + 3.1, 0.44) * optConstant, - 0.21 * limits.time[us] / double(timeLeft)) + 0.21 * limits.time[us] / timeLeft) * optExtra; maxScale = std::min(6.9, maxConstant + ply / 12.2); } @@ -110,7 +110,7 @@ void TimeManagement::init(Search::LimitsType& limits, // x moves in y seconds (+ z increment) else { - optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft)); + optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / timeLeft); maxScale = std::min(6.3, 1.5 + 0.11 * mtg); }