Added algo performance calibration (benchmarking) functionality

This commit is contained in:
MoneroOcean 2018-07-18 16:49:09 +02:00
parent a8d399e450
commit 9951bd756d
9 changed files with 244 additions and 1 deletions

View file

@ -56,6 +56,7 @@ set(HEADERS
src/net/strategies/DonateStrategy.h src/net/strategies/DonateStrategy.h
src/Summary.h src/Summary.h
src/version.h src/version.h
src/workers/Benchmark.h
src/workers/CpuThread.h src/workers/CpuThread.h
src/workers/Handle.h src/workers/Handle.h
src/workers/Hashrate.h src/workers/Hashrate.h
@ -110,6 +111,7 @@ set(SOURCES
src/net/Network.cpp src/net/Network.cpp
src/net/strategies/DonateStrategy.cpp src/net/strategies/DonateStrategy.cpp
src/Summary.cpp src/Summary.cpp
src/workers/Benchmark.cpp
src/workers/CpuThread.cpp src/workers/CpuThread.cpp
src/workers/Handle.cpp src/workers/Handle.cpp
src/workers/Hashrate.cpp src/workers/Hashrate.cpp

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -40,6 +41,7 @@
#include "Summary.h" #include "Summary.h"
#include "version.h" #include "version.h"
#include "workers/Workers.h" #include "workers/Workers.h"
#include "workers/Benchmark.h"
#ifndef XMRIG_NO_HTTPD #ifndef XMRIG_NO_HTTPD
@ -84,6 +86,8 @@ App::~App()
# endif # endif
} }
// this should be global since we register onJobResult using this object method
static Benchmark benchmark;
int App::exec() int App::exec()
{ {
@ -125,7 +129,16 @@ int App::exec()
Workers::start(m_controller); Workers::start(m_controller);
m_controller->network()->connect(); // run benchmark before pool mining or not?
if (m_controller->config()->isCalibrateAlgo()) {
benchmark.set_controller(m_controller); // we need controller there to access config and network objects
Workers::setListener(&benchmark); // register benchmark as job reault listener to compute hashrates there
benchmark.start_perf_bench(xmrig::PerfAlgo::PA_CN); // start benchmarking from first PerfAlgo in the list
} else {
// save config here to have option to store automatically generated "threads"
if (m_controller->config()->isSaveConfig()) m_controller->config()->save();
m_controller->network()->connect();
}
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop()); uv_loop_close(uv_default_loop());

View file

@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -120,6 +121,12 @@ bool Job::setBlob(const char *blob)
return true; return true;
} }
// for algo benchmarking
void Job::setRawBlob(const uint8_t *blob, const size_t size)
{
memcpy(m_blob, blob, m_size = size);
}
bool Job::setTarget(const char *target) bool Job::setTarget(const char *target)
{ {

View file

@ -7,6 +7,7 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -42,7 +43,10 @@ public:
~Job(); ~Job();
bool setBlob(const char *blob); bool setBlob(const char *blob);
void setRawBlob(const uint8_t *blob, const size_t size); // for algo benchmarking
bool setTarget(const char *target); bool setTarget(const char *target);
// for algo benchmarking to set PoW variant
void setAlgorithm(const xmrig::Algorithm& algorithm) { m_algorithm = algorithm; }
xmrig::Variant variant() const; xmrig::Variant variant() const;
inline bool isNicehash() const { return m_nicehash; } inline bool isNicehash() const { return m_nicehash; }

View file

@ -33,6 +33,12 @@
"retry-pause": 5, "retry-pause": 5,
"safe": false, "safe": false,
"threads": null, "threads": null,
"algo-perf": {
"cn": 1000,
"cn-fast": 2000,
"cn-lite": 2000,
"cn-heavy": 700
},
"user-agent": null, "user-agent": null,
"watch": false "watch": false
} }

92
src/workers/Benchmark.cpp Normal file
View file

@ -0,0 +1,92 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "workers/Benchmark.h"
#include "workers/Workers.h"
#include "core/Config.h"
#include "net/Network.h"
#include "common/log/Log.h"
#include <chrono>
// start performance measurements for specified perf algo
void Benchmark::start_perf_bench(const xmrig::PerfAlgo pa) {
m_pa = pa; // current perf algo
m_hash_count = 0; // number of hashes calculated for current perf algo
m_time_start = get_now(); // time of measurements start (in ms)
Workers::switch_algo(xmrig::Algorithm(pa)); // switch workers to new algo (Algo part)
// prepare test job for benchmark runs
Job job;
job.setId(xmrig::Algorithm::perfAlgoName(pa)); // need to set different id so that workers will see job change
const static uint8_t test_input[76] = {
0x99, // 0x99 here to trigger all future algo versions for auto veriant detection based on block version
0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01,
};
job.setRawBlob(test_input, 76);
job.setTarget("FFFFFFFFFFFFFFFF"); // set difficulty to 1 to get to onJobResult after every computed hash
job.setAlgorithm(xmrig::Algorithm(pa)); // set job algo (for Variant part)
if (!m_is_benchmark_time) { // write test before first benchmark round
Log::i()->text(m_controller->config()->isColors()
? GREEN_BOLD(" >>>>> ") WHITE_BOLD("STARTING ALGO PERFORMANCE CALIBRATION")
: " >>>>> STARTING ALGO PERFORMANCE CALIBRATION"
);
}
m_is_benchmark_time = true; // benchmarking is in process
Workers::setJob(job, false); // set job for workers to compute
}
void Benchmark::onJobResult(const JobResult& result) {
if (!m_is_benchmark_time) return; // ignore job results if we already stopeed benchmarking (before new job from the pool comes)
++ m_hash_count;
const uint64_t now = get_now();
if (now - m_time_start > m_bench_secs*1000) { // end of becnhmark round for m_pa
const float hashrate = static_cast<float>(m_hash_count) / (now - m_time_start) * 1000.0f;
m_controller->config()->set_algo_perf(m_pa, hashrate); // store hashrate result
Log::i()->text(m_controller->config()->isColors()
? GREEN_BOLD(" ===> ") CYAN_BOLD("%s") WHITE_BOLD(" hashrate: ") CYAN_BOLD("%f")
: " ===> %s hasrate: %f",
xmrig::Algorithm::perfAlgoName(m_pa),
hashrate
);
const xmrig::PerfAlgo pa = static_cast<xmrig::PerfAlgo>(m_pa + 1); // compute next perf algo to benchmark
if (pa != xmrig::PerfAlgo::PA_MAX) {
start_perf_bench(pa);
} else { // en of benchmarks and switching to jobs from the pool (network)
m_is_benchmark_time = false;
if (m_controller->config()->isSaveConfig()) m_controller->config()->save(); // save config with measured algo-perf
Workers::pause(); // do not compute anything before job from the pool
Workers::setListener(m_controller->network());
m_controller->network()->connect();
}
}
}
uint64_t Benchmark::get_now() const { // get current time in ms
using namespace std::chrono;
return time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
}

