Implemented static benchmark verification (--bench --seed --hash)

This commit is contained in:
XMRig 2020-10-24 13:53:49 +07:00
parent 027a6f8ae2
commit 36c1cb23e0
No known key found for this signature in database
GPG key ID: 446A53638BE94409
14 changed files with 220 additions and 107 deletions

View file

@ -21,6 +21,7 @@
#include "backend/common/interfaces/IWorker.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Chrono.h"
@ -39,6 +40,17 @@ static uint64_t hashCheck[2][10] = {
} // namespace xmrig
xmrig::Benchmark::Benchmark(const Job &job, size_t workers, const IBackend *backend) :
m_algo(job.algorithm()),
m_backend(backend),
m_workers(workers),
m_token(job.benchToken()),
m_end(job.benchSize()),
m_hash(job.benchHash())
{
}
bool xmrig::Benchmark::finish(uint64_t totalHashCount)
{
m_reset = true;
@ -48,13 +60,8 @@ bool xmrig::Benchmark::finish(uint64_t totalHashCount)
return false;
}
const double dt = (m_doneTime - m_startTime) / 1000.0;
uint64_t checkData = 0;
const uint32_t N = (m_end / 1000000) - 1;
if (((m_algo == Algorithm::RX_0) || (m_algo == Algorithm::RX_WOW)) && ((m_end % 1000000) == 0) && (N < 10)) {
checkData = hashCheck[(m_algo == Algorithm::RX_0) ? 0 : 1][N];
}
const double dt = static_cast<double>(m_doneTime - m_startTime) / 1000.0;
uint64_t checkData = referenceHash();
const char *color = checkData ? ((m_data == checkData) ? GREEN_BOLD_S : RED_BOLD_S) : BLACK_BOLD_S;
@ -77,7 +84,7 @@ void xmrig::Benchmark::printProgress() const
return;
}
const double dt = (Chrono::steadyMSecs() - m_startTime) / 1000.0;
const double dt = static_cast<double>(Chrono::steadyMSecs() - m_startTime) / 1000.0;
const double percent = static_cast<double>(m_current) / m_end * 100.0;
LOG_NOTICE("%s " MAGENTA_BOLD("%5.2f%% ") CYAN_BOLD("%" PRIu64) CYAN("/%" PRIu64) BLACK_BOLD(" (%.3fs)"), Tags::bench(), percent, m_current, m_end, dt);
@ -101,3 +108,18 @@ void xmrig::Benchmark::tick(IWorker *worker)
m_data ^= worker->benchData();
m_doneTime = std::max(doneTime, m_doneTime);
}
uint64_t xmrig::Benchmark::referenceHash() const
{
if (m_hash) {
return m_hash;
}
const uint32_t N = (m_end / 1000000) - 1;
if (((m_algo == Algorithm::RX_0) || (m_algo == Algorithm::RX_WOW)) && ((m_end % 1000000) == 0) && (N < 10)) {
return hashCheck[(m_algo == Algorithm::RX_0) ? 0 : 1][N];
}
return 0;
}

View file

@ -20,14 +20,17 @@
#define XMRIG_BENCHMARK_H
#include "base/tools/Object.h"
#include "base/crypto/Algorithm.h"
#include "base/tools/Object.h"
#include "base/tools/String.h"
namespace xmrig {
class IBackend;
class IWorker;
class Job;
class Benchmark
@ -35,7 +38,7 @@ class Benchmark
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Benchmark)
Benchmark(uint32_t end, const Algorithm &algo, size_t workers) : m_algo(algo), m_workers(workers), m_end(end) {}
Benchmark(const Job &job, size_t workers, const IBackend *backend);
~Benchmark() = default;
bool finish(uint64_t totalHashCount);
@ -44,10 +47,15 @@ public:
void tick(IWorker *worker);
private:
uint64_t referenceHash() const;
bool m_reset = false;
const Algorithm m_algo = Algorithm::RX_0;
const size_t m_workers = 0;
const uint64_t m_end = 0;
const Algorithm m_algo;
const IBackend *m_backend;
const size_t m_workers;
const String m_token;
const uint64_t m_end;
const uint64_t m_hash;
uint32_t m_done = 0;
uint64_t m_current = 0;
uint64_t m_data = 0;

