Skip to content

Commit

Permalink
Don't exit early when playouts are limited.
Browse files Browse the repository at this point in the history
When running with fixed playouts per move, even if we will not change
our selection of the best move, it is still beneficial to continue
thinking and expand our tree to benefit the search of the next move,
which will now accumulate more visits in total. (This reasoning does
not apply when running with fixed visits because the next search will
simply be shorter)

So disable early exits in the time management code for this case.

This is a trivial fix if our representation of "unlimited playouts" is
consistent, so fix that up first.

See also:
leela-zero#1127 (comment)
  • Loading branch information
gcp committed Apr 30, 2018
1 parent 492ac09 commit 1890590
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/GTP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ void GTP::setup_default_parameters() {
#else
cfg_num_threads = cfg_max_threads;
#endif
cfg_max_playouts = std::numeric_limits<decltype(cfg_max_playouts)>::max();
cfg_max_visits = std::numeric_limits<decltype(cfg_max_visits)>::max();
cfg_max_playouts = UCTSearch::UNLIMITED_PLAYOUTS;
cfg_max_visits = UCTSearch::UNLIMITED_PLAYOUTS;
cfg_timemanage = TimeManagement::AUTO;
cfg_lagbuffer_cs = 100;
#ifdef USE_OPENCL
Expand Down
6 changes: 2 additions & 4 deletions src/Leela.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ static void parse_commandline(int argc, char *argv[]) {

// 0 may be specified to mean "no limit"
if (cfg_max_playouts == 0) {
cfg_max_playouts =
std::numeric_limits<decltype(cfg_max_playouts)>::max();
cfg_max_playouts = UCTSearch::UNLIMITED_PLAYOUTS;
}
}

Expand All @@ -223,8 +222,7 @@ static void parse_commandline(int argc, char *argv[]) {

// 0 may be specified to mean "no limit"
if (cfg_max_visits == 0) {
cfg_max_visits =
std::numeric_limits<decltype(cfg_max_visits)>::max();
cfg_max_visits = UCTSearch::UNLIMITED_PLAYOUTS;
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/NNCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "NNCache.h"
#include "Utils.h"
#include "UCTSearch.h"

NNCache::NNCache(int size) : m_size(size) {}

Expand Down Expand Up @@ -80,15 +81,15 @@ void NNCache::set_size_from_playouts(int max_playouts) {
constexpr auto num_cache_moves = 3;
auto max_playouts_per_move =
std::min(max_playouts,
std::numeric_limits<decltype(max_playouts)>::max() /
num_cache_moves);
UCTSearch::UNLIMITED_PLAYOUTS / num_cache_moves);
auto max_size = num_cache_moves * max_playouts_per_move;
max_size = std::min(150'000, std::max(6'000, max_size));
NNCache::get_NNCache().resize(max_size);
}

void NNCache::dump_stats() {
Utils::myprintf("NNCache: %d/%d hits/lookups = %.1f%% hitrate, %d inserts, %u size\n",
Utils::myprintf(
"NNCache: %d/%d hits/lookups = %.1f%% hitrate, %d inserts, %u size\n",
m_hits, m_lookups, 100. * m_hits / (m_lookups + 1),
m_inserts, m_cache.size());
}
12 changes: 4 additions & 8 deletions src/UCTSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,8 @@ bool UCTSearch::have_alternate_moves(int elapsed_centis, int time_for_move) {
// think ahead about her next moves in the remaining time.
auto my_color = m_rootstate.get_to_move();
auto tc = m_rootstate.get_timecontrol();
if (!tc.can_accumulate_time(my_color)) {
if (!tc.can_accumulate_time(my_color)
|| m_maxplayouts < UCTSearch::UNLIMITED_PLAYOUTS) {
if (cfg_timemanage != TimeManagement::FAST) {
return true;
}
Expand Down Expand Up @@ -696,18 +697,13 @@ void UCTSearch::set_playout_limit(int playouts) {
static_assert(std::is_convertible<decltype(playouts),
decltype(m_maxplayouts)>::value,
"Inconsistent types for playout amount.");
// Limit to type max / 2 to prevent overflow when multithreading.
m_maxplayouts =
std::min(playouts,
std::numeric_limits<decltype(m_maxplayouts)>::max() / 2);
m_maxplayouts = std::min(playouts, UNLIMITED_PLAYOUTS);
}

void UCTSearch::set_visit_limit(int visits) {
static_assert(std::is_convertible<decltype(visits),
decltype(m_maxvisits)>::value,
"Inconsistent types for visits amount.");
// Limit to type max / 2 to prevent overflow when multithreading.
m_maxvisits =
std::min(visits,
std::numeric_limits<decltype(m_maxvisits)>::max() / 2);
m_maxvisits = std::min(visits, UNLIMITED_PLAYOUTS);
}
8 changes: 8 additions & 0 deletions src/UCTSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ class UCTSearch {
static constexpr auto MAX_TREE_SIZE =
(sizeof(void*) == 4 ? 25'000'000 : 100'000'000);

/*
Value representing unlimited visits or playouts. Due to
concurrent updates while multithreading, we need some
headroom within the native type.
*/
static constexpr auto UNLIMITED_PLAYOUTS =
std::numeric_limits<int>::max() / 2;

UCTSearch(GameState& g);
int think(int color, passflag_t passflag = NORMAL);
void set_playout_limit(int playouts);
Expand Down

0 comments on commit 1890590

Please sign in to comment.