From 450b9ec19a77eaaf1332ebe8c0a5e231bdf2f245 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Tue, 3 Dec 2019 20:25:51 +0100 Subject: [PATCH 1/2] Update VirtualMemory_unix.cpp --- src/crypto/common/VirtualMemory_unix.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index 3d099c761..ffa4b137d 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -58,12 +58,24 @@ void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size) void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) { + int flag_1gb = 0; + # if defined(__APPLE__) void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); # elif defined(__FreeBSD__) void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0); # else - void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0); + +# if defined(MAP_HUGE_1GB) + flag_1gb = (size > (1UL << 30)) ? MAP_HUGE_1GB : 0; +# elif defined(MAP_HUGE_SHIFT) + flag_1gb = (size > (1UL << 30)) ? (30 << MAP_HUGE_SHIFT) : 0; +# endif + + void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_1gb, 0, 0); + if (mem == MAP_FAILED) { + mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0); + } # endif return mem == MAP_FAILED ? nullptr : mem; From 1fbbae1e4a186cbb82cdeaff6088bb03f450e8b8 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Thu, 5 Dec 2019 19:39:47 +0100 Subject: [PATCH 2/2] Added 1GB hugepages support for Linux --- src/Summary.cpp | 9 +++-- src/backend/common/interfaces/IRxStorage.h | 6 ++-- src/backend/cpu/CpuConfig.cpp | 11 +++--- src/backend/cpu/CpuConfig.h | 2 ++ src/backend/cpu/interfaces/ICpuInfo.h | 1 + src/backend/cpu/platform/BasicCpuInfo.cpp | 14 +++++++- src/backend/cpu/platform/BasicCpuInfo.h | 2 ++ src/config.json | 1 + src/core/Miner.cpp | 2 +- src/crypto/common/VirtualMemory.h | 2 ++ src/crypto/common/VirtualMemory_unix.cpp | 42 ++++++++++++++++++---- src/crypto/common/VirtualMemory_win.cpp | 12 +++++++ src/crypto/randomx/allocator.cpp | 8 +++++ src/crypto/randomx/allocator.hpp | 5 +++ src/crypto/randomx/randomx.cpp | 6 +++- src/crypto/randomx/randomx.h | 1 + src/crypto/randomx/virtual_memory.cpp | 10 ++++++ src/crypto/randomx/virtual_memory.hpp | 1 + src/crypto/rx/Rx.cpp | 4 +-- src/crypto/rx/Rx.h | 2 +- src/crypto/rx/RxBasicStorage.cpp | 8 ++--- src/crypto/rx/RxBasicStorage.h | 2 +- src/crypto/rx/RxDataset.cpp | 21 +++++++---- src/crypto/rx/RxDataset.h | 8 +++-- src/crypto/rx/RxNUMAStorage.cpp | 12 +++---- src/crypto/rx/RxNUMAStorage.h | 2 +- src/crypto/rx/RxQueue.cpp | 6 ++-- src/crypto/rx/RxQueue.h | 6 ++-- 28 files changed, 156 insertions(+), 50 deletions(-) diff --git a/src/Summary.cpp b/src/Summary.cpp index 757297c52..db8ce9fa3 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -63,6 +63,8 @@ static void print_memory(Config *config) { # ifdef _WIN32 Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", "HUGE PAGES", config->cpu().isHugePages() ? (VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable")) : RED_BOLD("disabled")); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", + "1GB PAGES", Cpu::info()->hasOneGbPages() ? GREEN_BOLD("available on Linux") : RED_BOLD("unavailable")); # endif } @@ -71,12 +73,13 @@ static void print_cpu(Config *) { const ICpuInfo *info = Cpu::info(); - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%zu)") " %sx64 %sAES", + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%zu)") " %sx64 %sAES %sPDPE1GB", "CPU", info->brand(), info->packages(), - info->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-", - info->hasAES() ? GREEN_BOLD_S : RED_BOLD_S "-" + info->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-", + info->hasAES() ? GREEN_BOLD_S : RED_BOLD_S "-", + info->hasOneGbPages() ? GREEN_BOLD_S : RED_BOLD_S "-" ); # if defined(XMRIG_FEATURE_LIBCPUID) || defined (XMRIG_FEATURE_HWLOC) Log::print(WHITE_BOLD(" %-13s") BLACK_BOLD("L2:") WHITE_BOLD("%.1f MB") BLACK_BOLD(" L3:") WHITE_BOLD("%.1f MB") diff --git a/src/backend/common/interfaces/IRxStorage.h b/src/backend/common/interfaces/IRxStorage.h index 9e0407b04..f64850f77 100644 --- a/src/backend/common/interfaces/IRxStorage.h +++ b/src/backend/common/interfaces/IRxStorage.h @@ -44,9 +44,9 @@ 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, RxConfig::Mode mode) = 0; + 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, bool oneGbPages, RxConfig::Mode mode) = 0; }; diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 7ebe904bd..fb95f942e 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -34,6 +34,7 @@ namespace xmrig { static const char *kEnabled = "enabled"; static const char *kHugePages = "huge-pages"; +static const char *kOneGbPages = "1gb-pages"; static const char *kHwAes = "hw-aes"; static const char *kMaxThreadsHint = "max-threads-hint"; static const char *kMemoryPool = "memory-pool"; @@ -68,6 +69,7 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kEnabled), m_enabled, allocator); obj.AddMember(StringRef(kHugePages), m_hugePages, allocator); + obj.AddMember(StringRef(kOneGbPages), m_oneGbPages, allocator); obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator); obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator); obj.AddMember(StringRef(kMemoryPool), m_memoryPool < 1 ? Value(m_memoryPool < 0) : Value(m_memoryPool), allocator); @@ -119,10 +121,11 @@ std::vector xmrig::CpuConfig::get(const Miner *miner, cons void xmrig::CpuConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { - m_enabled = Json::getBool(value, kEnabled, m_enabled); - m_hugePages = Json::getBool(value, kHugePages, m_hugePages); - m_limit = Json::getUint(value, kMaxThreadsHint, m_limit); - m_yield = Json::getBool(value, kYield, m_yield); + m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_hugePages = Json::getBool(value, kHugePages, m_hugePages); + m_oneGbPages = Json::getBool(value, kOneGbPages, m_oneGbPages); + m_limit = Json::getUint(value, kMaxThreadsHint, m_limit); + m_yield = Json::getBool(value, kYield, m_yield); setAesMode(Json::getValue(value, kHwAes)); setPriority(Json::getInt(value, kPriority, -1)); diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 2306057fc..74894dcd3 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -54,6 +54,7 @@ public: inline bool isEnabled() const { return m_enabled; } inline bool isHugePages() const { return m_hugePages; } + inline bool isOneGbPages() const { return m_oneGbPages; } inline bool isShouldSave() const { return m_shouldSave; } inline bool isYield() const { return m_yield; } inline const Assembly &assembly() const { return m_assembly; } @@ -72,6 +73,7 @@ private: Assembly m_assembly; bool m_enabled = true; bool m_hugePages = true; + bool m_oneGbPages = false; bool m_shouldSave = false; bool m_yield = true; int m_memoryPool = 0; diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index 20e72391b..2ffd00f2c 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -48,6 +48,7 @@ public: virtual Assembly::Id assembly() const = 0; virtual bool hasAES() const = 0; virtual bool hasAVX2() const = 0; + virtual bool hasOneGbPages() const = 0; virtual const char *backend() const = 0; virtual const char *brand() const = 0; virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0; diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index db3741ee1..cdc810c30 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -45,6 +45,10 @@ # define bit_AVX2 (1 << 5) #endif +#ifndef bit_PDPE1GB +# define bit_PDPE1GB (1 << 26) +#endif + #include "backend/cpu/platform/BasicCpuInfo.h" #include "crypto/common/Assembly.h" @@ -53,6 +57,7 @@ #define VENDOR_ID (0) #define PROCESSOR_INFO (1) #define EXTENDED_FEATURES (7) +#define PROCESSOR_EXT_INFO (0x80000001) #define PROCESSOR_BRAND_STRING_1 (0x80000002) #define PROCESSOR_BRAND_STRING_2 (0x80000003) #define PROCESSOR_BRAND_STRING_3 (0x80000004) @@ -136,6 +141,12 @@ static inline bool has_avx2() } +static inline bool has_pdpe1gb() +{ + return has_feature(PROCESSOR_EXT_INFO, EDX_Reg, bit_PDPE1GB); +} + + } // namespace xmrig @@ -144,7 +155,8 @@ xmrig::BasicCpuInfo::BasicCpuInfo() : m_threads(std::thread::hardware_concurrency()), m_assembly(Assembly::NONE), m_aes(has_aes_ni()), - m_avx2(has_avx2()) + m_avx2(has_avx2()), + m_pdpe1gb(has_pdpe1gb()) { cpu_brand_string(m_brand); diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index 4c68c5f81..ecbd3e237 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -44,6 +44,7 @@ protected: inline Assembly::Id assembly() const override { return m_assembly; } inline bool hasAES() const override { return m_aes; } inline bool hasAVX2() const override { return m_avx2; } + inline bool hasOneGbPages() const override { return m_pdpe1gb; } inline const char *brand() const override { return m_brand; } inline size_t cores() const override { return 0; } inline size_t L2() const override { return 0; } @@ -60,6 +61,7 @@ private: Assembly m_assembly; bool m_aes; const bool m_avx2; + const bool m_pdpe1gb; }; diff --git a/src/config.json b/src/config.json index df366c0ff..dd64f407d 100644 --- a/src/config.json +++ b/src/config.json @@ -22,6 +22,7 @@ "cpu": { "enabled": true, "huge-pages": true, + "1gb-pages": false, "hw-aes": null, "priority": null, "memory-pool": false, diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 5551268a6..4e2f24bac 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -236,7 +236,7 @@ public: # ifdef XMRIG_ALGO_RANDOMX inline bool initRX() { - return Rx::init(job, controller->config()->rx(), controller->config()->cpu().isHugePages()); + return Rx::init(job, controller->config()->rx(), controller->config()->cpu().isHugePages(), controller->config()->cpu().isOneGbPages()); } # endif diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index 1c2e37d20..90ecdd691 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -61,6 +61,7 @@ public: static uint32_t bindToNUMANode(int64_t affinity); static void *allocateExecutableMemory(size_t size); static void *allocateLargePagesMemory(size_t size); + static void *allocateOneGbPagesMemory(size_t size); static void destroy(); static void flushInstructionCache(void *p, size_t size); static void freeLargePagesMemory(void *p, size_t size); @@ -81,6 +82,7 @@ private: static void osInit(bool hugePages); bool allocateLargePagesMemory(); + bool allocateOneGbPagesMemory(); void freeLargePagesMemory(); const size_t m_size; diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index ffa4b137d..2e6eed304 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -58,24 +58,33 @@ void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size) void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) { - int flag_1gb = 0; - # if defined(__APPLE__) void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); # elif defined(__FreeBSD__) void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0); # else + void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0); +# endif + + return mem == MAP_FAILED ? nullptr : mem; +} + + +void *xmrig::VirtualMemory::allocateOneGbPagesMemory(size_t size) +{ +# if defined(__APPLE__) + void *mem = MAP_FAILED; +# elif defined(__FreeBSD__) + void *mem = MAP_FAILED; +# else # if defined(MAP_HUGE_1GB) - flag_1gb = (size > (1UL << 30)) ? MAP_HUGE_1GB : 0; + constexpr int flag_1gb = MAP_HUGE_1GB; # elif defined(MAP_HUGE_SHIFT) - flag_1gb = (size > (1UL << 30)) ? (30 << MAP_HUGE_SHIFT) : 0; + constexpr int flag_1gb = (30 << MAP_HUGE_SHIFT); # endif void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_1gb, 0, 0); - if (mem == MAP_FAILED) { - mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0); - } # endif return mem == MAP_FAILED ? nullptr : mem; @@ -132,6 +141,25 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory() } +bool xmrig::VirtualMemory::allocateOneGbPagesMemory() +{ + m_scratchpad = static_cast(allocateOneGbPagesMemory(m_size)); + if (m_scratchpad) { + m_flags.set(FLAG_HUGEPAGES, true); + + madvise(m_scratchpad, m_size, MADV_RANDOM | MADV_WILLNEED); + + if (mlock(m_scratchpad, m_size) == 0) { + m_flags.set(FLAG_LOCK, true); + } + + return true; + } + + return false; +} + + void xmrig::VirtualMemory::freeLargePagesMemory() { if (m_flags.test(FLAG_LOCK)) { diff --git a/src/crypto/common/VirtualMemory_win.cpp b/src/crypto/common/VirtualMemory_win.cpp index bfd8de1d6..70e48d3a0 100644 --- a/src/crypto/common/VirtualMemory_win.cpp +++ b/src/crypto/common/VirtualMemory_win.cpp @@ -175,6 +175,12 @@ void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size) } +void *xmrig::VirtualMemory::allocateOneGbPagesMemory(size_t size) +{ + return nullptr; +} + + void xmrig::VirtualMemory::flushInstructionCache(void *p, size_t size) { ::FlushInstructionCache(GetCurrentProcess(), p, size); @@ -221,6 +227,12 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory() return false; } +bool xmrig::VirtualMemory::allocateOneGbPagesMemory() +{ + m_scratchpad = nullptr; + return false; +} + void xmrig::VirtualMemory::freeLargePagesMemory() { diff --git a/src/crypto/randomx/allocator.cpp b/src/crypto/randomx/allocator.cpp index ff708a62c..d46393f1f 100644 --- a/src/crypto/randomx/allocator.cpp +++ b/src/crypto/randomx/allocator.cpp @@ -57,4 +57,12 @@ namespace randomx { freePagedMemory(ptr, count); }; + void* OneGbPageAllocator::allocMemory(size_t count) { + return allocOneGbPagesMemory(count); + } + + void OneGbPageAllocator::freeMemory(void* ptr, size_t count) { + freePagedMemory(ptr, count); + }; + } diff --git a/src/crypto/randomx/allocator.hpp b/src/crypto/randomx/allocator.hpp index d7aa3f95d..74d8b0688 100644 --- a/src/crypto/randomx/allocator.hpp +++ b/src/crypto/randomx/allocator.hpp @@ -43,4 +43,9 @@ namespace randomx { static void freeMemory(void*, size_t); }; + struct OneGbPageAllocator { + static void* allocMemory(size_t); + static void freeMemory(void*, size_t); + }; + } \ No newline at end of file diff --git a/src/crypto/randomx/randomx.cpp b/src/crypto/randomx/randomx.cpp index f9ce93f8c..44d881ebf 100644 --- a/src/crypto/randomx/randomx.cpp +++ b/src/crypto/randomx/randomx.cpp @@ -333,7 +333,11 @@ extern "C" { try { dataset = new randomx_dataset(); - if (flags & RANDOMX_FLAG_LARGE_PAGES) { + if (flags & RANDOMX_FLAG_1GB_PAGES) { + dataset->dealloc = &randomx::deallocDataset; + dataset->memory = (uint8_t*)randomx::OneGbPageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); + } + else if (flags & RANDOMX_FLAG_LARGE_PAGES) { dataset->dealloc = &randomx::deallocDataset; dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); } diff --git a/src/crypto/randomx/randomx.h b/src/crypto/randomx/randomx.h index ea3bb0990..95bfdbf47 100644 --- a/src/crypto/randomx/randomx.h +++ b/src/crypto/randomx/randomx.h @@ -48,6 +48,7 @@ enum randomx_flags { RANDOMX_FLAG_HARD_AES = 2, RANDOMX_FLAG_FULL_MEM = 4, RANDOMX_FLAG_JIT = 8, + RANDOMX_FLAG_1GB_PAGES = 16, }; diff --git a/src/crypto/randomx/virtual_memory.cpp b/src/crypto/randomx/virtual_memory.cpp index 06165ffb6..48a8a8d25 100644 --- a/src/crypto/randomx/virtual_memory.cpp +++ b/src/crypto/randomx/virtual_memory.cpp @@ -53,6 +53,16 @@ void* allocLargePagesMemory(std::size_t bytes) { } +void* allocOneGbPagesMemory(std::size_t bytes) { + void* mem = xmrig::VirtualMemory::allocateOneGbPagesMemory(bytes); + if (mem == nullptr) { + throw std::runtime_error("Failed to allocate 1GB pages memory"); + } + + return mem; +} + + void freePagedMemory(void* ptr, std::size_t bytes) { xmrig::VirtualMemory::freeLargePagesMemory(ptr, bytes); } diff --git a/src/crypto/randomx/virtual_memory.hpp b/src/crypto/randomx/virtual_memory.hpp index d3b31db12..8c5b49005 100644 --- a/src/crypto/randomx/virtual_memory.hpp +++ b/src/crypto/randomx/virtual_memory.hpp @@ -32,4 +32,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. void* allocExecutableMemory(std::size_t); void* allocLargePagesMemory(std::size_t); +void* allocOneGbPagesMemory(std::size_t); void freePagedMemory(void*, std::size_t); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index b08f844e3..a5767352a 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -60,7 +60,7 @@ const char *xmrig::rx_tag() } -bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages) +bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages, bool oneGbPages) { if (job.algorithm().family() != Algorithm::RANDOM_X) { return true; @@ -70,7 +70,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages) return true; } - d_ptr->queue.enqueue(job, config.nodeset(), config.threads(), hugePages, config.mode()); + d_ptr->queue.enqueue(job, config.nodeset(), config.threads(), hugePages, oneGbPages, config.mode()); return false; } diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index 4a81f5d5b..74a7ef595 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -46,7 +46,7 @@ class RxDataset; class Rx { public: - static bool init(const Job &job, const RxConfig &config, bool hugePages); + static bool init(const Job &job, const RxConfig &config, bool hugePages, bool oneGbPages); static bool isReady(const Job &job); static RxDataset *dataset(const Job &job, uint32_t nodeId); static std::pair hugePages(); diff --git a/src/crypto/rx/RxBasicStorage.cpp b/src/crypto/rx/RxBasicStorage.cpp index bc1ceb2d3..67ede47f9 100644 --- a/src/crypto/rx/RxBasicStorage.cpp +++ b/src/crypto/rx/RxBasicStorage.cpp @@ -69,11 +69,11 @@ public: } - inline void createDataset(bool hugePages, RxConfig::Mode mode) + inline void createDataset(bool hugePages, bool oneGbPages, RxConfig::Mode mode) { const uint64_t ts = Chrono::steadyMSecs(); - m_dataset = new RxDataset(hugePages, true, mode); + m_dataset = new RxDataset(hugePages, oneGbPages, true, mode); printAllocStatus(ts); } @@ -157,12 +157,12 @@ std::pair xmrig::RxBasicStorage::hugePages() const } -void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) +void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) { d_ptr->setSeed(seed); if (!d_ptr->dataset()) { - d_ptr->createDataset(hugePages, mode); + d_ptr->createDataset(hugePages, oneGbPages, mode); } d_ptr->initDataset(threads); diff --git a/src/crypto/rx/RxBasicStorage.h b/src/crypto/rx/RxBasicStorage.h index bd6575d22..edabff658 100644 --- a/src/crypto/rx/RxBasicStorage.h +++ b/src/crypto/rx/RxBasicStorage.h @@ -50,7 +50,7 @@ public: 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, RxConfig::Mode mode) override; + void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) override; private: RxBasicStoragePrivate *d_ptr; diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index ce41a58ea..2b387e3c6 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -29,7 +29,6 @@ #include "backend/common/Tags.h" #include "base/io/log/Log.h" #include "crypto/common/VirtualMemory.h" -#include "crypto/randomx/randomx.h" #include "crypto/rx/RxAlgo.h" #include "crypto/rx/RxCache.h" @@ -41,10 +40,10 @@ static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch"); -xmrig::RxDataset::RxDataset(bool hugePages, bool cache, RxConfig::Mode mode) : +xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode) : m_mode(mode) { - allocate(hugePages); + allocate(hugePages, oneGbPages); if (cache) { m_cache = new RxCache(hugePages); @@ -123,11 +122,13 @@ size_t xmrig::RxDataset::size(bool cache) const std::pair xmrig::RxDataset::hugePages(bool cache) const { constexpr size_t twoMiB = 2U * 1024U * 1024U; + constexpr size_t oneGiB = 1024U * 1024U * 1024U; constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB; - size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB; + size_t datasetPageSize = isOneGbPages() ? oneGiB : twoMiB; + size_t total = VirtualMemory::align(maxSize(), datasetPageSize) / datasetPageSize; uint32_t count = 0; - if (isHugePages()) { + if (isHugePages() || isOneGbPages()) { count += total; } @@ -159,7 +160,7 @@ void xmrig::RxDataset::setRaw(const void *raw) } -void xmrig::RxDataset::allocate(bool hugePages) +void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages) { if (m_mode == RxConfig::LightMode) { LOG_ERR(CLEAR "%s" RED_BOLD_S "fast RandomX mode disabled by config", rx_tag()); @@ -174,8 +175,14 @@ void xmrig::RxDataset::allocate(bool hugePages) } if (hugePages) { - m_flags = RANDOMX_FLAG_LARGE_PAGES; + m_flags = oneGbPages ? RANDOMX_FLAG_1GB_PAGES : RANDOMX_FLAG_LARGE_PAGES; m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + + if (oneGbPages && !m_dataset) { + LOG_ERR(CLEAR "%s" RED_BOLD_S "Failed to allocate RandomX dataset using 1GB pages", rx_tag()); + m_flags = RANDOMX_FLAG_LARGE_PAGES; + m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + } } if (!m_dataset) { diff --git a/src/crypto/rx/RxDataset.h b/src/crypto/rx/RxDataset.h index 304559561..0dba79bb8 100644 --- a/src/crypto/rx/RxDataset.h +++ b/src/crypto/rx/RxDataset.h @@ -31,6 +31,7 @@ #include "base/tools/Object.h" #include "crypto/common/Algorithm.h" #include "crypto/randomx/configuration.h" +#include "crypto/randomx/randomx.h" #include "crypto/rx/RxConfig.h" @@ -50,11 +51,12 @@ class RxDataset public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset) - RxDataset(bool hugePages, bool cache, RxConfig::Mode mode); + RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode); RxDataset(RxCache *cache); ~RxDataset(); - inline bool isHugePages() const { return m_flags & 1; } + inline bool isHugePages() const { return m_flags & RANDOMX_FLAG_LARGE_PAGES; } + inline bool isOneGbPages() const { return m_flags & RANDOMX_FLAG_1GB_PAGES; } inline randomx_dataset *get() const { return m_dataset; } inline RxCache *cache() const { return m_cache; } inline void setCache(RxCache *cache) { m_cache = cache; } @@ -68,7 +70,7 @@ public: static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; } private: - void allocate(bool hugePages); + void allocate(bool hugePages, bool oneGbPages); const RxConfig::Mode m_mode = RxConfig::FastMode; int m_flags = 0; diff --git a/src/crypto/rx/RxNUMAStorage.cpp b/src/crypto/rx/RxNUMAStorage.cpp index 646d3d954..c99750681 100644 --- a/src/crypto/rx/RxNUMAStorage.cpp +++ b/src/crypto/rx/RxNUMAStorage.cpp @@ -120,12 +120,12 @@ public: } - inline void createDatasets(bool hugePages) + inline void createDatasets(bool hugePages, bool oneGbPages) { const uint64_t ts = Chrono::steadyMSecs(); for (uint32_t node : m_nodeset) { - m_threads.emplace_back(allocate, this, node, hugePages); + m_threads.emplace_back(allocate, this, node, hugePages, oneGbPages); } join(); @@ -188,7 +188,7 @@ public: private: - static void allocate(RxNUMAStoragePrivate *d_ptr, uint32_t nodeId, bool hugePages) + static void allocate(RxNUMAStoragePrivate *d_ptr, uint32_t nodeId, bool hugePages, bool oneGbPages) { const uint64_t ts = Chrono::steadyMSecs(); @@ -198,7 +198,7 @@ private: return; } - auto dataset = new RxDataset(hugePages, false, RxConfig::FastMode); + auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode); if (!dataset->get()) { printSkipped(nodeId, "failed to allocate dataset"); @@ -346,12 +346,12 @@ std::pair xmrig::RxNUMAStorage::hugePages() const } -void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode) +void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode) { d_ptr->setSeed(seed); if (!d_ptr->isAllocated()) { - d_ptr->createDatasets(hugePages); + d_ptr->createDatasets(hugePages, oneGbPages); } d_ptr->initDatasets(threads); diff --git a/src/crypto/rx/RxNUMAStorage.h b/src/crypto/rx/RxNUMAStorage.h index bed0bc75e..c3d77000a 100644 --- a/src/crypto/rx/RxNUMAStorage.h +++ b/src/crypto/rx/RxNUMAStorage.h @@ -53,7 +53,7 @@ public: 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, RxConfig::Mode mode) override; + void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) override; private: RxNUMAStoragePrivate *d_ptr; diff --git a/src/crypto/rx/RxQueue.cpp b/src/crypto/rx/RxQueue.cpp index b420d0c2d..286538f15 100644 --- a/src/crypto/rx/RxQueue.cpp +++ b/src/crypto/rx/RxQueue.cpp @@ -94,7 +94,7 @@ std::pair xmrig::RxQueue::hugePages() } -void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) +void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) { std::unique_lock lock(m_mutex); @@ -114,7 +114,7 @@ void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector &no return; } - m_queue.emplace_back(seed, nodeset, threads, hugePages, mode); + m_queue.emplace_back(seed, nodeset, threads, hugePages, oneGbPages, mode); m_seed = seed; m_state = STATE_PENDING; @@ -156,7 +156,7 @@ void xmrig::RxQueue::backgroundInit() Buffer::toHex(item.seed.data().data(), 8).data() ); - m_storage->init(item.seed, item.threads, item.hugePages, item.mode); + m_storage->init(item.seed, item.threads, item.hugePages, item.oneGbPages, item.mode); lock = std::unique_lock(m_mutex); diff --git a/src/crypto/rx/RxQueue.h b/src/crypto/rx/RxQueue.h index 2d77e2e3c..6d8fa3281 100644 --- a/src/crypto/rx/RxQueue.h +++ b/src/crypto/rx/RxQueue.h @@ -53,8 +53,9 @@ class RxDataset; class RxQueueItem { public: - RxQueueItem(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) : + RxQueueItem(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) : hugePages(hugePages), + oneGbPages(oneGbPages), mode(mode), seed(seed), nodeset(nodeset), @@ -62,6 +63,7 @@ public: {} const bool hugePages; + const bool oneGbPages; const RxConfig::Mode mode; const RxSeed seed; const std::vector nodeset; @@ -80,7 +82,7 @@ public: bool isReady(const Job &job); RxDataset *dataset(const Job &job, uint32_t nodeId); std::pair hugePages(); - void enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode); + void enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode); private: enum State {