Skip to content

Commit

Permalink
Linux 1GiB page support
Browse files Browse the repository at this point in the history
add 1 GiB page support for linux systems
  • Loading branch information
psychocrypt committed Dec 11, 2019
1 parent 5048764 commit 760aca1
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 15 deletions.
21 changes: 21 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,26 @@
## 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.

## 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 @@ -174,7 +174,7 @@ xmrstak::VirtualMemory::~VirtualMemory()
}


void *xmrstak::VirtualMemory::allocateExecutableMemory(size_t size)
void *xmrstak::VirtualMemory::allocateExecutableMemory(size_t size, size_t)
{
return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
Expand Down
19 changes: 17 additions & 2 deletions xmrstak/backend/cpu/crypto/cryptonight.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,25 @@ 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);
#ifdef __linux__
randomx_dataset* dataset = randomx_alloc_dataset(static_cast<randomx_flags>(RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_LARGE_PAGES_1G));
if (!dataset) {
dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
printer::inst()->print_msg(LDEBUG,"Warning: dataset allocation with 1 GiB pages failed");
#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);

0 comments on commit 760aca1

Please sign in to comment.