View file

@ -87,13 +87,6 @@ xmrig::Workers<T>::~Workers()
}
template<class T>
xmrig::Benchmark *xmrig::Workers<T>::benchmark() const
{
return d_ptr->benchmark.get();
}
template<class T>
static void getHashrateData(xmrig::IWorker* worker, uint64_t& hashCount, uint64_t& timeStamp)
{
@ -168,41 +161,6 @@ void xmrig::Workers<T>::setBackend(IBackend *backend)
}
template<class T>
void xmrig::Workers<T>::start(const std::vector<T> &data)
{
# ifdef XMRIG_FEATURE_BENCHMARK
if (!data.empty() && data.front().benchSize) {
d_ptr->benchmark = std::make_shared<Benchmark>(data.front().benchSize, data.front().algorithm, data.size());
}
# endif
for (const T &item : data) {
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), item));
}
d_ptr->hashrate = std::make_shared<Hashrate>(m_workers.size());
Nonce::touch(T::backend());
for (Thread<T> *worker : m_workers) {
worker->start(Workers<T>::onReady);
# ifdef XMRIG_FEATURE_BENCHMARK
if (!d_ptr->benchmark)
# endif
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
# ifdef XMRIG_FEATURE_BENCHMARK
if (d_ptr->benchmark) {
d_ptr->benchmark->start();
}
# endif
}
template<class T>
void xmrig::Workers<T>::stop()
{
@ -219,6 +177,22 @@ void xmrig::Workers<T>::stop()
}
#ifdef XMRIG_FEATURE_BENCHMARK
template<class T>
void xmrig::Workers<T>::start(const std::vector<T> &data, const std::shared_ptr<Benchmark> &benchmark)
{
if (!benchmark) {
return start(data, true);
}
start(data, false);
d_ptr->benchmark = benchmark;
d_ptr->benchmark->start();
}
#endif
template<class T>
xmrig::IWorker *xmrig::Workers<T>::create(Thread<T> *)
{
@ -250,6 +224,29 @@ void xmrig::Workers<T>::onReady(void *arg)
}
template<class T>
void xmrig::Workers<T>::start(const std::vector<T> &data, bool sleep)
{
for (const auto &item : data) {
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), item));
}
d_ptr->hashrate = std::make_shared<Hashrate>(m_workers.size());
Nonce::touch(T::backend());
for (auto worker : m_workers) {
worker->start(Workers<T>::onReady);
// This sleep is important for optimal caching!
// Threads must allocate scratchpads in order so that adjacent cores will use adjacent scratchpads
// Sub-optimal caching can result in up to 0.5% hashrate penalty
if (sleep) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
}
namespace xmrig {

View file

@ -59,18 +59,24 @@ public:
Workers();
~Workers();
Benchmark *benchmark() const;
inline void start(const std::vector<T> &data) { start(data, true); }
bool tick(uint64_t ticks);
const Hashrate *hashrate() const;
void jobEarlyNotification(const Job&);
void setBackend(IBackend *backend);
void start(const std::vector<T> &data);
void stop();
# ifdef XMRIG_FEATURE_BENCHMARK
void start(const std::vector<T> &data, const std::shared_ptr<Benchmark> &benchmark);
# endif
private:
static IWorker *create(Thread<T> *handle);
static void onReady(void *arg);
void start(const std::vector<T> &data, bool sleep);
std::vector<Thread<T> *> m_workers;
WorkersPrivate *d_ptr;
};

View file

@ -138,10 +138,7 @@ private:
class CpuBackendPrivate
{
public:
inline CpuBackendPrivate(Controller *controller) :
controller(controller)
{
}
inline CpuBackendPrivate(Controller *controller) : controller(controller) {}
inline void start()
@ -155,7 +152,12 @@ public:
);
status.start(threads, algo.l3());
# ifdef XMRIG_FEATURE_BENCHMARK
workers.start(threads, benchmark);
# else
workers.start(threads);
# endif
}
@ -204,6 +206,10 @@ public:
std::vector<CpuLaunchData> threads;
String profileName;
Workers<CpuLaunchData> workers;
# ifdef XMRIG_FEATURE_BENCHMARK
std::shared_ptr<Benchmark> benchmark;
# endif
};
@ -338,7 +344,7 @@ void xmrig::CpuBackend::setJob(const Job &job)
return stop();
}
const CpuConfig &cpu = d_ptr->controller->config()->cpu();
const auto &cpu = d_ptr->controller->config()->cpu();
std::vector<CpuLaunchData> threads = cpu.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->controller->config()->pools().benchSize());
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
@ -356,6 +362,12 @@ void xmrig::CpuBackend::setJob(const Job &job)
stop();
# ifdef XMRIG_FEATURE_BENCHMARK
if (job.benchSize()) {
d_ptr->benchmark = std::make_shared<Benchmark>(job, threads.size(), this);
}
# endif
d_ptr->threads = std::move(threads);
d_ptr->start();
}
@ -469,15 +481,14 @@ void xmrig::CpuBackend::handleRequest(IApiRequest &request)
#ifdef XMRIG_FEATURE_BENCHMARK
xmrig::Benchmark *xmrig::CpuBackend::benchmark() const
{
return d_ptr->workers.benchmark();
return d_ptr->benchmark.get();
}
void xmrig::CpuBackend::printBenchProgress() const
{
auto benchmark = d_ptr->workers.benchmark();
if (benchmark) {
benchmark->printProgress();
if (d_ptr->benchmark) {
d_ptr->benchmark->printProgress();
}
}
#endif

View file

@ -34,6 +34,7 @@
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/http/Fetch.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpListener.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/tools/Buffer.h"
#include "base/tools/Timer.h"

View file

@ -27,8 +27,8 @@
#define XMRIG_DAEMONCLIENT_H
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "base/net/http/HttpListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/tools/Object.h"

View file

@ -174,6 +174,12 @@ void xmrig::Job::copy(const Job &other)
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
m_benchHash = other.m_benchHash;
m_benchToken = other.m_benchToken;
# endif
}
@ -205,4 +211,10 @@ void xmrig::Job::move(Job &&other)
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
m_benchHash = other.m_benchHash;
m_benchToken = std::move(other.m_benchToken);
# endif
}

View file

@ -111,6 +111,15 @@ public:
inline Job &operator=(const Job &other) { copy(other); return *this; }
inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; }
# ifdef XMRIG_FEATURE_BENCHMARK
inline const String &benchToken() const { return m_benchToken; }
inline uint32_t benchSize() const { return m_benchSize; }
inline uint64_t benchHash() const { return m_benchHash; }
inline void setBenchHash(uint64_t benchHash) { m_benchHash = benchHash; }
inline void setBenchSize(uint32_t size) { m_benchSize = size; }
inline void setBenchToken(const String &token) { m_benchToken = token; }
# endif
private:
void copy(const Job &other);
void move(Job &&other);
@ -135,6 +144,12 @@ private:
char m_rawTarget[24]{};
String m_rawSeedHash;
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
String m_benchToken;
uint32_t m_benchSize = 0;
uint64_t m_benchHash = 0;
# endif
};

View file

