Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RX] Linux 1GiB page support #2627

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions doc/tuning.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Content Overview
* [Fast Startup](#fast-startup)
* [Huge Page Support](#huge-page-support)
* [Benchmark](#benchmark)
* [Windows](#windows)
* [Managing GPUs](#managing-GPUs)
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion xmrstak/backend/cpu/crypto/common/VirtualMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 12 additions & 3 deletions xmrstak/backend/cpu/crypto/common/VirtualMemory_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion xmrstak/backend/cpu/crypto/common/VirtualMemory_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 22 additions & 3 deletions xmrstak/backend/cpu/crypto/cryptonight.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_flags>(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_flags>(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES));
if (!m_rx_cache) {
m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT);
Expand Down
4 changes: 2 additions & 2 deletions xmrstak/backend/cpu/crypto/randomx/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ namespace randomx {

template struct AlignedAllocator<CacheLineSize>;

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) {
Expand Down
2 changes: 1 addition & 1 deletion xmrstak/backend/cpu/crypto/randomx/allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down
7 changes: 6 additions & 1 deletion xmrstak/backend/cpu/crypto/randomx/randomx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,12 @@ extern "C" {
dataset = new randomx_dataset();
if (flags & RANDOMX_FLAG_LARGE_PAGES) {
dataset->dealloc = &randomx::deallocDataset<randomx::LargePageAllocator>;
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<randomx::DefaultAllocator>;
Expand Down
1 change: 1 addition & 0 deletions xmrstak/backend/cpu/crypto/randomx/randomx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};


Expand Down
8 changes: 5 additions & 3 deletions xmrstak/backend/cpu/crypto/randomx/virtual_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <string>


void* allocExecutableMemory(std::size_t bytes) {
void *mem = xmrstak::VirtualMemory::allocateExecutableMemory(bytes);
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion xmrstak/backend/cpu/crypto/randomx/virtual_memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstddef>

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);