This commit is contained in:
commit
01e2945ab7
125 changed files with 4772 additions and 2073 deletions
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "crypto/rx/Rx.h"
|
||||
#include "backend/common/Tags.h"
|
||||
#include "backend/cpu/CpuConfig.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "crypto/rx/RxQueue.h"
|
||||
|
@ -38,8 +39,9 @@ namespace xmrig {
|
|||
class RxPrivate;
|
||||
|
||||
|
||||
static const char *tag = BLUE_BG(WHITE_BOLD_S " rx ") " ";
|
||||
static RxPrivate *d_ptr = nullptr;
|
||||
static bool osInitialized = false;
|
||||
static const char *tag = BLUE_BG(WHITE_BOLD_S " rx ") " ";
|
||||
static RxPrivate *d_ptr = nullptr;
|
||||
|
||||
|
||||
class RxPrivate
|
||||
|
@ -60,7 +62,7 @@ const char *xmrig::rx_tag()
|
|||
}
|
||||
|
||||
|
||||
bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages)
|
||||
bool xmrig::Rx::init(const Job &job, const RxConfig &config, const CpuConfig &cpu)
|
||||
{
|
||||
if (job.algorithm().family() != Algorithm::RANDOM_X) {
|
||||
return true;
|
||||
|
@ -70,7 +72,12 @@ bool xmrig::Rx::init(const Job &job, const RxConfig &config, bool hugePages)
|
|||
return true;
|
||||
}
|
||||
|
||||
d_ptr->queue.enqueue(job, config.nodeset(), config.threads(), hugePages, config.mode());
|
||||
if (!osInitialized) {
|
||||
osInit(config);
|
||||
osInitialized = true;
|
||||
}
|
||||
|
||||
d_ptr->queue.enqueue(job, config.nodeset(), config.threads(cpu.limit()), cpu.isHugePages(), config.isOneGbPages(), config.mode(), cpu.priority());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -82,15 +89,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,3 +113,10 @@ void xmrig::Rx::init(IRxListener *listener)
|
|||
{
|
||||
d_ptr = new RxPrivate(listener);
|
||||
}
|
||||
|
||||
|
||||
#if !defined(XMRIG_OS_LINUX) || defined(XMRIG_ARM)
|
||||
void xmrig::Rx::osInit(const RxConfig &)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -32,11 +32,15 @@
|
|||
#include <utility>
|
||||
|
||||
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
|
||||
|
||||
namespace xmrig
|
||||
{
|
||||
|
||||
|
||||
class Algorithm;
|
||||
class CpuConfig;
|
||||
class IRxListener;
|
||||
class Job;
|
||||
class RxConfig;
|
||||
|
@ -46,12 +50,15 @@ class RxDataset;
|
|||
class Rx
|
||||
{
|
||||
public:
|
||||
static bool init(const Job &job, const RxConfig &config, bool hugePages);
|
||||
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);
|
||||
|
||||
private:
|
||||
static void osInit(const RxConfig &config);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -69,20 +69,20 @@ public:
|
|||
}
|
||||
|
||||
|
||||
inline void createDataset(bool hugePages, RxConfig::Mode mode)
|
||||
inline void createDataset(bool hugePages, bool oneGbPages, RxConfig::Mode mode)
|
||||
{
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
m_dataset = new RxDataset(hugePages, true, mode);
|
||||
m_dataset = new RxDataset(hugePages, oneGbPages, true, mode, 0);
|
||||
printAllocStatus(ts);
|
||||
}
|
||||
|
||||
|
||||
inline void initDataset(uint32_t threads)
|
||||
inline void initDataset(uint32_t threads, int priority)
|
||||
{
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
m_dataset->init(m_seed.data(), threads);
|
||||
m_dataset->init(m_seed.data(), threads, priority);
|
||||
|
||||
LOG_INFO("%s" GREEN_BOLD("dataset ready") BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - 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,23 +156,13 @@ 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, RxConfig::Mode mode)
|
||||
void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority)
|
||||
{
|
||||
d_ptr->setSeed(seed);
|
||||
|
||||
if (!d_ptr->dataset()) {
|
||||
d_ptr->createDataset(hugePages, mode);
|
||||
d_ptr->createDataset(hugePages, oneGbPages, mode);
|
||||
}
|
||||
|
||||
d_ptr->initDataset(threads);
|
||||
d_ptr->initDataset(threads, priority);
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ 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, RxConfig::Mode mode) override;
|
||||
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
|
||||
|
||||
private:
|
||||
RxBasicStoragePrivate *d_ptr;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -25,11 +25,18 @@
|
|||
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/json/Json.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_HWLOC
|
||||
# include "backend/cpu/platform/HwlocCpuInfo.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -39,11 +46,106 @@
|
|||
|
||||
namespace xmrig {
|
||||
|
||||
static const char *kInit = "init";
|
||||
static const char *kMode = "mode";
|
||||
static const char *kOneGbPages = "1gb-pages";
|
||||
static const char *kWrmsr = "wrmsr";
|
||||
|
||||
#ifdef XMRIG_FEATURE_HWLOC
|
||||
static const char *kNUMA = "numa";
|
||||
#endif
|
||||
|
||||
static const std::array<const char *, RxConfig::ModeMax> modeNames = { "auto", "fast", "light" };
|
||||
|
||||
}
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
bool xmrig::RxConfig::read(const rapidjson::Value &value)
|
||||
{
|
||||
if (value.IsObject()) {
|
||||
m_threads = Json::getInt(value, kInit, m_threads);
|
||||
m_mode = readMode(Json::getValue(value, kMode));
|
||||
m_wrmsr = readMSR(Json::getValue(value, kWrmsr));
|
||||
|
||||
# ifdef XMRIG_OS_LINUX
|
||||
m_oneGbPages = Json::getBool(value, kOneGbPages, m_oneGbPages);
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
if (m_mode == LightMode) {
|
||||
m_numa = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto &numa = Json::getValue(value, kNUMA);
|
||||
if (numa.IsArray()) {
|
||||
m_nodeset.reserve(numa.Size());
|
||||
|
||||
for (const auto &node : numa.GetArray()) {
|
||||
if (node.IsUint()) {
|
||||
m_nodeset.emplace_back(node.GetUint());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (numa.IsBool()) {
|
||||
m_numa = numa.GetBool();
|
||||
}
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const
|
||||
{
|
||||
using namespace rapidjson;
|
||||
auto &allocator = doc.GetAllocator();
|
||||
|
||||
Value obj(kObjectType);
|
||||
obj.AddMember(StringRef(kInit), m_threads, allocator);
|
||||
obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator);
|
||||
obj.AddMember(StringRef(kOneGbPages), m_oneGbPages, allocator);
|
||||
|
||||
if (m_wrmsr < 0 || m_wrmsr == 6) {
|
||||
obj.AddMember(StringRef(kWrmsr), m_wrmsr == 6, allocator);
|
||||
}
|
||||
else {
|
||||
obj.AddMember(StringRef(kWrmsr), m_wrmsr, allocator);
|
||||
}
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
if (!m_nodeset.empty()) {
|
||||
Value numa(kArrayType);
|
||||
|
||||
for (uint32_t i : m_nodeset) {
|
||||
numa.PushBack(i, allocator);
|
||||
}
|
||||
|
||||
obj.AddMember(StringRef(kNUMA), numa, allocator);
|
||||
}
|
||||
else {
|
||||
obj.AddMember(StringRef(kNUMA), m_numa, allocator);
|
||||
}
|
||||
# endif
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_HWLOC
|
||||
std::vector<uint32_t> xmrig::RxConfig::nodeset() const
|
||||
{
|
||||
if (!m_nodeset.empty()) {
|
||||
return m_nodeset;
|
||||
}
|
||||
|
||||
return (m_numa && Cpu::info()->nodes() > 1) ? static_cast<HwlocCpuInfo *>(Cpu::info())->nodeset() : std::vector<uint32_t>();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const char *xmrig::RxConfig::modeName() const
|
||||
|
@ -52,9 +154,31 @@ const char *xmrig::RxConfig::modeName() const
|
|||
}
|
||||
|
||||
|
||||
uint32_t xmrig::RxConfig::threads() const
|
||||
uint32_t xmrig::RxConfig::threads(uint32_t limit) const
|
||||
{
|
||||
return m_threads < 1 ? static_cast<uint32_t>(Cpu::info()->threads()) : static_cast<uint32_t>(m_threads);
|
||||
if (m_threads > 0) {
|
||||
return m_threads;
|
||||
}
|
||||
|
||||
if (limit < 100) {
|
||||
return std::max(static_cast<uint32_t>(round(Cpu::info()->threads() * (limit / 100.0))), 1U);
|
||||
}
|
||||
|
||||
return Cpu::info()->threads();
|
||||
}
|
||||
|
||||
|
||||
int xmrig::RxConfig::readMSR(const rapidjson::Value &value) const
|
||||
{
|
||||
if (value.IsInt()) {
|
||||
return std::min(value.GetInt(), 15);
|
||||
}
|
||||
|
||||
if (value.IsBool() && !value.GetBool()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_wrmsr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,16 +55,21 @@ public:
|
|||
# endif
|
||||
|
||||
const char *modeName() const;
|
||||
uint32_t threads() const;
|
||||
uint32_t threads(uint32_t limit = 100) const;
|
||||
|
||||
inline Mode mode() const { return m_mode; }
|
||||
inline bool isOneGbPages() const { return m_oneGbPages; }
|
||||
inline int wrmsr() const { return m_wrmsr; }
|
||||
inline Mode mode() const { return m_mode; }
|
||||
|
||||
private:
|
||||
int readMSR(const rapidjson::Value &value) const;
|
||||
Mode readMode(const rapidjson::Value &value) const;
|
||||
|
||||
bool m_numa = true;
|
||||
int m_threads = -1;
|
||||
Mode m_mode = AutoMode;
|
||||
bool m_numa = true;
|
||||
bool m_oneGbPages = false;
|
||||
int m_threads = -1;
|
||||
int m_wrmsr = 6;
|
||||
Mode m_mode = AutoMode;
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
std::vector<uint32_t> m_nodeset;
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/* 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/rx/RxConfig.h"
|
||||
#include "base/io/json/Json.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
static const char *kInit = "init";
|
||||
static const char *kMode = "mode";
|
||||
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const
|
||||
{
|
||||
using namespace rapidjson;
|
||||
auto &allocator = doc.GetAllocator();
|
||||
|
||||
Value obj(kObjectType);
|
||||
obj.AddMember(StringRef(kInit), m_threads, allocator);
|
||||
obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::RxConfig::read(const rapidjson::Value &value)
|
||||
{
|
||||
if (value.IsObject()) {
|
||||
m_threads = Json::getInt(value, kInit, m_threads);
|
||||
m_mode = readMode(Json::getValue(value, kMode));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/* 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 "backend/cpu/Cpu.h"
|
||||
#include "backend/cpu/platform/HwlocCpuInfo.h"
|
||||
#include "base/io/json/Json.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
static const char *kInit = "init";
|
||||
static const char *kMode = "mode";
|
||||
static const char *kNUMA = "numa";
|
||||
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const
|
||||
{
|
||||
using namespace rapidjson;
|
||||
auto &allocator = doc.GetAllocator();
|
||||
|
||||
Value obj(kObjectType);
|
||||
|
||||
obj.AddMember(StringRef(kInit), m_threads, allocator);
|
||||
obj.AddMember(StringRef(kMode), StringRef(modeName()), allocator);
|
||||
|
||||
if (!m_nodeset.empty()) {
|
||||
Value numa(kArrayType);
|
||||
|
||||
for (uint32_t i : m_nodeset) {
|
||||
numa.PushBack(i, allocator);
|
||||
}
|
||||
|
||||
obj.AddMember(StringRef(kNUMA), numa, allocator);
|
||||
}
|
||||
else {
|
||||
obj.AddMember(StringRef(kNUMA), m_numa, allocator);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::RxConfig::read(const rapidjson::Value &value)
|
||||
{
|
||||
if (value.IsObject()) {
|
||||
m_threads = Json::getInt(value, kInit, m_threads);
|
||||
m_mode = readMode(Json::getValue(value, kMode));
|
||||
|
||||
if (m_mode == LightMode) {
|
||||
m_numa = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto &numa = Json::getValue(value, kNUMA);
|
||||
if (numa.IsArray()) {
|
||||
m_nodeset.reserve(numa.Size());
|
||||
|
||||
for (const auto &node : numa.GetArray()) {
|
||||
if (node.IsUint()) {
|
||||
m_nodeset.emplace_back(node.GetUint());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (numa.IsBool()) {
|
||||
m_numa = numa.GetBool();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint32_t> xmrig::RxConfig::nodeset() const
|
||||
{
|
||||
if (!m_nodeset.empty()) {
|
||||
return m_nodeset;
|
||||
}
|
||||
|
||||
return (m_numa && Cpu::info()->nodes() > 1) ? static_cast<HwlocCpuInfo *>(Cpu::info())->nodeset() : std::vector<uint32_t>();
|
||||
}
|
|
@ -28,8 +28,8 @@
|
|||
#include "crypto/rx/RxDataset.h"
|
||||
#include "backend/common/Tags.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/kernel/Platform.h"
|
||||
#include "crypto/common/VirtualMemory.h"
|
||||
#include "crypto/randomx/randomx.h"
|
||||
#include "crypto/rx/RxAlgo.h"
|
||||
#include "crypto/rx/RxCache.h"
|
||||
|
||||
|
@ -38,21 +38,40 @@
|
|||
#include <uv.h>
|
||||
|
||||
|
||||
static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch");
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
xmrig::RxDataset::RxDataset(bool hugePages, bool cache, RxConfig::Mode mode) :
|
||||
m_mode(mode)
|
||||
static void init_dataset_wrapper(randomx_dataset *dataset, randomx_cache *cache, unsigned long startItem, unsigned long itemCount, int priority)
|
||||
{
|
||||
allocate(hugePages);
|
||||
Platform::setThreadPriority(priority);
|
||||
|
||||
randomx_init_dataset(dataset, cache, startItem, itemCount);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
@ -60,15 +79,14 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads)
|
||||
bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads, int priority)
|
||||
{
|
||||
if (!m_cache) {
|
||||
return false;
|
||||
|
@ -89,7 +107,7 @@ bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads)
|
|||
for (uint64_t i = 0; i < numThreads; ++i) {
|
||||
const uint32_t a = (datasetItemCount * i) / numThreads;
|
||||
const uint32_t b = (datasetItemCount * (i + 1)) / numThreads;
|
||||
threads.emplace_back(randomx_init_dataset, m_dataset, m_cache->get(), a, b - a);
|
||||
threads.emplace_back(init_dataset_wrapper, m_dataset, m_cache->get(), a, b - a, priority);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < numThreads; ++i) {
|
||||
|
@ -97,13 +115,37 @@ bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads)
|
|||
}
|
||||
}
|
||||
else {
|
||||
randomx_init_dataset(m_dataset, m_cache->get(), 0, datasetItemCount);
|
||||
init_dataset_wrapper(m_dataset, m_cache->get(), 0, datasetItemCount, priority);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -120,29 +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 cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB;
|
||||
size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB;
|
||||
|
||||
uint32_t count = 0;
|
||||
if (isHugePages()) {
|
||||
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;
|
||||
|
@ -159,7 +178,7 @@ void xmrig::RxDataset::setRaw(const void *raw)
|
|||
}
|
||||
|
||||
|
||||
void xmrig::RxDataset::allocate(bool hugePages)
|
||||
void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages)
|
||||
{
|
||||
if (m_mode == RxConfig::LightMode) {
|
||||
LOG_ERR(CLEAR "%s" RED_BOLD_S "fast RandomX mode disabled by config", rx_tag());
|
||||
|
@ -173,13 +192,12 @@ void xmrig::RxDataset::allocate(bool hugePages)
|
|||
return;
|
||||
}
|
||||
|
||||
if (hugePages) {
|
||||
m_flags = 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 (!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,7 +30,9 @@
|
|||
|
||||
#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"
|
||||
|
||||
|
||||
|
@ -43,6 +45,7 @@ namespace xmrig
|
|||
|
||||
class Buffer;
|
||||
class RxCache;
|
||||
class VirtualMemory;
|
||||
|
||||
|
||||
class RxDataset
|
||||
|
@ -50,30 +53,32 @@ class RxDataset
|
|||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset)
|
||||
|
||||
RxDataset(bool hugePages, 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 & 1; }
|
||||
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);
|
||||
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);
|
||||
|
||||
static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; }
|
||||
|
||||
private:
|
||||
void allocate(bool hugePages);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -120,18 +120,20 @@ public:
|
|||
}
|
||||
|
||||
|
||||
inline void createDatasets(bool hugePages)
|
||||
inline void createDatasets(bool hugePages, bool oneGbPages)
|
||||
{
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
for (uint32_t node : m_nodeset) {
|
||||
m_threads.emplace_back(allocate, this, node, hugePages);
|
||||
m_threads.emplace_back(allocate, this, node, hugePages, oneGbPages);
|
||||
}
|
||||
|
||||
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,13 +152,29 @@ public:
|
|||
}
|
||||
|
||||
|
||||
inline void initDatasets(uint32_t threads)
|
||||
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();
|
||||
auto id = m_nodeset.front();
|
||||
auto primary = dataset(id);
|
||||
|
||||
primary->init(m_seed.data(), threads);
|
||||
primary->init(m_seed.data(), threads, priority);
|
||||
|
||||
printDatasetReady(id, ts);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -188,7 +206,7 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
static void allocate(RxNUMAStoragePrivate *d_ptr, uint32_t nodeId, bool hugePages)
|
||||
static void allocate(RxNUMAStoragePrivate *d_ptr, uint32_t nodeId, bool hugePages, bool oneGbPages)
|
||||
{
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
|
@ -198,7 +216,7 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
auto dataset = new RxDataset(hugePages, 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,23 +356,13 @@ 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, RxConfig::Mode)
|
||||
void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode, int priority)
|
||||
{
|
||||
d_ptr->setSeed(seed);
|
||||
|
||||
if (!d_ptr->isAllocated()) {
|
||||
d_ptr->createDatasets(hugePages);
|
||||
d_ptr->createDatasets(hugePages, oneGbPages);
|
||||
}
|
||||
|
||||
d_ptr->initDatasets(threads);
|
||||
d_ptr->initDatasets(threads, priority);
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ 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, RxConfig::Mode mode) override;
|
||||
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
|
||||
|
||||
private:
|
||||
RxNUMAStoragePrivate *d_ptr;
|
||||
|
|
|
@ -86,15 +86,15 @@ 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();
|
||||
}
|
||||
|
||||
|
||||
void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode)
|
||||
void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
|
@ -114,7 +114,7 @@ void xmrig::RxQueue::enqueue(const RxSeed &seed, const std::vector<uint32_t> &no
|
|||
return;
|
||||
}
|
||||
|
||||
m_queue.emplace_back(seed, nodeset, threads, hugePages, mode);
|
||||
m_queue.emplace_back(seed, nodeset, threads, hugePages, oneGbPages, mode, priority);
|
||||
m_seed = seed;
|
||||
m_state = STATE_PENDING;
|
||||
|
||||
|
@ -156,7 +156,7 @@ void xmrig::RxQueue::backgroundInit()
|
|||
Buffer::toHex(item.seed.data().data(), 8).data()
|
||||
);
|
||||
|
||||
m_storage->init(item.seed, item.threads, item.hugePages, item.mode);
|
||||
m_storage->init(item.seed, item.threads, item.hugePages, item.oneGbPages, item.mode, item.priority);
|
||||
|
||||
lock = std::unique_lock<std::mutex>(m_mutex);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "crypto/rx/RxSeed.h"
|
||||
|
||||
|
@ -53,8 +54,10 @@ class RxDataset;
|
|||
class RxQueueItem
|
||||
{
|
||||
public:
|
||||
RxQueueItem(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode) :
|
||||
RxQueueItem(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) :
|
||||
hugePages(hugePages),
|
||||
oneGbPages(oneGbPages),
|
||||
priority(priority),
|
||||
mode(mode),
|
||||
seed(seed),
|
||||
nodeset(nodeset),
|
||||
|
@ -62,6 +65,8 @@ public:
|
|||
{}
|
||||
|
||||
const bool hugePages;
|
||||
const bool oneGbPages;
|
||||
const int priority;
|
||||
const RxConfig::Mode mode;
|
||||
const RxSeed seed;
|
||||
const std::vector<uint32_t> nodeset;
|
||||
|
@ -79,8 +84,8 @@ public:
|
|||
|
||||
bool isReady(const Job &job);
|
||||
RxDataset *dataset(const Job &job, uint32_t nodeId);
|
||||
std::pair<uint32_t, uint32_t> hugePages();
|
||||
void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, RxConfig::Mode mode);
|
||||
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:
|
||||
enum State {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "crypto/rx/RxVm.h"
|
||||
|
||||
|
||||
xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes)
|
||||
xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes, xmrig::Assembly assembly)
|
||||
{
|
||||
if (!softAes) {
|
||||
m_flags |= RANDOMX_FLAG_HARD_AES;
|
||||
|
@ -45,6 +45,10 @@ xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes)
|
|||
m_flags |= RANDOMX_FLAG_JIT;
|
||||
}
|
||||
|
||||
if ((assembly == Assembly::RYZEN) || ((assembly == Assembly::AUTO) && (Cpu::info()->assembly() == Assembly::RYZEN))) {
|
||||
m_flags |= RANDOMX_FLAG_RYZEN;
|
||||
}
|
||||
|
||||
m_vm = randomx_create_vm(static_cast<randomx_flags>(m_flags), dataset->cache() ? dataset->cache()->get() : nullptr, dataset->get(), scratchpad);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
@ -49,7 +50,7 @@ class RxVm
|
|||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxVm);
|
||||
|
||||
RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes);
|
||||
RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes, xmrig::Assembly assembly);
|
||||
~RxVm();
|
||||
|
||||
inline randomx_vm *get() const { return m_vm; }
|
||||
|
|
131
src/crypto/rx/Rx_linux.cpp
Normal file
131
src/crypto/rx/Rx_linux.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||
* Copyright 2018-2019 tevador <tevador@gmail.com>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2000 Transmeta Corporation <https://github.com/intel/msr-tools>
|
||||
* Copyright 2004-2008 H. Peter Anvin <https://github.com/intel/msr-tools>
|
||||
* 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/rx/Rx.h"
|
||||
#include "backend/common/Tags.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
|
||||
|
||||
#include <cctype>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static inline int dir_filter(const struct dirent *dirp)
|
||||
{
|
||||
return isdigit(dirp->d_name[0]) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr_on_cpu(uint32_t reg, uint32_t cpu, uint64_t value)
|
||||
{
|
||||
char msr_file_name[64]{};
|
||||
|
||||
sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
|
||||
int fd = open(msr_file_name, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool success = pwrite(fd, &value, sizeof value, reg) == sizeof value;
|
||||
|
||||
close(fd);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr_on_all_cpus(uint32_t reg, uint64_t value)
|
||||
{
|
||||
struct dirent **namelist;
|
||||
int dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0);
|
||||
int errors = 0;
|
||||
|
||||
while (dir_entries--) {
|
||||
if (!wrmsr_on_cpu(reg, strtoul(namelist[dir_entries]->d_name, nullptr, 10), value)) {
|
||||
++errors;
|
||||
}
|
||||
|
||||
free(namelist[dir_entries]);
|
||||
}
|
||||
|
||||
free(namelist);
|
||||
|
||||
if (errors) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "cannot set MSR 0x%08" PRIx32 " to 0x%08" PRIx64, rx_tag(), reg, value);
|
||||
}
|
||||
|
||||
return errors == 0;
|
||||
}
|
||||
|
||||
|
||||
static bool wrmsr_modprobe()
|
||||
{
|
||||
if (system("/sbin/modprobe msr > /dev/null 2>&1") != 0) {
|
||||
LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "msr kernel module is not available", rx_tag());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
void xmrig::Rx::osInit(const RxConfig &config)
|
||||
{
|
||||
if (config.wrmsr() < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cpu::info()->assembly() == Assembly::RYZEN && wrmsr_modprobe()) {
|
||||
wrmsr_on_all_cpus(0xC0011022, 0x510000);
|
||||
wrmsr_on_all_cpus(0xC001102b, 0x1808cc16);
|
||||
wrmsr_on_all_cpus(0xC0011020, 0);
|
||||
wrmsr_on_all_cpus(0xC0011021, 0x40);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cpu::info()->vendor() == ICpuInfo::VENDOR_INTEL && wrmsr_modprobe()) {
|
||||
wrmsr_on_all_cpus(0x1a4, config.wrmsr());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue