diff --git a/src/backend/common/Worker.cpp b/src/backend/common/Worker.cpp index 98da61d41..5676f2c49 100644 --- a/src/backend/common/Worker.cpp +++ b/src/backend/common/Worker.cpp @@ -30,6 +30,7 @@ xmrig::Worker::Worker(size_t id, int64_t affinity, int priority) : + m_affinity(affinity), m_id(id), m_hashCount(0), m_timestamp(0), diff --git a/src/backend/common/Worker.h b/src/backend/common/Worker.h index faebf128c..a601ab05c 100644 --- a/src/backend/common/Worker.h +++ b/src/backend/common/Worker.h @@ -50,6 +50,7 @@ public: protected: void storeStats(); + const int64_t m_affinity; const size_t m_id; std::atomic m_hashCount; std::atomic m_timestamp; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index ffc21597b..2fc34b59c 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -295,7 +295,7 @@ rapidjson::Value xmrig::CpuBackend::toJSON(rapidjson::Document &doc) const # ifdef XMRIG_ALGO_RANDOMX if (d_ptr->algo.family() == Algorithm::RANDOM_X) { - RxDataset *dataset = Rx::dataset(); + RxDataset *dataset = Rx::dataset(-1); // FIXME if (dataset) { const auto rxPages = dataset->hugePages(); pages[0] += rxPages.first; diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 039c65f4a..ba66a45f6 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -29,11 +29,6 @@ #include "rapidjson/document.h" -#ifdef XMRIG_ALGO_RANDOMX -# include "crypto/rx/Rx.h" -#endif - - namespace xmrig { static const char *kCn = "cn"; @@ -140,10 +135,6 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value) m_assembly = Json::getValue(value, kAsm); # endif -# ifdef XMRIG_ALGO_RANDOMX - Rx::setInitThreads(m_initThreads); -# endif - if (!m_threads.read(value)) { generate(); } diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 0c44972fe..fc06bab91 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -56,6 +56,7 @@ public: inline bool isShouldSave() const { return m_shouldSave; } inline const Assembly &assembly() const { return m_assembly; } inline const Threads &threads() const { return m_threads; } + inline int initThreads() const { return m_initThreads; } inline int priority() const { return m_priority; } private: diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index b391654df..28642cd73 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -81,7 +81,15 @@ xmrig::CpuWorker::~CpuWorker() template void xmrig::CpuWorker::allocateRandomX_VM() { - RxDataset *dataset = Rx::dataset(m_job.currentJob().seedHash(), m_job.currentJob().algorithm()); + while (!Rx::isReady(m_job.currentJob(), m_affinity)) { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + if (Nonce::sequence(Nonce::CPU) == 0) { + break; + } + } + + RxDataset *dataset = Rx::dataset(m_affinity); if (!m_vm) { m_vm = new RxVm(dataset, m_memory->scratchpad(), !m_hwAES); diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 526c4fbfb..42f4247eb 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -24,6 +24,7 @@ #include +#include #include @@ -38,6 +39,7 @@ #include "core/Controller.h" #include "core/Miner.h" #include "crypto/common/Nonce.h" +#include "crypto/rx/Rx.h" #include "rapidjson/document.h" #include "version.h" @@ -362,6 +364,11 @@ void xmrig::Miner::setJob(const Job &job, bool donate) d_ptr->userJobId = job.id(); } +# ifdef XMRIG_ALGO_RANDOMX + const CpuConfig &cpu = d_ptr->controller->config()->cpu(); + Rx::init(job, cpu.initThreads(), cpu.isHugePages()); +# endif + uv_rwlock_wrunlock(&d_ptr->rwlock); d_ptr->handleJobChange(reset); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 6f2085964..88c9fbb2d 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -31,6 +31,7 @@ #include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" +#include "base/net/stratum/Job.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" #include "crypto/rx/Rx.h" @@ -52,7 +53,10 @@ public: inline ~RxPrivate() { - delete dataset; + for (RxDataset *dataset : datasets) { + delete dataset; + } + uv_mutex_destroy(&mutex); } @@ -61,35 +65,82 @@ public: inline void unlock() { uv_mutex_unlock(&mutex); } - int initThreads = -1; - RxDataset *dataset = nullptr; + std::vector datasets; uv_mutex_t mutex; }; static RxPrivate *d_ptr = new RxPrivate(); -static const char *tag = BLUE_BG(" rx "); +static const char *tag = BLUE_BG(WHITE_BOLD_S " rx "); } // namespace xmrig -xmrig::RxDataset *xmrig::Rx::dataset() +bool xmrig::Rx::isReady(const Job &job, int64_t) { d_ptr->lock(); - RxDataset *dataset = d_ptr->dataset; + const bool rc = isReady(job.seedHash(), job.algorithm()); + d_ptr->unlock(); + + return rc; +} + + + +xmrig::RxDataset *xmrig::Rx::dataset(int64_t) +{ + d_ptr->lock(); + RxDataset *dataset = d_ptr->datasets[0]; d_ptr->unlock(); return dataset; } -xmrig::RxDataset *xmrig::Rx::dataset(const uint8_t *seed, const Algorithm &algorithm, bool hugePages) +void xmrig::Rx::init(const Job &job, int initThreads, bool hugePages) +{ + d_ptr->lock(); + if (d_ptr->datasets.empty()) { + d_ptr->datasets.push_back(nullptr); + } + + if (isReady(job.seedHash(), job.algorithm())) { + d_ptr->unlock(); + + return; + } + + const uint32_t threads = initThreads < 1 ? static_cast(Cpu::info()->threads()) + : static_cast(initThreads); + + std::thread thread(initDataset, 0, job.seedHash(), job.algorithm(), threads, hugePages); + thread.detach(); + + d_ptr->unlock(); +} + + +void xmrig::Rx::stop() +{ + delete d_ptr; + + d_ptr = nullptr; +} + + +bool xmrig::Rx::isReady(const uint8_t *seed, const Algorithm &algorithm) +{ + return !d_ptr->datasets.empty() && d_ptr->datasets[0] != nullptr && d_ptr->datasets[0]->isReady(seed, algorithm); +} + + +void xmrig::Rx::initDataset(size_t index, const uint8_t *seed, const Algorithm &algorithm, uint32_t threads, bool hugePages) { d_ptr->lock(); - if (!d_ptr->dataset) { + if (!d_ptr->datasets[index]) { const uint64_t ts = Chrono::steadyMSecs(); LOG_INFO("%s" MAGENTA_BOLD(" allocate") CYAN_BOLD(" %zu MiB") BLACK_BOLD(" (%zu+%zu) for RandomX dataset & cache"), @@ -99,10 +150,10 @@ xmrig::RxDataset *xmrig::Rx::dataset(const uint8_t *seed, const Algorithm &algor RxCache::size() / 1024 / 1024 ); - d_ptr->dataset = new RxDataset(hugePages); + d_ptr->datasets[index] = new RxDataset(hugePages); - if (d_ptr->dataset->get() != nullptr) { - const auto hugePages = d_ptr->dataset->hugePages(); + if (d_ptr->datasets[index]->get() != nullptr) { + const auto hugePages = d_ptr->datasets[index]->hugePages(); const double percent = hugePages.first == 0 ? 0.0 : static_cast(hugePages.first) / hugePages.second * 100.0; LOG_INFO("%s" GREEN(" allocate done") " huge pages %s%u/%u %1.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), @@ -111,7 +162,7 @@ xmrig::RxDataset *xmrig::Rx::dataset(const uint8_t *seed, const Algorithm &algor hugePages.first, hugePages.second, percent, - d_ptr->dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", + d_ptr->datasets[index]->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", Chrono::steadyMSecs() - ts ); } @@ -120,12 +171,10 @@ xmrig::RxDataset *xmrig::Rx::dataset(const uint8_t *seed, const Algorithm &algor } } - if (!d_ptr->dataset->isReady(seed, algorithm)) { - const uint64_t ts = Chrono::steadyMSecs(); - const uint32_t threads = d_ptr->initThreads < 1 ? static_cast(Cpu::info()->threads()) - : static_cast(d_ptr->initThreads); + if (!d_ptr->datasets[index]->isReady(seed, algorithm)) { + const uint64_t ts = Chrono::steadyMSecs(); - if (d_ptr->dataset->get() != nullptr) { + if (d_ptr->datasets[index]->get() != nullptr) { LOG_INFO("%s" MAGENTA_BOLD(" init dataset") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."), tag, algorithm.shortName(), @@ -141,29 +190,10 @@ xmrig::RxDataset *xmrig::Rx::dataset(const uint8_t *seed, const Algorithm &algor ); } - d_ptr->dataset->init(seed, algorithm, threads); + d_ptr->datasets[index]->init(seed, algorithm, threads); LOG_INFO("%s" GREEN(" init done") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts); } - RxDataset *dataset = d_ptr->dataset; - d_ptr->unlock(); - - return dataset; -} - - -void xmrig::Rx::setInitThreads(int count) -{ - d_ptr->lock(); - d_ptr->initThreads = count; d_ptr->unlock(); } - - -void xmrig::Rx::stop() -{ - delete d_ptr; - - d_ptr = nullptr; -} diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index 1758c08ec..456dfe4e0 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -37,15 +37,20 @@ namespace xmrig class Algorithm; class RxDataset; +class Job; class Rx { public: - static RxDataset *dataset(); - static RxDataset *dataset(const uint8_t *seed, const Algorithm &algorithm, bool hugePages = true); - static void setInitThreads(int count); + static bool isReady(const Job &job, int64_t affinity); + static RxDataset *dataset(int64_t affinity); + static void init(const Job &job, int initThreads, bool hugePages); static void stop(); + +private: + static bool isReady(const uint8_t *seed, const Algorithm &algorithm); + static void initDataset(size_t index, const uint8_t *seed, const Algorithm &algorithm, uint32_t threads, bool hugePages); };