Skip to content

Commit

Permalink
Rename benchmark -> perfchk everywhere (to avoid new upstream feature)
Browse files Browse the repository at this point in the history
  • Loading branch information
Spudz76 committed Oct 19, 2020
1 parent 5676105 commit 810aa70
Show file tree
Hide file tree
Showing 18 changed files with 326 additions and 323 deletions.
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (on
option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL backend enabled)" ON)
option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)
option(WITH_BENCHMARK "Enable Benchmark module and algo-perf feature (for MoneroOcean)" ON)
option(WITH_PROFILING "Enable profiling for developers" OFF)
option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON)
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
option(WITH_PERFCHK "Enable PerfChk module and algo-perf feature (for MoneroOcean)" ON)

option(BUILD_STATIC "Build static binary" OFF)
option(ARM_TARGET "Force use specific ARM target 8 or 7" 0)
Expand Down Expand Up @@ -124,11 +124,11 @@ set(SOURCES_CRYPTO
src/crypto/common/VirtualMemory.cpp
)

if (WITH_BENCHMARK)
if (WITH_PERFCHK)
list(APPEND SOURCES
src/core/MoBenchmark.cpp
src/3rdparty/moneroocean/PerfChk.cpp
)
add_definitions(/DXMRIG_FEATURE_BENCHMARK)
add_definitions(/DXMRIG_FEATURE_PERFCHK)
endif()

