mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-18 10:01:06 +00:00
Added 1GB hugepages support for Linux
This commit is contained in:
parent
caa2da8bb3
commit
1fbbae1e4a
28 changed files with 156 additions and 50 deletions
|
@ -63,6 +63,8 @@ static void print_memory(Config *config) {
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s",
|
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"));
|
"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
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,12 +73,13 @@ static void print_cpu(Config *)
|
||||||
{
|
{
|
||||||
const ICpuInfo *info = Cpu::info();
|
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",
|
"CPU",
|
||||||
info->brand(),
|
info->brand(),
|
||||||
info->packages(),
|
info->packages(),
|
||||||
info->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-",
|
info->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-",
|
||||||
info->hasAES() ? 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)
|
# 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")
|
Log::print(WHITE_BOLD(" %-13s") BLACK_BOLD("L2:") WHITE_BOLD("%.1f MB") BLACK_BOLD(" L3:") WHITE_BOLD("%.1f MB")
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
|
|
||||||
virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0;
|
virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0;
|
||||||
virtual std::pair<uint32_t, uint32_t> hugePages() const = 0;
|
virtual std::pair<uint32_t, uint32_t> hugePages() const = 0;
|
||||||
virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) = 0;
|
virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace xmrig {
|
||||||
|
|
||||||
static const char *kEnabled = "enabled";
|
static const char *kEnabled = "enabled";
|
||||||
static const char *kHugePages = "huge-pages";
|
static const char *kHugePages = "huge-pages";
|
||||||
|
static const char *kOneGbPages = "1gb-pages";
|
||||||
static const char *kHwAes = "hw-aes";
|
static const char *kHwAes = "hw-aes";
|
||||||
static const char *kMaxThreadsHint = "max-threads-hint";
|
static const char *kMaxThreadsHint = "max-threads-hint";
|
||||||
static const char *kMemoryPool = "memory-pool";
|
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(kEnabled), m_enabled, allocator);
|
||||||
obj.AddMember(StringRef(kHugePages), m_hugePages, 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(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(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
|
||||||
obj.AddMember(StringRef(kMemoryPool), m_memoryPool < 1 ? Value(m_memoryPool < 0) : Value(m_memoryPool), allocator);
|
obj.AddMember(StringRef(kMemoryPool), m_memoryPool < 1 ? Value(m_memoryPool < 0) : Value(m_memoryPool), allocator);
|
||||||
|
@ -121,6 +123,7 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value)
|
||||||
if (value.IsObject()) {
|
if (value.IsObject()) {
|
||||||
m_enabled = Json::getBool(value, kEnabled, m_enabled);
|
m_enabled = Json::getBool(value, kEnabled, m_enabled);
|
||||||
m_hugePages = Json::getBool(value, kHugePages, m_hugePages);
|
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_limit = Json::getUint(value, kMaxThreadsHint, m_limit);
|
||||||
m_yield = Json::getBool(value, kYield, m_yield);
|
m_yield = Json::getBool(value, kYield, m_yield);
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
|
|
||||||
inline bool isEnabled() const { return m_enabled; }
|
inline bool isEnabled() const { return m_enabled; }
|
||||||
inline bool isHugePages() const { return m_hugePages; }
|
inline bool isHugePages() const { return m_hugePages; }
|
||||||
|
inline bool isOneGbPages() const { return m_oneGbPages; }
|
||||||
inline bool isShouldSave() const { return m_shouldSave; }
|
inline bool isShouldSave() const { return m_shouldSave; }
|
||||||
inline bool isYield() const { return m_yield; }
|
inline bool isYield() const { return m_yield; }
|
||||||
inline const Assembly &assembly() const { return m_assembly; }
|
inline const Assembly &assembly() const { return m_assembly; }
|
||||||
|
@ -72,6 +73,7 @@ private:
|
||||||
Assembly m_assembly;
|
Assembly m_assembly;
|
||||||
bool m_enabled = true;
|
bool m_enabled = true;
|
||||||
bool m_hugePages = true;
|
bool m_hugePages = true;
|
||||||
|
bool m_oneGbPages = false;
|
||||||
bool m_shouldSave = false;
|
bool m_shouldSave = false;
|
||||||
bool m_yield = true;
|
bool m_yield = true;
|
||||||
int m_memoryPool = 0;
|
int m_memoryPool = 0;
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
virtual Assembly::Id assembly() const = 0;
|
virtual Assembly::Id assembly() const = 0;
|
||||||
virtual bool hasAES() const = 0;
|
virtual bool hasAES() const = 0;
|
||||||
virtual bool hasAVX2() const = 0;
|
virtual bool hasAVX2() const = 0;
|
||||||
|
virtual bool hasOneGbPages() const = 0;
|
||||||
virtual const char *backend() const = 0;
|
virtual const char *backend() const = 0;
|
||||||
virtual const char *brand() const = 0;
|
virtual const char *brand() const = 0;
|
||||||
virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0;
|
virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0;
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
# define bit_AVX2 (1 << 5)
|
# define bit_AVX2 (1 << 5)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef bit_PDPE1GB
|
||||||
|
# define bit_PDPE1GB (1 << 26)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "backend/cpu/platform/BasicCpuInfo.h"
|
#include "backend/cpu/platform/BasicCpuInfo.h"
|
||||||
#include "crypto/common/Assembly.h"
|
#include "crypto/common/Assembly.h"
|
||||||
|
@ -53,6 +57,7 @@
|
||||||
#define VENDOR_ID (0)
|
#define VENDOR_ID (0)
|
||||||
#define PROCESSOR_INFO (1)
|
#define PROCESSOR_INFO (1)
|
||||||
#define EXTENDED_FEATURES (7)
|
#define EXTENDED_FEATURES (7)
|
||||||
|
#define PROCESSOR_EXT_INFO (0x80000001)
|
||||||
#define PROCESSOR_BRAND_STRING_1 (0x80000002)
|
#define PROCESSOR_BRAND_STRING_1 (0x80000002)
|
||||||
#define PROCESSOR_BRAND_STRING_2 (0x80000003)
|
#define PROCESSOR_BRAND_STRING_2 (0x80000003)
|
||||||
#define PROCESSOR_BRAND_STRING_3 (0x80000004)
|
#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
|
} // namespace xmrig
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,7 +155,8 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
|
||||||
m_threads(std::thread::hardware_concurrency()),
|
m_threads(std::thread::hardware_concurrency()),
|
||||||
m_assembly(Assembly::NONE),
|
m_assembly(Assembly::NONE),
|
||||||
m_aes(has_aes_ni()),
|
m_aes(has_aes_ni()),
|
||||||
m_avx2(has_avx2())
|
m_avx2(has_avx2()),
|
||||||
|
m_pdpe1gb(has_pdpe1gb())
|
||||||
{
|
{
|
||||||
cpu_brand_string(m_brand);
|
cpu_brand_string(m_brand);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ protected:
|
||||||
inline Assembly::Id assembly() const override { return m_assembly; }
|
inline Assembly::Id assembly() const override { return m_assembly; }
|
||||||
inline bool hasAES() const override { return m_aes; }
|
inline bool hasAES() const override { return m_aes; }
|
||||||
inline bool hasAVX2() const override { return m_avx2; }
|
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 const char *brand() const override { return m_brand; }
|
||||||
inline size_t cores() const override { return 0; }
|
inline size_t cores() const override { return 0; }
|
||||||
inline size_t L2() const override { return 0; }
|
inline size_t L2() const override { return 0; }
|
||||||
|
@ -60,6 +61,7 @@ private:
|
||||||
Assembly m_assembly;
|
Assembly m_assembly;
|
||||||
bool m_aes;
|
bool m_aes;
|
||||||
const bool m_avx2;
|
const bool m_avx2;
|
||||||
|
const bool m_pdpe1gb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"cpu": {
|
"cpu": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"huge-pages": true,
|
"huge-pages": true,
|
||||||
|
"1gb-pages": false,
|
||||||
"hw-aes": null,
|
"hw-aes": null,
|
||||||
"priority": null,
|
"priority": null,
|
||||||
"memory-pool": false,
|
"memory-pool": false,
|
||||||
|
|
|
@ -236,7 +236,7 @@ public:
|
||||||
# ifdef XMRIG_ALGO_RANDOMX
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
inline bool initRX()
|
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
|
# endif
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
static uint32_t bindToNUMANode(int64_t affinity);
|
static uint32_t bindToNUMANode(int64_t affinity);
|
||||||
static void *allocateExecutableMemory(size_t size);
|
static void *allocateExecutableMemory(size_t size);
|
||||||
static void *allocateLargePagesMemory(size_t size);
|
static void *allocateLargePagesMemory(size_t size);
|
||||||
|
static void *allocateOneGbPagesMemory(size_t size);
|
||||||
static void destroy();
|
static void destroy();
|
||||||
static void flushInstructionCache(void *p, size_t size);
|
static void flushInstructionCache(void *p, size_t size);
|
||||||
static void freeLargePagesMemory(void *p, size_t size);
|
static void freeLargePagesMemory(void *p, size_t size);
|
||||||
|
@ -81,6 +82,7 @@ private:
|
||||||
static void osInit(bool hugePages);
|
static void osInit(bool hugePages);
|
||||||
|
|
||||||
bool allocateLargePagesMemory();
|
bool allocateLargePagesMemory();
|
||||||
|
bool allocateOneGbPagesMemory();
|
||||||
void freeLargePagesMemory();
|
void freeLargePagesMemory();
|
||||||
|
|
||||||
const size_t m_size;
|
const size_t m_size;
|
||||||
|
|
|
@ -58,24 +58,33 @@ void *xmrig::VirtualMemory::allocateExecutableMemory(size_t size)
|
||||||
|
|
||||||
void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size)
|
void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size)
|
||||||
{
|
{
|
||||||
int flag_1gb = 0;
|
|
||||||
|
|
||||||
# if defined(__APPLE__)
|
# if defined(__APPLE__)
|
||||||
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
|
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
|
||||||
# elif defined(__FreeBSD__)
|
# elif defined(__FreeBSD__)
|
||||||
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0);
|
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0);
|
||||||
# else
|
# 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)
|
# 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)
|
# elif defined(MAP_HUGE_SHIFT)
|
||||||
flag_1gb = (size > (1UL << 30)) ? (30 << MAP_HUGE_SHIFT) : 0;
|
constexpr int flag_1gb = (30 << MAP_HUGE_SHIFT);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_1gb, 0, 0);
|
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
|
# endif
|
||||||
|
|
||||||
return mem == MAP_FAILED ? nullptr : mem;
|
return mem == MAP_FAILED ? nullptr : mem;
|
||||||
|
@ -132,6 +141,25 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::VirtualMemory::allocateOneGbPagesMemory()
|
||||||
|
{
|
||||||
|
m_scratchpad = static_cast<uint8_t*>(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()
|
void xmrig::VirtualMemory::freeLargePagesMemory()
|
||||||
{
|
{
|
||||||
if (m_flags.test(FLAG_LOCK)) {
|
if (m_flags.test(FLAG_LOCK)) {
|
||||||
|
|
|
@ -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)
|
void xmrig::VirtualMemory::flushInstructionCache(void *p, size_t size)
|
||||||
{
|
{
|
||||||
::FlushInstructionCache(GetCurrentProcess(), p, size);
|
::FlushInstructionCache(GetCurrentProcess(), p, size);
|
||||||
|
@ -221,6 +227,12 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool xmrig::VirtualMemory::allocateOneGbPagesMemory()
|
||||||
|
{
|
||||||
|
m_scratchpad = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::VirtualMemory::freeLargePagesMemory()
|
void xmrig::VirtualMemory::freeLargePagesMemory()
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,4 +57,12 @@ namespace randomx {
|
||||||
freePagedMemory(ptr, count);
|
freePagedMemory(ptr, count);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void* OneGbPageAllocator::allocMemory(size_t count) {
|
||||||
|
return allocOneGbPagesMemory(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneGbPageAllocator::freeMemory(void* ptr, size_t count) {
|
||||||
|
freePagedMemory(ptr, count);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,4 +43,9 @@ namespace randomx {
|
||||||
static void freeMemory(void*, size_t);
|
static void freeMemory(void*, size_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OneGbPageAllocator {
|
||||||
|
static void* allocMemory(size_t);
|
||||||
|
static void freeMemory(void*, size_t);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -333,7 +333,11 @@ extern "C" {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dataset = new randomx_dataset();
|
dataset = new randomx_dataset();
|
||||||
if (flags & RANDOMX_FLAG_LARGE_PAGES) {
|
if (flags & RANDOMX_FLAG_1GB_PAGES) {
|
||||||
|
dataset->dealloc = &randomx::deallocDataset<randomx::OneGbPageAllocator>;
|
||||||
|
dataset->memory = (uint8_t*)randomx::OneGbPageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE);
|
||||||
|
}
|
||||||
|
else if (flags & RANDOMX_FLAG_LARGE_PAGES) {
|
||||||
dataset->dealloc = &randomx::deallocDataset<randomx::LargePageAllocator>;
|
dataset->dealloc = &randomx::deallocDataset<randomx::LargePageAllocator>;
|
||||||
dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE);
|
dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ enum randomx_flags {
|
||||||
RANDOMX_FLAG_HARD_AES = 2,
|
RANDOMX_FLAG_HARD_AES = 2,
|
||||||
RANDOMX_FLAG_FULL_MEM = 4,
|
RANDOMX_FLAG_FULL_MEM = 4,
|
||||||
RANDOMX_FLAG_JIT = 8,
|
RANDOMX_FLAG_JIT = 8,
|
||||||
|
RANDOMX_FLAG_1GB_PAGES = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
void freePagedMemory(void* ptr, std::size_t bytes) {
|
||||||
xmrig::VirtualMemory::freeLargePagesMemory(ptr, bytes);
|
xmrig::VirtualMemory::freeLargePagesMemory(ptr, bytes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,4 +32,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
void* allocExecutableMemory(std::size_t);
|
void* allocExecutableMemory(std::size_t);
|
||||||
void* allocLargePagesMemory(std::size_t);
|
void* allocLargePagesMemory(std::size_t);
|
||||||
|
void* allocOneGbPagesMemory(std::size_t);
|
||||||
void freePagedMemory(void*, std::size_t);
|
void freePagedMemory(void*, std::size_t);
|
||||||
|
|
|
@ -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) {
|
if (job.algorithm().family() != Algorithm::RANDOM_X) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -70,7 +70,7 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages)
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class RxDataset;
|
||||||
class Rx
|
class Rx
|
||||||
{
|
{
|
||||||
public:
|
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 bool isReady(const Job &job);
|
||||||
static RxDataset *dataset(const Job &job, uint32_t nodeId);
|
static RxDataset *dataset(const Job &job, uint32_t nodeId);
|
||||||
static std::pair<uint32_t, uint32_t> hugePages();
|
static std::pair<uint32_t, uint32_t> hugePages();
|
||||||
|
|
|
@ -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();
|
const uint64_t ts = Chrono::steadyMSecs();
|
||||||
|
|
||||||
m_dataset = new RxDataset(hugePages, true, mode);
|
m_dataset = new RxDataset(hugePages, oneGbPages, true, mode);
|
||||||
printAllocStatus(ts);
|
printAllocStatus(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +157,12 @@ std::pair<uint32_t, uint32_t> 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);
|
d_ptr->setSeed(seed);
|
||||||
|
|
||||||
if (!d_ptr->dataset()) {
|
if (!d_ptr->dataset()) {
|
||||||
d_ptr->createDataset(hugePages, mode);
|
d_ptr->createDataset(hugePages, oneGbPages, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
d_ptr->initDataset(threads);
|
d_ptr->initDataset(threads);
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
|
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
|
||||||
std::pair<uint32_t, uint32_t> hugePages() const override;
|
std::pair<uint32_t, uint32_t> 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:
|
private:
|
||||||
RxBasicStoragePrivate *d_ptr;
|
RxBasicStoragePrivate *d_ptr;
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "backend/common/Tags.h"
|
#include "backend/common/Tags.h"
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
#include "crypto/common/VirtualMemory.h"
|
#include "crypto/common/VirtualMemory.h"
|
||||||
#include "crypto/randomx/randomx.h"
|
|
||||||
#include "crypto/rx/RxAlgo.h"
|
#include "crypto/rx/RxAlgo.h"
|
||||||
#include "crypto/rx/RxCache.h"
|
#include "crypto/rx/RxCache.h"
|
||||||
|
|
||||||
|
@ -41,10 +40,10 @@
|
||||||
static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch");
|
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)
|
m_mode(mode)
|
||||||
{
|
{
|
||||||
allocate(hugePages);
|
allocate(hugePages, oneGbPages);
|
||||||
|
|
||||||
if (cache) {
|
if (cache) {
|
||||||
m_cache = new RxCache(hugePages);
|
m_cache = new RxCache(hugePages);
|
||||||
|
@ -123,11 +122,13 @@ size_t xmrig::RxDataset::size(bool cache) const
|
||||||
std::pair<uint32_t, uint32_t> xmrig::RxDataset::hugePages(bool cache) const
|
std::pair<uint32_t, uint32_t> xmrig::RxDataset::hugePages(bool cache) const
|
||||||
{
|
{
|
||||||
constexpr size_t twoMiB = 2U * 1024U * 1024U;
|
constexpr size_t twoMiB = 2U * 1024U * 1024U;
|
||||||
|
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
|
||||||
constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB;
|
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;
|
uint32_t count = 0;
|
||||||
if (isHugePages()) {
|
if (isHugePages() || isOneGbPages()) {
|
||||||
count += total;
|
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) {
|
if (m_mode == RxConfig::LightMode) {
|
||||||
LOG_ERR(CLEAR "%s" RED_BOLD_S "fast RandomX mode disabled by config", rx_tag());
|
LOG_ERR(CLEAR "%s" RED_BOLD_S "fast RandomX mode disabled by config", rx_tag());
|
||||||
|
@ -174,9 +175,15 @@ void xmrig::RxDataset::allocate(bool hugePages)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hugePages) {
|
if (hugePages) {
|
||||||
|
m_flags = oneGbPages ? RANDOMX_FLAG_1GB_PAGES : RANDOMX_FLAG_LARGE_PAGES;
|
||||||
|
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(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_flags = RANDOMX_FLAG_LARGE_PAGES;
|
||||||
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
|
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_dataset) {
|
if (!m_dataset) {
|
||||||
m_flags = RANDOMX_FLAG_DEFAULT;
|
m_flags = RANDOMX_FLAG_DEFAULT;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "base/tools/Object.h"
|
#include "base/tools/Object.h"
|
||||||
#include "crypto/common/Algorithm.h"
|
#include "crypto/common/Algorithm.h"
|
||||||
#include "crypto/randomx/configuration.h"
|
#include "crypto/randomx/configuration.h"
|
||||||
|
#include "crypto/randomx/randomx.h"
|
||||||
#include "crypto/rx/RxConfig.h"
|
#include "crypto/rx/RxConfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,11 +51,12 @@ class RxDataset
|
||||||
public:
|
public:
|
||||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset)
|
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(RxCache *cache);
|
||||||
~RxDataset();
|
~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 randomx_dataset *get() const { return m_dataset; }
|
||||||
inline RxCache *cache() const { return m_cache; }
|
inline RxCache *cache() const { return m_cache; }
|
||||||
inline void setCache(RxCache *cache) { m_cache = 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; }
|
static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void allocate(bool hugePages);
|
void allocate(bool hugePages, bool oneGbPages);
|
||||||
|
|
||||||
const RxConfig::Mode m_mode = RxConfig::FastMode;
|
const RxConfig::Mode m_mode = RxConfig::FastMode;
|
||||||
int m_flags = 0;
|
int m_flags = 0;
|
||||||
|
|
|
@ -120,12 +120,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void createDatasets(bool hugePages)
|
inline void createDatasets(bool hugePages, bool oneGbPages)
|
||||||
{
|
{
|
||||||
const uint64_t ts = Chrono::steadyMSecs();
|
const uint64_t ts = Chrono::steadyMSecs();
|
||||||
|
|
||||||
for (uint32_t node : m_nodeset) {
|
for (uint32_t node : m_nodeset) {
|
||||||
m_threads.emplace_back(allocate, this, node, hugePages);
|
m_threads.emplace_back(allocate, this, node, hugePages, oneGbPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
join();
|
join();
|
||||||
|
@ -188,7 +188,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
private:
|
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();
|
const uint64_t ts = Chrono::steadyMSecs();
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dataset = new RxDataset(hugePages, false, RxConfig::FastMode);
|
auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode);
|
||||||
if (!dataset->get()) {
|
if (!dataset->get()) {
|
||||||
printSkipped(nodeId, "failed to allocate dataset");
|
printSkipped(nodeId, "failed to allocate dataset");
|
||||||
|
|
||||||
|
@ -346,12 +346,12 @@ std::pair<uint32_t, uint32_t> 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);
|
d_ptr->setSeed(seed);
|
||||||
|
|
||||||
if (!d_ptr->isAllocated()) {
|
if (!d_ptr->isAllocated()) {
|
||||||
d_ptr->createDatasets(hugePages);
|
d_ptr->createDatasets(hugePages, oneGbPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
d_ptr->initDatasets(threads);
|
d_ptr->initDatasets(threads);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
|
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
|
||||||
std::pair<uint32_t, uint32_t> hugePages() const override;
|
std::pair<uint32_t, uint32_t> 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:
|
private:
|
||||||
RxNUMAStoragePrivate *d_ptr;
|
RxNUMAStoragePrivate *d_ptr;
|
||||||
|
|
|
@ -94,7 +94,7 @@ std::pair<uint32_t, uint32_t> xmrig::RxQueue::hugePages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode)
|
void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &no
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_queue.emplace_back(seed, nodeset, threads, hugePages, mode);
|
m_queue.emplace_back(seed, nodeset, threads, hugePages, oneGbPages, mode);
|
||||||
m_seed = seed;
|
m_seed = seed;
|
||||||
m_state = STATE_PENDING;
|
m_state = STATE_PENDING;
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ void xmrig::RxQueue::backgroundInit()
|
||||||
Buffer::toHex(item.seed.data().data(), 8).data()
|
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<std::mutex>(m_mutex);
|
lock = std::unique_lock<std::mutex>(m_mutex);
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,9 @@ class RxDataset;
|
||||||
class RxQueueItem
|
class RxQueueItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RxQueueItem(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) :
|
RxQueueItem(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode) :
|
||||||
hugePages(hugePages),
|
hugePages(hugePages),
|
||||||
|
oneGbPages(oneGbPages),
|
||||||
mode(mode),
|
mode(mode),
|
||||||
seed(seed),
|
seed(seed),
|
||||||
nodeset(nodeset),
|
nodeset(nodeset),
|
||||||
|
@ -62,6 +63,7 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const bool hugePages;
|
const bool hugePages;
|
||||||
|
const bool oneGbPages;
|
||||||
const RxConfig::Mode mode;
|
const RxConfig::Mode mode;
|
||||||
const RxSeed seed;
|
const RxSeed seed;
|
||||||
const std::vector<uint32_t> nodeset;
|
const std::vector<uint32_t> nodeset;
|
||||||
|
@ -80,7 +82,7 @@ public:
|
||||||
bool isReady(const Job &job);
|
bool isReady(const Job &job);
|
||||||
RxDataset *dataset(const Job &job, uint32_t nodeId);
|
RxDataset *dataset(const Job &job, uint32_t nodeId);
|
||||||
std::pair<uint32_t, uint32_t> hugePages();
|
std::pair<uint32_t, uint32_t> hugePages();
|
||||||
void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode);
|
void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum State {
|
enum State {
|
||||||
|
|
Loading…
Reference in a new issue