51
src/workers/Benchmark.h Normal file
View file

@ -0,0 +1,51 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include "common/xmrig.h"
#include "interfaces/IJobResultListener.h"
#include "core/Controller.h"
class Benchmark : public IJobResultListener {
const uint64_t m_bench_secs = 5; // time in seconds to benchmark each perf algo
bool m_is_benchmark_time; // true is we benchmark some perf algo now
xmrig::PerfAlgo m_pa; // current perf algo we benchmark
uint64_t m_hash_count; // number of hashes calculated for current perf algo
uint64_t m_time_start; // time of measurements start for current perf algo (in ms)
xmrig::Controller* m_controller; // to get access to config and network
uint64_t get_now() const; // get current time in ms
void onJobResult(const JobResult&) override; // onJobResult is called after each computed benchmark hash
public:
Benchmark() : m_is_benchmark_time(false) {}
virtual ~Benchmark() {}
void set_controller(xmrig::Controller* controller) { m_controller = controller; }
void start_perf_bench(const xmrig::PerfAlgo); // start benchmark for specified perf algo
};

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -194,6 +195,69 @@ void Workers::start(xmrig::Controller *controller)
} }
} }
void Workers::soft_stop() // stop current workers leaving uv stuff intact (used in switch_algo)
{
if (m_hashrate) {
m_hashrate->stop();
delete m_hashrate;
}
m_sequence = 0;
m_paused = 0;
for (size_t i = 0; i < m_workers.size(); ++i) {
m_workers[i]->join();
delete m_workers[i];
}
m_workers.clear();
}
// setups workers based on specified algorithm (or its basic perf algo more specifically)
void Workers::switch_algo(const xmrig::Algorithm algorithm)
{
if (m_status.algo == algorithm.algo()) return;
soft_stop();
m_sequence = 1;
m_paused = 1;
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads(algorithm.perf_algo());
m_status.algo = algorithm.algo();
m_status.threads = threads.size();
// string with multiway thread info
std::string str_threads;
for (const xmrig::IThread *thread : threads) {
if (!str_threads.empty()) str_threads = str_threads + ", ";
str_threads = str_threads + "x" + std::to_string(thread->multiway());
}
Log::i()->text(m_controller->config()->isColors()
? GREEN_BOLD(" >>> ") WHITE_BOLD("ALGO CHANGE: ") CYAN_BOLD("%s") ", " CYAN_BOLD("%d (%s)") " thread(s)"
: " >>> ALGO CHANGE: %s, %d (%s) thread(s)",
algorithm.name(),
threads.size(),
str_threads.c_str()
);
m_status.ways = 0;
for (const xmrig::IThread *thread : threads) {
m_status.ways += thread->multiway();
}
m_hashrate = new Hashrate(threads.size(), m_controller);
uint32_t offset = 0;
for (xmrig::IThread *thread : threads) {
Handle *handle = new Handle(thread, offset, m_status.ways);
offset += thread->multiway();
m_workers.push_back(handle);
handle->start(Workers::onReady);
}
}
void Workers::stop() void Workers::stop()
{ {

View file

@ -6,6 +6,7 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com> * Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -56,6 +57,8 @@ public:
static void setEnabled(bool enabled); static void setEnabled(bool enabled);
static void setJob(const Job &job, bool donate); static void setJob(const Job &job, bool donate);
static void start(xmrig::Controller *controller); static void start(xmrig::Controller *controller);
// setups workers based on specified algorithm (or its basic perf algo more specifically)
static void switch_algo(xmrig::Algorithm);
static void stop(); static void stop();
static void submit(const JobResult &result); static void submit(const JobResult &result);
@ -76,6 +79,7 @@ private:
static void onResult(uv_async_t *handle); static void onResult(uv_async_t *handle);
static void onTick(uv_timer_t *handle); static void onTick(uv_timer_t *handle);
static void start(IWorker *worker); static void start(IWorker *worker);
static void soft_stop(); // stop current workers leaving uv stuff intact (used in switch_algo)
class LaunchStatus class LaunchStatus
{ {