From f34031a9849668560df364adfc3add48d5348dc6 Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 4 Oct 2019 08:45:13 +0700 Subject: [PATCH] Added interface IRxStorage and RxBasicStorage class. --- cmake/randomx.cmake | 2 + src/backend/common/Tags.h | 5 + src/backend/common/common.cmake | 1 + src/backend/common/interfaces/IRxStorage.h | 53 +++++ src/crypto/rx/Rx.cpp | 229 ++++----------------- src/crypto/rx/Rx.h | 2 +- src/crypto/rx/RxBasicStorage.cpp | 160 ++++++++++++++ src/crypto/rx/RxBasicStorage.h | 63 ++++++ src/crypto/rx/RxDataset.cpp | 61 ++++-- src/crypto/rx/RxDataset.h | 6 +- 10 files changed, 372 insertions(+), 210 deletions(-) create mode 100644 src/backend/common/interfaces/IRxStorage.h create mode 100644 src/crypto/rx/RxBasicStorage.cpp create mode 100644 src/crypto/rx/RxBasicStorage.h diff --git a/cmake/randomx.cmake b/cmake/randomx.cmake index ac0acde9b..6c150d491 100644 --- a/cmake/randomx.cmake +++ b/cmake/randomx.cmake @@ -4,6 +4,7 @@ if (WITH_RANDOMX) list(APPEND HEADERS_CRYPTO src/crypto/rx/Rx.h src/crypto/rx/RxAlgo.h + src/crypto/rx/RxBasicStorage.h src/crypto/rx/RxCache.h src/crypto/rx/RxConfig.h src/crypto/rx/RxDataset.h @@ -33,6 +34,7 @@ if (WITH_RANDOMX) src/crypto/randomx/vm_interpreted.cpp src/crypto/rx/Rx.cpp src/crypto/rx/RxAlgo.cpp + src/crypto/rx/RxBasicStorage.cpp src/crypto/rx/RxCache.cpp src/crypto/rx/RxConfig.cpp src/crypto/rx/RxDataset.cpp diff --git a/src/backend/common/Tags.h b/src/backend/common/Tags.h index 938a1bc49..16022e33e 100644 --- a/src/backend/common/Tags.h +++ b/src/backend/common/Tags.h @@ -38,6 +38,11 @@ const char *ocl_tag(); #endif +#ifdef XMRIG_ALGO_RANDOMX +const char *rx_tag(); +#endif + + } // namespace xmrig diff --git a/src/backend/common/common.cmake b/src/backend/common/common.cmake index cddd40014..9dd0fb3c1 100644 --- a/src/backend/common/common.cmake +++ b/src/backend/common/common.cmake @@ -3,6 +3,7 @@ set(HEADERS_BACKEND_COMMON src/backend/common/Tags.h src/backend/common/interfaces/IBackend.h src/backend/common/interfaces/IRxListener.h + src/backend/common/interfaces/IRxStorage.h src/backend/common/interfaces/IThread.h src/backend/common/interfaces/IWorker.h src/backend/common/misc/PciTopology.h diff --git a/src/backend/common/interfaces/IRxStorage.h b/src/backend/common/interfaces/IRxStorage.h new file mode 100644 index 000000000..49273ee3d --- /dev/null +++ b/src/backend/common/interfaces/IRxStorage.h @@ -0,0 +1,53 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * 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 XMRIG_IRXSTORAGE_H +#define XMRIG_IRXSTORAGE_H + + +#include +#include + + +namespace xmrig { + + +class Job; +class RxDataset; +class RxSeed; + + +class IRxStorage +{ +public: + virtual ~IRxStorage() = default; + + virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0; + virtual std::pair hugePages() const = 0; + virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IRXSTORAGE_H diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 25b633ec9..f688a9dd7 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -28,6 +28,8 @@ #include "crypto/rx/Rx.h" #include "backend/common/interfaces/IRxListener.h" +#include "backend/common/interfaces/IRxStorage.h" +#include "backend/common/Tags.h" #include "backend/cpu/Cpu.h" #include "base/io/log/Log.h" #include "base/kernel/Platform.h" @@ -37,18 +39,13 @@ #include "base/tools/Handle.h" #include "base/tools/Object.h" #include "crypto/rx/RxAlgo.h" +#include "crypto/rx/RxBasicStorage.h" #include "crypto/rx/RxCache.h" #include "crypto/rx/RxConfig.h" #include "crypto/rx/RxDataset.h" #include "crypto/rx/RxSeed.h" -#ifdef XMRIG_FEATURE_HWLOC -# include -# include "backend/cpu/platform/HwlocCpuInfo.h" -#endif - - #include #include #include @@ -67,58 +64,18 @@ static RxPrivate *d_ptr = nullptr; static std::mutex mutex; -#ifdef XMRIG_FEATURE_HWLOC -static void bindToNUMANode(uint32_t nodeId) -{ - hwloc_topology_t topology; - hwloc_topology_init(&topology); - hwloc_topology_load(topology); - - hwloc_obj_t node = hwloc_get_numanode_obj_by_os_index(topology, nodeId); - if (node) { - if (HwlocCpuInfo::has(HwlocCpuInfo::SET_THISTHREAD_MEMBIND)) { -# if HWLOC_API_VERSION >= 0x20000 - hwloc_set_membind(topology, node->nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET); -# else - hwloc_set_membind_nodeset(topology, node->nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD); -# endif - } - - Platform::setThreadAffinity(static_cast(hwloc_bitmap_first(node->cpuset))); - } - - hwloc_topology_destroy(topology); -} -#else -inline static void bindToNUMANode(uint32_t) {} -#endif - - class RxPrivate { public: XMRIG_DISABLE_COPY_MOVE(RxPrivate) inline RxPrivate() : - m_counter(0), - m_last(0) + m_pending(0) { m_async = new uv_async_t; m_async->data = this; - uv_async_init(uv_default_loop(), m_async, [](uv_async_t *) { d_ptr->onReady(); }); - -# ifdef XMRIG_FEATURE_HWLOC - if (Cpu::info()->nodes() > 1) { - for (uint32_t nodeId : HwlocCpuInfo::nodeIndexes()) { - datasets.insert({ nodeId, nullptr }); - } - } - else -# endif - { - datasets.insert({ 0, nullptr }); - } + uv_async_init(uv_default_loop(), m_async, [](uv_async_t *handle) { static_cast(handle->data)->onReady(); }); } @@ -126,130 +83,66 @@ public: { Handle::close(m_async); - for (auto const &item : datasets) { - delete item.second; - } - - datasets.clear(); + delete m_storage; } - inline bool isNUMA() const { return m_numa; } - inline bool isReady(const Job &job) const { return m_ready == count() && m_seed == job; } - inline const Algorithm &algorithm() const { return m_seed.algorithm(); } - inline size_t count() const { return isNUMA() ? datasets.size() : 1; } - inline uint64_t counter() { return m_counter.load(std::memory_order_relaxed); } - inline void asyncSend(uint64_t counter) { m_ready++; if (m_ready == count()) { m_last = counter; uv_async_send(m_async); } } + inline bool isReady(const Job &job) const { return pending() == 0 && m_seed == job; } + inline RxDataset *dataset(const Job &job, uint32_t nodeId) { return m_storage ? m_storage->dataset(job, nodeId) : nullptr; } + inline std::pair hugePages() { return m_storage ? m_storage->hugePages() : std::pair(0u, 0u); } + inline uint64_t pending() const { return m_pending.load(std::memory_order_relaxed); } + inline void asyncSend() { --m_pending; if (pending() == 0) { uv_async_send(m_async); } } - static void allocate(uint32_t nodeId) + + inline IRxStorage *storage() { - const uint64_t ts = Chrono::steadyMSecs(); - - if (d_ptr->isNUMA()) { - bindToNUMANode(nodeId); + if (!m_storage) { + m_storage = new RxBasicStorage(); } - LOG_INFO("%s" CYAN_BOLD("#%u") MAGENTA_BOLD(" allocate") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu) for RandomX dataset & cache"), - tag, - nodeId, - (RxDataset::maxSize() + RxCache::maxSize()) / 1024 / 1024, - RxDataset::maxSize() / 1024 / 1024, - RxCache::maxSize() / 1024 / 1024 - ); - - auto dataset = new RxDataset(d_ptr->m_hugePages); - d_ptr->datasets[nodeId] = dataset; - - if (dataset->get() != nullptr) { - const auto hugePages = dataset->hugePages(); - const double percent = hugePages.first == 0 ? 0.0 : static_cast(hugePages.first) / hugePages.second * 100.0; - - LOG_INFO("%s" CYAN_BOLD("#%u") GREEN(" allocate done") " huge pages %s%u/%u %1.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), - tag, - nodeId, - (hugePages.first == hugePages.second ? GREEN_BOLD_S : (hugePages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), - hugePages.first, - hugePages.second, - percent, - dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", - Chrono::steadyMSecs() - ts - ); - } - else { - LOG_WARN(CLEAR "%s" CYAN_BOLD("#%u") YELLOW_BOLD_S " failed to allocate RandomX dataset, switching to slow mode", tag, nodeId); - } + return m_storage; } - static void initDataset(uint32_t nodeId, uint32_t threads, uint64_t counter) + static void initDataset(const RxSeed &seed, uint32_t threads, bool hugePages) { std::lock_guard lock(mutex); - const uint64_t ts = Chrono::steadyMSecs(); + LOG_INFO("%s" MAGENTA_BOLD("init dataset%s") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."), + tag, + false ? "s" : "", // FIXME + seed.algorithm().shortName(), + threads, + Buffer::toHex(seed.data().data(), 8).data() + ); - d_ptr->getOrAllocate(nodeId)->init(d_ptr->m_seed.data(), threads); - d_ptr->asyncSend(counter); - - LOG_INFO("%s" CYAN_BOLD("#%u") GREEN(" init done ") CYAN_BOLD("%zu/%zu") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, nodeId, d_ptr->m_ready, d_ptr->count(), Chrono::steadyMSecs() - ts); + d_ptr->storage()->init(seed, threads, hugePages); + d_ptr->asyncSend(); } - inline RxDataset *getOrAllocate(uint32_t nodeId) + inline void setState(const Job &job, IRxListener *listener) { - RxDataset *dataset = datasets.at(nodeId); - - if (dataset == nullptr) { - # ifdef XMRIG_FEATURE_HWLOC - if (d_ptr->isNUMA()) { - std::thread thread(allocate, nodeId); - thread.join(); - } else - # endif - { - allocate(nodeId); - } - - dataset = datasets.at(nodeId); - } - - return dataset; - } - - - inline void setState(const Job &job, bool hugePages, bool numa, IRxListener *listener) - { - if (m_seed.algorithm() != job.algorithm()) { - RxAlgo::apply(job.algorithm()); - } - - m_ready = 0; - m_numa = numa; - m_hugePages = hugePages; m_listener = listener; m_seed = job; - ++m_counter; + ++m_pending; } - std::map datasets; - private: inline void onReady() { - if (m_listener && counter() == m_last.load(std::memory_order_relaxed)) { + if (m_listener && pending() == 0) { m_listener->onDatasetReady(); } } - bool m_hugePages = true; - bool m_numa = true; - RxSeed m_seed; IRxListener *m_listener = nullptr; - size_t m_ready = 0; - std::atomic m_counter; - std::atomic m_last; + IRxStorage *m_storage = nullptr; + RxSeed m_seed; + std::atomic m_pending; uv_async_t *m_async = nullptr; }; @@ -257,44 +150,26 @@ private: } // namespace xmrig +const char *xmrig::rx_tag() +{ + return tag; +} + + bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages, IRxListener *listener) { if (job.algorithm().family() != Algorithm::RANDOM_X) { return true; } - std::lock_guard lock(mutex); - if (d_ptr->isReady(job)) { return true; } - d_ptr->setState(job, hugePages, config.isNUMA(), listener); - const uint32_t threads = config.threads(); - const String buf = Buffer::toHex(job.seed().data(), 8); - const uint64_t counter = d_ptr->counter(); + d_ptr->setState(job, listener); - LOG_INFO("%s" MAGENTA_BOLD("init dataset%s") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."), - tag, - d_ptr->count() > 1 ? "s" : "", - job.algorithm().shortName(), - threads, - buf.data() - ); - -# ifdef XMRIG_FEATURE_HWLOC - if (d_ptr->isNUMA()) { - for (auto const &item : d_ptr->datasets) { - std::thread thread(RxPrivate::initDataset, item.first, threads, counter); - thread.detach(); - } - } - else -# endif - { - std::thread thread(RxPrivate::initDataset, 0, threads, counter); - thread.detach(); - } + std::thread thread(RxPrivate::initDataset, job, config.threads(), hugePages); + thread.detach(); return false; } @@ -302,8 +177,6 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages, IRx bool xmrig::Rx::isReady(const Job &job) { - std::lock_guard lock(mutex); - return d_ptr->isReady(job); } @@ -311,30 +184,16 @@ bool xmrig::Rx::isReady(const Job &job) xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) { std::lock_guard lock(mutex); - if (!d_ptr->isReady(job)) { - return nullptr; - } - return d_ptr->datasets.at(d_ptr->isNUMA() ? (d_ptr->datasets.count(nodeId) ? nodeId : HwlocCpuInfo::nodeIndexes().front()) : 0); + return d_ptr->dataset(job, nodeId); } -std::pair xmrig::Rx::hugePages() +std::pair xmrig::Rx::hugePages() { - std::pair pages(0, 0); std::lock_guard lock(mutex); - for (auto const &item : d_ptr->datasets) { - if (!item.second) { - continue; - } - - const auto p = item.second->hugePages(); - pages.first += p.first; - pages.second += p.second; - } - - return pages; + return d_ptr->hugePages(); } diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index 33eddc189..df3194137 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -49,7 +49,7 @@ public: static bool init(const Job &job, const RxConfig &config, bool hugePages, IRxListener *listener); static bool isReady(const Job &job); static RxDataset *dataset(const Job &job, uint32_t nodeId); - static std::pair hugePages(); + static std::pair hugePages(); static void destroy(); static void init(); }; diff --git a/src/crypto/rx/RxBasicStorage.cpp b/src/crypto/rx/RxBasicStorage.cpp new file mode 100644 index 000000000..6b1509cc8 --- /dev/null +++ b/src/crypto/rx/RxBasicStorage.cpp @@ -0,0 +1,160 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2019 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 tevador + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "crypto/rx/RxBasicStorage.h" +#include "backend/common/Tags.h" +#include "base/io/log/Log.h" +#include "base/tools/Chrono.h" +#include "crypto/rx/RxAlgo.h" +#include "crypto/rx/RxCache.h" +#include "crypto/rx/RxDataset.h" +#include "crypto/rx/RxSeed.h" + + +namespace xmrig { + + +constexpr size_t oneMiB = 1024 * 1024; + + +class RxBasicStoragePrivate +{ +public: + inline bool isReady(const Job &job) const { return m_ready && m_seed == job; } + inline RxDataset *dataset() const { return m_dataset; } + + + inline void setSeed(const RxSeed &seed) + { + m_ready = false; + + if (m_seed.algorithm() != seed.algorithm()) { + RxAlgo::apply(seed.algorithm()); + } + + m_seed = seed; + } + + + inline void createDataset(bool hugePages) + { + const uint64_t ts = Chrono::steadyMSecs(); + + m_dataset = new RxDataset(hugePages, true); + printAllocStatus(ts); + } + + + inline void initDataset(uint32_t threads, uint64_t ts) + { + m_dataset->init(m_seed.data(), threads); + + LOG_INFO("%s" GREEN_BOLD("dataset ready") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts); + + m_ready = true; + } + + +private: + void printAllocStatus(uint64_t ts) + { + if (m_dataset->get() != nullptr) { + const auto pages = m_dataset->hugePages(); + const double percent = pages.first == 0 ? 0.0 : static_cast(pages.first) / pages.second * 100.0; + + LOG_INFO("%s" GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu)") " huge pages %s%u/%u %1.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), + rx_tag(), + (RxDataset::maxSize() + RxCache::maxSize()) / oneMiB, + RxDataset::maxSize() / oneMiB, + RxCache::maxSize() / oneMiB, + (pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + pages.first, + pages.second, + percent, + m_dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", + Chrono::steadyMSecs() - ts + ); + } + else { + LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "failed to allocate RandomX dataset, switching to slow mode" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts); + } + } + + + bool m_ready = false; + RxDataset *m_dataset = nullptr; + RxSeed m_seed; +}; + + +} // namespace xmrig + + +xmrig::RxBasicStorage::RxBasicStorage() : + d_ptr(new RxBasicStoragePrivate()) +{ +} + + +xmrig::RxBasicStorage::~RxBasicStorage() +{ + delete d_ptr; +} + + +xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const +{ + if (!d_ptr->isReady(job)) { + return nullptr; + } + + return d_ptr->dataset(); +} + + +std::pair xmrig::RxBasicStorage::hugePages() const +{ + if (!d_ptr->dataset()) { + return { 0u, 0u }; + } + + return d_ptr->dataset()->hugePages(); +} + + +void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages) +{ + const uint64_t ts = Chrono::steadyMSecs(); + + d_ptr->setSeed(seed); + + if (!d_ptr->dataset()) { + d_ptr->createDataset(hugePages); + } + + d_ptr->initDataset(threads, ts); +} diff --git a/src/crypto/rx/RxBasicStorage.h b/src/crypto/rx/RxBasicStorage.h new file mode 100644 index 000000000..d6dad10dc --- /dev/null +++ b/src/crypto/rx/RxBasicStorage.h @@ -0,0 +1,63 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2019 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 tevador + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 XMRIG_RX_VM_H +#define XMRIG_RX_VM_H + + +#include "backend/common/interfaces/IRxStorage.h" +#include "base/tools/Object.h" + + +namespace xmrig +{ + + +class RxBasicStoragePrivate; + + +class RxBasicStorage : public IRxStorage +{ +public: + XMRIG_DISABLE_COPY_MOVE(RxBasicStorage); + + RxBasicStorage(); + ~RxBasicStorage() override; + +protected: + RxDataset *dataset(const Job &job, uint32_t nodeId) const override; + std::pair hugePages() const override; + void init(const RxSeed &seed, uint32_t threads, bool hugePages) override; + +private: + RxBasicStoragePrivate *d_ptr; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_RX_VM_H */ diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index 7384a9825..f5572c2a8 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -25,32 +25,26 @@ */ -#include - - +#include "crypto/rx/RxDataset.h" #include "crypto/common/VirtualMemory.h" #include "crypto/randomx/randomx.h" #include "crypto/rx/RxAlgo.h" #include "crypto/rx/RxCache.h" -#include "crypto/rx/RxDataset.h" + + +#include static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch"); -xmrig::RxDataset::RxDataset(bool hugePages) +xmrig::RxDataset::RxDataset(bool hugePages, bool cache) { - if (hugePages) { - m_flags = RANDOMX_FLAG_LARGE_PAGES; - m_dataset = randomx_alloc_dataset(static_cast(m_flags)); - } + allocate(hugePages); - if (!m_dataset) { - m_flags = RANDOMX_FLAG_DEFAULT; - m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + if (cache) { + m_cache = new RxCache(hugePages); } - - m_cache = new RxCache(hugePages); } @@ -66,7 +60,11 @@ xmrig::RxDataset::~RxDataset() bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads) { - cache()->init(seed); + if (!m_cache) { + return false; + } + + m_cache->init(seed); if (!get()) { return true; @@ -96,18 +94,23 @@ bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads) } -std::pair xmrig::RxDataset::hugePages() const +std::pair xmrig::RxDataset::hugePages(bool cache) const { - constexpr size_t twoMiB = 2u * 1024u * 1024u; - constexpr const size_t total = (VirtualMemory::align(maxSize(), twoMiB) + VirtualMemory::align(RxCache::maxSize(), twoMiB)) / twoMiB; + constexpr size_t twoMiB = 2u * 1024u * 1024u; + constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB; + size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB; - size_t count = 0; + uint32_t count = 0; if (isHugePages()) { - count += VirtualMemory::align(maxSize(), twoMiB) / twoMiB; + count += total; } - if (m_cache->isHugePages()) { - count += VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB; + if (cache && m_cache) { + total += cacheSize; + + if (m_cache->isHugePages()) { + count += cacheSize; + } } return { count, total }; @@ -118,3 +121,17 @@ void *xmrig::RxDataset::raw() const { return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr; } + + +void xmrig::RxDataset::allocate(bool hugePages) +{ + if (hugePages) { + m_flags = RANDOMX_FLAG_LARGE_PAGES; + m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + } + + if (!m_dataset) { + m_flags = RANDOMX_FLAG_DEFAULT; + m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + } +} diff --git a/src/crypto/rx/RxDataset.h b/src/crypto/rx/RxDataset.h index e1b359a40..5ca10e004 100644 --- a/src/crypto/rx/RxDataset.h +++ b/src/crypto/rx/RxDataset.h @@ -49,7 +49,7 @@ class RxDataset public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset) - RxDataset(bool hugePages = true); + RxDataset(bool hugePages, bool cache); ~RxDataset(); inline bool isHugePages() const { return m_flags & 1; } @@ -58,12 +58,14 @@ public: inline size_t size() const { return maxSize(); } bool init(const Buffer &seed, uint32_t numThreads); - std::pair hugePages() const; + std::pair hugePages(bool cache = true) const; void *raw() const; static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; } private: + void allocate(bool hugePages); + Algorithm m_algorithm; int m_flags = 0; randomx_dataset *m_dataset = nullptr;