mirror of
https://github.com/xmrig/xmrig.git
synced 2024-12-22 19:49:36 +00:00
Memory allocation refactoring.
This commit is contained in:
parent
8a13e0febd
commit
d32df84ca5
32 changed files with 516 additions and 272 deletions
|
@ -76,6 +76,7 @@ set(HEADERS_CRYPTO
|
|||
src/crypto/cn/soft_aes.h
|
||||
src/crypto/common/Algorithm.h
|
||||
src/crypto/common/Coin.h
|
||||
src/crypto/common/HugePagesInfo.h
|
||||
src/crypto/common/keccak.h
|
||||
src/crypto/common/MemoryPool.h
|
||||
src/crypto/common/Nonce.h
|
||||
|
@ -115,6 +116,7 @@ set(SOURCES_CRYPTO
|
|||
src/crypto/cn/CnHash.cpp
|
||||
src/crypto/common/Algorithm.cpp
|
||||
src/crypto/common/Coin.cpp
|
||||
src/crypto/common/HugePagesInfo.cpp
|
||||
src/crypto/common/keccak.cpp
|
||||
src/crypto/common/MemoryPool.cpp
|
||||
src/crypto/common/Nonce.cpp
|
||||
|
@ -154,6 +156,11 @@ else()
|
|||
if (XMRIG_OS_ANDROID)
|
||||
set(EXTRA_LIBS pthread rt dl log)
|
||||
elseif (XMRIG_OS_LINUX)
|
||||
list(APPEND SOURCES_OS
|
||||
src/crypto/common/LinuxMemory.h
|
||||
src/crypto/common/LinuxMemory.cpp
|
||||
)
|
||||
|
||||
set(EXTRA_LIBS pthread rt dl)
|
||||
elseif (XMRIG_OS_FREEBSD)
|
||||
set(EXTRA_LIBS kvm pthread)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
@ -44,8 +45,8 @@ class IRxStorage
|
|||
public:
|
||||
virtual ~IRxStorage() = default;
|
||||
|
||||
virtual HugePagesInfo hugePages() 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;
|
||||
};
|
||||
|
||||
|
|
|
@ -68,17 +68,15 @@ static std::mutex mutex;
|
|||
struct CpuLaunchStatus
|
||||
{
|
||||
public:
|
||||
inline size_t hugePages() const { return m_hugePages; }
|
||||
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 ways() const { return m_ways; }
|
||||
inline const HugePagesInfo &hugePages() const { return m_hugePages; }
|
||||
inline size_t memory() const { return m_ways * m_memory; }
|
||||
inline size_t threads() const { return m_threads; }
|
||||
inline size_t ways() const { return m_ways; }
|
||||
|
||||
inline void start(const std::vector<CpuLaunchData> &threads, size_t memory)
|
||||
{
|
||||
m_hugePages = 0;
|
||||
m_hugePages.reset();
|
||||
m_memory = memory;
|
||||
m_pages = 0;
|
||||
m_started = 0;
|
||||
m_errors = 0;
|
||||
m_threads = threads.size();
|
||||
|
@ -89,11 +87,9 @@ public:
|
|||
inline bool started(IWorker *worker, bool ready)
|
||||
{
|
||||
if (ready) {
|
||||
auto hugePages = worker->memory()->hugePages();
|
||||
|
||||
m_started++;
|
||||
m_hugePages += hugePages.first;
|
||||
m_pages += hugePages.second;
|
||||
|
||||
m_hugePages += worker->memory()->hugePages();
|
||||
m_ways += worker->intensity();
|
||||
}
|
||||
else {
|
||||
|
@ -115,19 +111,18 @@ public:
|
|||
tag,
|
||||
m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S,
|
||||
m_started, m_threads, m_ways,
|
||||
(m_hugePages == m_pages ? GREEN_BOLD_S : (m_hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
m_hugePages == 0 ? 0.0 : static_cast<double>(m_hugePages) / m_pages * 100.0,
|
||||
m_hugePages, m_pages,
|
||||
(m_hugePages.isFullyAllocated() ? GREEN_BOLD_S : (m_hugePages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
m_hugePages.percent(),
|
||||
m_hugePages.allocated, m_hugePages.total,
|
||||
memory() / 1024,
|
||||
Chrono::steadyMSecs() - m_ts
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
HugePagesInfo m_hugePages;
|
||||
size_t m_errors = 0;
|
||||
size_t m_hugePages = 0;
|
||||
size_t m_memory = 0;
|
||||
size_t m_pages = 0;
|
||||
size_t m_started = 0;
|
||||
size_t m_threads = 0;
|
||||
size_t m_ways = 0;
|
||||
|
@ -169,18 +164,17 @@ public:
|
|||
|
||||
rapidjson::Value hugePages(int version, rapidjson::Document &doc)
|
||||
{
|
||||
std::pair<unsigned, unsigned> pages(0, 0);
|
||||
HugePagesInfo pages;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (algo.family() == Algorithm::RANDOM_X) {
|
||||
pages = Rx::hugePages();
|
||||
pages += Rx::hugePages();
|
||||
}
|
||||
# endif
|
||||
|
||||
mutex.lock();
|
||||
|
||||
pages.first += status.hugePages();
|
||||
pages.second += status.pages();
|
||||
pages += status.hugePages();
|
||||
|
||||
mutex.unlock();
|
||||
|
||||
|
@ -188,11 +182,11 @@ public:
|
|||
|
||||
if (version > 1) {
|
||||
hugepages.SetArray();
|
||||
hugepages.PushBack(pages.first, doc.GetAllocator());
|
||||
hugepages.PushBack(pages.second, doc.GetAllocator());
|
||||
hugepages.PushBack(static_cast<uint64_t>(pages.allocated), doc.GetAllocator());
|
||||
hugepages.PushBack(static_cast<uint64_t>(pages.total), doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
hugepages = pages.first == pages.second;
|
||||
hugepages = pages.isFullyAllocated();
|
||||
}
|
||||
|
||||
return hugepages;
|
||||
|
|
|
@ -63,7 +63,7 @@ xmrig::CpuWorker<N>::CpuWorker(size_t id, const CpuLaunchData &data) :
|
|||
m_miner(data.miner),
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
50
src/crypto/common/HugePagesInfo.cpp
Normal file
50
src/crypto/common/HugePagesInfo.cpp
Normal 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;
|
||||
}
|
||||
}
|
67
src/crypto/common/HugePagesInfo.h
Normal file
67
src/crypto/common/HugePagesInfo.h
Normal 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 */
|
103
src/crypto/common/LinuxMemory.cpp
Normal file
103
src/crypto/common/LinuxMemory.cpp
Normal 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;
|
||||
}
|
49
src/crypto/common/LinuxMemory.h
Normal file
49
src/crypto/common/LinuxMemory.h
Normal 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 */
|
|
@ -47,7 +47,7 @@ xmrig::MemoryPool::MemoryPool(size_t size, bool hugePages, uint32_t node)
|
|||
return;
|
||||
}
|
||||
|
||||
m_memory = new VirtualMemory(size * pageSize, hugePages, false, node);
|
||||
m_memory = new VirtualMemory(size * pageSize, hugePages, false, false, node);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,10 +46,13 @@ namespace xmrig {
|
|||
static IMemoryPool *pool = nullptr;
|
||||
static std::mutex mutex;
|
||||
|
||||
constexpr size_t twoMiB = 2U * 1024U * 1024U;
|
||||
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
|
||||
|
||||
} // 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_node(node)
|
||||
{
|
||||
|
@ -68,6 +71,10 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool usePool, u
|
|||
}
|
||||
}
|
||||
|
||||
if (oneGbPages && allocateOneGbPagesMemory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hugePages && allocateLargePagesMemory()) {
|
||||
return;
|
||||
}
|
||||
|
@ -86,7 +93,7 @@ xmrig::VirtualMemory::~VirtualMemory()
|
|||
std::lock_guard<std::mutex> lock(mutex);
|
||||
pool->release(m_node);
|
||||
}
|
||||
else if (isHugePages()) {
|
||||
else if (isHugePages() || isOneGbPages()) {
|
||||
freeLargePagesMemory();
|
||||
}
|
||||
else {
|
||||
|
@ -95,6 +102,12 @@ xmrig::VirtualMemory::~VirtualMemory()
|
|||
}
|
||||
|
||||
|
||||
xmrig::HugePagesInfo xmrig::VirtualMemory::hugePages() const
|
||||
{
|
||||
return { this };
|
||||
}
|
||||
|
||||
|
||||
#ifndef XMRIG_FEATURE_HWLOC
|
||||
uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
|
||||
|
||||
#include <bitset>
|
||||
|
@ -45,17 +46,16 @@ class VirtualMemory
|
|||
public:
|
||||
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();
|
||||
|
||||
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 uint8_t *raw() const { return m_scratchpad; }
|
||||
inline uint8_t *scratchpad() const { return m_scratchpad; }
|
||||
|
||||
inline std::pair<size_t, size_t> hugePages() const
|
||||
{
|
||||
return { isHugePages() ? (align(size()) / 2097152) : 0, align(size()) / 2097152 };
|
||||
}
|
||||
HugePagesInfo hugePages() const;
|
||||
|
||||
static bool isHugepagesAvailable();
|
||||
static bool isOneGbPagesAvailable();
|
||||
|
@ -75,6 +75,7 @@ public:
|
|||
private:
|
||||
enum Flags {
|
||||
FLAG_HUGEPAGES,
|
||||
FLAG_1GB_PAGES,
|
||||
FLAG_LOCK,
|
||||
FLAG_EXTERNAL,
|
||||
FLAG_MAX
|
||||
|
|
|
@ -39,8 +39,11 @@
|
|||
#endif
|
||||
|
||||
|
||||
#if defined (XMRIG_OS_LINUX) && (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT))
|
||||
# define XMRIG_HAS_1GB_PAGES
|
||||
#if defined(XMRIG_OS_LINUX)
|
||||
# if (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT))
|
||||
# define XMRIG_HAS_1GB_PAGES
|
||||
# endif
|
||||
# include "crypto/common/LinuxMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -141,6 +144,10 @@ void xmrig::VirtualMemory::osInit(bool)
|
|||
|
||||
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));
|
||||
if (m_scratchpad) {
|
||||
m_flags.set(FLAG_HUGEPAGES, true);
|
||||
|
@ -160,9 +167,13 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory()
|
|||
|
||||
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));
|
||||
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);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace randomx {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,4 @@ namespace randomx {
|
|||
freePagedMemory(ptr, count);
|
||||
};
|
||||
|
||||
void* OneGbPageAllocator::allocMemory(size_t count) {
|
||||
return allocOneGbPagesMemory(count);
|
||||
}
|
||||
|
||||
void OneGbPageAllocator::freeMemory(void* ptr, size_t count) {
|
||||
freePagedMemory(ptr, count);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -167,7 +167,5 @@ namespace randomx {
|
|||
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(DatasetDeallocFunc)(randomx_dataset*);
|
||||
typedef void(CacheDeallocFunc)(randomx_cache*);
|
||||
typedef void(CacheInitializeFunc)(randomx_cache*, const void*, size_t);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/* Global scope for C binding */
|
||||
struct randomx_dataset {
|
||||
uint8_t* memory = nullptr;
|
||||
randomx::DatasetDeallocFunc* dealloc;
|
||||
};
|
||||
|
||||
/* Global scope for C binding */
|
||||
struct randomx_cache {
|
||||
uint8_t* memory = nullptr;
|
||||
randomx::CacheDeallocFunc* dealloc;
|
||||
randomx::JitCompiler* jit;
|
||||
randomx::CacheInitializeFunc* initialize;
|
||||
randomx::DatasetInitFunc* datasetInit;
|
||||
|
|
|
@ -272,42 +272,24 @@ RandomX_ConfigurationBase RandomX_CurrentConfig;
|
|||
|
||||
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;
|
||||
|
||||
try {
|
||||
cache = new randomx_cache();
|
||||
switch (flags & (RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)) {
|
||||
switch (flags & RANDOMX_FLAG_JIT) {
|
||||
case RANDOMX_FLAG_DEFAULT:
|
||||
cache->dealloc = &randomx::deallocCache<randomx::DefaultAllocator>;
|
||||
cache->jit = nullptr;
|
||||
cache->initialize = &randomx::initCache;
|
||||
cache->datasetInit = &randomx::initDataset;
|
||||
cache->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE);
|
||||
cache->jit = nullptr;
|
||||
cache->initialize = &randomx::initCache;
|
||||
cache->datasetInit = &randomx::initDataset;
|
||||
cache->memory = memory;
|
||||
break;
|
||||
|
||||
case RANDOMX_FLAG_JIT:
|
||||
cache->dealloc = &randomx::deallocCache<randomx::DefaultAllocator>;
|
||||
cache->jit = new randomx::JitCompiler();
|
||||
cache->initialize = &randomx::initCacheCompile;
|
||||
cache->datasetInit = cache->jit->getDatasetInitFunc();
|
||||
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);
|
||||
cache->jit = new randomx::JitCompiler();
|
||||
cache->initialize = &randomx::initCacheCompile;
|
||||
cache->datasetInit = cache->jit->getDatasetInitFunc();
|
||||
cache->memory = memory;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -331,35 +313,12 @@ extern "C" {
|
|||
}
|
||||
|
||||
void randomx_release_cache(randomx_cache* cache) {
|
||||
assert(cache != nullptr);
|
||||
cache->dealloc(cache);
|
||||
delete cache;
|
||||
}
|
||||
|
||||
randomx_dataset *randomx_alloc_dataset(randomx_flags flags) {
|
||||
randomx_dataset *dataset = nullptr;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
randomx_dataset *randomx_create_dataset(uint8_t *memory) {
|
||||
auto dataset = new randomx_dataset();
|
||||
dataset->memory = memory;
|
||||
|
||||
return dataset;
|
||||
}
|
||||
|
@ -384,8 +343,6 @@ extern "C" {
|
|||
}
|
||||
|
||||
void randomx_release_dataset(randomx_dataset *dataset) {
|
||||
assert(dataset != nullptr);
|
||||
dataset->dealloc(dataset);
|
||||
delete dataset;
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ extern "C" {
|
|||
* 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.
|
||||
*/
|
||||
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.
|
||||
|
@ -242,7 +242,7 @@ RANDOMX_EXPORT void randomx_release_cache(randomx_cache* cache);
|
|||
* @return Pointer to an allocated randomx_dataset structure.
|
||||
* 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.
|
||||
|
|
|
@ -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) {
|
||||
xmrig::VirtualMemory::freeLargePagesMemory(ptr, bytes);
|
||||
}
|
||||
|
|
|
@ -32,5 +32,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
void* allocExecutableMemory(std::size_t);
|
||||
void* allocLargePagesMemory(std::size_t);
|
||||
void* allocOneGbPagesMemory(std::size_t);
|
||||
void freePagedMemory(void*, std::size_t);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include <utility>
|
||||
|
||||
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
|
||||
|
||||
namespace xmrig
|
||||
{
|
||||
|
||||
|
@ -49,8 +52,8 @@ class Rx
|
|||
public:
|
||||
static bool init(const Job &job, const RxConfig &config, const CpuConfig &cpu);
|
||||
static bool isReady(const Job &job);
|
||||
static HugePagesInfo hugePages();
|
||||
static RxDataset *dataset(const Job &job, uint32_t nodeId);
|
||||
static std::pair<uint32_t, uint32_t> hugePages();
|
||||
static void destroy();
|
||||
static void init(IRxListener *listener);
|
||||
};
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -94,18 +94,17 @@ private:
|
|||
void printAllocStatus(uint64_t ts)
|
||||
{
|
||||
if (m_dataset->get() != nullptr) {
|
||||
const auto pages = m_dataset->hugePages();
|
||||
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
|
||||
const auto pages = m_dataset->hugePages();
|
||||
|
||||
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(),
|
||||
m_dataset->size() / oneMiB,
|
||||
pages.size / oneMiB,
|
||||
RxDataset::maxSize() / oneMiB,
|
||||
RxCache::maxSize() / oneMiB,
|
||||
(pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
percent,
|
||||
pages.first,
|
||||
pages.second,
|
||||
(pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
pages.percent(),
|
||||
pages.allocated,
|
||||
pages.total,
|
||||
m_dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-",
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
d_ptr->setSeed(seed);
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
~RxBasicStorage() override;
|
||||
|
||||
protected:
|
||||
HugePagesInfo hugePages() 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;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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_flags = RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES;
|
||||
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags));
|
||||
}
|
||||
m_memory = new VirtualMemory(maxSize(), hugePages, false, false, nodeId);
|
||||
|
||||
if (!m_cache) {
|
||||
m_flags = RANDOMX_FLAG_JIT;
|
||||
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags));
|
||||
}
|
||||
create(m_memory->raw());
|
||||
}
|
||||
|
||||
if (!m_cache) {
|
||||
m_flags = RANDOMX_FLAG_DEFAULT;
|
||||
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(m_flags));
|
||||
}
|
||||
|
||||
xmrig::RxCache::RxCache(uint8_t *memory)
|
||||
{
|
||||
create(memory);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
constexpr size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB;
|
||||
|
||||
uint32_t count = 0;
|
||||
if (isHugePages()) {
|
||||
count += total;
|
||||
}
|
||||
|
||||
return { count, total };
|
||||
return m_memory ? m_memory->hugePages() : HugePagesInfo();
|
||||
}
|
||||
|
||||
|
||||
void xmrig::RxCache::create(uint8_t *memory)
|
||||
{
|
||||
m_cache = randomx_create_cache(RANDOMX_FLAG_JIT, memory);
|
||||
|
||||
if (!m_cache) {
|
||||
m_jit = false;
|
||||
m_cache = randomx_create_cache(RANDOMX_FLAG_DEFAULT, memory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "base/tools/Buffer.h"
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
#include "crypto/randomx/configuration.h"
|
||||
|
||||
|
||||
|
@ -48,24 +49,27 @@ class RxCache
|
|||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxCache)
|
||||
|
||||
RxCache(bool hugePages = true);
|
||||
RxCache(bool hugePages, uint32_t nodeId);
|
||||
RxCache(uint8_t *memory);
|
||||
~RxCache();
|
||||
|
||||
inline bool isHugePages() const { return m_flags & 1; }
|
||||
inline bool isJIT() const { return m_flags & 8; }
|
||||
inline bool isJIT() const { return m_jit; }
|
||||
inline const Buffer &seed() const { return m_seed; }
|
||||
inline randomx_cache *get() const { return m_cache; }
|
||||
inline size_t size() const { return maxSize(); }
|
||||
|
||||
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; }
|
||||
|
||||
private:
|
||||
void create(uint8_t *memory);
|
||||
|
||||
bool m_jit = true;
|
||||
Buffer m_seed;
|
||||
int m_flags = 0;
|
||||
randomx_cache *m_cache = nullptr;
|
||||
randomx_cache *m_cache = nullptr;
|
||||
VirtualMemory *m_memory = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,9 +38,6 @@
|
|||
#include <uv.h>
|
||||
|
||||
|
||||
static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch");
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
|
@ -55,18 +52,26 @@ static void init_dataset_wrapper(randomx_dataset *dataset, randomx_cache *cache,
|
|||
} // namespace xmrig
|
||||
|
||||
|
||||
xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode) :
|
||||
m_mode(mode)
|
||||
xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode, uint32_t node) :
|
||||
m_mode(mode),
|
||||
m_node(node)
|
||||
{
|
||||
allocate(hugePages, oneGbPages);
|
||||
|
||||
if (isOneGbPages()) {
|
||||
m_cache = new RxCache(m_memory->raw() + VirtualMemory::align(maxSize()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
m_cache = new RxCache(hugePages);
|
||||
m_cache = new RxCache(hugePages, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xmrig::RxDataset::RxDataset(RxCache *cache) :
|
||||
m_node(0),
|
||||
m_cache(cache)
|
||||
{
|
||||
}
|
||||
|
@ -74,11 +79,10 @@ xmrig::RxDataset::RxDataset(RxCache *cache) :
|
|||
|
||||
xmrig::RxDataset::~RxDataset()
|
||||
{
|
||||
if (m_dataset) {
|
||||
randomx_release_dataset(m_dataset);
|
||||
}
|
||||
randomx_release_dataset(m_dataset);
|
||||
|
||||
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 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
|
||||
{
|
||||
return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr;
|
||||
|
@ -189,19 +192,12 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages)
|
|||
return;
|
||||
}
|
||||
|
||||
if (hugePages) {
|
||||
m_flags = oneGbPages ? RANDOMX_FLAG_1GB_PAGES : RANDOMX_FLAG_LARGE_PAGES;
|
||||
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(m_flags));
|
||||
m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node);
|
||||
m_dataset = randomx_create_dataset(m_memory->raw());
|
||||
|
||||
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_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));
|
||||
# ifdef XMRIG_OS_LINUX
|
||||
if (oneGbPages && !isOneGbPages()) {
|
||||
LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to allocate RandomX dataset using 1GB pages", rx_tag());
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/Algorithm.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
#include "crypto/randomx/configuration.h"
|
||||
#include "crypto/randomx/randomx.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
|
@ -44,6 +45,7 @@ namespace xmrig
|
|||
|
||||
class Buffer;
|
||||
class RxCache;
|
||||
class VirtualMemory;
|
||||
|
||||
|
||||
class RxDataset
|
||||
|
@ -51,19 +53,19 @@ class RxDataset
|
|||
public:
|
||||
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();
|
||||
|
||||
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 RxCache *cache() const { return m_cache; }
|
||||
inline void setCache(RxCache *cache) { m_cache = cache; }
|
||||
|
||||
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;
|
||||
std::pair<uint32_t, uint32_t> hugePages(bool cache = true) const;
|
||||
void *raw() const;
|
||||
void setRaw(const void *raw);
|
||||
|
||||
|
@ -73,9 +75,10 @@ private:
|
|||
void allocate(bool hugePages, bool oneGbPages);
|
||||
|
||||
const RxConfig::Mode m_mode = RxConfig::FastMode;
|
||||
int m_flags = 0;
|
||||
const uint32_t m_node;
|
||||
randomx_dataset *m_dataset = nullptr;
|
||||
RxCache *m_cache = nullptr;
|
||||
VirtualMemory *m_memory = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -130,8 +130,10 @@ public:
|
|||
|
||||
join();
|
||||
|
||||
std::thread thread(allocateCache, this, m_nodeset.front(), hugePages);
|
||||
thread.join();
|
||||
if (isCacheRequired()) {
|
||||
std::thread thread(allocateCache, this, m_nodeset.front(), hugePages);
|
||||
thread.join();
|
||||
}
|
||||
|
||||
if (m_datasets.empty()) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
dataset(m_nodeset.front())->setCache(m_cache);
|
||||
if (m_cache) {
|
||||
dataset(m_nodeset.front())->setCache(m_cache);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
const auto p = item.second->hugePages(false);
|
||||
pages.first += p.first;
|
||||
pages.second += p.second;
|
||||
pages += item.second->hugePages();
|
||||
}
|
||||
|
||||
return pages;
|
||||
|
@ -198,7 +216,7 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode);
|
||||
auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode, nodeId);
|
||||
if (!dataset->get()) {
|
||||
printSkipped(nodeId, "failed to allocate dataset");
|
||||
|
||||
|
@ -218,7 +236,7 @@ private:
|
|||
|
||||
bindToNUMANode(nodeId);
|
||||
|
||||
auto cache = new RxCache(hugePages);
|
||||
auto cache = new RxCache(hugePages, nodeId);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
d_ptr->m_cache = cache;
|
||||
|
@ -238,15 +256,14 @@ private:
|
|||
|
||||
void printAllocStatus(RxDataset *dataset, uint32_t nodeId, uint64_t ts)
|
||||
{
|
||||
const auto pages = dataset->hugePages();
|
||||
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
|
||||
const auto pages = dataset->hugePages();
|
||||
|
||||
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(),
|
||||
nodeId,
|
||||
dataset->size() / oneMiB,
|
||||
(pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S),
|
||||
percent,
|
||||
pages.size / oneMiB,
|
||||
(pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S),
|
||||
pages.percent(),
|
||||
Chrono::steadyMSecs() - ts
|
||||
);
|
||||
}
|
||||
|
@ -254,15 +271,14 @@ private:
|
|||
|
||||
void printAllocStatus(RxCache *cache, uint32_t nodeId, uint64_t ts)
|
||||
{
|
||||
const auto pages = cache->hugePages();
|
||||
const double percent = pages.first == 0 ? 0.0 : static_cast<double>(pages.first) / pages.second * 100.0;
|
||||
const auto pages = cache->hugePages();
|
||||
|
||||
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(),
|
||||
nodeId,
|
||||
cache->size() / oneMiB,
|
||||
(pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S),
|
||||
percent,
|
||||
(pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S),
|
||||
pages.percent(),
|
||||
cache->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-",
|
||||
Chrono::steadyMSecs() - ts
|
||||
);
|
||||
|
@ -271,21 +287,15 @@ private:
|
|||
|
||||
void printAllocStatus(uint64_t ts)
|
||||
{
|
||||
size_t memory = m_cache->size();
|
||||
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);
|
||||
}
|
||||
auto pages = hugePages();
|
||||
|
||||
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(),
|
||||
memory / oneMiB,
|
||||
(pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
percent,
|
||||
pages.first,
|
||||
pages.second,
|
||||
pages.size / oneMiB,
|
||||
(pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
pages.percent(),
|
||||
pages.allocated,
|
||||
pages.total,
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
d_ptr->setSeed(seed);
|
||||
|
|
|
@ -51,8 +51,8 @@ public:
|
|||
~RxNUMAStorage() override;
|
||||
|
||||
protected:
|
||||
HugePagesInfo hugePages() 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;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "crypto/rx/RxSeed.h"
|
||||
|
||||
|
@ -83,7 +84,7 @@ public:
|
|||
|
||||
bool isReady(const Job &job);
|
||||
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);
|
||||
|
||||
private:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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 };
|
||||
|
||||
if (algorithm.family() == Algorithm::RANDOM_X) {
|
||||
|
|
Loading…
Reference in a new issue