Added benchmark and stress test

Easy to use and zero configuration embedded benchmark/stress test.
This commit is contained in:
SChernykh 2020-10-14 19:45:05 +02:00
parent 9fcc542676
commit 2ecece7b3d
28 changed files with 354 additions and 55 deletions

View file

@ -45,6 +45,8 @@ public:
inline const VirtualMemory *memory() const override { return nullptr; }
inline size_t id() const override { return m_id; }
inline uint64_t rawHashes() const override { return m_count; }
inline uint64_t benchData() const override { return m_benchData; }
inline uint64_t benchDoneTime() const override { return m_benchDoneTime; }
void getHashrateData(uint64_t& hashCount, uint64_t& timeStamp) const override;
inline void jobEarlyNotification(const Job&) override {}
@ -56,8 +58,11 @@ protected:
uint64_t m_hashCount[2] = {};
uint64_t m_timestamp[2] = {};
std::atomic<uint32_t> m_index = {};
uint32_t m_node = 0;
uint64_t m_count = 0;
uint32_t m_node = 0;
uint64_t m_count = 0;
uint64_t m_benchData = 0;
uint64_t m_benchDoneTime = 0;
};

View file

@ -68,7 +68,7 @@ public:
{
m_rounds[index()]++;
if ((m_rounds[index()] % rounds) == 0) {
if ((m_rounds[index()] & (rounds - 1)) == 0) {
for (size_t i = 0; i < N; ++i) {
if (!Nonce::next(index(), nonce(i), rounds * roundSize, nonceMask())) {
return false;
@ -130,7 +130,7 @@ inline bool xmrig::WorkerJob<1>::nextRound(uint32_t rounds, uint32_t roundSize)
uint32_t* n = nonce();
if ((m_rounds[index()] % rounds) == 0) {
if ((m_rounds[index()] & (rounds - 1)) == 0) {
if (!Nonce::next(index(), n, rounds * roundSize, nonceMask())) {
return false;
}

View file

@ -29,8 +29,10 @@
#include "backend/common/Workers.h"
#include "backend/cpu/CpuWorker.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "base/tools/Chrono.h"
#include "base/tools/Object.h"
#include "core/Miner.h"
#ifdef XMRIG_FEATURE_OPENCL
@ -63,6 +65,10 @@ public:
Hashrate *hashrate = nullptr;
IBackend *backend = nullptr;
uint32_t bench = 0;
Algorithm benchAlgo = Algorithm::RX_0;
uint64_t startTime = 0;
};
@ -101,6 +107,11 @@ void xmrig::Workers<T>::setBackend(IBackend *backend)
template<class T>
void xmrig::Workers<T>::start(const std::vector<T> &data)
{
if (!data.empty()) {
d_ptr->bench = data.front().miner->job().bench();
d_ptr->benchAlgo = data.front().miner->job().algorithm();
}
for (const T &item : data) {
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), item));
}
@ -111,11 +122,12 @@ void xmrig::Workers<T>::start(const std::vector<T> &data)
for (Thread<T> *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
std::this_thread::sleep_for(std::chrono::milliseconds(20));
if (!d_ptr->bench) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
d_ptr->startTime = Chrono::steadyMSecs();
}
@ -137,55 +149,91 @@ void xmrig::Workers<T>::stop()
template<class T>
void xmrig::Workers<T>::tick(uint64_t)
static void getHashrateData(xmrig::IWorker* worker, uint64_t& hashCount, uint64_t& timeStamp)
{
worker->getHashrateData(hashCount, timeStamp);
}
template<>
static void getHashrateData<xmrig::CpuLaunchData>(xmrig::IWorker* worker, uint64_t& hashCount, uint64_t&)
{
hashCount = worker->rawHashes();
}
template<class T>
bool xmrig::Workers<T>::tick(uint64_t)
{
if (!d_ptr->hashrate) {
return;
return true;
}
uint64_t timeStamp = Chrono::steadyMSecs();
bool totalAvailable = true;
uint64_t totalHashCount = 0;
uint32_t benchDone = 0;
uint64_t benchData = 0;
uint64_t benchDoneTime = 0;
for (Thread<T> *handle : m_workers) {
if (handle->worker()) {
uint64_t hashCount, timeStamp;
handle->worker()->getHashrateData(hashCount, timeStamp);
IWorker* worker = handle->worker();
if (worker) {
uint64_t hashCount;
getHashrateData<T>(worker, hashCount, timeStamp);
d_ptr->hashrate->add(handle->id() + 1, hashCount, timeStamp);
const uint64_t n = handle->worker()->rawHashes();
const uint64_t n = worker->rawHashes();
if (n == 0) {
totalAvailable = false;
}
totalHashCount += n;
if (d_ptr->bench && worker->benchDoneTime()) {
++benchDone;
benchData ^= worker->benchData();
if (worker->benchDoneTime() > benchDoneTime) {
benchDoneTime = worker->benchDoneTime();
}
}
}
}
if (totalAvailable) {
d_ptr->hashrate->add(0, totalHashCount, Chrono::steadyMSecs());
}
}
if (d_ptr->bench && (benchDone == m_workers.size())) {
const double dt = (benchDoneTime - d_ptr->startTime) / 1000.0;
template<>
void xmrig::Workers<xmrig::CpuLaunchData>::tick(uint64_t)
{
if (!d_ptr->hashrate) {
return;
}
static uint64_t hashCheck[Algorithm::MAX][2] = {};
hashCheck[Algorithm::RX_0][0] = 0x898B6E0431C28A6BULL;
hashCheck[Algorithm::RX_0][1] = 0xB5231262E2792B26ULL;
hashCheck[Algorithm::RX_WOW][0] = 0x0F3E5400B39EA96AULL;
hashCheck[Algorithm::RX_WOW][1] = 0x0F9E00C5A511C200ULL;
const uint64_t timestamp = Chrono::steadyMSecs();
uint64_t totalHashCount = 0;
for (Thread<CpuLaunchData> *handle : m_workers) {
if (handle->worker()) {
const uint64_t hashCount = handle->worker()->rawHashes();
d_ptr->hashrate->add(handle->id() + 1, hashCount, timestamp);
totalHashCount += hashCount;
int k = -1;
switch (d_ptr->bench) {
case 1000000:
k = 0;
break;
case 10000000:
k = 1;
break;
}
const uint64_t checkData = (k >= 0) ? hashCheck[d_ptr->benchAlgo.id()][k] : 0;
const char* color = checkData ? ((benchData == checkData) ? GREEN_BOLD_S : RED_BOLD_S) : BLACK_BOLD_S;
LOG_INFO("%s Benchmark finished in %.3f seconds, hash sum = %s%016" PRIX64 CLEAR, Tags::miner(), dt, color, benchData);
return false;
}
if (totalHashCount > 0) {
d_ptr->hashrate->add(0, totalHashCount, timestamp);
}
return true;
}

View file

@ -63,7 +63,7 @@ public:
void setBackend(IBackend *backend);
void start(const std::vector<T> &data);
void stop();
void tick(uint64_t ticks);
bool tick(uint64_t ticks);
void jobEarlyNotification(const Job&);
private:
@ -88,8 +88,6 @@ void xmrig::Workers<T>::jobEarlyNotification(const Job& job)
template<>
IWorker *Workers<CpuLaunchData>::create(Thread<CpuLaunchData> *handle);
template<>
void Workers<CpuLaunchData>::tick(uint64_t);
extern template class Workers<CpuLaunchData>;

View file

@ -60,7 +60,7 @@ public:
virtual void setJob(const Job &job) = 0;
virtual void start(IWorker *worker, bool ready) = 0;
virtual void stop() = 0;
virtual void tick(uint64_t ticks) = 0;
virtual bool tick(uint64_t ticks) = 0;
# ifdef XMRIG_FEATURE_API
virtual rapidjson::Value toJSON(rapidjson::Document &doc) const = 0;

View file

@ -47,6 +47,8 @@ public:
virtual size_t id() const = 0;
virtual size_t intensity() const = 0;
virtual uint64_t rawHashes() const = 0;
virtual uint64_t benchData() const = 0;
virtual uint64_t benchDoneTime() const = 0;
virtual void getHashrateData(uint64_t&, uint64_t&) const = 0;
virtual void start() = 0;
virtual void jobEarlyNotification(const Job&) = 0;

View file

@ -387,9 +387,9 @@ void xmrig::CpuBackend::stop()
}
void xmrig::CpuBackend::tick(uint64_t ticks)
bool xmrig::CpuBackend::tick(uint64_t ticks)
{
d_ptr->workers.tick(ticks);
return d_ptr->workers.tick(ticks);
}

View file

@ -63,7 +63,7 @@ protected:
void setJob(const Job &job) override;
void start(IWorker *worker, bool ready) override;
void stop() override;
void tick(uint64_t ticks) override;
bool tick(uint64_t ticks) override;
# ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const override;

View file

@ -29,6 +29,7 @@
#include "backend/cpu/CpuWorker.h"
#include "base/tools/Chrono.h"
#include "core/Miner.h"
#include "crypto/cn/CnCtx.h"
#include "crypto/cn/CryptoNight_test.h"
@ -59,8 +60,10 @@ static constexpr uint32_t kReserveCount = 32768;
template<size_t N>
inline bool nextRound(WorkerJob<N> &job)
{
if (!job.nextRound(kReserveCount, 1)) {
JobResults::done(job.currentJob());
const Job& curJob = job.currentJob();
const uint32_t bench = curJob.bench();
if (!job.nextRound(bench ? 1 : kReserveCount, 1)) {
JobResults::done(curJob);
return false;
}
@ -265,7 +268,18 @@ void xmrig::CpuWorker<N>::start()
if (valid) {
for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < job.target()) {
const uint64_t value = *reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24);
if (job.bench()) {
if (current_job_nonces[i] < job.bench()) {
m_benchData ^= value;
}
else {
m_benchDoneTime = Chrono::steadyMSecs();
return;
}
}
else if (value < job.target()) {
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32));
}
}
@ -362,7 +376,8 @@ void xmrig::CpuWorker<N>::consumeJob()
return;
}
m_job.add(m_miner->job(), kReserveCount, Nonce::CPU);
const uint32_t bench = m_miner->job().bench();
m_job.add(m_miner->job(), bench ? 1 : kReserveCount, Nonce::CPU);
# ifdef XMRIG_ALGO_RANDOMX
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {

View file

@ -501,9 +501,9 @@ void xmrig::CudaBackend::stop()
}
void xmrig::CudaBackend::tick(uint64_t ticks)
bool xmrig::CudaBackend::tick(uint64_t ticks)
{
d_ptr->workers.tick(ticks);
return d_ptr->workers.tick(ticks);
}

View file

@ -63,7 +63,7 @@ protected:
void setJob(const Job &job) override;
void start(IWorker *worker, bool ready) override;
void stop() override;
void tick(uint64_t ticks) override;
bool tick(uint64_t ticks) override;
# ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const override;

View file

@ -485,9 +485,9 @@ void xmrig::OclBackend::stop()
}
void xmrig::OclBackend::tick(uint64_t ticks)
bool xmrig::OclBackend::tick(uint64_t ticks)
{
d_ptr->workers.tick(ticks);
return d_ptr->workers.tick(ticks);
}

View file

@ -63,7 +63,7 @@ protected:
void setJob(const Job &job) override;
void start(IWorker *worker, bool ready) override;
void stop() override;
void tick(uint64_t ticks) override;
bool tick(uint64_t ticks) override;
# ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const override;