17 #include "../utils/parsing.h"
34 std::filesystem::path,
44 void parse_result_file(
const Jobs& jobs,
const std::filesystem::path& file, std::map<size_t, JobData>& results) {
46 std::ifstream in(file);
47 std::string content((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
48 auto extension = file.extension();
50 if (extension ==
".out") {
51 std::regex filere(
"Executing (.+)\\n# START ([0-9]+) #([^#]*)# END \\2 #(?:([^#]*)# END DATA \\2 #)?");
52 auto reBegin = std::sregex_iterator(content.begin(), content.end(), filere);
53 auto reEnd = std::sregex_iterator();
54 for (
auto i = reBegin; i != reEnd; ++i) {
55 std::size_t
id = std::stoull((*i)[2]) - 1;
58 bool toolFound =
false;
59 std::string cmdline = (*i)[1];
60 for (
const auto& tool : jobs.
tools()) {
61 auto t = tool->parseCommandline(cmdline);
63 std::get<0>(results[
id]) = tool.get();
64 std::get<1>(results[
id]) = std::filesystem::path(*t);
73 auto& res = std::get<2>(results[
id]);
77 BENCHMAX_LOG_DEBUG(
"benchmax.slurm",
"Got " << res <<
" for task " <<
id <<
" from stdout");
79 }
else if (extension ==
".err") {
80 std::regex filere(
"# START ([0-9]+) #([^#]*)# END \\1 #(?:([^#]*)# END DATA \\1 #)?");
81 auto reBegin = std::sregex_iterator(content.begin(), content.end(), filere);
82 auto reEnd = std::sregex_iterator();
83 for (
auto i = reBegin; i != reEnd; ++i) {
84 std::size_t
id = std::stoull((*i)[1]) - 1;
87 auto& res = std::get<2>(results[
id]);
90 BENCHMAX_LOG_DEBUG(
"benchmax.slurm",
"Got " << res <<
" for task " <<
id <<
" from stderr");
93 BENCHMAX_LOG_WARN(
"benchmax.slurm",
"Trying to parse output file with unexpected extension " << extension);
97 std::pair<std::size_t,std::size_t>
get_job_range(std::size_t n, std::size_t numJobs)
const {
99 return std::make_pair(
101 std::min(job_size * (n + 1), numJobs)
107 std::ofstream out(
settings_slurm().tmp_dir +
"/slurmjobs", std::ios_base::app);
108 out << jobid << std::endl;
114 std::vector<int> res;
121 res.push_back(jobid);
133 void run_job_async(std::size_t n,
const std::vector<JobData>& results,
bool wait_for_termination) {
136 std::string jobsfilename =
settings_slurm().tmp_dir +
"/jobs-" + std::to_string(
settings_core().start_time) +
"-" + std::to_string(n+1) +
".jobs";
141 std::to_string(
settings_core().start_time) +
"-" + std::to_string(n),
159 std::stringstream cmd;
161 if (wait_for_termination) cmd <<
" --wait";
162 cmd <<
" --array=1-" << std::to_string(
settings_slurm().array_size);
164 cmd <<
" " + submitfile;
169 if (wait_for_termination) {
178 if (check_finished) {
181 if (jobids.size() == 0) {
185 for (
int jobid : jobids) {
194 std::map<size_t, JobData> results;
196 for (
const auto& f: files) {
200 for (
auto& [rid, r]: results) {
201 addResult(std::get<0>(r), std::get<1>(r), std::move(std::get<2>(r)));
211 if (check_finished) {
222 void run(
const Jobs& jobs,
bool wait_for_termination) {
224 BENCHMAX_LOG_ERROR(
"benchmax.slurm",
"Benchmax is still running in the specified tmp_dir! If this is not the case, please delete " +
settings_slurm().tmp_dir +
"/slurmjobs");
228 std::vector<JobData> results;
229 for (
const auto& [tool, file]: jobs.
randomized()) {
234 std::vector<std::future<void>> tasks;
237 for (std::size_t i = 0; i < count; ++i) {
238 tasks.emplace_back(std::async(std::launch::async,
239 [i,&results,wait_for_termination,
this](){
244 for (
auto& f: tasks) {
247 if (wait_for_termination) {
#define BENCHMAX_LOG_DEBUG(channel, msg)
Log debug messages.
#define BENCHMAX_LOG_WARN(channel, msg)
Log warnings.
#define BENCHMAX_LOG_INFO(channel, msg)
Log informational messages.
#define BENCHMAX_LOG_ERROR(channel, msg)
Log errors.
Base class for all backends.
void addResult(const Tool *tool, const fs::path &file, BenchmarkResult &&result)
Add a result.
Represents a set of jobs, constructed as the cartesian product of a set of tools and a set of benchma...
const auto & tools() const
Returns the set of tools.
auto randomized() const
Returns all jobs in a pseudo-randomized order.
Backend for the Slurm workload manager.
bool collect_results(const Jobs &jobs, bool check_finished) override
void store_job_id(int jobid)
std::pair< std::size_t, std::size_t > get_job_range(std::size_t n, std::size_t numJobs) const
void run(const Jobs &jobs, bool wait_for_termination)
Run all tools on all benchmarks using Slurm.
std::vector< int > load_job_ids()
std::mutex mSubmissionMutex
Mutex for submission delay.
void run_job_async(std::size_t n, const std::vector< JobData > &results, bool wait_for_termination)
std::mutex mSlurmjobMutex
Mutex for slurmjobs file.
std::tuple< const Tool *, std::filesystem::path, BenchmarkResult > JobData
A job consists of a tool, an input file, a base dir and results.
void parse_result_file(const Jobs &jobs, const std::filesystem::path &file, std::map< size_t, JobData > &results)
Parse the content of an output file.
static void remove(V &ts, const T &t)
void clear_directory(const fs::path &basedir)
Clear log files from directory.
void remove_log_files(const std::vector< fs::path > &files, bool remove)
Remove the given list of files.
void archive_log_files(const ArchiveProperties &p)
Put all log files into an archive.
std::string generate_submit_file_chunked(const ChunkedSubmitfileProperties &p)
void generate_jobs_file(const std::string &filename, std::pair< std::size_t, std::size_t > range, const Jobs &jobs)
int parse_job_id(const std::string &output)
Parses the job id from the output of sbatch.
std::vector< fs::path > collect_result_files(const fs::path &basedir)
Collects all result files in the given base directory for this job id.
std::string parse_result_info(const std::string &content, const std::string &name)
Parse a single result information from the output.
bool is_job_finished(int jobid)
Checks if the given job is finished.
int call_program(const std::string &commandline, std::string &stdout, bool print_to_stdout=false)
Runs an external program from some command line and records the output to stdout.
const auto & settings_core()
Retrieved core settings.
const auto & settings_slurm()
Return the Slurm settings.
const auto & settings_benchmarks()
Return the benchmark settings.
std::size_t parse_peak_memory(const std::string &output)
auto get(const It &it, level)
Results for a single benchmark run.