Memory allocation refactoring.

This commit is contained in:
XMRig 2019-12-08 23:17:39 +07:00
parent 8a13e0febd
commit d32df84ca5
No known key found for this signature in database
GPG key ID: 446A53638BE94409
32 changed files with 516 additions and 272 deletions

View file

@ -76,6 +76,7 @@ set(HEADERS_CRYPTO
src/crypto/cn/soft_aes.h src/crypto/cn/soft_aes.h
src/crypto/common/Algorithm.h src/crypto/common/Algorithm.h
src/crypto/common/Coin.h src/crypto/common/Coin.h
src/crypto/common/HugePagesInfo.h
src/crypto/common/keccak.h src/crypto/common/keccak.h
src/crypto/common/MemoryPool.h src/crypto/common/MemoryPool.h
src/crypto/common/Nonce.h src/crypto/common/Nonce.h
@ -115,6 +116,7 @@ set(SOURCES_CRYPTO
src/crypto/cn/CnHash.cpp src/crypto/cn/CnHash.cpp
src/crypto/common/Algorithm.cpp src/crypto/common/Algorithm.cpp
src/crypto/common/Coin.cpp src/crypto/common/Coin.cpp
src/crypto/common/HugePagesInfo.cpp
src/crypto/common/keccak.cpp src/crypto/common/keccak.cpp
src/crypto/common/MemoryPool.cpp src/crypto/common/MemoryPool.cpp
src/crypto/common/Nonce.cpp src/crypto/common/Nonce.cpp
@ -154,6 +156,11 @@ else()
if (XMRIG_OS_ANDROID) if (XMRIG_OS_ANDROID)
set(EXTRA_LIBS pthread rt dl log) set(EXTRA_LIBS pthread rt dl log)
elseif (XMRIG_OS_LINUX) elseif (XMRIG_OS_LINUX)
list(APPEND SOURCES_OS
src/crypto/common/LinuxMemory.h
src/crypto/common/LinuxMemory.cpp
)
set(EXTRA_LIBS pthread rt dl) set(EXTRA_LIBS pthread rt dl)
elseif (XMRIG_OS_FREEBSD) elseif (XMRIG_OS_FREEBSD)
set(EXTRA_LIBS kvm pthread) set(EXTRA_LIBS kvm pthread)

View file

@ -25,6 +25,7 @@
#include "crypto/rx/RxConfig.h" #include "crypto/rx/RxConfig.h"
#include "crypto/common/HugePagesInfo.h"
#include <cstdint> #include <cstdint>
@ -44,8 +45,8 @@ class IRxStorage
public: public:
virtual ~IRxStorage() = default; virtual ~IRxStorage() = default;
virtual HugePagesInfo hugePages() const = 0;
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 void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) = 0; virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) = 0;
}; };

View file

@ -68,17 +68,15 @@ static std::mutex mutex;
struct CpuLaunchStatus struct CpuLaunchStatus
{ {
public: public:
inline size_t hugePages() const { return m_hugePages; } inline const HugePagesInfo &hugePages() const { return m_hugePages; }
inline size_t memory() const { return m_ways * m_memory; } inline size_t memory() const { return m_ways * m_memory; }
inline size_t pages() const { return m_pages; } inline size_t threads() const { return m_threads; }
inline size_t threads() const { return m_threads; } inline size_t ways() const { return m_ways; }
inline size_t ways() const { return m_ways; }
inline void start(const std::vector<CpuLaunchData> &threads, size_t memory) inline void start(const std::vector<CpuLaunchData> &threads, size_t memory)
{ {
m_hugePages = 0; m_hugePages.reset();
m_memory = memory; m_memory = memory;
m_pages = 0;
m_started = 0; m_started = 0;
m_errors = 0; m_errors = 0;
m_threads = threads.size(); m_threads = threads.size();
@ -89,11 +87,9 @@ public:
inline bool started(IWorker *worker, bool ready) inline bool started(IWorker *worker, bool ready)
{ {
if (ready) { if (ready) {
auto hugePages = worker->memory()->hugePages();
m_started++; m_started++;
m_hugePages += hugePages.first;
m_pages += hugePages.second; m_hugePages += worker->memory()->hugePages();
m_ways += worker->intensity(); m_ways += worker->intensity();
} }
else { else {
@ -115,19 +111,18 @@ public:
tag, tag,
m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S, m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S,
m_started, m_threads, m_ways, m_started, m_threads, m_ways,
(m_hugePages == m_pages ? GREEN_BOLD_S : (m_hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), (m_hugePages.isFullyAllocated() ? GREEN_BOLD_S : (m_hugePages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
m_hugePages == 0 ? 0.0 : static_cast<double>(m_hugePages) / m_pages * 100.0, m_hugePages.percent(),
m_hugePages, m_pages, m_hugePages.allocated, m_hugePages.total,
memory() / 1024, memory() / 1024,
Chrono::steadyMSecs() - m_ts Chrono::steadyMSecs() - m_ts
); );
} }
private: private:
HugePagesInfo m_hugePages;
size_t m_errors = 0; size_t m_errors = 0;
size_t m_hugePages = 0;
size_t m_memory = 0; size_t m_memory = 0;
size_t m_pages = 0;
size_t m_started = 0; size_t m_started = 0;
size_t m_threads = 0; size_t m_threads = 0;
size_t m_ways = 0; size_t m_ways = 0;
@ -169,18 +164,17 @@ public:
rapidjson::Value hugePages(int version, rapidjson::Document &doc) rapidjson::Value hugePages(int version, rapidjson::Document &doc)
{ {
std::pair<unsigned, unsigned> pages(0, 0); HugePagesInfo pages;
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if (algo.family() == Algorithm::RANDOM_X) { if (algo.family() == Algorithm::RANDOM_X) {
pages = Rx::hugePages(); pages += Rx::hugePages();
} }
# endif # endif
mutex.lock(); mutex.lock();
pages.first += status.hugePages(); pages += status.hugePages();
pages.second += status.pages();
mutex.unlock(); mutex.unlock();
@ -188,11 +182,11 @@ public:
if (version > 1) { if (version > 1) {
hugepages.SetArray(); hugepages.SetArray();
hugepages.PushBack(pages.first, doc.GetAllocator()); hugepages.PushBack(static_cast<uint64_t>(pages.allocated), doc.GetAllocator());
hugepages.PushBack(pages.second, doc.GetAllocator()); hugepages.PushBack(static_cast<uint64_t>(pages.total), doc.GetAllocator());
} }
else { else {
hugepages = pages.first == pages.second; hugepages = pages.isFullyAllocated();
} }
return hugepages; return hugepages;

View file

@ -63,7 +63,7 @@ xmrig::CpuWorker<N>::CpuWorker(size_t id, const CpuLaunchData &data) :
m_miner(data.miner), m_miner(data.miner),
m_ctx() m_ctx()
{ {
m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, true, m_node); m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, false, true, m_node);
} }

View file

@ -0,0 +1,50 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "crypto/common/HugePagesInfo.h"
#include "crypto/common/VirtualMemory.h"
namespace xmrig {
constexpr size_t twoMiB = 2U * 1024U * 1024U;
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
} // namespace xmrig
xmrig::HugePagesInfo::HugePagesInfo(const VirtualMemory *memory)
{
if (memory->isOneGbPages()) {
size = VirtualMemory::align(memory->size(), oneGiB);
total = size / oneGiB;
allocated = size / oneGiB;
}
else {
size = memory->size();
total = size / twoMiB;
allocated = memory->isHugePages() ? total : 0;
}
}

View file

@ -0,0 +1,67 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_HUGEPAGESINFO_H
#define XMRIG_HUGEPAGESINFO_H
#include <cstdint>
#include <cstddef>
namespace xmrig {
class VirtualMemory;
class HugePagesInfo
{
public:
HugePagesInfo() = default;
HugePagesInfo(const VirtualMemory *memory);
size_t allocated = 0;
size_t total = 0;
size_t size = 0;
inline bool isFullyAllocated() const { return allocated == total; }
inline double percent() const { return allocated == 0 ? 0.0 : static_cast<double>(allocated) / total * 100.0; }
inline void reset() { allocated = 0; total = 0; size = 0; }
inline HugePagesInfo &operator+=(const HugePagesInfo &other)
{
allocated += other.allocated;
total += other.total;
size += other.size;
return *this;
}
};
} /* namespace xmrig */
#endif /* XMRIG_HUGEPAGESINFO_H */

View file

@ -0,0 +1,103 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//#include <iostream>
#include "crypto/common/LinuxMemory.h"
#include "base/io/log/Log.h"
#include "crypto/common/VirtualMemory.h"
#include "backend/cpu/Cpu.h"
#include <algorithm>
#include <fstream>
#include <string>
#include <mutex>
namespace xmrig {
static std::mutex mutex;
constexpr size_t twoMiB = 2U * 1024U * 1024U;
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
static inline std::string sysfs_path(uint32_t node, bool oneGbPages, bool nr)
{
return "/sys/devices/system/node/node" + std::to_string(node) + "/hugepages/hugepages-" + (oneGbPages ? "1048576" : "2048") + "kB/" + (nr ? "nr" : "free") + "_hugepages";
}
static inline bool write_nr_hugepages(uint32_t node, bool oneGbPages, uint64_t count) { return LinuxMemory::write(sysfs_path(node, oneGbPages, true).c_str(), count); }
static inline int64_t free_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, false).c_str()); }
static inline int64_t nr_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, true).c_str()); }
} // namespace xmrig
bool xmrig::LinuxMemory::reserve(size_t size, uint32_t node, bool oneGbPages)
{
std::lock_guard<std::mutex> lock(mutex);
const size_t pageSize = oneGbPages ? oneGiB : twoMiB;
const size_t required = VirtualMemory::align(size, pageSize) / pageSize;
const auto available = free_hugepages(node, oneGbPages);
if (available < 0 || static_cast<size_t>(available) >= required) {
return false;
}
return write_nr_hugepages(node, oneGbPages, std::max<size_t>(nr_hugepages(node, oneGbPages), 0) + (required - available));
}
bool xmrig::LinuxMemory::write(const char *path, uint64_t value)
{
std::ofstream file(path, std::ios::out | std::ios::binary | std::ios::trunc);
if (!file.is_open()) {
return false;
}
file << value;
file.flush();
return true;
}
int64_t xmrig::LinuxMemory::read(const char *path)
{
std::ifstream file(path);
if (!file.is_open()) {
return -1;
}
uint64_t value = 0;
file >> value;
return value;
}

View file

@ -0,0 +1,49 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_LINUXMEMORY_H
#define XMRIG_LINUXMEMORY_H
#include <cstdint>
#include <cstddef>
namespace xmrig {
class LinuxMemory
{
public:
static bool reserve(size_t size, uint32_t node, bool oneGbPages = false);
static bool write(const char *path, uint64_t value);
static int64_t read(const char *path);
};
} /* namespace xmrig */
#endif /* XMRIG_LINUXMEMORY_H */

View file

@ -47,7 +47,7 @@ xmrig::MemoryPool::MemoryPool(size_t size, bool hugePages, uint32_t node)
return; return;
} }
m_memory = new VirtualMemory(size * pageSize, hugePages, false, node); m_memory = new VirtualMemory(size * pageSize, hugePages, false, false, node);
} }

View file

@ -46,10 +46,13 @@ namespace xmrig {
static IMemoryPool *pool = nullptr; static IMemoryPool *pool = nullptr;
static std::mutex mutex; static std::mutex mutex;
constexpr size_t twoMiB = 2U * 1024U * 1024U;
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
} // namespace xmrig } // namespace xmrig
xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool usePool, uint32_t node, size_t alignSize) : xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node, size_t alignSize) :
m_size(align(size)), m_size(align(size)),
m_node(node) m_node(node)
{ {
@ -68,6 +71,10 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool usePool, u
} }
} }
if (oneGbPages && allocateOneGbPagesMemory()) {
return;
}
if (hugePages && allocateLargePagesMemory()) { if (hugePages && allocateLargePagesMemory()) {
return; return;
} }
@ -86,7 +93,7 @@ xmrig::VirtualMemory::~VirtualMemory()
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
pool->release(m_node); pool->release(m_node);
} }
else if (isHugePages()) { else if (isHugePages() || isOneGbPages()) {
freeLargePagesMemory(); freeLargePagesMemory();
} }
else { else {
@ -95,6 +102,12 @@ xmrig::VirtualMemory::~VirtualMemory()
} }
xmrig::HugePagesInfo xmrig::VirtualMemory::hugePages() const
{
return { this };
}
#ifndef XMRIG_FEATURE_HWLOC #ifndef XMRIG_FEATURE_HWLOC
uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t) uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t)
{ {

View file

@ -29,6 +29,7 @@
#include "base/tools/Object.h" #include "base/tools/Object.h"
#include "crypto/common/HugePagesInfo.h"
#include <bitset> #include <bitset>
@ -45,17 +46,16 @@ class VirtualMemory
public: public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(VirtualMemory) XMRIG_DISABLE_COPY_MOVE_DEFAULT(VirtualMemory)
VirtualMemory(size_t size, bool hugePages, bool usePool, uint32_t node = 0, size_t alignSize = 64); VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node = 0, size_t alignSize = 64);
~VirtualMemory(); ~VirtualMemory();
inline bool isHugePages() const { return m_flags.test(FLAG_HUGEPAGES); } inline bool isHugePages() const { return m_flags.test(FLAG_HUGEPAGES); }
inline bool isOneGbPages() const { return m_flags.test(FLAG_1GB_PAGES); }
inline size_t size() const { return m_size; } inline size_t size() const { return m_size; }
inline uint8_t *raw() const { return m_scratchpad; }
inline uint8_t *scratchpad() const { return m_scratchpad; } inline uint8_t *scratchpad() const { return m_scratchpad; }
inline std::pair<size_t, size_t> hugePages() const HugePagesInfo hugePages() const;
{
return { isHugePages() ? (align(size()) / 2097152) : 0, align(size()) / 2097152 };
}
static bool isHugepagesAvailable(); static bool isHugepagesAvailable();
static bool isOneGbPagesAvailable(); static bool isOneGbPagesAvailable();
@ -75,6 +75,7 @@ public:
private: private:
enum Flags { enum Flags {
FLAG_HUGEPAGES, FLAG_HUGEPAGES,
FLAG_1GB_PAGES,
FLAG_LOCK, FLAG_LOCK,
FLAG_EXTERNAL, FLAG_EXTERNAL,
FLAG_MAX FLAG_MAX

View file

@ -39,8 +39,11 @@
#endif #endif
#if defined (XMRIG_OS_LINUX) && (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT)) #if defined(XMRIG_OS_LINUX)
# define XMRIG_HAS_1GB_PAGES # if (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT))
# define XMRIG_HAS_1GB_PAGES
# endif
# include "crypto/common/LinuxMemory.h"
#endif #endif
@ -141,6 +144,10 @@ void xmrig::VirtualMemory::osInit(bool)
bool xmrig::VirtualMemory::allocateLargePagesMemory() bool xmrig::VirtualMemory::allocateLargePagesMemory()
{ {
# if defined(XMRIG_OS_LINUX)
LinuxMemory::reserve(m_size, m_node);
# endif
m_scratchpad = static_cast<uint8_t*>(allocateLargePagesMemory(m_size)); m_scratchpad = static_cast<uint8_t*>(allocateLargePagesMemory(m_size));
if (m_scratchpad) { if (m_scratchpad) {
m_flags.set(FLAG_HUGEPAGES, true); m_flags.set(FLAG_HUGEPAGES, true);
@ -160,9 +167,13 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory()
bool xmrig::VirtualMemory::allocateOneGbPagesMemory() bool xmrig::VirtualMemory::allocateOneGbPagesMemory()
{ {
# if defined(XMRIG_HAS_1GB_PAGES)
LinuxMemory::reserve(m_size, m_node, true);
# endif
m_scratchpad = static_cast<uint8_t*>(allocateOneGbPagesMemory(m_size)); m_scratchpad = static_cast<uint8_t*>(allocateOneGbPagesMemory(m_size));
if (m_scratchpad) { if (m_scratchpad) {
m_flags.set(FLAG_HUGEPAGES, true); m_flags.set(FLAG_1GB_PAGES, true);
madvise(m_scratchpad, m_size, MADV_RANDOM | MADV_WILLNEED); madvise(m_scratchpad, m_size, MADV_RANDOM | MADV_WILLNEED);

View file

@ -43,7 +43,7 @@ namespace randomx {
} }
template<size_t alignment> template<size_t alignment>
void AlignedAllocator<alignment>::freeMemory(void* ptr, size_t count) { void AlignedAllocator<alignment>::freeMemory(void* ptr, size_t) {
rx_aligned_free(ptr); rx_aligned_free(ptr);
} }
@ -57,12 +57,4 @@ 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);
};
} }

View file

@ -167,7 +167,5 @@ namespace randomx {
typedef void(ProgramFunc)(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t); typedef void(ProgramFunc)(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t);
typedef void(DatasetInitFunc)(randomx_cache* cache, uint8_t* dataset, uint32_t startBlock, uint32_t endBlock); typedef void(DatasetInitFunc)(randomx_cache* cache, uint8_t* dataset, uint32_t startBlock, uint32_t endBlock);
typedef void(DatasetDeallocFunc)(randomx_dataset*);
typedef void(CacheDeallocFunc)(randomx_cache*);
typedef void(CacheInitializeFunc)(randomx_cache*, const void*, size_t); typedef void(CacheInitializeFunc)(randomx_cache*, const void*, size_t);
} }

View file

@ -38,13 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Global scope for C binding */ /* Global scope for C binding */
struct randomx_dataset { struct randomx_dataset {
uint8_t* memory = nullptr; uint8_t* memory = nullptr;
randomx::DatasetDeallocFunc* dealloc;
}; };
/* Global scope for C binding */ /* Global scope for C binding */
struct randomx_cache { struct randomx_cache {
uint8_t* memory = nullptr; uint8_t* memory = nullptr;
randomx::CacheDeallocFunc* dealloc;
randomx::JitCompiler* jit; randomx::JitCompiler* jit;
randomx::CacheInitializeFunc* initialize; randomx::CacheInitializeFunc* initialize;
randomx::DatasetInitFunc* datasetInit; randomx::DatasetInitFunc* datasetInit;

View file

@ -272,42 +272,24 @@ RandomX_ConfigurationBase RandomX_CurrentConfig;
extern "C" { extern "C" {
randomx_cache *randomx_alloc_cache(randomx_flags flags) { randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory) {
randomx_cache *cache = nullptr; randomx_cache *cache = nullptr;
try { try {
cache = new randomx_cache(); cache = new randomx_cache();
switch (flags & (RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)) { switch (flags & RANDOMX_FLAG_JIT) {
case RANDOMX_FLAG_DEFAULT: case RANDOMX_FLAG_DEFAULT:
cache->dealloc = &randomx::deallocCache<randomx::DefaultAllocator>; cache->jit = nullptr;
cache->jit = nullptr; cache->initialize = &randomx::initCache;
cache->initialize = &randomx::initCache; cache->datasetInit = &randomx::initDataset;
cache->datasetInit = &randomx::initDataset; cache->memory = memory;
cache->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE);
break; break;
case RANDOMX_FLAG_JIT: case RANDOMX_FLAG_JIT:
cache->dealloc = &randomx::deallocCache<randomx::DefaultAllocator>; cache->jit = new randomx::JitCompiler();
cache->jit = new randomx::JitCompiler(); cache->initialize = &randomx::initCacheCompile;
cache->initialize = &randomx::initCacheCompile; cache->datasetInit = cache->jit->getDatasetInitFunc();
cache->datasetInit = cache->jit->getDatasetInitFunc(); cache->memory = memory;
cache->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE);
break;
case RANDOMX_FLAG_LARGE_PAGES:
cache->dealloc = &randomx::deallocCache<randomx::LargePageAllocator>;
cache->jit = nullptr;
cache->initialize = &randomx::initCache;
cache->datasetInit = &randomx::initDataset;
cache->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE);
break;
case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES:
cache->dealloc = &randomx::deallocCache<randomx::LargePageAllocator>;
cache->jit = new randomx::JitCompiler();
cache->initialize = &randomx::initCacheCompile;
cache->datasetInit = cache->jit->getDatasetInitFunc();
cache->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE);
break; break;
default: default:
@ -331,35 +313,12 @@ extern "C" {
} }
void randomx_release_cache(randomx_cache* cache) { void randomx_release_cache(randomx_cache* cache) {
assert(cache != nullptr);
cache->dealloc(cache);
delete cache; delete cache;
} }
randomx_dataset *randomx_alloc_dataset(randomx_flags flags) { randomx_dataset *randomx_create_dataset(uint8_t *memory) {
randomx_dataset *dataset = nullptr; auto dataset = new randomx_dataset();
dataset->memory = memory;
try {
dataset = new randomx_dataset();
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->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE);
}
else {
dataset->dealloc = &randomx::deallocDataset<randomx::DefaultAllocator>;
dataset->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE);
}
}
catch (std::exception &ex) {
if (dataset != nullptr) {
randomx_release_dataset(dataset);
dataset = nullptr;
}
}
return dataset; return dataset;
} }
@ -384,8 +343,6 @@ extern "C" {
} }
void randomx_release_dataset(randomx_dataset *dataset) { void randomx_release_dataset(randomx_dataset *dataset) {
assert(dataset != nullptr);
dataset->dealloc(dataset);
delete dataset; delete dataset;
} }

View file

@ -215,7 +215,7 @@ extern "C" {
* NULL is returned if memory allocation fails or if the RANDOMX_FLAG_JIT * NULL is returned if memory allocation fails or if the RANDOMX_FLAG_JIT
* is set and JIT compilation is not supported on the current platform. * is set and JIT compilation is not supported on the current platform.
*/ */
RANDOMX_EXPORT randomx_cache *randomx_alloc_cache(randomx_flags flags); RANDOMX_EXPORT randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory);
/** /**
* Initializes the cache memory and SuperscalarHash using the provided key value. * Initializes the cache memory and SuperscalarHash using the provided key value.
@ -242,7 +242,7 @@ RANDOMX_EXPORT void randomx_release_cache(randomx_cache* cache);
* @return Pointer to an allocated randomx_dataset structure. * @return Pointer to an allocated randomx_dataset structure.
* NULL is returned if memory allocation fails. * NULL is returned if memory allocation fails.
*/ */
RANDOMX_EXPORT randomx_dataset *randomx_alloc_dataset(randomx_flags flags); RANDOMX_EXPORT randomx_dataset *randomx_create_dataset(uint8_t *memory);
/** /**
* Gets the number of items contained in the dataset. * Gets the number of items contained in the dataset.

View file

@ -53,16 +53,6 @@ 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);
} }

View file

@ -32,5 +32,4 @@ 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);

View file

@ -83,15 +83,15 @@ bool xmrig::Rx::isReady(const Job &job)
} }
xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) xmrig::HugePagesInfo xmrig::Rx::hugePages()
{ {
return d_ptr->queue.dataset(job, nodeId); return d_ptr->queue.hugePages();
} }
std::pair<uint32_t, uint32_t> xmrig::Rx::hugePages() xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId)
{ {
return d_ptr->queue.hugePages(); return d_ptr->queue.dataset(job, nodeId);
} }

View file

@ -32,6 +32,9 @@
#include <utility> #include <utility>
#include "crypto/common/HugePagesInfo.h"
namespace xmrig namespace xmrig
{ {
@ -49,8 +52,8 @@ class Rx
public: public:
static bool init(const Job &job, const RxConfig &config, const CpuConfig &cpu); static bool init(const Job &job, const RxConfig &config, const CpuConfig &cpu);
static bool isReady(const Job &job); static bool isReady(const Job &job);
static HugePagesInfo hugePages();
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 void destroy(); static void destroy();
static void init(IRxListener *listener); static void init(IRxListener *listener);
}; };

View file

@ -73,7 +73,7 @@ public:
{ {
const uint64_t ts = Chrono::steadyMSecs(); const uint64_t ts = Chrono::steadyMSecs();
m_dataset = new RxDataset(hugePages, oneGbPages, true, mode); m_dataset = new RxDataset(hugePages, oneGbPages, true, mode, 0);
printAllocStatus(ts); printAllocStatus(ts);
} }
@ -94,18 +94,17 @@ private:
void printAllocStatus(uint64_t ts) void printAllocStatus(uint64_t ts)
{ {
if (m_dataset->get() != nullptr) { if (m_dataset->get() != nullptr) {
const auto pages = m_dataset->hugePages(); const auto pages = m_dataset->hugePages();
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
LOG_INFO("%s" GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu)") " huge pages %s%1.0f%% %u/%u" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), LOG_INFO("%s" GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu)") " huge pages %s%1.0f%% %u/%u" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"),
rx_tag(), rx_tag(),
m_dataset->size() / oneMiB, pages.size / oneMiB,
RxDataset::maxSize() / oneMiB, RxDataset::maxSize() / oneMiB,
RxCache::maxSize() / oneMiB, RxCache::maxSize() / oneMiB,
(pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), (pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
percent, pages.percent(),
pages.first, pages.allocated,
pages.second, pages.total,
m_dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", m_dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-",
Chrono::steadyMSecs() - ts Chrono::steadyMSecs() - ts
); );
@ -137,6 +136,16 @@ xmrig::RxBasicStorage::~RxBasicStorage()
} }
xmrig::HugePagesInfo xmrig::RxBasicStorage::hugePages() const
{
if (!d_ptr->dataset()) {
return {};
}
return d_ptr->dataset()->hugePages();
}
xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const
{ {
if (!d_ptr->isReady(job)) { if (!d_ptr->isReady(job)) {
@ -147,16 +156,6 @@ xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const
} }
std::pair<uint32_t, uint32_t> xmrig::RxBasicStorage::hugePages() const
{
if (!d_ptr->dataset()) {
return { 0U, 0U };
}
return d_ptr->dataset()->hugePages();
}
void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority)
{ {
d_ptr->setSeed(seed); d_ptr->setSeed(seed);

View file

@ -48,8 +48,8 @@ public:
~RxBasicStorage() override; ~RxBasicStorage() override;
protected: protected:
HugePagesInfo hugePages() const override;
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;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override; void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
private: private:

View file

@ -35,30 +35,25 @@ static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mism
xmrig::RxCache::RxCache(bool hugePages) xmrig::RxCache::RxCache(bool hugePages, uint32_t nodeId)
{ {
if (hugePages) { m_memory = new VirtualMemory(maxSize(), hugePages, false, false, nodeId);
m_flags = RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES;
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags));
}
if (!m_cache) { create(m_memory->raw());
m_flags = RANDOMX_FLAG_JIT; }
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags));
}
if (!m_cache) {
m_flags = RANDOMX_FLAG_DEFAULT; xmrig::RxCache::RxCache(uint8_t *memory)
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags)); {
} create(memory);
} }
xmrig::RxCache::~RxCache() xmrig::RxCache::~RxCache()
{ {
if (m_cache) { randomx_release_cache(m_cache);
randomx_release_cache(m_cache);
} delete m_memory;
} }
@ -75,15 +70,18 @@ bool xmrig::RxCache::init(const Buffer &seed)
} }
std::pair<uint32_t, uint32_t> xmrig::RxCache::hugePages() const xmrig::HugePagesInfo xmrig::RxCache::hugePages() const
{ {
constexpr size_t twoMiB = 2u * 1024u * 1024u; return m_memory ? m_memory->hugePages() : HugePagesInfo();
constexpr size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB; }
uint32_t count = 0;
if (isHugePages()) { void xmrig::RxCache::create(uint8_t *memory)
count += total; {
} m_cache = randomx_create_cache(RANDOMX_FLAG_JIT, memory);
return { count, total }; if (!m_cache) {
m_jit = false;
m_cache = randomx_create_cache(RANDOMX_FLAG_DEFAULT, memory);
}
} }

View file

@ -33,6 +33,7 @@
#include "base/tools/Buffer.h" #include "base/tools/Buffer.h"
#include "base/tools/Object.h" #include "base/tools/Object.h"
#include "crypto/common/HugePagesInfo.h"
#include "crypto/randomx/configuration.h" #include "crypto/randomx/configuration.h"
@ -48,24 +49,27 @@ class RxCache
public: public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxCache) XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxCache)
RxCache(bool hugePages = true); RxCache(bool hugePages, uint32_t nodeId);
RxCache(uint8_t *memory);
~RxCache(); ~RxCache();
inline bool isHugePages() const { return m_flags & 1; } inline bool isJIT() const { return m_jit; }
inline bool isJIT() const { return m_flags & 8; }
inline const Buffer &seed() const { return m_seed; } inline const Buffer &seed() const { return m_seed; }
inline randomx_cache *get() const { return m_cache; } inline randomx_cache *get() const { return m_cache; }
inline size_t size() const { return maxSize(); } inline size_t size() const { return maxSize(); }
bool init(const Buffer &seed); bool init(const Buffer &seed);
std::pair<uint32_t, uint32_t> hugePages() const; HugePagesInfo hugePages() const;
static inline constexpr size_t maxSize() { return RANDOMX_CACHE_MAX_SIZE; } static inline constexpr size_t maxSize() { return RANDOMX_CACHE_MAX_SIZE; }
private: private:
void create(uint8_t *memory);
bool m_jit = true;
Buffer m_seed; Buffer m_seed;
int m_flags = 0; randomx_cache *m_cache = nullptr;
randomx_cache *m_cache = nullptr; VirtualMemory *m_memory = nullptr;
}; };

View file

@ -38,9 +38,6 @@
#include <uv.h> #include <uv.h>
static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch");
namespace xmrig { namespace xmrig {
@ -55,18 +52,26 @@ static void init_dataset_wrapper(randomx_dataset *dataset, randomx_cache *cache,
} // namespace xmrig } // namespace xmrig
xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode) : xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode, uint32_t node) :
m_mode(mode) m_mode(mode),
m_node(node)
{ {
allocate(hugePages, oneGbPages); allocate(hugePages, oneGbPages);
if (isOneGbPages()) {
m_cache = new RxCache(m_memory->raw() + VirtualMemory::align(maxSize()));
return;
}
if (cache) { if (cache) {
m_cache = new RxCache(hugePages); m_cache = new RxCache(hugePages, node);
} }
} }
xmrig::RxDataset::RxDataset(RxCache *cache) : xmrig::RxDataset::RxDataset(RxCache *cache) :
m_node(0),
m_cache(cache) m_cache(cache)
{ {
} }
@ -74,11 +79,10 @@ xmrig::RxDataset::RxDataset(RxCache *cache) :
xmrig::RxDataset::~RxDataset() xmrig::RxDataset::~RxDataset()
{ {
if (m_dataset) { randomx_release_dataset(m_dataset);
randomx_release_dataset(m_dataset);
}
delete m_cache; delete m_cache;
delete m_memory;
} }
@ -118,6 +122,30 @@ bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads, int priorit
} }
bool xmrig::RxDataset::isHugePages() const
{
return m_memory && m_memory->isHugePages();
}
bool xmrig::RxDataset::isOneGbPages() const
{
return m_memory && m_memory->isOneGbPages();
}
xmrig::HugePagesInfo xmrig::RxDataset::hugePages(bool cache) const
{
auto pages = m_memory ? m_memory->hugePages() : HugePagesInfo();
if (cache && m_cache) {
pages += m_cache->hugePages();
}
return pages;
}
size_t xmrig::RxDataset::size(bool cache) const size_t xmrig::RxDataset::size(bool cache) const
{ {
size_t size = 0; size_t size = 0;
@ -134,31 +162,6 @@ size_t xmrig::RxDataset::size(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 oneGiB = 1024U * 1024U * 1024U;
constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB;
size_t datasetPageSize = isOneGbPages() ? oneGiB : twoMiB;
size_t total = VirtualMemory::align(maxSize(), datasetPageSize) / datasetPageSize;
uint32_t count = 0;
if (isHugePages() || isOneGbPages()) {
count += total;
}
if (cache && m_cache) {
total += cacheSize;
if (m_cache->isHugePages()) {
count += cacheSize;
}
}
return { count, total };
}
void *xmrig::RxDataset::raw() const void *xmrig::RxDataset::raw() const
{ {
return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr; return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr;
@ -189,19 +192,12 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages)
return; return;
} }
if (hugePages) { m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node);
m_flags = oneGbPages ? RANDOMX_FLAG_1GB_PAGES : RANDOMX_FLAG_LARGE_PAGES; m_dataset = randomx_create_dataset(m_memory->raw());
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
if (oneGbPages && !m_dataset) { # ifdef XMRIG_OS_LINUX
LOG_ERR(CLEAR "%s" RED_BOLD_S "Failed to allocate RandomX dataset using 1GB pages", rx_tag()); if (oneGbPages && !isOneGbPages()) {
m_flags = RANDOMX_FLAG_LARGE_PAGES; LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to allocate RandomX dataset using 1GB pages", rx_tag());
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
}
}
if (!m_dataset) {
m_flags = RANDOMX_FLAG_DEFAULT;
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
} }
# endif
} }

View file

@ -30,6 +30,7 @@
#include "base/tools/Object.h" #include "base/tools/Object.h"
#include "crypto/common/Algorithm.h" #include "crypto/common/Algorithm.h"
#include "crypto/common/HugePagesInfo.h"
#include "crypto/randomx/configuration.h" #include "crypto/randomx/configuration.h"
#include "crypto/randomx/randomx.h" #include "crypto/randomx/randomx.h"
#include "crypto/rx/RxConfig.h" #include "crypto/rx/RxConfig.h"
@ -44,6 +45,7 @@ namespace xmrig
class Buffer; class Buffer;
class RxCache; class RxCache;
class VirtualMemory;
class RxDataset class RxDataset
@ -51,19 +53,19 @@ class RxDataset
public: public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset) XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset)
RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode); RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode, uint32_t node);
RxDataset(RxCache *cache); RxDataset(RxCache *cache);
~RxDataset(); ~RxDataset();
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; }
bool init(const Buffer &seed, uint32_t numThreads, int priority); bool init(const Buffer &seed, uint32_t numThreads, int priority);
bool isHugePages() const;
bool isOneGbPages() const;
HugePagesInfo hugePages(bool cache = true) const;
size_t size(bool cache = true) const; size_t size(bool cache = true) const;
std::pair<uint32_t, uint32_t> hugePages(bool cache = true) const;
void *raw() const; void *raw() const;
void setRaw(const void *raw); void setRaw(const void *raw);
@ -73,9 +75,10 @@ private:
void allocate(bool hugePages, bool oneGbPages); void allocate(bool hugePages, bool oneGbPages);
const RxConfig::Mode m_mode = RxConfig::FastMode; const RxConfig::Mode m_mode = RxConfig::FastMode;
int m_flags = 0; const uint32_t m_node;
randomx_dataset *m_dataset = nullptr; randomx_dataset *m_dataset = nullptr;
RxCache *m_cache = nullptr; RxCache *m_cache = nullptr;
VirtualMemory *m_memory = nullptr;
}; };

View file

@ -130,8 +130,10 @@ public:
join(); join();
std::thread thread(allocateCache, this, m_nodeset.front(), hugePages); if (isCacheRequired()) {
thread.join(); std::thread thread(allocateCache, this, m_nodeset.front(), hugePages);
thread.join();
}
if (m_datasets.empty()) { if (m_datasets.empty()) {
m_datasets.insert({ m_nodeset.front(), new RxDataset(m_cache) }); m_datasets.insert({ m_nodeset.front(), new RxDataset(m_cache) });
@ -139,7 +141,9 @@ public:
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "failed to allocate RandomX datasets, switching to slow mode" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts); LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "failed to allocate RandomX datasets, switching to slow mode" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts);
} }
else { else {
dataset(m_nodeset.front())->setCache(m_cache); if (m_cache) {
dataset(m_nodeset.front())->setCache(m_cache);
}
printAllocStatus(ts); printAllocStatus(ts);
} }
@ -148,6 +152,22 @@ public:
} }
inline bool isCacheRequired() const
{
if (m_datasets.empty()) {
return true;
}
for (const auto kv : m_datasets) {
if (kv.second->isOneGbPages()) {
return false;
}
}
return true;
}
inline void initDatasets(uint32_t threads, int priority) inline void initDatasets(uint32_t threads, int priority)
{ {
uint64_t ts = Chrono::steadyMSecs(); uint64_t ts = Chrono::steadyMSecs();
@ -174,13 +194,11 @@ public:
} }
inline std::pair<uint32_t, uint32_t> hugePages() const inline HugePagesInfo hugePages() const
{ {
auto pages = m_cache->hugePages(); HugePagesInfo pages;
for (auto const &item : m_datasets) { for (auto const &item : m_datasets) {
const auto p = item.second->hugePages(false); pages += item.second->hugePages();
pages.first += p.first;
pages.second += p.second;
} }
return pages; return pages;
@ -198,7 +216,7 @@ private:
return; return;
} }
auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode); auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode, nodeId);
if (!dataset->get()) { if (!dataset->get()) {
printSkipped(nodeId, "failed to allocate dataset"); printSkipped(nodeId, "failed to allocate dataset");
@ -218,7 +236,7 @@ private:
bindToNUMANode(nodeId); bindToNUMANode(nodeId);
auto cache = new RxCache(hugePages); auto cache = new RxCache(hugePages, nodeId);
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
d_ptr->m_cache = cache; d_ptr->m_cache = cache;
@ -238,15 +256,14 @@ private:
void printAllocStatus(RxDataset *dataset, uint32_t nodeId, uint64_t ts) void printAllocStatus(RxDataset *dataset, uint32_t nodeId, uint64_t ts)
{ {
const auto pages = dataset->hugePages(); const auto pages = dataset->hugePages();
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") " huge pages %s%3.0f%%" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"), LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") " huge pages %s%3.0f%%" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"),
rx_tag(), rx_tag(),
nodeId, nodeId,
dataset->size() / oneMiB, pages.size / oneMiB,
(pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S), (pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S),
percent, pages.percent(),
Chrono::steadyMSecs() - ts Chrono::steadyMSecs() - ts
); );
} }
@ -254,15 +271,14 @@ private:
void printAllocStatus(RxCache *cache, uint32_t nodeId, uint64_t ts) void printAllocStatus(RxCache *cache, uint32_t nodeId, uint64_t ts)
{ {
const auto pages = cache->hugePages(); const auto pages = cache->hugePages();
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"),
rx_tag(), rx_tag(),
nodeId, nodeId,
cache->size() / oneMiB, cache->size() / oneMiB,
(pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S), (pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S),
percent, pages.percent(),
cache->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", cache->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-",
Chrono::steadyMSecs() - ts Chrono::steadyMSecs() - ts
); );
@ -271,21 +287,15 @@ private:
void printAllocStatus(uint64_t ts) void printAllocStatus(uint64_t ts)
{ {
size_t memory = m_cache->size(); auto pages = hugePages();
auto pages = hugePages();
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
for (auto const &item : m_datasets) {
memory += item.second->size(false);
}
LOG_INFO("%s" CYAN_BOLD("-- ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%% %u/%u" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"), LOG_INFO("%s" CYAN_BOLD("-- ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%% %u/%u" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"),
rx_tag(), rx_tag(),
memory / oneMiB, pages.size / oneMiB,
(pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), (pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
percent, pages.percent(),
pages.first, pages.allocated,
pages.second, pages.total,
Chrono::steadyMSecs() - ts Chrono::steadyMSecs() - ts
); );
} }
@ -326,6 +336,16 @@ xmrig::RxNUMAStorage::~RxNUMAStorage()
} }
xmrig::HugePagesInfo xmrig::RxNUMAStorage::hugePages() const
{
if (!d_ptr->isAllocated()) {
return {};
}
return d_ptr->hugePages();
}
xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId) const xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId) const
{ {
if (!d_ptr->isReady(job)) { if (!d_ptr->isReady(job)) {
@ -336,16 +356,6 @@ xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId)
} }
std::pair<uint32_t, uint32_t> xmrig::RxNUMAStorage::hugePages() const
{
if (!d_ptr->isAllocated()) {
return { 0U, 0U };
}
return d_ptr->hugePages();
}
void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode, int priority) void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode, int priority)
{ {
d_ptr->setSeed(seed); d_ptr->setSeed(seed);

View file

@ -51,8 +51,8 @@ public:
~RxNUMAStorage() override; ~RxNUMAStorage() override;
protected: protected:
HugePagesInfo hugePages() const override;
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;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override; void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
private: private:

View file

@ -86,11 +86,11 @@ xmrig::RxDataset *xmrig::RxQueue::dataset(const Job &job, uint32_t nodeId)
} }
std::pair<uint32_t, uint32_t> xmrig::RxQueue::hugePages() xmrig::HugePagesInfo xmrig::RxQueue::hugePages()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : std::pair<uint32_t, uint32_t>(0U, 0U); return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : HugePagesInfo();
} }

View file

@ -29,6 +29,7 @@
#include "base/tools/Object.h" #include "base/tools/Object.h"
#include "crypto/common/HugePagesInfo.h"
#include "crypto/rx/RxConfig.h" #include "crypto/rx/RxConfig.h"
#include "crypto/rx/RxSeed.h" #include "crypto/rx/RxSeed.h"
@ -83,7 +84,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(); HugePagesInfo hugePages();
void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority); void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority);
private: private:

View file

@ -105,7 +105,7 @@ static inline void checkHash(const JobBundle &bundle, std::vector<JobResult> &re
static void getResults(JobBundle &bundle, std::vector<JobResult> &results, uint32_t &errors, bool hwAES) static void getResults(JobBundle &bundle, std::vector<JobResult> &results, uint32_t &errors, bool hwAES)
{ {
const auto &algorithm = bundle.job.algorithm(); const auto &algorithm = bundle.job.algorithm();
auto memory = new VirtualMemory(algorithm.l3(), false, false); auto memory = new VirtualMemory(algorithm.l3(), false, false, false);
uint8_t hash[32]{ 0 }; uint8_t hash[32]{ 0 };
if (algorithm.family() == Algorithm::RANDOM_X) { if (algorithm.family() == Algorithm::RANDOM_X) {