diff --git a/doc/tuning.md b/doc/tuning.md index 98f766fc5..19427b4b2 100644 --- a/doc/tuning.md +++ b/doc/tuning.md @@ -2,6 +2,7 @@ ## Content Overview * [Fast Startup](#fast-startup) +* [Huge Page Support](#huge-page-support) * [Benchmark](#benchmark) * [Windows](#windows) * [Managing GPUs](#managing-GPUs) @@ -23,6 +24,28 @@ ## Fast Startup You can disable the miner self test performed on each miner start by adding the command line option `--noTest` +## Huge Page Support + +In Linux you can enable 2 MiB huge pages with the following command. + +``` +sudo sysctl -w vm.nr_hugepages=1300 +``` + +In linux there is also the possibility to use 1 GiB pages for the dataset, this can be enabled with. + +``` +sudo sh -c ' echo 3 >/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages' +# check if the pages are enabled +cat /sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages +``` + +If the last must return `3` else the OS was not able to allocate 1 GiB pages. +Reasons for this can be that the you have to less main memory, you should have at least 8 GiB main memory. +If the system already runs for a while it could be your memory is already fragmented, a restart could help. +xmr-stak-rx is always using gigabyte pages when available, if this has a negative effect on your hashrate set the number +of gigabyte pages back to zero. + ## Benchmark You can benchmark the miner in two ways: - Edit `config.txt` and set `verbose_level` to 4 and `h_print_time` to 30 and start the miner. You will see hash report each 30 seconds. diff --git a/xmrstak/backend/cpu/crypto/common/VirtualMemory.h b/xmrstak/backend/cpu/crypto/common/VirtualMemory.h index 0b3f0eadf..49742b654 100644 --- a/xmrstak/backend/cpu/crypto/common/VirtualMemory.h +++ b/xmrstak/backend/cpu/crypto/common/VirtualMemory.h @@ -52,7 +52,7 @@ class VirtualMemory } static void *allocateExecutableMemory(size_t size); - static void *allocateLargePagesMemory(size_t size); + static void *allocateLargePagesMemory(size_t size, size_t page_size = 2u); static void flushInstructionCache(void *p, size_t size); static void freeLargePagesMemory(void *p, size_t size); static void init(bool hugePages); diff --git a/xmrstak/backend/cpu/crypto/common/VirtualMemory_unix.cpp b/xmrstak/backend/cpu/crypto/common/VirtualMemory_unix.cpp index 7fb6a2aa2..68e970839 100644 --- a/xmrstak/backend/cpu/crypto/common/VirtualMemory_unix.cpp +++ b/xmrstak/backend/cpu/crypto/common/VirtualMemory_unix.cpp @@ -94,15 +94,24 @@ void *xmrstak::VirtualMemory::allocateExecutableMemory(size_t size) return mem == MAP_FAILED ? nullptr : mem; } - -void *xmrstak::VirtualMemory::allocateLargePagesMemory(size_t size) +void *xmrstak::VirtualMemory::allocateLargePagesMemory(size_t size, size_t page_size) { # 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); + constexpr int MAP_HUGE_2MB = (21 << MAP_HUGE_SHIFT); + constexpr int MAP_HUGE_1GB = (30 << MAP_HUGE_SHIFT); + + int page_size_flags = 0; + if(page_size == 2u) + page_size_flags |= MAP_HUGE_2MB; + else if(page_size == 1024u) + page_size_flags |= MAP_HUGE_1GB; + #define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) + #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) + void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | page_size_flags, 0, 0); # endif return mem == MAP_FAILED ? nullptr : mem; diff --git a/xmrstak/backend/cpu/crypto/common/VirtualMemory_win.cpp b/xmrstak/backend/cpu/crypto/common/VirtualMemory_win.cpp index a2300ff08..a629475ea 100644 --- a/xmrstak/backend/cpu/crypto/common/VirtualMemory_win.cpp +++ b/xmrstak/backend/cpu/crypto/common/VirtualMemory_win.cpp @@ -180,7 +180,7 @@ void *xmrstak::VirtualMemory::allocateExecutableMemory(size_t size) } -void *xmrstak::VirtualMemory::allocateLargePagesMemory(size_t size) +void *xmrstak::VirtualMemory::allocateLargePagesMemory(size_t size, size_t) { const size_t min = GetLargePageMinimum(); void *mem = nullptr; diff --git a/xmrstak/backend/cpu/crypto/cryptonight.h b/xmrstak/backend/cpu/crypto/cryptonight.h index 8b293a94c..8b9e9e39f 100644 --- a/xmrstak/backend/cpu/crypto/cryptonight.h +++ b/xmrstak/backend/cpu/crypto/cryptonight.h @@ -101,10 +101,29 @@ struct randomX_global_ctx private: randomX_global_ctx() : m_rx_dataset_init_thread_counter(0u) { - randomx_dataset* dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); - if (!dataset) { - dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); +#ifdef __linux__ + randomx_dataset* dataset = randomx_alloc_dataset(static_cast(RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_LARGE_PAGES_1G)); + if (!dataset) + { + printer::inst()->print_msg(LDEBUG,"Warning: dataset allocation with 1 GiB pages failed"); +#else + randomx_dataset* dataset = nullptr; +#endif + dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); + if (!dataset) + { + printer::inst()->print_msg(LDEBUG,"Warning: dataset allocation with 2 MiB pages failed"); + dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); + printer::inst()->print_msg(LDEBUG,"dataset allocated without huge pages"); + } + else + printer::inst()->print_msg(LDEBUG,"dataset allocated with 2 MiB pages"); +#ifdef __linux__ } + else + printer::inst()->print_msg(LDEBUG,"dataset allocated with 1 GiB pages"); +#endif + m_rx_cache = randomx_alloc_cache(static_cast(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)); if (!m_rx_cache) { m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT); diff --git a/xmrstak/backend/cpu/crypto/randomx/allocator.cpp b/xmrstak/backend/cpu/crypto/randomx/allocator.cpp index ff708a62c..61f823461 100644 --- a/xmrstak/backend/cpu/crypto/randomx/allocator.cpp +++ b/xmrstak/backend/cpu/crypto/randomx/allocator.cpp @@ -49,8 +49,8 @@ namespace randomx { template struct AlignedAllocator; - void* LargePageAllocator::allocMemory(size_t count) { - return allocLargePagesMemory(count); + void* LargePageAllocator::allocMemory(size_t count, size_t page_size) { + return allocLargePagesMemory(count, page_size); } void LargePageAllocator::freeMemory(void* ptr, size_t count) { diff --git a/xmrstak/backend/cpu/crypto/randomx/allocator.hpp b/xmrstak/backend/cpu/crypto/randomx/allocator.hpp index d7aa3f95d..df18f73a1 100644 --- a/xmrstak/backend/cpu/crypto/randomx/allocator.hpp +++ b/xmrstak/backend/cpu/crypto/randomx/allocator.hpp @@ -39,7 +39,7 @@ namespace randomx { }; struct LargePageAllocator { - static void* allocMemory(size_t); + static void* allocMemory(size_t, size_t page_size = 2u); static void freeMemory(void*, size_t); }; diff --git a/xmrstak/backend/cpu/crypto/randomx/randomx.cpp b/xmrstak/backend/cpu/crypto/randomx/randomx.cpp index 2ee097fda..2937459c1 100644 --- a/xmrstak/backend/cpu/crypto/randomx/randomx.cpp +++ b/xmrstak/backend/cpu/crypto/randomx/randomx.cpp @@ -320,7 +320,12 @@ extern "C" { dataset = new randomx_dataset(); if (flags & RANDOMX_FLAG_LARGE_PAGES) { dataset->dealloc = &randomx::deallocDataset; - dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); + if(flags & RANDOMX_FLAG_LARGE_PAGES_1G) { + dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE, 1024u); + } + else { + dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE, 2u); + } } else { dataset->dealloc = &randomx::deallocDataset; diff --git a/xmrstak/backend/cpu/crypto/randomx/randomx.h b/xmrstak/backend/cpu/crypto/randomx/randomx.h index 51c66334d..6fece9a4f 100644 --- a/xmrstak/backend/cpu/crypto/randomx/randomx.h +++ b/xmrstak/backend/cpu/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_LARGE_PAGES_1G = 16 }; diff --git a/xmrstak/backend/cpu/crypto/randomx/virtual_memory.cpp b/xmrstak/backend/cpu/crypto/randomx/virtual_memory.cpp index ced3b78c8..42e6af2e3 100644 --- a/xmrstak/backend/cpu/crypto/randomx/virtual_memory.cpp +++ b/xmrstak/backend/cpu/crypto/randomx/virtual_memory.cpp @@ -32,6 +32,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "crypto/common/VirtualMemory.h" #include "crypto/randomx/virtual_memory.hpp" +#include + void* allocExecutableMemory(std::size_t bytes) { void *mem = xmrstak::VirtualMemory::allocateExecutableMemory(bytes); @@ -43,10 +45,10 @@ void* allocExecutableMemory(std::size_t bytes) { } -void* allocLargePagesMemory(std::size_t bytes) { - void *mem = xmrstak::VirtualMemory::allocateLargePagesMemory(bytes); +void* allocLargePagesMemory(std::size_t bytes, size_t page_size) { + void *mem = xmrstak::VirtualMemory::allocateLargePagesMemory(bytes, page_size); if (mem == nullptr) { - throw std::runtime_error("Failed to allocate large pages memory"); + throw std::runtime_error(std::string("Failed to allocate large pages memory (page size: " + std::to_string(page_size) + " MiB")); } return mem; diff --git a/xmrstak/backend/cpu/crypto/randomx/virtual_memory.hpp b/xmrstak/backend/cpu/crypto/randomx/virtual_memory.hpp index d3b31db12..90ade304b 100644 --- a/xmrstak/backend/cpu/crypto/randomx/virtual_memory.hpp +++ b/xmrstak/backend/cpu/crypto/randomx/virtual_memory.hpp @@ -31,5 +31,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include void* allocExecutableMemory(std::size_t); -void* allocLargePagesMemory(std::size_t); +void* allocLargePagesMemory(std::size_t, size_t page_size); void freePagedMemory(void*, std::size_t);