diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index 6990de204..bb2ca0f62 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -36,6 +36,7 @@ #include "crypto/common/Nonce.h" #include "crypto/common/VirtualMemory.h" #include "crypto/rx/Rx.h" +#include "crypto/rx/RxDataset.h" #include "crypto/rx/RxVm.h" #include "net/JobResults.h" @@ -118,7 +119,9 @@ void xmrig::CpuWorker::allocateRandomX_VM() } if (!m_vm) { - m_vm = RxVm::create(dataset, m_memory->scratchpad(), !m_hwAES, m_assembly, m_node); + // Try to allocate scratchpad from dataset's 1 GB huge pages, if normal huge pages are not available + uint8_t* scratchpad = m_memory->isHugePages() ? m_memory->scratchpad() : dataset->tryAllocateScrathpad(); + m_vm = RxVm::create(dataset, scratchpad ? scratchpad : m_memory->scratchpad(), !m_hwAES, m_assembly, m_node); } } #endif diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp index c6becb891..b34e6de0e 100644 --- a/src/crypto/common/VirtualMemory.cpp +++ b/src/crypto/common/VirtualMemory.cpp @@ -51,6 +51,7 @@ static std::mutex mutex; xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node, size_t alignSize) : m_size(align(size)), + m_capacity(m_size), m_node(node) { if (usePool) { @@ -69,6 +70,7 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages } if (oneGbPages && allocateOneGbPagesMemory()) { + m_capacity = align(size, 1ULL << 30); return; } diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index 0ca307755..d7fe783fa 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -52,6 +52,7 @@ public: inline bool isHugePages() const { return m_flags.test(FLAG_HUGEPAGES); } inline bool isOneGbPages() const { return m_flags.test(FLAG_1GB_PAGES); } inline size_t size() const { return m_size; } + inline size_t capacity() const { return m_capacity; } inline uint8_t *raw() const { return m_scratchpad; } inline uint8_t *scratchpad() const { return m_scratchpad; } @@ -88,6 +89,7 @@ private: void freeLargePagesMemory(); const size_t m_size; + size_t m_capacity; const uint32_t m_node; std::bitset m_flags; uint8_t *m_scratchpad = nullptr; diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index ef2371e0e..03b0f1559 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -193,6 +193,12 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages) } m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node); + + if (m_memory->isOneGbPages()) { + m_scratchpadOffset = maxSize() + RANDOMX_CACHE_MAX_SIZE; + m_scratchpadLimit = m_memory->capacity(); + } + m_dataset = randomx_create_dataset(m_memory->raw()); # ifdef XMRIG_OS_LINUX @@ -201,3 +207,19 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages) } # endif } + + +uint8_t* xmrig::RxDataset::tryAllocateScrathpad() +{ + uint8_t* p = reinterpret_cast(raw()); + if (!p) { + return nullptr; + } + + const size_t offset = m_scratchpadOffset.fetch_add(RANDOMX_SCRATCHPAD_L3_MAX_SIZE); + if (offset + RANDOMX_SCRATCHPAD_L3_MAX_SIZE > m_scratchpadLimit) { + return nullptr; + } + + return p + offset; +} diff --git a/src/crypto/rx/RxDataset.h b/src/crypto/rx/RxDataset.h index a6bb74557..798ec9965 100644 --- a/src/crypto/rx/RxDataset.h +++ b/src/crypto/rx/RxDataset.h @@ -36,6 +36,8 @@ #include "crypto/randomx/randomx.h" #include "crypto/rx/RxConfig.h" +#include + struct randomx_dataset; @@ -69,6 +71,8 @@ public: void *raw() const; void setRaw(const void *raw); + uint8_t *tryAllocateScrathpad(); + static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; } private: @@ -79,6 +83,9 @@ private: randomx_dataset *m_dataset = nullptr; RxCache *m_cache = nullptr; VirtualMemory *m_memory = nullptr; + + std::atomic m_scratchpadOffset; + size_t m_scratchpadLimit = 0; };