From e3fcb99d84b1c6686ab1f771b31c28fe2cecef52 Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Tue, 17 Sep 2019 02:22:59 +0700 Subject: [PATCH] Allow partially started threads. --- src/backend/common/Thread.h | 9 +++-- src/backend/common/Workers.cpp | 8 +++- src/backend/common/Workers.h | 3 ++ src/backend/common/interfaces/IBackend.h | 2 +- src/backend/common/interfaces/IWorker.h | 5 ++- src/backend/cpu/CpuBackend.cpp | 47 ++++++++++++++-------- src/backend/cpu/CpuBackend.h | 11 +++-- src/backend/cpu/CpuWorker.h | 1 + src/backend/opencl/OclBackend.cpp | 30 +++++++++++--- src/backend/opencl/OclBackend.h | 2 +- src/backend/opencl/OclWorker.cpp | 6 +++ src/backend/opencl/OclWorker.h | 1 + src/backend/opencl/interfaces/IOclRunner.h | 5 ++- src/backend/opencl/runners/OclBaseRunner.h | 1 + 14 files changed, 94 insertions(+), 37 deletions(-) diff --git a/src/backend/common/Thread.h b/src/backend/common/Thread.h index 3bef53194..ab88441c9 100644 --- a/src/backend/common/Thread.h +++ b/src/backend/common/Thread.h @@ -26,10 +26,11 @@ #define XMRIG_THREAD_H -#include <thread> - - #include "backend/common/interfaces/IWorker.h" +#include "base/tools/Object.h" + + +#include <thread> namespace xmrig { @@ -42,6 +43,8 @@ template<class T> class Thread { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Thread) + inline Thread(IBackend *backend, size_t id, const T &config) : m_id(id), m_config(config), m_backend(backend) {} inline ~Thread() { m_thread.join(); delete m_worker; } diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 2d0729f32..2c90dfe02 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -133,7 +133,7 @@ void xmrig::Workers<T>::tick(uint64_t) for (Thread<T> *handle : m_workers) { if (!handle->worker()) { - return; + continue; } d_ptr->hashrate->add(handle->id(), handle->worker()->hashCount(), handle->worker()->timestamp()); @@ -156,17 +156,21 @@ void xmrig::Workers<T>::onReady(void *arg) auto handle = static_cast<Thread<T>* >(arg); IWorker *worker = create(handle); + assert(worker != nullptr); + if (!worker || !worker->selfTest()) { LOG_ERR("%s " RED("thread ") RED_BOLD("#%zu") RED(" self-test failed"), T::tag(), worker->id()); + handle->backend()->start(worker, false); delete worker; + return; } assert(handle->backend() != nullptr); handle->setWorker(worker); - handle->backend()->start(worker); + handle->backend()->start(worker, true); } diff --git a/src/backend/common/Workers.h b/src/backend/common/Workers.h index bb35157a4..2688a1e39 100644 --- a/src/backend/common/Workers.h +++ b/src/backend/common/Workers.h @@ -29,6 +29,7 @@ #include "backend/common/Thread.h" #include "backend/cpu/CpuLaunchData.h" +#include "base/tools/Object.h" #ifdef XMRIG_FEATURE_OPENCL @@ -47,6 +48,8 @@ template<class T> class Workers { public: + XMRIG_DISABLE_COPY_MOVE(Workers) + Workers(); ~Workers(); diff --git a/src/backend/common/interfaces/IBackend.h b/src/backend/common/interfaces/IBackend.h index b284d1881..f90732293 100644 --- a/src/backend/common/interfaces/IBackend.h +++ b/src/backend/common/interfaces/IBackend.h @@ -56,7 +56,7 @@ public: virtual void prepare(const Job &nextJob) = 0; virtual void printHashrate(bool details) = 0; virtual void setJob(const Job &job) = 0; - virtual void start(IWorker *worker) = 0; + virtual void start(IWorker *worker, bool ready) = 0; virtual void stop() = 0; virtual void tick(uint64_t ticks) = 0; diff --git a/src/backend/common/interfaces/IWorker.h b/src/backend/common/interfaces/IWorker.h index 0d7fe1d26..9dd1274d3 100644 --- a/src/backend/common/interfaces/IWorker.h +++ b/src/backend/common/interfaces/IWorker.h @@ -26,8 +26,8 @@ #define XMRIG_IWORKER_H -#include <stdint.h> -#include <stddef.h> +#include <cstdint> +#include <cstddef> namespace xmrig { @@ -44,6 +44,7 @@ public: virtual bool selfTest() = 0; virtual const VirtualMemory *memory() const = 0; virtual size_t id() const = 0; + virtual size_t intensity() const = 0; virtual uint64_t hashCount() const = 0; virtual uint64_t timestamp() const = 0; virtual void start() = 0; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index 22ae63d87..de2e61103 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -60,7 +60,7 @@ namespace xmrig { extern template class Threads<CpuThreads>; -static const char *tag = CYAN_BG_BOLD(" cpu "); +static const char *tag = CYAN_BG_BOLD(WHITE_BOLD_S " cpu "); static const String kType = "cpu"; static std::mutex mutex; @@ -80,38 +80,51 @@ public: m_memory = memory; m_pages = 0; m_started = 0; + m_errors = 0; m_threads = threads.size(); m_ways = 0; m_ts = Chrono::steadyMSecs(); - - for (const CpuLaunchData &data : threads) { - m_ways += data.intensity; - } } - inline bool started(const std::pair<size_t, size_t> &hugePages) + inline bool started(IWorker *worker, bool ready) { - m_started++; - m_hugePages += hugePages.first; - m_pages += hugePages.second; + if (ready) { + auto hugePages = worker->memory()->hugePages(); - return m_started == m_threads; + m_started++; + m_hugePages += hugePages.first; + m_pages += hugePages.second; + m_ways += worker->intensity(); + } + else { + m_errors++; + } + + return (m_started + m_errors) == m_threads; } inline void print() const { - LOG_INFO("%s" GREEN_BOLD(" READY") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") BLACK_BOLD(" (%" PRIu64 " ms)"), + if (m_started == 0) { + LOG_ERR("%s " RED_BOLD("disabled") YELLOW(" (failed to start threads)"), tag); + + return; + } + + LOG_INFO("%s" GREEN_BOLD(" READY") " threads %s%zu/%zu (%zu)" CLEAR " huge pages %s%zu/%zu %1.0f%%" CLEAR " memory " CYAN_BOLD("%zu KB") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, - m_threads, m_ways, + m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S, + m_started, m_threads, m_ways, (m_hugePages == m_pages ? GREEN_BOLD_S : (m_hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), m_hugePages, m_pages, m_hugePages == 0 ? 0.0 : static_cast<double>(m_hugePages) / m_pages * 100.0, - m_ways * m_memory / 1024, + memory() / 1024, Chrono::steadyMSecs() - m_ts ); } private: + size_t m_errors = 0; size_t m_hugePages = 0; size_t m_memory = 0; size_t m_pages = 0; @@ -322,17 +335,19 @@ void xmrig::CpuBackend::setJob(const Job &job) } -void xmrig::CpuBackend::start(IWorker *worker) +void xmrig::CpuBackend::start(IWorker *worker, bool ready) { mutex.lock(); - if (d_ptr->status.started(worker->memory()->hugePages())) { + if (d_ptr->status.started(worker, ready)) { d_ptr->status.print(); } mutex.unlock(); - worker->start(); + if (ready) { + worker->start(); + } } diff --git a/src/backend/cpu/CpuBackend.h b/src/backend/cpu/CpuBackend.h index 9d6d85ac4..d5d9fbf6c 100644 --- a/src/backend/cpu/CpuBackend.h +++ b/src/backend/cpu/CpuBackend.h @@ -26,10 +26,11 @@ #define XMRIG_CPUBACKEND_H -#include <utility> - - #include "backend/common/interfaces/IBackend.h" +#include "base/tools/Object.h" + + +#include <utility> namespace xmrig { @@ -43,6 +44,8 @@ class Miner; class CpuBackend : public IBackend { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(CpuBackend) + CpuBackend(Controller *controller); ~CpuBackend() override; @@ -55,7 +58,7 @@ protected: void prepare(const Job &nextJob) override; void printHashrate(bool details) override; void setJob(const Job &job) override; - void start(IWorker *worker) override; + void start(IWorker *worker, bool ready) override; void stop() override; void tick(uint64_t ticks) override; diff --git a/src/backend/cpu/CpuWorker.h b/src/backend/cpu/CpuWorker.h index 02ce0826c..31819de97 100644 --- a/src/backend/cpu/CpuWorker.h +++ b/src/backend/cpu/CpuWorker.h @@ -54,6 +54,7 @@ protected: void start() override; inline const VirtualMemory *memory() const override { return m_memory; } + inline size_t intensity() const override { return N; } private: inline cn_hash_fun fn(const Algorithm &algorithm) const { return CnHash::fn(algorithm, m_av, m_assembly); } diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 614aa8d23..2bce87b84 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -72,12 +72,19 @@ static void printDisabled(const char *reason) struct OclLaunchStatus { public: - inline bool started() { m_started++; return m_started == m_threads; } - inline size_t threads() const { return m_threads; } + inline size_t threads() const { return m_threads; } + + inline bool started(bool ready) + { + ready ? m_started++ : m_errors++; + + return (m_started + m_errors) == m_threads; + } inline void start(size_t threads) { m_started = 0; + m_errors = 0; m_threads = threads; m_ts = Chrono::steadyMSecs(); OclWorker::ready = false; @@ -85,14 +92,23 @@ public: inline void print() const { - LOG_INFO("%s" GREEN_BOLD(" READY") " threads " CYAN_BOLD("%zu") BLACK_BOLD(" (%" PRIu64 " ms)"), + if (m_started == 0) { + LOG_ERR("%s " RED_BOLD("disabled") YELLOW(" (failed to start threads)"), tag); + + return; + } + + LOG_INFO("%s" GREEN_BOLD(" READY") " threads " "%s%zu/%zu" BLACK_BOLD(" (%" PRIu64 " ms)"), tag, + m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S, + m_started, m_threads, Chrono::steadyMSecs() - m_ts ); } private: + size_t m_errors = 0; size_t m_started = 0; size_t m_threads = 0; uint64_t m_ts = 0; @@ -319,11 +335,11 @@ void xmrig::OclBackend::setJob(const Job &job) } -void xmrig::OclBackend::start(IWorker *worker) +void xmrig::OclBackend::start(IWorker *worker, bool ready) { mutex.lock(); - if (d_ptr->status.started()) { + if (d_ptr->status.started(ready)) { d_ptr->status.print(); OclWorker::ready = true; @@ -331,7 +347,9 @@ void xmrig::OclBackend::start(IWorker *worker) mutex.unlock(); - worker->start(); + if (ready) { + worker->start(); + } } diff --git a/src/backend/opencl/OclBackend.h b/src/backend/opencl/OclBackend.h index e6ba092ee..ade560baf 100644 --- a/src/backend/opencl/OclBackend.h +++ b/src/backend/opencl/OclBackend.h @@ -62,7 +62,7 @@ protected: void prepare(const Job &nextJob) override; void printHashrate(bool details) override; void setJob(const Job &job) override; - void start(IWorker *worker) override; + void start(IWorker *worker, bool ready) override; void stop() override; void tick(uint64_t ticks) override; diff --git a/src/backend/opencl/OclWorker.cpp b/src/backend/opencl/OclWorker.cpp index 4247fb786..b4132e3dd 100644 --- a/src/backend/opencl/OclWorker.cpp +++ b/src/backend/opencl/OclWorker.cpp @@ -137,6 +137,12 @@ bool xmrig::OclWorker::selfTest() } +size_t xmrig::OclWorker::intensity() const +{ + return m_runner ? m_runner->intensity() : 0; +} + + void xmrig::OclWorker::start() { cl_uint results[0x100]; diff --git a/src/backend/opencl/OclWorker.h b/src/backend/opencl/OclWorker.h index e28c784dc..93de8afd7 100644 --- a/src/backend/opencl/OclWorker.h +++ b/src/backend/opencl/OclWorker.h @@ -56,6 +56,7 @@ public: protected: bool selfTest() override; + size_t intensity() const override; void start() override; private: diff --git a/src/backend/opencl/interfaces/IOclRunner.h b/src/backend/opencl/interfaces/IOclRunner.h index c1718a2a7..0b47bcd29 100644 --- a/src/backend/opencl/interfaces/IOclRunner.h +++ b/src/backend/opencl/interfaces/IOclRunner.h @@ -51,18 +51,19 @@ public: IOclRunner() = default; virtual ~IOclRunner() = default; - virtual void run(uint32_t nonce, uint32_t *hashOutput) = 0; - virtual void set(const Job &job, uint8_t *blob) = 0; virtual cl_context ctx() const = 0; virtual const Algorithm &algorithm() const = 0; virtual const char *buildOptions() const = 0; virtual const char *deviceKey() const = 0; virtual const char *source() const = 0; virtual const OclLaunchData &data() const = 0; + virtual size_t intensity() const = 0; virtual size_t threadId() const = 0; virtual uint32_t deviceIndex() const = 0; virtual void build() = 0; virtual void init() = 0; + virtual void run(uint32_t nonce, uint32_t *hashOutput) = 0; + virtual void set(const Job &job, uint8_t *blob) = 0; protected: virtual size_t bufferSize() const = 0; diff --git a/src/backend/opencl/runners/OclBaseRunner.h b/src/backend/opencl/runners/OclBaseRunner.h index ea115957b..558d68077 100644 --- a/src/backend/opencl/runners/OclBaseRunner.h +++ b/src/backend/opencl/runners/OclBaseRunner.h @@ -55,6 +55,7 @@ protected: inline const char *deviceKey() const override { return m_deviceKey.c_str(); } inline const char *source() const override { return m_source; } inline const OclLaunchData &data() const override { return m_data; } + inline size_t intensity() const override { return m_intensity; } inline size_t threadId() const override { return m_threadId; } size_t bufferSize() const override;