@ -19,35 +19,58 @@
#include "base/net/stratum/benchmark/BenchClient.h"
#include "3rdparty/rapidjson/document.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/http/HttpListener.h"
#include "base/net/stratum/benchmark/BenchConfig.h"
xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, IClientListener* listener) :
m_listener(listener)
m_listener(listener),
m_benchmark(benchmark)
{
m_job.setAlgorithm(benchmark->algorithm());
m_httpListener = std::make_shared<HttpListener>(this);
std::vector<char> blob(112 * 2 + 1, '0');
blob.back() = '\0';
m_job.setBlob(blob.data());
m_job.setAlgorithm(m_benchmark->algorithm());
m_job.setDiff(std::numeric_limits<uint64_t>::max());
m_job.setHeight(1);
m_job.setBenchSize(m_benchmark->size());
m_job.setBenchHash(m_benchmark->hash());
if (m_benchmark->isSubmit()) {
m_mode = ONLINE_BENCH;
return;
}
if (!m_benchmark->id().isEmpty()) {
m_job.setId(m_benchmark->id());
m_mode = ONLINE_VERIFY;
return;
}
m_job.setId("00000000");
if (m_job.benchHash() && m_job.setSeedHash(m_benchmark->seed())) {
m_mode = STATIC_VERIFY;
return;
}
blob[Job::kMaxSeedSize * 2] = '\0';
m_job.setSeedHash(blob.data());
m_job.setDiff(uint64_t(-1));
m_job.setHeight(1);
m_job.setId("00000000");
}
void xmrig::BenchClient::connect()
{
if (m_mode == STATIC_BENCH || m_mode == STATIC_VERIFY) {
m_listener->onLoginSuccess(this);
rapidjson::Value params;
m_listener->onJobReceived(this, m_job, params);
m_listener->onJobReceived(this, m_job, rapidjson::Value());
}
}
@ -55,3 +78,8 @@ void xmrig::BenchClient::setPool(const Pool &pool)
{
m_pool = pool;
}
void xmrig::BenchClient::onHttpData(const HttpData &data)
{
}

View file

@ -21,12 +21,13 @@
#include "base/net/stratum/Client.h"
#include "base/kernel/interfaces/IHttpListener.h"
namespace xmrig {
class BenchClient : public IClient
class BenchClient : public IClient, public IHttpListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(BenchClient)
@ -63,12 +64,24 @@ public:
void connect() override;
void setPool(const Pool &pool) override;
protected:
void onHttpData(const HttpData &data) override;
private:
enum Mode : uint32_t {
STATIC_BENCH,
ONLINE_BENCH,
STATIC_VERIFY,
ONLINE_VERIFY
};
IClientListener* m_listener;
Job m_job;
Pool m_pool;
std::shared_ptr<BenchConfig> m_benchmark;
std::shared_ptr<IHttpListener> m_httpListener;
String m_ip;
Mode m_mode = STATIC_BENCH;
};

View file

@ -50,6 +50,11 @@ xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson
if (!m_algorithm.isValid() || m_algorithm.family() != Algorithm::RANDOM_X) {
m_algorithm = Algorithm::RX_0;
}
const char *hash = Json::getString(object, kHash);
if (hash) {
m_hash = strtoull(hash, nullptr, 16);
}
}

View file

@ -341,9 +341,9 @@ public:
Algorithm algorithm;
Algorithms algorithms;
bool active = false;
bool battery_power = false;
bool enabled = true;
bool reset = true;
bool battery_power = false;
Controller *controller;
Job job;
mutable std::map<Algorithm::Id, double> maxHashrate;

View file

@ -128,14 +128,6 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client)
# ifdef XMRIG_FEATURE_BENCHMARK
if (pool.mode() == Pool::MODE_BENCHMARK) {
m_benchSize = pool.benchSize();
LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%" PRIu64 "M") " algo " WHITE_BOLD("%s") " print_time " CYAN_BOLD("%us"),
Tags::bench(),
pool.benchSize() / 1000000,
client->job().algorithm().shortName(),
m_controller->config()->printTime());
return;
}
# endif
@ -272,18 +264,21 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate)
const char *scale = NetworkState::scaleDiff(diff);
# ifdef XMRIG_FEATURE_BENCHMARK
if (!m_benchSize)
if (job.benchSize()) {
LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%" PRIu64 "M") " algo " WHITE_BOLD("%s") " print_time " CYAN_BOLD("%us"),
Tags::bench(),
job.benchSize() / 1000000,
job.algorithm().shortName(),
m_controller->config()->printTime());
LOG_NOTICE("%s " WHITE_BOLD("seed ") BLACK_BOLD("%s"), Tags::bench(), job.seed().toHex().data());
}
else
# endif
{
if (job.height()) {
LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64),
Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height());
}
else {
LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s"),
Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName());
}
}
if (!donate && m_donate) {
m_donate->setAlgo(job.algorithm());