Skip to content

Commit

Permalink
refactor: tournament scheduler logic (#784)
Browse files Browse the repository at this point in the history
  • Loading branch information
Disservin authored Jan 17, 2025
1 parent b0e0eee commit fe4ba27
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 66 deletions.
43 changes: 36 additions & 7 deletions app/src/matchmaking/tournament/base/tournament.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <matchmaking/output/output.hpp>
#include <matchmaking/output/output_factory.hpp>
#include <matchmaking/scoreboard.hpp>
#include <matchmaking/tournament/schedule/scheduler.hpp>
#include <types/tournament.hpp>

namespace fastchess {
Expand All @@ -22,17 +23,15 @@ extern std::atomic_bool stop;
} // namespace atomic

BaseTournament::BaseTournament(const stats_map &results) {
const auto &config = *config::TournamentConfig;
const auto total = setResults(results);
const auto num_players = config::EngineConfigs->size();
const auto &config = *config::TournamentConfig;
const auto total = setResults(results);

initial_matchcount_ = total;
match_count_ = total;

output_ = OutputFactory::create(config.output, config.report_penta);
cores_ = std::make_unique<affinity::AffinityManager>(config.affinity, getMaxAffinity(*config::EngineConfigs));
book_ = std::make_unique<book::OpeningBook>(config, initial_matchcount_);
generator_ = std::make_unique<MatchGenerator>(book_.get(), num_players, config.rounds, config.games, total);
output_ = OutputFactory::create(config.output, config.report_penta);
cores_ = std::make_unique<affinity::AffinityManager>(config.affinity, getMaxAffinity(*config::EngineConfigs));
book_ = std::make_unique<book::OpeningBook>(config, initial_matchcount_);

if (!config.pgn.file.empty()) file_writer_pgn_ = std::make_unique<util::FileWriter>(config.pgn.file);
if (!config.epd.file.empty()) file_writer_epd_ = std::make_unique<util::FileWriter>(config.epd.file);
Expand All @@ -42,9 +41,29 @@ BaseTournament::BaseTournament(const stats_map &results) {

BaseTournament::~BaseTournament() {
Logger::trace("~BaseTournament()");

saveJson();

Logger::trace("Instructing engines to stop...");
writeToOpenPipes();

pool_.kill();

if (config::TournamentConfig->output == OutputType::FASTCHESS) {
if (tracker_.begin() != tracker_.end()) {
Logger::info("");
}

for (const auto &[name, tracked] : tracker_) {
Logger::info("Player: {}", name);
Logger::info(" Timeouts: {}", tracked.timeouts);
Logger::info(" Crashed: {}", tracked.disconnects);
}

if (tracker_.begin() != tracker_.end()) {
Logger::info("");
}
}
}

void BaseTournament::start() {
Expand All @@ -53,6 +72,16 @@ void BaseTournament::start() {
create();
}

void BaseTournament::create() {
Logger::trace("Creating matches...");

total_ = generator_->total();

for (int i = 0; i < pool_.getNumThreads(); i++) {
startNext();
}
}

void BaseTournament::saveJson() {
Logger::trace("Saving results...");

Expand Down
9 changes: 6 additions & 3 deletions app/src/matchmaking/tournament/base/tournament.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <matchmaking/output/output.hpp>
#include <matchmaking/scoreboard.hpp>
#include <matchmaking/timeout_tracker.hpp>
#include <matchmaking/tournament/roundrobin/match_generator.hpp>
#include <matchmaking/tournament/schedule/scheduler.hpp>
#include <types/tournament.hpp>

namespace fastchess {
Expand All @@ -39,7 +39,7 @@ class BaseTournament {
virtual void startNext() = 0;

// creates the matches
virtual void create() = 0;
void create();

// Function to save the config file
void saveJson();
Expand All @@ -55,7 +55,7 @@ class BaseTournament {
ScoreBoard scoreboard_ = ScoreBoard();
PlayerTracker tracker_ = PlayerTracker();

std::unique_ptr<MatchGenerator> generator_;
std::unique_ptr<Scheduler> generator_;
std::unique_ptr<IOutput> output_;
std::unique_ptr<affinity::AffinityManager> cores_;
std::unique_ptr<util::FileWriter> file_writer_pgn_;
Expand All @@ -66,6 +66,9 @@ class BaseTournament {
std::atomic<std::uint64_t> match_count_ = 0;
std::uint64_t initial_matchcount_;

// number of games to be played
std::atomic<uint64_t> total_ = 0;

private:
[[nodiscard]] std::size_t setResults(const stats_map &results);

Expand Down
46 changes: 10 additions & 36 deletions app/src/matchmaking/tournament/roundrobin/roundrobin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,35 @@
#include <core/rand.hpp>
#include <game/pgn/pgn_builder.hpp>
#include <matchmaking/output/output_factory.hpp>
#include <matchmaking/tournament/roundrobin/scheduler.hpp>

namespace fastchess {

RoundRobin::RoundRobin(const stats_map& results) : BaseTournament(results) {
// Initialize the SPRT test
sprt_ = SPRT(config::TournamentConfig->sprt.alpha, config::TournamentConfig->sprt.beta,
config::TournamentConfig->sprt.elo0, config::TournamentConfig->sprt.elo1,
config::TournamentConfig->sprt.model, config::TournamentConfig->sprt.enabled);

const auto& config = *config::TournamentConfig;
const auto num_players = config::EngineConfigs->size();

generator_ =
std::make_unique<RoundRobinScheduler>(book_.get(), num_players, config.rounds, config.games, match_count_);
}

RoundRobin::~RoundRobin() { Logger::trace("~RoundRobin()"); }

void RoundRobin::start() {
Logger::trace("Starting round robin tournament...");

BaseTournament::start();

// If autosave is enabled, save the results every save_interval games
const auto save_interval = config::TournamentConfig->autosaveinterval;

// Account for the initial matchcount
auto save_iter = initial_matchcount_ + save_interval;

BaseTournament::start();

// Wait for games to finish
while (match_count_ < total_ && !atomic::stop) {
if (save_interval > 0 && match_count_ >= save_iter) {
Expand All @@ -39,27 +45,6 @@ void RoundRobin::start() {

std::this_thread::sleep_for(std::chrono::seconds(1));
}

Logger::trace("Instructing engines to stop...");
writeToOpenPipes();

pool_.kill();

if (config::TournamentConfig->output == OutputType::FASTCHESS) {
if (tracker_.begin() != tracker_.end()) {
Logger::info("");
}

for (const auto& [name, tracked] : tracker_) {
Logger::info("Player: {}", name);
Logger::info(" Timeouts: {}", tracked.timeouts);
Logger::info(" Crashed: {}", tracked.disconnects);
}

if (tracker_.begin() != tracker_.end()) {
Logger::info("");
}
}
}

void RoundRobin::startNext() {
Expand All @@ -77,18 +62,7 @@ void RoundRobin::startNext() {
pool_.enqueue(&RoundRobin::createMatch, this, match.value());
}

void RoundRobin::create() {
Logger::trace("Creating matches...");

total_ = (config::EngineConfigs->size() * (config::EngineConfigs->size() - 1) / 2) *
config::TournamentConfig->rounds * config::TournamentConfig->games;

for (int i = 0; i < pool_.getNumThreads(); i++) {
startNext();
}
}

void RoundRobin::createMatch(const MatchGenerator::Pairing& pairing) {
void RoundRobin::createMatch(const Scheduler::Pairing& pairing) {
const auto opening = (*book_)[pairing.opening_id];
const auto first = (*config::EngineConfigs)[pairing.player1];
const auto second = (*config::EngineConfigs)[pairing.player2];
Expand Down
8 changes: 1 addition & 7 deletions app/src/matchmaking/tournament/roundrobin/roundrobin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ class RoundRobin : public BaseTournament {
protected:
void startNext() override;

// creates the matches
void create() override;

private:
bool shouldPrintRatingInterval(std::size_t round_id) const noexcept;

Expand All @@ -43,7 +40,7 @@ class RoundRobin : public BaseTournament {

bool allMatchesPlayed() const noexcept { return match_count_ + 1 == total_; }

void createMatch(const MatchGenerator::Pairing& pairing);
void createMatch(const Scheduler::Pairing& pairing);

// update the current running sprt. SPRT Config has to be valid.
void updateSprtStatus(const std::vector<EngineConfiguration>& engine_configs, const engines& engines);
Expand All @@ -52,8 +49,5 @@ class RoundRobin : public BaseTournament {

std::mutex output_mutex_;
std::mutex game_gen_mutex_;

// number of games to be played
std::atomic<uint64_t> total_ = 0;
};
} // namespace fastchess
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,18 @@
#include <vector>

#include <game/book/opening_book.hpp>
#include <matchmaking/tournament/schedule/scheduler.hpp>

namespace fastchess {

/**
* Generate matches for a round-robin tournament.
* Everytime a new match is required the next() function is called.
*/
class MatchGenerator {
class RoundRobinScheduler : public Scheduler {
public:
struct Pairing {
std::size_t round_id;
std::size_t pairing_id;
std::size_t game_id;
std::optional<std::size_t> opening_id;
std::size_t player1;
std::size_t player2;
};

MatchGenerator(book::OpeningBook* opening_book, std::size_t players, std::size_t rounds, std::size_t games,
std::size_t played_games)
RoundRobinScheduler(book::OpeningBook* opening_book, std::size_t players, std::size_t rounds, std::size_t games,
std::size_t played_games)
: opening_book_(opening_book),
n_players(players),
n_rounds(rounds),
Expand All @@ -44,7 +36,7 @@ class MatchGenerator {
}

// Function to generate the next game pairing
std::optional<Pairing> next() {
std::optional<Pairing> next() override {
Pairing next_game;

// Check if the current round is beyond the number of rounds
Expand Down Expand Up @@ -91,6 +83,8 @@ class MatchGenerator {
return next_game;
}

std::size_t total() const override { return (n_players * (n_players - 1) / 2) * n_rounds * n_games_per_round; }

private:
book::OpeningBook* opening_book_;
std::optional<std::size_t> opening;
Expand Down
26 changes: 26 additions & 0 deletions app/src/matchmaking/tournament/schedule/scheduler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <cstdint>
#include <optional>

namespace fastchess {

class Scheduler {
public:
struct Pairing {
std::size_t round_id;
std::size_t pairing_id;
std::size_t game_id;
std::optional<std::size_t> opening_id;
std::size_t player1;
std::size_t player2;
};

virtual ~Scheduler() = default;

virtual std::optional<Pairing> next() = 0;

virtual std::size_t total() const = 0;
};

} // namespace fastchess

0 comments on commit fe4ba27

Please sign in to comment.