if (WITH_HWLOC)
Expand Down
230 changes: 230 additions & 0 deletions src/3rdparty/moneroocean/PerfChk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/* XMRig
* Copyright 2018-2020 MoneroOcean <https://github.com/MoneroOcean>, <[email protected]>
*
* 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 "3rdparty/moneroocean/PerfChk.h"
#include "3rdparty/rapidjson/document.h"
#include "backend/common/Hashrate.h"
#include "backend/common/interfaces/IBackend.h"
#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"
#include "net/JobResult.h"
#include "net/JobResults.h"
#include "net/Network.h"

#include <chrono>

namespace xmrig {

PerfChk::PerfChk() : m_controller(nullptr), m_isNewPerfChkRun(true) {
for (PerfChkAlgo perfchk_algo = PerfChkAlgo::MIN; perfchk_algo != PerfChkAlgo::MAX; perfchk_algo = static_cast<PerfChkAlgo>(perfchk_algo + 1)) {
m_perfchk_job[perfchk_algo] = new Job(false, Algorithm(ba2a[perfchk_algo]), "perfchk");
}
}

PerfChk::~PerfChk() {
for (PerfChkAlgo perfchk_algo = PerfChkAlgo::MIN; perfchk_algo != PerfChkAlgo::MAX; perfchk_algo = static_cast<PerfChkAlgo>(perfchk_algo + 1)) {
delete m_perfchk_job[perfchk_algo];
}
}

// start performance measurements from the first perfchk_algo
void PerfChk::start() {
JobResults::setListener(this, m_controller->config()->cpu().isHwAES()); // register perfchk as job result listener to compute hashrates there
// write text before first perfchk round
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " STARTING ALGO PERFORMANCE CHECK (with " MAGENTA_BOLD_S "%i" CYAN_BOLD_S " seconds round) "), Tags::perfchk(), m_controller->config()->perfChkAlgoTime());
// start perfchking from first PerfAlgo in the list
start(PerfChkAlgo::MIN);
m_isNewPerfChkRun = true;
}

// end of perfchks, switch to jobs from the pool (network), fill algo_perf
void PerfChk::finish() {
for (Algorithm::Id algo = Algorithm::MIN; algo != Algorithm::MAX; algo = static_cast<Algorithm::Id>(algo + 1)) {
algo_perf[algo] = get_algo_perf(algo);
}
m_perfchk_algo = PerfChkAlgo::INVALID;
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " ALGO PERFORMANCE CHECK COMPLETE "), Tags::perfchk());
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();
}

rapidjson::Value PerfChk::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();

Value obj(kObjectType);

for (const auto &a : m_controller->miner()->algorithms()) {
obj.AddMember(StringRef(a.shortName()), algo_perf[a.id()], allocator);
}

return obj;
}

void PerfChk::read(const rapidjson::Value &value)
{
for (Algorithm::Id algo = Algorithm::MIN; algo != Algorithm::MAX; algo = static_cast<Algorithm::Id>(algo + 1)) {
algo_perf[algo] = 0.0f;
}
if (value.IsObject()) {
for (auto &member : value.GetObject()) {
const Algorithm algo(member.name.GetString());
if (!algo.isValid()) {
LOG_INFO("%s " BRIGHT_BLACK_BG(MAGENTA_BOLD_S " Ignoring wrong name for algo-perf[%s] "), Tags::perfchk(), member.name.GetString());
continue;
}
if (member.value.IsFloat()) {
algo_perf[algo.id()] = member.value.GetFloat();
m_isNewPerfChkRun = false;
continue;
}
if (member.value.IsInt()) {
algo_perf[algo.id()] = member.value.GetInt();
m_isNewPerfChkRun = false;
continue;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(MAGENTA_BOLD_S " Ignoring wrong value for algo-perf[%s] "), Tags::perfchk(), member.name.GetString());
}
}
}

double PerfChk::get_algo_perf(Algorithm::Id algo) const {
switch (algo) {
case Algorithm::CN_CCX: return m_perfchk_algo_perf[PerfChkAlgo::CN_CCX];
case Algorithm::CN_0: return m_perfchk_algo_perf[PerfChkAlgo::CN_CCX] / 2;
case Algorithm::CN_1: return m_perfchk_algo_perf[PerfChkAlgo::CN_R];
case Algorithm::CN_2: return m_perfchk_algo_perf[PerfChkAlgo::CN_R];
case Algorithm::CN_R: return m_perfchk_algo_perf[PerfChkAlgo::CN_R];
case Algorithm::CN_RTO: return m_perfchk_algo_perf[PerfChkAlgo::CN_R];
case Algorithm::CN_XAO: return m_perfchk_algo_perf[PerfChkAlgo::CN_R];
case Algorithm::CN_FAST: return m_perfchk_algo_perf[PerfChkAlgo::CN_R] * 2;
case Algorithm::CN_HALF: return m_perfchk_algo_perf[PerfChkAlgo::CN_R] * 2;
case Algorithm::CN_RWZ: return m_perfchk_algo_perf[PerfChkAlgo::CN_R] / 3 * 4;
case Algorithm::CN_ZLS: return m_perfchk_algo_perf[PerfChkAlgo::CN_R] / 3 * 4;
case Algorithm::CN_DOUBLE: return m_perfchk_algo_perf[PerfChkAlgo::CN_R] / 2;
case Algorithm::CN_LITE_0: return m_perfchk_algo_perf[PerfChkAlgo::CN_LITE_1];
case Algorithm::CN_LITE_1: return m_perfchk_algo_perf[PerfChkAlgo::CN_LITE_1];
case Algorithm::CN_HEAVY_0: return m_perfchk_algo_perf[PerfChkAlgo::CN_HEAVY_TUBE];
case Algorithm::CN_HEAVY_TUBE: return m_perfchk_algo_perf[PerfChkAlgo::CN_HEAVY_TUBE];
case Algorithm::CN_HEAVY_XHV: return m_perfchk_algo_perf[PerfChkAlgo::CN_HEAVY_XHV];
case Algorithm::CN_PICO_0: return m_perfchk_algo_perf[PerfChkAlgo::CN_PICO_0];
case Algorithm::CN_PICO_TLO: return m_perfchk_algo_perf[PerfChkAlgo::CN_PICO_0];
case Algorithm::CN_GPU: return m_perfchk_algo_perf[PerfChkAlgo::CN_GPU];
case Algorithm::AR2_CHUKWA: return m_perfchk_algo_perf[PerfChkAlgo::AR2_CHUKWA];
case Algorithm::AR2_WRKZ: return m_perfchk_algo_perf[PerfChkAlgo::AR2_WRKZ];
case Algorithm::ASTROBWT_DERO: return m_perfchk_algo_perf[PerfChkAlgo::ASTROBWT_DERO];
case Algorithm::RX_0: return m_perfchk_algo_perf[PerfChkAlgo::RX_0];
case Algorithm::RX_LOKI: return m_perfchk_algo_perf[PerfChkAlgo::RX_0];
case Algorithm::RX_SFX: return m_perfchk_algo_perf[PerfChkAlgo::RX_0];
case Algorithm::RX_WOW: return m_perfchk_algo_perf[PerfChkAlgo::RX_WOW];
case Algorithm::RX_ARQ: return m_perfchk_algo_perf[PerfChkAlgo::RX_ARQ];
case Algorithm::RX_KEVA: return m_perfchk_algo_perf[PerfChkAlgo::RX_KEVA];
case Algorithm::RX_XLA: return m_perfchk_algo_perf[PerfChkAlgo::RX_XLA];
default: return 0.0f;
}
}

// start performance measurements for specified perf perfchk_algo
void PerfChk::start(const PerfChkAlgo perfchk_algo) {
// calculate number of active miner backends in m_enabled_backend_count
m_enabled_backend_count = 0;
const Algorithm algo(ba2a[perfchk_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_perfchk_algo(perfchk_algo);
return;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Preparation "), Tags::perfchk(), algo.shortName());
// prepare test job for perfchk runs ("perfchk" client id is to make sure we can detect perfchk jobs)
Job& job = *m_perfchk_job[perfchk_algo];
job.setId(algo.shortName()); // need to set different id so that workers will see job change
// 99 here to trigger all future perfchk_algo versions for auto variant 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_perfchk_algo = perfchk_algo; // current perf perfchk_algo
m_hash_count = 0; // number of hashes calculated for current perf perfchk_algo
m_time_start = 0; // init time of the first result (in ms) during the first onJobResult
m_perfchk_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
}

// run next perfchk algo or finish perfchk for the last one
void PerfChk::run_next_perfchk_algo(const PerfChkAlgo perfchk_algo) {
const PerfChkAlgo next_perfchk_algo = static_cast<PerfChkAlgo>(perfchk_algo + 1); // compute next perf perfchk_algo to perfchk
if (next_perfchk_algo != PerfChkAlgo::MAX) {
start(next_perfchk_algo);
} else {
finish();
}
}

void PerfChk::onJobResult(const JobResult& result) {
if (result.clientId != String("perfchk")) { // switch to network pool jobs
JobResults::setListener(m_controller->network(), m_controller->config()->cpu().isHwAES());
static_cast<IJobResultListener*>(m_controller->network())->onJobResult(result);
return;
}
// ignore perfchk results for other perf perfchk_algo
if (m_perfchk_algo == PerfChkAlgo::INVALID || result.jobId != String(Algorithm(ba2a[m_perfchk_algo]).shortName())) 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_perfchk_start) {
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Starting test "), Tags::perfchk(), Algorithm(ba2a[m_perfchk_algo]).shortName());
m_perfchk_start = now; // time of measurements start (in ms)
} else if (now - m_perfchk_start > static_cast<unsigned>(m_controller->config()->perfChkAlgoTime()*1000)) { // end of perfchk round for m_perfchk_algo
double t[3] = { 0.0 };
for (auto backend : m_controller->miner()->backends()) {
const Hashrate *hr = backend->hashrate();
if (!hr) {
continue;
}
t[0] += hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval);
}
double hashrate = 0.0f;
if (!(hashrate = t[2]))
if (!(hashrate = t[1]))
if (!(hashrate = t[0]))
hashrate = static_cast<double>(m_hash_count) * result.diff / (now - m_perfchk_start) * 1000.0f;
m_perfchk_algo_perf[m_perfchk_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::perfchk(), Algorithm(ba2a[m_perfchk_algo]).shortName(), hashrate);
run_next_perfchk_algo(m_perfchk_algo);
}
}

uint64_t PerfChk::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();
}

} // namespace xmrig
50 changes: 25 additions & 25 deletions src/core/MoBenchmark.h → src/3rdparty/moneroocean/PerfChk.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ class Controller;
class Miner;
class Job;

class MoBenchmark : public IJobResultListener {
class PerfChk : public IJobResultListener {

enum BenchAlgo : int {
enum PerfChkAlgo : int {
CN_R, // "cn/r" CryptoNightR (Monero's variant 4).
CN_LITE_1, // "cn-lite/1" CryptoNight-Lite variant 1.
CN_HEAVY_TUBE, // "cn-heavy/tube" CryptoNight-Heavy (modified, TUBE only).
Expand All @@ -49,7 +49,7 @@ class MoBenchmark : public IJobResultListener {
INVALID = -1,
};

const Algorithm::Id ba2a[BenchAlgo::MAX] = {
const Algorithm::Id ba2a[PerfChkAlgo::MAX] = {
Algorithm::CN_R,
Algorithm::CN_LITE_1,
Algorithm::CN_HEAVY_TUBE,
Expand All @@ -65,34 +65,34 @@ class MoBenchmark : public IJobResultListener {
Algorithm::RX_XLA,
};

Job* m_bench_job[BenchAlgo::MAX];
double m_bench_algo_perf[BenchAlgo::MAX];

Controller* m_controller; // to get access to config and network
bool m_isNewBenchRun; // true if benchmark is need to be executed or was executed
MoBenchmark::BenchAlgo m_bench_algo; // 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 the first resultt for current perf algo (in ms)
uint64_t m_bench_start; // time of measurements start for current perf algo (in ms) after all backends are started
unsigned m_enabled_backend_count; // number of active miner backends
std::set<uint32_t> m_backends_started; // id of backend started for benchmark

uint64_t get_now() const; // get current time in ms
double get_algo_perf(Algorithm::Id algo) const; // get algo perf based on m_bench_algo_perf
void start(const MoBenchmark::BenchAlgo); // start benchmark for specified perf algo
void finish(); // end of benchmarks, switch to jobs from the pool (network), fill algo_perf
void onJobResult(const JobResult&) override; // onJobResult is called after each computed benchmark hash
void run_next_bench_algo(BenchAlgo); // run next bench algo or finish benchmark for the last one
Job* m_perfchk_job[PerfChkAlgo::MAX];
double m_perfchk_algo_perf[PerfChkAlgo::MAX];

Controller* m_controller; // to get access to config and network
bool m_isNewPerfChkRun; // true if perfchk is need to be executed or was executed
PerfChk::PerfChkAlgo m_perfchk_algo; // current perf algo we perfchk
uint64_t m_hash_count; // number of hashes calculated for current perf algo
uint64_t m_time_start; // time of the first resultt for current perf algo (in ms)
uint64_t m_perfchk_start; // time of measurements start for current perf algo (in ms) after all backends are started
unsigned m_enabled_backend_count; // number of active miner backends
std::set<uint32_t> m_backends_started; // id of backend started for perfchk

uint64_t get_now() const; // get current time in ms
double get_algo_perf(Algorithm::Id algo) const; // get algo perf based on m_perfchk_algo_perf
void start(const PerfChk::PerfChkAlgo); // start perfchk for specified perf algo
void finish(); // end of perfchks, switch to jobs from the pool (network), fill algo_perf
void onJobResult(const JobResult&) override; // onJobResult is called after each computed perfchk hash
void run_next_perfchk_algo(PerfChkAlgo); // run next perfchk algo or finish perfchk for the last one

public:
MoBenchmark();
virtual ~MoBenchmark();
PerfChk();
virtual ~PerfChk();

void set_controller(Controller* controller) { m_controller = controller; }

void start(); // start benchmarks
void start(); // start perfchks

bool isNewBenchRun() const { return m_isNewBenchRun; }
bool isNewPerfChkRun() const { return m_isNewPerfChkRun; }
double algo_perf[Algorithm::MAX];

rapidjson::Value toJSON(rapidjson::Document &doc) const;
Expand Down
8 changes: 4 additions & 4 deletions src/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ int xmrig::App::exec()
return 0;
}

# ifdef XMRIG_FEATURE_BENCHMARK
# ifdef XMRIG_FEATURE_PERFCHK
m_controller->pre_start();
m_controller->config()->benchmark().set_controller(m_controller);
m_controller->config()->perfchk().set_controller(m_controller);

if (m_controller->config()->benchmark().isNewBenchRun() || m_controller->config()->isRebenchAlgo()) {
m_controller->config()->benchmark().start();
if (m_controller->config()->perfchk().isNewPerfChkRun() || m_controller->config()->isReChkAlgo()) {
m_controller->config()->perfchk().start();
} else {
m_controller->start();
}
Expand Down
6 changes: 3 additions & 3 deletions src/base/io/log/Tags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ const char *xmrig::Tags::opencl()
#endif


#ifdef XMRIG_FEATURE_BENCHMARK
const char *xmrig::Tags::benchmark()
#ifdef XMRIG_FEATURE_PERFCHK
const char *xmrig::Tags::perfchk()
{
static const char *tag = BRIGHT_BLACK_BG(CYAN_BOLD_S " benchmk ");
static const char *tag = BRIGHT_BLACK_BG(CYAN_BOLD_S " perfchk ");

return tag;
}
Expand Down
4 changes: 2 additions & 2 deletions src/base/io/log/Tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class Tags
static const char *opencl();
# endif

# ifdef XMRIG_FEATURE_BENCHMARK
static const char *benchmark();
# ifdef XMRIG_FEATURE_PERFCHK
static const char *perfchk();
# endif

# ifdef XMRIG_FEATURE_PROFILING
Expand Down
Loading

0 comments on commit 810aa70

Please sign in to comment.