Skip to content

Commit 9dbfafd

Browse files
committed
Additional reporting details for selfplay to support T50+ (#821)
* Hack to report average nodes per move for monitoring training. * WDLstyle resign false positive reporting * Make this less WIP and more submittable. * Cast correctly. * Fix typo in last commit... * Add comment about unsupported combination.
1 parent 44f1a8c commit 9dbfafd

File tree

5 files changed

+30
-3
lines changed

5 files changed

+30
-3
lines changed

src/chess/callbacks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ struct TournamentInfo {
118118
// e.g. results[2][1] is how many times player 1 lost as black.
119119
int results[3][2] = {{0, 0}, {0, 0}, {0, 0}};
120120
using Callback = std::function<void(const TournamentInfo&)>;
121+
int move_count_ = 0;
122+
uint64_t nodes_total_ = 0;
121123
};
122124

123125
} // namespace lczero

src/selfplay/game.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ void SelfPlayGame::Play(int white_threads, int black_threads, bool training,
101101

102102
// Do search.
103103
search_->RunBlocking(blacks_move ? black_threads : white_threads);
104+
move_count_++;
105+
nodes_total_ += search_->GetTotalPlayouts();
104106
if (abort_) break;
105107

106108
auto best_eval = search_->GetBestEval();
@@ -117,15 +119,18 @@ void SelfPlayGame::Play(int white_threads, int black_threads, bool training,
117119
eval = (eval + 1) / 2;
118120
if (eval < min_eval_[idx]) min_eval_[idx] = eval;
119121
const int move_number = tree_[0]->GetPositionHistory().GetLength() / 2 + 1;
122+
auto best_w = (best_eval.first + 1.0f - best_eval.second) / 2.0f;
123+
auto best_d = best_eval.second;
124+
auto best_l = best_w - best_eval.first;
125+
max_eval_[0] = std::max(max_eval_[0], blacks_move ? best_l : best_w);
126+
max_eval_[1] = std::max(max_eval_[1], best_d);
127+
max_eval_[2] = std::max(max_eval_[2], blacks_move ? best_w : best_l);
120128
if (enable_resign && move_number >= options_[idx].uci_options->Get<int>(
121129
kResignEarliestMoveId.GetId())) {
122130
const float resignpct =
123131
options_[idx].uci_options->Get<float>(kResignPercentageId.GetId()) /
124132
100;
125133
if (options_[idx].uci_options->Get<bool>(kResignWDLStyleId.GetId())) {
126-
auto best_w = (best_eval.first + 1.0f - best_eval.second) / 2.0f;
127-
auto best_d = best_eval.second;
128-
auto best_l = best_w - best_eval.first;
129134
auto threshold = 1.0f - resignpct;
130135
if (best_w > threshold) {
131136
game_result_ =
@@ -171,6 +176,17 @@ std::vector<Move> SelfPlayGame::GetMoves() const {
171176
}
172177

173178
float SelfPlayGame::GetWorstEvalForWinnerOrDraw() const {
179+
// TODO: This assumes both players have the same resign style.
180+
// Supporting otherwise involves mixing the meaning of worst.
181+
if (options_[0].uci_options->Get<bool>(kResignWDLStyleId.GetId())) {
182+
if (game_result_ == GameResult::WHITE_WON) {
183+
return std::max(max_eval_[1], max_eval_[2]);
184+
} else if (game_result_ == GameResult::BLACK_WON) {
185+
return std::max(max_eval_[1], max_eval_[0]);
186+
} else {
187+
return std::max(max_eval_[2], max_eval_[0]);
188+
}
189+
}
174190
if (game_result_ == GameResult::WHITE_WON) return min_eval_[0];
175191
if (game_result_ == GameResult::BLACK_WON) return min_eval_[1];
176192
return std::min(min_eval_[0], min_eval_[1]);

src/selfplay/game.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class SelfPlayGame {
8383
// Gets the eval which required the biggest swing up to get the final outcome.
8484
// Eval is the expected outcome in the range 0<->1.
8585
float GetWorstEvalForWinnerOrDraw() const;
86+
int move_count_ = 0;
87+
uint64_t nodes_total_ = 0;
8688

8789
private:
8890
// options_[0] is for white player, [1] for black.
@@ -99,6 +101,8 @@ class SelfPlayGame {
99101
// Track minimum eval for each player so that GetWorstEvalForWinnerOrDraw()
100102
// can be calculated after end of game.
101103
float min_eval_[2] = {1.0f, 1.0f};
104+
// Track the maximum eval for white win, draw, black win for comparison to actual outcome.
105+
float max_eval_[3] = {0.0f, 0.0f, 0.0f};
102106
std::mutex mutex_;
103107

104108
// Training data to send.

src/selfplay/loop.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ void SelfPlayLoop::SendTournament(const TournamentInfo& info) {
173173
<< info.results[1][0];
174174
oss << " P1-B: +" << info.results[0][1] << " -" << info.results[2][1] << " ="
175175
<< info.results[1][1];
176+
oss << " npm " + std::to_string(static_cast<double>(info.nodes_total_) / info.move_count_);
177+
oss << " nodes " + std::to_string(info.nodes_total_);
178+
oss << " moves " + std::to_string(info.move_count_);
176179
SendResponse(oss.str());
177180
}
178181

src/selfplay/tournament.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ void SelfPlayTournament::PlayOneGame(int game_number) {
273273
: game.GetGameResult() == GameResult::WHITE_WON ? 0 : 2;
274274
if (player1_black) result = 2 - result;
275275
++tournament_info_.results[result][player1_black ? 1 : 0];
276+
tournament_info_.move_count_ += game.move_count_;
277+
tournament_info_.nodes_total_ += game.nodes_total_;
276278
tournament_callback_(tournament_info_);
277279
}
278280
}

0 commit comments

Comments
 (0)