mirror of
https://github.com/sockspls/badfish
synced 2025-05-02 01:29:36 +00:00
Use per-thread dynamic contempt
We now use per-thread dynamic contempt. This patch has the following effects: * for Threads=1: **non-functional** * for Threads>1: * with MultiPV=1: **no regression, little to no ELO gain** * with MultiPV>1: **clear improvement over master** First, I tried testing at standard MultiPV=1 play with [0,5] bounds. This yielded 2 yellow and 1 red test: 5+0.05, Threads=5: LLR: -2.96 (-2.94,2.94) [0.00,5.00] Total: 82689 W: 16439 L: 16190 D: 50060 http://tests.stockfishchess.org/tests/view/5aa93a5a0ebc5902952892e6 5+0.05, Threads=8: LLR: -2.96 (-2.94,2.94) [0.00,5.00] Total: 27164 W: 4974 L: 4983 D: 17207 http://tests.stockfishchess.org/tests/view/5ab2639b0ebc5902a6fbefd5 5+0.5, Threads=16: LLR: -2.97 (-2.94,2.94) [0.00,5.00] Total: 41396 W: 7127 L: 7082 D: 27187 http://tests.stockfishchess.org/tests/view/5ab124220ebc59029516cb62 Then, I tested with Skill Level=17 (implicitly MutliPV=4), showing a clear improvement: 5+0.05, Threads=5: LLR: 2.96 (-2.94,2.94) [0.00,5.00] Total: 3498 W: 1316 L: 1135 D: 1047 http://tests.stockfishchess.org/tests/view/5ab4b6580ebc5902932aeca2 Next, I tested the patch with MultiPV=1 again, this time checking for non-regression ([-3, 1]): 5+0.5, Threads=5: LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 65575 W: 12786 L: 12745 D: 40044 http://tests.stockfishchess.org/tests/view/5ab4e8500ebc5902932aecb3 Finally, I ran some tests with fixed number of games, checking if reverting dynamic contempt gains more elo with Skill Level=17 (i.e. MultiPV) than applying the "prevScore" fix and this patch. These tests showed, that this patch gains 15 ELO when playing with Skill Level=17: 5+0.05, Threads=3, "revert dynamic contempt" vs. "WITHOUT this patch": ELO: -11.43 +-4.1 (95%) LOS: 0.0% Total: 20000 W: 7085 L: 7743 D: 5172 http://tests.stockfishchess.org/tests/view/5ab636450ebc590295d88536 5+0.05, Threads=3, "revert dynamic contempt" vs. "WITH this patch": ELO: -26.42 +-4.1 (95%) LOS: 0.0% Total: 20000 W: 6661 L: 8179 D: 5160 http://tests.stockfishchess.org/tests/view/5ab62e680ebc590295d88524 --- ***FAQ*** **Why should this be commited?** I believe that the gain for multi-thread MultiPV search is a sufficient justification for this otherwise neutral change. I also believe this implementation of dynamic contempt is more logical, although this may be just my opinion. **Why is per-thread contempt better at MultiPV?** A likely explanation for the gain in MultiPV mode is that during search each thread independently switches between rootMoves and via the shared contempt score skews each other's evaluation. **Why were the tests done with Skill Level=17?** This was originally suggested by @Hanamuke and the idea is that with Skill Level Stockfish sometimes plays also moves it thinks are slightly sub-optimal and thus the quality of all moves offered by the MultiPV search is checked by the test. **Why are the ELO differences so huge?** This is most likely because of the nature of Skill Level mode -- since it slower and weaker than normal mode, bugs in evaluation have much greater effect. --- Closes https://github.com/official-stockfish/Stockfish/pull/1515. No functional change -- in single thread mode.
This commit is contained in:
parent
c959871a59
commit
c8ef80f466
4 changed files with 8 additions and 10 deletions
|
@ -28,8 +28,7 @@
|
||||||
#include "evaluate.h"
|
#include "evaluate.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "pawns.h"
|
#include "pawns.h"
|
||||||
|
#include "thread.h"
|
||||||
std::atomic<Score> Eval::Contempt;
|
|
||||||
|
|
||||||
namespace Trace {
|
namespace Trace {
|
||||||
|
|
||||||
|
@ -844,7 +843,7 @@ namespace {
|
||||||
// Initialize score by reading the incrementally updated scores included in
|
// Initialize score by reading the incrementally updated scores included in
|
||||||
// the position object (material + piece square tables) and the material
|
// the position object (material + piece square tables) and the material
|
||||||
// imbalance. Score is computed internally from the white point of view.
|
// imbalance. Score is computed internally from the white point of view.
|
||||||
Score score = pos.psq_score() + me->imbalance() + Eval::Contempt;
|
Score score = pos.psq_score() + me->imbalance() + pos.this_thread()->contempt;
|
||||||
|
|
||||||
// Probe the pawn hash table
|
// Probe the pawn hash table
|
||||||
pe = Pawns::probe(pos);
|
pe = Pawns::probe(pos);
|
||||||
|
@ -915,7 +914,7 @@ std::string Eval::trace(const Position& pos) {
|
||||||
|
|
||||||
std::memset(scores, 0, sizeof(scores));
|
std::memset(scores, 0, sizeof(scores));
|
||||||
|
|
||||||
Eval::Contempt = SCORE_ZERO; // Reset any dynamic contempt
|
pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt
|
||||||
|
|
||||||
Value v = Evaluation<TRACE>(pos).value();
|
Value v = Evaluation<TRACE>(pos).value();
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@ namespace Eval {
|
||||||
|
|
||||||
constexpr Value Tempo = Value(20); // Must be visible to search
|
constexpr Value Tempo = Value(20); // Must be visible to search
|
||||||
|
|
||||||
extern std::atomic<Score> Contempt;
|
|
||||||
|
|
||||||
std::string trace(const Position& pos);
|
std::string trace(const Position& pos);
|
||||||
|
|
||||||
Value evaluate(const Position& pos);
|
Value evaluate(const Position& pos);
|
||||||
|
|
|
@ -309,8 +309,8 @@ void Thread::search() {
|
||||||
multiPV = std::min(multiPV, rootMoves.size());
|
multiPV = std::min(multiPV, rootMoves.size());
|
||||||
|
|
||||||
int ct = Options["Contempt"] * PawnValueEg / 100; // From centipawns
|
int ct = Options["Contempt"] * PawnValueEg / 100; // From centipawns
|
||||||
Eval::Contempt = (us == WHITE ? make_score(ct, ct / 2)
|
contempt = (us == WHITE ? make_score(ct, ct / 2)
|
||||||
: -make_score(ct, ct / 2));
|
: -make_score(ct, ct / 2));
|
||||||
|
|
||||||
// Iterative deepening loop until requested to stop or the target depth is reached
|
// Iterative deepening loop until requested to stop or the target depth is reached
|
||||||
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
|
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
|
||||||
|
@ -353,8 +353,8 @@ void Thread::search() {
|
||||||
// Adjust contempt based on root move's previousScore (dynamic contempt)
|
// Adjust contempt based on root move's previousScore (dynamic contempt)
|
||||||
ct += int(std::round(48 * atan(float(previousScore) / 128)));
|
ct += int(std::round(48 * atan(float(previousScore) / 128)));
|
||||||
|
|
||||||
Eval::Contempt = (us == WHITE ? make_score(ct, ct / 2)
|
contempt = (us == WHITE ? make_score(ct, ct / 2)
|
||||||
: -make_score(ct, ct / 2));
|
: -make_score(ct, ct / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start with a small aspiration window and, in the case of a fail
|
// Start with a small aspiration window and, in the case of a fail
|
||||||
|
|
|
@ -71,6 +71,7 @@ public:
|
||||||
ButterflyHistory mainHistory;
|
ButterflyHistory mainHistory;
|
||||||
CapturePieceToHistory captureHistory;
|
CapturePieceToHistory captureHistory;
|
||||||
ContinuationHistory contHistory;
|
ContinuationHistory contHistory;
|
||||||
|
Score contempt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue