Skip to content

Commit

Permalink
Improved MO benchmark logic
Browse files Browse the repository at this point in the history
  • Loading branch information
MoneroOcean committed May 28, 2024
1 parent 69b5f93 commit a936d10
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 120 deletions.
5 changes: 4 additions & 1 deletion src/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ int xmrig::App::exec()
if (m_controller->config()->isShouldSave()) {
m_controller->config()->save();
}
m_controller->config()->benchmark().start();
if (m_controller->config()->isRebenchAlgo()) {
m_controller->config()->benchmark().flush_perf();
}
m_controller->config()->benchmark().start_perf();
} else {
m_controller->start();
}
Expand Down
161 changes: 73 additions & 88 deletions src/core/MoBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "backend/common/Tags.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "base/net/stratum/Job.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.h"
Expand All @@ -34,38 +33,29 @@

namespace xmrig {

MoBenchmark::MoBenchmark() : m_controller(nullptr), m_isNewBenchRun(true) {
for (BenchAlgo bench_algo = BenchAlgo::MIN; bench_algo != BenchAlgo::MAX; bench_algo = static_cast<BenchAlgo>(bench_algo + 1)) {
m_bench_job[bench_algo] = new Job(false, Algorithm(ba2a[bench_algo]), "benchmark");
}
}
MoBenchmark::MoBenchmark() : m_controller(nullptr), m_isNewBenchRun(true) {}

MoBenchmark::~MoBenchmark() {
for (BenchAlgo bench_algo = BenchAlgo::MIN; bench_algo != BenchAlgo::MAX; bench_algo = static_cast<BenchAlgo>(bench_algo + 1)) {
delete m_bench_job[bench_algo];
}
}
MoBenchmark::~MoBenchmark() {}

// start performance measurements from the first bench_algo
void MoBenchmark::start() {
void MoBenchmark::start_perf() {
JobResults::setListener(this, m_controller->config()->cpu().isHwAES()); // register benchmark as job result listener to compute hashrates there
// write text before first benchmark round
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " STARTING ALGO PERFORMANCE CALIBRATION (with " MAGENTA_BOLD_S "%i" CYAN_BOLD_S " seconds round) "), Tags::benchmark(), m_controller->config()->benchAlgoTime());
// start benchmarking from first PerfAlgo in the list
start(BenchAlgo::MIN);
m_isNewBenchRun = true;
m_bench_algo = 0;
start();
m_isNewBenchRun = true; // need to save it to true to save config after benchmark
}

// end of benchmarks, switch to jobs from the pool (network), fill algo_perf
void MoBenchmark::finish() {
for (const Algorithm::Id algo : Algorithm::all([this](const Algorithm &algo) { return true; })) {
algo_perf[algo] = get_algo_perf(algo);
if (algo_perf[algo] == 0.0f) algo_perf[algo] = get_algo_perf(algo);
}
m_bench_algo = BenchAlgo::INVALID;
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " ALGO PERFORMANCE CALIBRATION COMPLETE "), Tags::benchmark());
m_controller->miner()->pause(); // do not compute anything before job from the pool
JobResults::stop();
JobResults::setListener(m_controller->network(), m_controller->config()->cpu().isHwAES());
m_controller->start();
}

Expand All @@ -77,18 +67,19 @@ rapidjson::Value MoBenchmark::toJSON(rapidjson::Document &doc) const
Value obj(kObjectType);

for (const Algorithm a : Algorithm::all()) {
if (algo_perf[a.id()] == 0.0f) continue;
obj.AddMember(StringRef(a.name()), algo_perf[a.id()], allocator);
}

return obj;
}

void MoBenchmark::flush_perf() {
for (const Algorithm::Id algo : Algorithm::all()) algo_perf[algo] = 0.0f;
}

void MoBenchmark::read(const rapidjson::Value &value)
{
for (const Algorithm::Id algo : Algorithm::all()) {
algo_perf[algo] = 0.0f;
}
flush_perf();
if (value.IsObject()) {
for (auto &member : value.GetObject()) {
const Algorithm algo(member.name.GetString());
Expand All @@ -98,100 +89,94 @@ void MoBenchmark::read(const rapidjson::Value &value)
}
if (member.value.IsDouble()) {
algo_perf[algo.id()] = member.value.GetDouble();
m_isNewBenchRun = false;
continue;
}
if (member.value.IsInt()) {
algo_perf[algo.id()] = member.value.GetInt();
m_isNewBenchRun = false;
continue;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(MAGENTA_BOLD_S " Ignoring wrong value for algo-perf[%s] "), Tags::benchmark(), member.name.GetString());
}
}
m_isNewBenchRun = false;
for (int i = 0; bench_algos[i] != Algorithm::INVALID; ++ i)
if (algo_perf[bench_algos[i]] == 0.0f) {
m_isNewBenchRun = true;
return;
}
}

double MoBenchmark::get_algo_perf(Algorithm::Id algo) const {
switch (algo) {
case Algorithm::CN_CCX: return m_bench_algo_perf[BenchAlgo::CN_CCX];
case Algorithm::CN_0: return m_bench_algo_perf[BenchAlgo::CN_CCX] / 2;
case Algorithm::CN_1: return m_bench_algo_perf[BenchAlgo::CN_R];
case Algorithm::CN_2: return m_bench_algo_perf[BenchAlgo::CN_R];
case Algorithm::CN_R: return m_bench_algo_perf[BenchAlgo::CN_R];
case Algorithm::CN_RTO: return m_bench_algo_perf[BenchAlgo::CN_R];
case Algorithm::CN_XAO: return m_bench_algo_perf[BenchAlgo::CN_R];
case Algorithm::CN_FAST: return m_bench_algo_perf[BenchAlgo::CN_R] * 2;
case Algorithm::CN_HALF: return m_bench_algo_perf[BenchAlgo::CN_R] * 2;
case Algorithm::CN_RWZ: return m_bench_algo_perf[BenchAlgo::CN_R] / 3 * 4;
case Algorithm::CN_ZLS: return m_bench_algo_perf[BenchAlgo::CN_R] / 3 * 4;
case Algorithm::CN_DOUBLE: return m_bench_algo_perf[BenchAlgo::CN_R] / 2;
case Algorithm::CN_LITE_0: return m_bench_algo_perf[BenchAlgo::CN_LITE_1];
case Algorithm::CN_LITE_1: return m_bench_algo_perf[BenchAlgo::CN_LITE_1];
case Algorithm::CN_HEAVY_XHV: return m_bench_algo_perf[BenchAlgo::CN_HEAVY_XHV];
case Algorithm::CN_PICO_0: return m_bench_algo_perf[BenchAlgo::CN_PICO_0];
case Algorithm::CN_PICO_TLO: return m_bench_algo_perf[BenchAlgo::CN_PICO_0];
case Algorithm::CN_GPU: return m_bench_algo_perf[BenchAlgo::CN_GPU];
case Algorithm::AR2_CHUKWA_V2: return m_bench_algo_perf[BenchAlgo::AR2_CHUKWA_V2];
case Algorithm::KAWPOW_RVN: return m_bench_algo_perf[BenchAlgo::KAWPOW_RVN];
case Algorithm::RX_0: return m_bench_algo_perf[BenchAlgo::RX_0];
case Algorithm::RX_SFX: return m_bench_algo_perf[BenchAlgo::RX_0];
case Algorithm::RX_GRAFT: return m_bench_algo_perf[BenchAlgo::RX_GRAFT];
case Algorithm::RX_ARQ: return m_bench_algo_perf[BenchAlgo::RX_ARQ];
case Algorithm::RX_XEQ: return m_bench_algo_perf[BenchAlgo::RX_ARQ];
case Algorithm::RX_XLA: return m_bench_algo_perf[BenchAlgo::RX_XLA];
case Algorithm::GHOSTRIDER_RTM: return m_bench_algo_perf[BenchAlgo::GHOSTRIDER_RTM];
case Algorithm::FLEX_KCN: return m_bench_algo_perf[BenchAlgo::FLEX_KCN];
default: return 0.0f;
case Algorithm::CN_0: return algo_perf[Algorithm::CN_CCX] / 2;
case Algorithm::CN_1: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_2: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_RTO: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_XAO: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_FAST: return algo_perf[Algorithm::CN_R] * 2;
case Algorithm::CN_HALF: return algo_perf[Algorithm::CN_R] * 2;
case Algorithm::CN_RWZ: return algo_perf[Algorithm::CN_R] / 3 * 4;
case Algorithm::CN_ZLS: return algo_perf[Algorithm::CN_R] / 3 * 4;
case Algorithm::CN_DOUBLE: return algo_perf[Algorithm::CN_R] / 2;
case Algorithm::CN_LITE_0: return algo_perf[Algorithm::CN_LITE_1];
case Algorithm::CN_PICO_TLO: return algo_perf[Algorithm::CN_PICO_0];
case Algorithm::RX_SFX: return algo_perf[Algorithm::RX_0];
case Algorithm::RX_XEQ: return algo_perf[Algorithm::RX_ARQ];
default: return algo_perf[algo];
}
}

// start performance measurements for specified perf bench_algo
void MoBenchmark::start(const BenchAlgo bench_algo) {
// start performance measurements for bench_algos[m_bench_algo]
void MoBenchmark::start() {
const Algorithm algo(bench_algos[m_bench_algo]);
if (algo_perf[algo.id()] > 0.0f) {
run_next_bench_algo();
return;
}
// calculate number of active miner backends in m_enabled_backend_count
m_enabled_backend_count = 0;
const Algorithm algo(ba2a[bench_algo]);
for (auto backend : m_controller->miner()->backends()) if (backend->isEnabled() && backend->isEnabled(algo)) ++ m_enabled_backend_count;
if (m_enabled_backend_count == 0) {
run_next_bench_algo(bench_algo);
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " is skipped due to a disabled backend"), Tags::benchmark(), algo.name());
run_next_bench_algo();
return;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Preparation "), Tags::benchmark(), algo.name());
// prepare test job for benchmark runs ("benchmark" client id is to make sure we can detect benchmark jobs)
Job& job = *m_bench_job[bench_algo];
job.setId(algo.name()); // need to set different id so that workers will see job change
switch(bench_algo) {
case BenchAlgo::KAWPOW_RVN:
job.setBlob("4c38e8a5f7b2944d1e4274635d828519b97bc64a1f1c7896ecdbb139988aa0e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
job.setDiff(Job::toDiff(strtoull("000000639c000000", nullptr, 16)));
job.setHeight(1500000);
m_bench_job = Job(false, Algorithm(bench_algos[m_bench_algo]), "benchmark");
m_bench_job.setId(algo.name()); // need to set different id so that workers will see job change
switch (algo.id()) {
case Algorithm::KAWPOW_RVN:
m_bench_job.setBlob("4c38e8a5f7b2944d1e4274635d828519b97bc64a1f1c7896ecdbb139989aa0e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
m_bench_job.setDiff(Job::toDiff(strtoull("000000639c000000", nullptr, 16)));
m_bench_job.setHeight(1500000);
break;

case BenchAlgo::GHOSTRIDER_RTM:
case BenchAlgo::FLEX_KCN:
job.setBlob("000000208c246d0b90c3b389c4086e8b672ee040d64db5b9648527133e217fbfa48da64c0f3c0a0b0e8350800568b40fbb323ac3ccdf2965de51b9aaeb939b4f11ff81c49b74a16156ff251c00000000");
job.setDiff(1000);
case Algorithm::GHOSTRIDER_RTM:
case Algorithm::FLEX_KCN:
m_bench_job.setBlob("000000208c246d0b90c3b389c4086e8b672ee040d64db5b9648527133e217fbfa48da64c0f3c0a0b0e8350800568b40fbb323ac3ccdf2965de51b9aaeb939b4f11ff81c49b74a16156ff251c00000000");
m_bench_job.setDiff(1000);
break;

default:
// 99 here to trigger all future bench_algo versions for auto veriant detection based on block version
job.setBlob("9905A0DBD6BF05CF16E503F3A66F78007CBF34144332ECBFC22ED95C8700383B309ACE1923A0964B00000008BA939A62724C0D7581FCE5761E9D8A0E6A1C3F924FDD8493D1115649C05EB601");
job.setTarget("FFFFFFFFFFFFFF20"); // set difficulty to 8 cause onJobResult after every 8-th computed hash
job.setHeight(1000);
job.setSeedHash("0000000000000000000000000000000000000000000000000000000000000001");
m_bench_job.setBlob("9905A0DBD6BF05CF16E503F3A66F78007CBF34144332ECBFC22ED95C8700383B309ACE1923A0964B00000008BA939A62724C0D7581FCE5761E9D8A0E6A1C3F924FDD8493D1115649C05EB601");
m_bench_job.setTarget("FFFFFFFFFFFFFF20"); // set difficulty to 8 cause onJobResult after every 8-th computed hash
m_bench_job.setHeight(1000);
m_bench_job.setSeedHash("0000000000000000000000000000000000000000000000000000000000000001");
}
m_bench_algo = bench_algo; // current perf bench_algo
m_hash_count = 0; // number of hashes calculated for current perf bench_algo
m_time_start = 0; // init time of the first result (in ms) during the first onJobResult
m_bench_start = 0; // init time of measurements start (in ms) during the first onJobResult
m_backends_started.clear();
m_controller->miner()->setJob(job, false); // set job for workers to compute
m_controller->miner()->setJob(m_bench_job, false); // set job for workers to compute
}

// run next bench algo or finish benchmark for the last one
void MoBenchmark::run_next_bench_algo(const BenchAlgo bench_algo) {
const BenchAlgo next_bench_algo = static_cast<BenchAlgo>(bench_algo + 1); // compute next perf bench_algo to benchmark
if (next_bench_algo != BenchAlgo::MAX) {
start(next_bench_algo);
void MoBenchmark::run_next_bench_algo() {
++ m_bench_algo;
if (bench_algos[m_bench_algo] != Algorithm::INVALID) {
start();
} else {
finish();
}
Expand All @@ -203,16 +188,17 @@ void MoBenchmark::onJobResult(const JobResult& result) {
static_cast<IJobResultListener*>(m_controller->network())->onJobResult(result);
return;
}
const Algorithm algo(bench_algos[m_bench_algo]);
// ignore benchmark results for other perf bench_algo
if (m_bench_algo == BenchAlgo::INVALID || result.jobId != String(Algorithm(ba2a[m_bench_algo]).name())) return;
if (algo.id() == Algorithm::INVALID || result.jobId != String(algo.name())) return;
const uint64_t now = get_now();
if (!m_time_start) m_time_start = now; // time of the first result (in ms)
m_backends_started.insert(result.backend);
// waiting for all backends to start
if (m_backends_started.size() < m_enabled_backend_count && (now - m_time_start < static_cast<unsigned>(3*60*1000))) return;
++ m_hash_count;
if (!m_bench_start) {
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Starting test "), Tags::benchmark(), Algorithm(ba2a[m_bench_algo]).name());
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Starting test "), Tags::benchmark(), algo.name());
m_bench_start = now; // time of measurements start (in ms)
} else if (now - m_bench_start > static_cast<unsigned>(m_controller->config()->benchAlgoTime()*1000)) { // end of benchmark round for m_bench_algo
double t[3] = { 0.0 };
Expand All @@ -228,16 +214,15 @@ void MoBenchmark::onJobResult(const JobResult& result) {
if (!(hashrate = t[1]))
if (!(hashrate = t[0]))
hashrate = static_cast<double>(m_hash_count) * result.diff / (now - m_bench_start) * 1000.0f;
if (m_bench_algo == KAWPOW_RVN) hashrate /= ((double)0xFFFFFFFFFFFFFFFF) / 0xFF000000;
m_bench_algo_perf[m_bench_algo] = hashrate; // store hashrate result
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " hashrate: " CYAN_BOLD_S "%f "), Tags::benchmark(), Algorithm(ba2a[m_bench_algo]).name(), hashrate);
run_next_bench_algo(m_bench_algo);
} else switch(m_bench_algo) { // Update GhostRider algo job to produce more accurate perf results
case BenchAlgo::GHOSTRIDER_RTM: {
Job& job = *m_bench_job[m_bench_algo];
uint8_t* blob = job.blob();
if (algo.id() == Algorithm::KAWPOW_RVN) hashrate /= ((double)0xFFFFFFFFFFFFFFFF) / 0xFF000000;
algo_perf[algo.id()] = hashrate; // store hashrate result
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " hashrate: " CYAN_BOLD_S "%f "), Tags::benchmark(), algo.name(), hashrate);
run_next_bench_algo();
} else switch (algo.id()) { // Update GhostRider algo job to produce more accurate perf results
case Algorithm::GHOSTRIDER_RTM: {
uint8_t* blob = m_bench_job.blob();
++ *reinterpret_cast<uint32_t*>(blob+4);
m_controller->miner()->setJob(job, false);
m_controller->miner()->setJob(m_bench_job, false);
break;
}
default:;
Expand Down
Loading

0 comments on commit a936d10

Please sign in to comment.