From 4b71b7aa29e6ff89e20e8679625f4599edf75b40 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 14 Apr 2018 22:14:57 +0700 Subject: [PATCH] Added class MultiWorker and remove classes SingleWorker and DoubleWorker. --- CMakeLists.txt | 6 +- src/interfaces/IWorker.h | 3 +- src/net/Job.cpp | 11 + src/net/Job.h | 4 + src/workers/DoubleWorker.cpp | 189 ------------------ src/workers/DoubleWorker.h | 59 ------ src/workers/Handle.cpp | 4 +- src/workers/Handle.h | 9 +- .../{SingleWorker.cpp => MultiWorker.cpp} | 135 +++++++------ src/workers/{SingleWorker.h => MultiWorker.h} | 34 +++- src/workers/Worker.cpp | 4 +- src/workers/Worker.h | 8 +- src/workers/Workers.cpp | 52 +++-- 13 files changed, 173 insertions(+), 345 deletions(-) delete mode 100644 src/workers/DoubleWorker.cpp delete mode 100644 src/workers/DoubleWorker.h rename src/workers/{SingleWorker.cpp => MultiWorker.cpp} (61%) rename src/workers/{SingleWorker.h => MultiWorker.h} (72%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8d381d4..ecb65b22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,10 +55,9 @@ set(HEADERS src/Summary.h src/version.h src/workers/CpuThread.h - src/workers/DoubleWorker.h src/workers/Handle.h src/workers/Hashrate.h - src/workers/SingleWorker.h + src/workers/MultiWorker.h src/workers/Worker.h src/workers/Workers.h ) @@ -109,10 +108,9 @@ set(SOURCES src/net/SubmitResult.cpp src/Summary.cpp src/workers/CpuThread.cpp - src/workers/DoubleWorker.cpp src/workers/Handle.cpp src/workers/Hashrate.cpp - src/workers/SingleWorker.cpp + src/workers/MultiWorker.cpp src/workers/Worker.cpp src/workers/Workers.cpp src/xmrig.cpp diff --git a/src/interfaces/IWorker.h b/src/interfaces/IWorker.h index a90abe11..90394c2c 100644 --- a/src/interfaces/IWorker.h +++ b/src/interfaces/IWorker.h @@ -33,10 +33,11 @@ class IWorker public: virtual ~IWorker() {} - virtual bool start() = 0; + virtual bool selfTest() = 0; virtual size_t id() const = 0; virtual uint64_t hashCount() const = 0; virtual uint64_t timestamp() const = 0; + virtual void start() = 0; }; diff --git a/src/net/Job.cpp b/src/net/Job.cpp index 17d8266f..1434c87f 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -209,6 +209,17 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out) } +#ifdef APP_DEBUG +char *Job::toHex(const unsigned char* in, unsigned int len) +{ + char *out = new char[len * 2 + 1](); + toHex(in, len, out); + + return out; +} +#endif + + bool Job::operator==(const Job &other) const { return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; diff --git a/src/net/Job.h b/src/net/Job.h index a60f061c..ee4728e3 100644 --- a/src/net/Job.h +++ b/src/net/Job.h @@ -69,6 +69,10 @@ public: static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; } static void toHex(const unsigned char* in, unsigned int len, char* out); +# ifdef APP_DEBUG + static char *toHex(const unsigned char* in, unsigned int len); +# endif + bool operator==(const Job &other) const; bool operator!=(const Job &other) const; diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp deleted file mode 100644 index 6ba5c47f..00000000 --- a/src/workers/DoubleWorker.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2016-2018 XMRig , - * - * 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 . - */ - - -#include - - -#include "crypto/CryptoNight_test.h" -#include "workers/CpuThread.h" -#include "workers/DoubleWorker.h" -#include "workers/Workers.h" - - -class DoubleWorker::State -{ -public: - inline State() : - nonce1(0), - nonce2(0) - {} - - Job job; - uint32_t nonce1; - uint32_t nonce2; - uint8_t blob[84 * 2]; -}; - - -DoubleWorker::DoubleWorker(Handle *handle) - : Worker(handle) -{ - m_state = new State(); - m_pausedState = new State(); -} - - -DoubleWorker::~DoubleWorker() -{ - delete m_state; - delete m_pausedState; -} - - -bool DoubleWorker::start() -{ - if (!selfTest()) { - return false; - } - - while (Workers::sequence() > 0) { - if (Workers::isPaused()) { - do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - while (Workers::isPaused()); - - if (Workers::sequence() == 0) { - break; - } - - consumeJob(); - } - - while (!Workers::isOutdated(m_sequence)) { - if ((m_count & 0xF) == 0) { - storeStats(); - } - - m_count += 2; - *Job::nonce(m_state->blob) = ++m_state->nonce1; - *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2; - - m_thread->fn(m_state->job.variant())(m_state->blob, m_state->job.size(), m_hash, m_ctx); - - if (*reinterpret_cast(m_hash + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff())); - } - - if (*reinterpret_cast(m_hash + 32 + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff())); - } - - std::this_thread::yield(); - } - - consumeJob(); - } - - return true; -} - - -bool DoubleWorker::resume(const Job &job) -{ - if (m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) { - *m_state = *m_pausedState; - return true; - } - - return false; -} - - -bool DoubleWorker::selfTest() -{ - if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) { - return false; - } - - m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx); - - if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, 64) == 0) { - m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx); - - return memcmp(m_hash, test_output_v1, 64) == 0; - } - -# ifndef XMRIG_NO_AEON - if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, 64) == 0) { - m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx); - - return memcmp(m_hash, test_output_v1_lite, 64) == 0; - } -# endif - -# ifndef XMRIG_NO_SUMO - return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_hash, test_output_heavy, 64) == 0; -# else - return false; -# endif -} - - -void DoubleWorker::consumeJob() -{ - Job job = Workers::job(); - m_sequence = Workers::sequence(); - if (m_state->job == job) { - return; - } - - save(job); - - if (resume(job)) { - return; - } - - m_state->job = std::move(job); - memcpy(m_state->blob, m_state->job.blob(), m_state->job.size()); - memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size()); - - if (m_state->job.isNicehash()) { - m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / m_totalWays * m_id); - m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalThreads)); - } - else { - m_state->nonce1 = 0xffffffffU / m_totalWays * m_id; - m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalThreads); - } -} - - -void DoubleWorker::save(const Job &job) -{ - if (job.poolId() == -1 && m_state->job.poolId() >= 0) { - *m_pausedState = *m_state; - } -} diff --git a/src/workers/DoubleWorker.h b/src/workers/DoubleWorker.h deleted file mode 100644 index e8847282..00000000 --- a/src/workers/DoubleWorker.h +++ /dev/null @@ -1,59 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2016-2018 XMRig , - * - * 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 . - */ - -#ifndef __DOUBLEWORKER_H__ -#define __DOUBLEWORKER_H__ - - -#include "net/Job.h" -#include "net/JobResult.h" -#include "workers/Worker.h" - - -class Handle; - - -class DoubleWorker : public Worker -{ -public: - DoubleWorker(Handle *handle); - ~DoubleWorker(); - - bool start() override; - -private: - bool resume(const Job &job); - bool selfTest(); - void consumeJob(); - void save(const Job &job); - - class State; - - uint8_t m_hash[64]; - State *m_state; - State *m_pausedState; -}; - - -#endif /* __SINGLEWORKER_H__ */ diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index 29f57fb2..d42ea368 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -25,10 +25,10 @@ #include "workers/Handle.h" -Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays) : +Handle::Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays) : m_worker(nullptr), - m_totalThreads(totalThreads), m_totalWays(totalWays), + m_offset(offset), m_config(config) { } diff --git a/src/workers/Handle.h b/src/workers/Handle.h index b3a7c76f..4bb899f9 100644 --- a/src/workers/Handle.h +++ b/src/workers/Handle.h @@ -25,6 +25,7 @@ #define __HANDLE_H__ +#include #include #include @@ -38,21 +39,21 @@ class IWorker; class Handle { public: - Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays); + Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays); void join(); void start(void (*callback) (void *)); inline IWorker *worker() const { return m_worker; } inline size_t threadId() const { return m_config->index(); } - inline size_t totalThreads() const { return m_totalThreads; } inline size_t totalWays() const { return m_totalWays; } - inline void setWorker(IWorker *worker) { m_worker = worker; } + inline uint32_t offset() const { return m_offset; } + inline void setWorker(IWorker *worker) { assert(worker != nullptr); m_worker = worker; } inline xmrig::IThread *config() const { return m_config; } private: IWorker *m_worker; - size_t m_totalThreads; size_t m_totalWays; + uint32_t m_offset; uv_thread_t m_thread; xmrig::IThread *m_config; }; diff --git a/src/workers/SingleWorker.cpp b/src/workers/MultiWorker.cpp similarity index 61% rename from src/workers/SingleWorker.cpp rename to src/workers/MultiWorker.cpp index 815b965d..0007b0cb 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -28,22 +28,51 @@ #include "crypto/CryptoNight_test.h" #include "workers/CpuThread.h" -#include "workers/SingleWorker.h" +#include "workers/MultiWorker.h" #include "workers/Workers.h" -SingleWorker::SingleWorker(Handle *handle) +template +MultiWorker::MultiWorker(Handle *handle) : Worker(handle) { } -bool SingleWorker::start() +template +bool MultiWorker::selfTest() { - if (!selfTest()) { + if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) { return false; } + m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_result.result, m_ctxLegacy); + + if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_result.result, test_output_v0, 32) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctxLegacy); + + return memcmp(m_result.result, test_output_v1, 32) == 0; + } + +# ifndef XMRIG_NO_AEON + if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_result.result, test_output_v0_lite, 32) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctxLegacy); + + return memcmp(m_result.result, test_output_v1_lite, 32) == 0; + } +# endif + +# ifndef XMRIG_NO_SUMO + return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_result.result, test_output_heavy, 32) == 0; +# else + return false; +# endif +} + + +template +void MultiWorker::start() +{ while (Workers::sequence() > 0) { if (Workers::isPaused()) { do { @@ -59,34 +88,35 @@ bool SingleWorker::start() } while (!Workers::isOutdated(m_sequence)) { - if ((m_count & 0xF) == 0) { + if ((m_count & 0x7) == 0) { storeStats(); } - m_count++; - *m_job.nonce() = ++m_result.nonce; + m_thread->fn(m_state.job.variant())(m_state.blob, m_state.job.size(), m_hash, m_ctxLegacy); - m_thread->fn(m_job.variant())(m_job.blob(), m_job.size(), m_result.result, m_ctx); - if (*reinterpret_cast(m_result.result + 24) < m_job.target()) { - Workers::submit(m_result); + for (size_t i = 0; i < N; ++i) { + if (*reinterpret_cast(m_hash + (i * 32) + 24) < m_state.job.target()) { + Workers::submit(JobResult(m_state.job.poolId(), m_state.job.id(), *nonce(i), m_hash, m_state.job.diff())); + } + + *nonce(i) += 1; } + m_count += N; + std::this_thread::yield(); } consumeJob(); } - - return true; } -bool SingleWorker::resume(const Job &job) +template +bool MultiWorker::resume(const Job &job) { - if (m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) { - m_job = m_paused; - m_result = m_job; - m_result.nonce = *m_job.nonce(); + if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) { + m_state = m_pausedState; return true; } @@ -94,41 +124,12 @@ bool SingleWorker::resume(const Job &job) } -bool SingleWorker::selfTest() -{ - if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) { - return false; - } - - m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_result.result, m_ctx); - - if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_result.result, test_output_v0, 32) == 0) { - m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx); - - return memcmp(m_result.result, test_output_v1, 32) == 0; - } - -# ifndef XMRIG_NO_AEON - if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_result.result, test_output_v0_lite, 32) == 0) { - m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx); - - return memcmp(m_result.result, test_output_v1_lite, 32) == 0; - } -# endif - -# ifndef XMRIG_NO_SUMO - return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_result.result, test_output_heavy, 32) == 0; -# else - return false; -# endif -} - - -void SingleWorker::consumeJob() +template +void MultiWorker::consumeJob() { Job job = Workers::job(); m_sequence = Workers::sequence(); - if (m_job == job) { + if (m_state.job == job) { return; } @@ -138,21 +139,39 @@ void SingleWorker::consumeJob() return; } - m_job = std::move(job); - m_result = m_job; + m_state.job = job; - if (m_job.isNicehash()) { - m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_totalWays * m_id); + const size_t size = m_state.job.size(); + memcpy(m_state.blob, m_state.job.blob(), m_state.job.size()); + + if (N > 1) { + for (size_t i = 1; i < N; ++i) { + memcpy(m_state.blob + (i * size), m_state.blob, size); + } } - else { - m_result.nonce = 0xffffffffU / m_totalWays * m_id; + + for (size_t i = 0; i < N; ++i) { + if (m_state.job.isNicehash()) { + *nonce(i) = (*nonce(i) & 0xff000000U) + (0xffffffU / m_totalWays * (m_offset + i)); + } + else { + *nonce(i) = 0xffffffffU / m_totalWays * (m_offset + i); + } } } -void SingleWorker::save(const Job &job) +template +void MultiWorker::save(const Job &job) { - if (job.poolId() == -1 && m_job.poolId() >= 0) { - m_paused = m_job; + if (job.poolId() == -1 && m_state.job.poolId() >= 0) { + m_pausedState = m_state; } } + + +template class MultiWorker<1>; +template class MultiWorker<2>; +template class MultiWorker<3>; +template class MultiWorker<4>; +template class MultiWorker<5>; diff --git a/src/workers/SingleWorker.h b/src/workers/MultiWorker.h similarity index 72% rename from src/workers/SingleWorker.h rename to src/workers/MultiWorker.h index 061f5084..d384b0ba 100644 --- a/src/workers/SingleWorker.h +++ b/src/workers/MultiWorker.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __SINGLEWORKER_H__ -#define __SINGLEWORKER_H__ +#ifndef __MULTIWORKER_H__ +#define __MULTIWORKER_H__ #include "net/Job.h" @@ -34,23 +34,43 @@ class Handle; -class SingleWorker : public Worker +template +class MultiWorker : public Worker { public: - SingleWorker(Handle *handle); + MultiWorker(Handle *handle); - bool start() override; +protected: + bool selfTest() override; + void start() override; private: bool resume(const Job &job); - bool selfTest(); void consumeJob(); void save(const Job &job); + inline uint32_t *nonce(size_t index) + { + return reinterpret_cast(m_state.blob + (index * m_state.job.size()) + 39); + } + + struct State + { + alignas(16) uint8_t blob[96 * N]; + Job job; + }; + + +// cryptonight_ctx *m_ctx[N]; + + uint8_t m_hash[N * 32]; + State m_state; + State m_pausedState; + Job m_job; Job m_paused; JobResult m_result; }; -#endif /* __SINGLEWORKER_H__ */ +#endif /* __MULTIWORKER_H__ */ diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 59434390..e0ed846b 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -34,8 +34,8 @@ Worker::Worker(Handle *handle) : m_id(handle->threadId()), - m_totalThreads(handle->totalThreads()), m_totalWays(handle->totalWays()), + m_offset(handle->offset()), m_hashCount(0), m_timestamp(0), m_count(0), @@ -47,7 +47,7 @@ Worker::Worker(Handle *handle) : } Platform::setThreadPriority(m_thread->priority()); - m_ctx = Mem::create(m_id); + m_ctxLegacy = Mem::create(m_id); } diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 88f6ee42..72b3beb2 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -54,10 +54,10 @@ public: protected: void storeStats(); - cryptonight_ctx *m_ctx; - size_t m_id; - size_t m_totalThreads; - size_t m_totalWays; + const size_t m_id; + const size_t m_totalWays; + const uint32_t m_offset; + cryptonight_ctx *m_ctxLegacy; std::atomic m_hashCount; std::atomic m_timestamp; uint64_t m_count; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 44ac399f..21379db4 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -30,15 +30,13 @@ #include "core/Controller.h" #include "interfaces/IJobResultListener.h" #include "interfaces/IThread.h" +#include "log/Log.h" #include "Mem.h" -#include "workers/DoubleWorker.h" #include "workers/Handle.h" #include "workers/Hashrate.h" -#include "workers/SingleWorker.h" +#include "workers/MultiWorker.h" #include "workers/Workers.h" -#include "log/Log.h" - bool Workers::m_active = false; bool Workers::m_enabled = true; @@ -112,8 +110,6 @@ void Workers::start(xmrig::Controller *controller) { const std::vector &threads = controller->config()->threads(); - LOG_NOTICE("- %d", std::this_thread::get_id()); - size_t totalWays = 0; for (const xmrig::IThread *thread : threads) { totalWays += thread->multiway(); @@ -131,8 +127,12 @@ void Workers::start(xmrig::Controller *controller) uv_timer_init(uv_default_loop(), &m_timer); uv_timer_start(&m_timer, Workers::onTick, 500, 500); + uint32_t offset = 0; + for (xmrig::IThread *thread : threads) { - Handle *handle = new Handle(thread, threads.size(), totalWays); + Handle *handle = new Handle(thread, offset, totalWays); + offset += thread->multiway(); + m_workers.push_back(handle); handle->start(Workers::onReady); } @@ -168,20 +168,42 @@ void Workers::onReady(void *arg) { auto handle = static_cast(arg); - LOG_NOTICE("%zu %d", handle->threadId(), std::this_thread::get_id()); + IWorker *worker = nullptr; - if (Mem::isDoubleHash()) { - handle->setWorker(new DoubleWorker(handle)); - } - else { - handle->setWorker(new SingleWorker(handle)); + switch (handle->config()->multiway()) { + case 1: + worker = new MultiWorker<1>(handle); + break; + + case 2: + worker = new MultiWorker<2>(handle); + break; + + case 3: + worker = new MultiWorker<3>(handle); + break; + + case 4: + worker = new MultiWorker<4>(handle); + break; + + case 5: + worker = new MultiWorker<5>(handle); + break; + + default: + break; } - const bool rc = handle->worker()->start(); + handle->setWorker(worker); - if (!rc) { + if (!worker->selfTest()) { LOG_ERR("thread %zu error: \"hash self-test failed\".", handle->worker()->id()); + + return; } + + worker->start(); }