Merged v4.0.0-beta

This commit is contained in:
MoneroOcean 2019-09-17 15:48:01 -07:00
commit 993733cb1f
231 changed files with 32642 additions and 3380 deletions

View file

@ -25,9 +25,20 @@
*/
#include <map>
#include <mutex>
#include <thread>
#include "crypto/rx/Rx.h"
#include "backend/common/interfaces/IRxListener.h"
#include "backend/cpu/Cpu.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Buffer.h"
#include "base/tools/Chrono.h"
#include "base/tools/Handle.h"
#include "base/tools/Object.h"
#include "crypto/rx/RxAlgo.h"
#include "crypto/rx/RxCache.h"
#include "crypto/rx/RxDataset.h"
#ifdef XMRIG_FEATURE_HWLOC
@ -36,16 +47,10 @@
#endif
#include "backend/cpu/Cpu.h"
#include "base/io/log/Log.h"
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Buffer.h"
#include "base/tools/Chrono.h"
#include "crypto/rx/Rx.h"
#include "crypto/rx/RxAlgo.h"
#include "crypto/rx/RxCache.h"
#include "crypto/rx/RxDataset.h"
#include <map>
#include <mutex>
#include <thread>
#include <uv.h>
namespace xmrig {
@ -56,6 +61,7 @@ class RxPrivate;
static const char *tag = BLUE_BG(WHITE_BOLD_S " rx ") " ";
static RxPrivate *d_ptr = nullptr;
static std::mutex mutex;
#ifdef XMRIG_FEATURE_HWLOC
@ -88,9 +94,15 @@ inline static void bindToNUMANode(uint32_t) {}
class RxPrivate
{
public:
inline RxPrivate() :
m_seed()
XMRIG_DISABLE_COPY_MOVE(RxPrivate)
inline RxPrivate()
{
m_async = new uv_async_t;
m_async->data = this;
uv_async_init(uv_default_loop(), m_async, RxPrivate::onReady);
# ifdef XMRIG_FEATURE_HWLOC
if (Cpu::info()->nodes() > 1) {
for (uint32_t nodeId : HwlocCpuInfo::nodeIndexes()) {
@ -107,6 +119,8 @@ public:
inline ~RxPrivate()
{
Handle::close(m_async);
for (auto const &item : datasets) {
delete item.second;
}
@ -117,8 +131,9 @@ public:
inline bool isNUMA() const { return m_numa; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const uint8_t *seed() const { return m_seed; }
inline const Buffer &seed() const { return m_seed; }
inline size_t count() const { return isNUMA() ? datasets.size() : 1; }
inline void asyncSend() { m_ready++; if (m_ready == count()) { uv_async_send(m_async); } }
static void allocate(uint32_t nodeId)
@ -132,12 +147,12 @@ public:
LOG_INFO("%s" CYAN_BOLD("#%u") MAGENTA_BOLD(" allocate") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu) for RandomX dataset & cache"),
tag,
nodeId,
(RxDataset::size() + RxCache::size()) / 1024 / 1024,
RxDataset::size() / 1024 / 1024,
RxCache::size() / 1024 / 1024
(RxDataset::maxSize() + RxCache::maxSize()) / 1024 / 1024,
RxDataset::maxSize() / 1024 / 1024,
RxCache::maxSize() / 1024 / 1024
);
RxDataset *dataset = new RxDataset(d_ptr->m_hugePages);
auto dataset = new RxDataset(d_ptr->m_hugePages);
d_ptr->datasets[nodeId] = dataset;
if (dataset->get() != nullptr) {
@ -163,14 +178,14 @@ public:
static void initDataset(uint32_t nodeId, uint32_t threads)
{
std::lock_guard<std::mutex> lock(d_ptr->mutex);
std::lock_guard<std::mutex> lock(mutex);
const uint64_t ts = Chrono::steadyMSecs();
d_ptr->getOrAllocate(nodeId)->init(d_ptr->seed(), threads);
d_ptr->m_ready++;
d_ptr->asyncSend();
LOG_INFO("%s" CYAN_BOLD("#%u") GREEN(" init done") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, nodeId, Chrono::steadyMSecs() - ts);
LOG_INFO("%s" CYAN_BOLD("#%u") GREEN(" init done ") CYAN_BOLD("%zu/%zu") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, nodeId, d_ptr->m_ready, d_ptr->count(), Chrono::steadyMSecs() - ts);
}
@ -196,7 +211,7 @@ public:
}
inline void setState(const Job &job, bool hugePages, bool numa)
inline void setState(const Job &job, bool hugePages, bool numa, IRxListener *listener)
{
if (m_algorithm != job.algorithm()) {
m_algorithm = RxAlgo::apply(job.algorithm());
@ -205,35 +220,85 @@ public:
m_ready = 0;
m_numa = numa && Cpu::info()->nodes() > 1;
m_hugePages = hugePages;
memcpy(m_seed, job.seedHash(), sizeof(m_seed));
m_listener = listener;
m_seed = job.seed();
}
inline bool isReady(const Job &job)
{
return m_ready == count() && m_algorithm == job.algorithm() && memcmp(m_seed, job.seedHash(), sizeof(m_seed)) == 0;
return m_ready == count() && m_algorithm == job.algorithm() && m_seed == job.seed();
}
std::map<uint32_t, RxDataset *> datasets;
std::mutex mutex;
private:
bool m_hugePages = true;
bool m_numa = true;
static void onReady(uv_async_t *)
{
if (d_ptr->m_listener) {
d_ptr->m_listener->onDatasetReady();
}
}
Algorithm m_algorithm;
size_t m_ready = 0;
uint8_t m_seed[32];
bool m_hugePages = true;
bool m_numa = true;
Buffer m_seed;
IRxListener *m_listener = nullptr;
size_t m_ready = 0;
uv_async_t *m_async;
};
} // namespace xmrig
bool xmrig::Rx::init(const Job &job, int initThreads, bool hugePages, bool numa, IRxListener *listener)
{
if (job.algorithm().family() != Algorithm::RANDOM_X) {
return true;
}
std::lock_guard<std::mutex> lock(mutex);
if (d_ptr->isReady(job)) {
return true;
}
d_ptr->setState(job, hugePages, numa, listener);
const uint32_t threads = initThreads < 1 ? static_cast<uint32_t>(Cpu::info()->threads()) : static_cast<uint32_t>(initThreads);
const String buf = Buffer::toHex(job.seed().data(), 8);
LOG_INFO("%s" MAGENTA_BOLD("init dataset%s") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."),
tag,
d_ptr->count() > 1 ? "s" : "",
job.algorithm().shortName(),
threads,
buf.data()
);
# ifdef XMRIG_FEATURE_HWLOC
if (d_ptr->isNUMA()) {
for (auto const &item : d_ptr->datasets) {
std::thread thread(RxPrivate::initDataset, item.first, threads);
thread.detach();
}
}
else
# endif
{
std::thread thread(RxPrivate::initDataset, 0, threads);
thread.detach();
}
return false;
}
bool xmrig::Rx::isReady(const Job &job)
{
std::lock_guard<std::mutex> lock(d_ptr->mutex);
std::lock_guard<std::mutex> lock(mutex);
return d_ptr->isReady(job);
}
@ -241,7 +306,7 @@ bool xmrig::Rx::isReady(const Job &job)
xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId)
{
std::lock_guard<std::mutex> lock(d_ptr->mutex);
std::lock_guard<std::mutex> lock(mutex);
if (!d_ptr->isReady(job)) {
return nullptr;
}
@ -253,7 +318,7 @@ xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId)
std::pair<unsigned, unsigned> xmrig::Rx::hugePages()
{
std::pair<unsigned, unsigned> pages(0, 0);
std::lock_guard<std::mutex> lock(d_ptr->mutex);
std::lock_guard<std::mutex> lock(mutex);
for (auto const &item : d_ptr->datasets) {
if (!item.second) {
@ -281,43 +346,3 @@ void xmrig::Rx::init()
{
d_ptr = new RxPrivate();
}
void xmrig::Rx::init(const Job &job, int initThreads, bool hugePages, bool numa)
{
if (job.algorithm().family() != Algorithm::RANDOM_X) {
return;
}
std::lock_guard<std::mutex> lock(d_ptr->mutex);
if (d_ptr->isReady(job)) {
return;
}
d_ptr->setState(job, hugePages, numa);
const uint32_t threads = initThreads < 1 ? static_cast<uint32_t>(Cpu::info()->threads()) : static_cast<uint32_t>(initThreads);
const String buf = Buffer::toHex(job.seedHash(), 8);
LOG_INFO("%s" MAGENTA_BOLD("init dataset%s") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."),
tag,
d_ptr->count() > 1 ? "s" : "",
job.algorithm().shortName(),
threads,
buf.data()
);
# ifdef XMRIG_FEATURE_HWLOC
if (d_ptr->isNUMA()) {
for (auto const &item : d_ptr->datasets) {
std::thread thread(RxPrivate::initDataset, item.first, threads);
thread.detach();
}
}
else
# endif
{
std::thread thread(RxPrivate::initDataset, 0, threads);
thread.detach();
}
}

View file

@ -28,7 +28,7 @@
#define XMRIG_RX_H
#include <stdint.h>
#include <cstdint>
#include <utility>
@ -37,19 +37,20 @@ namespace xmrig
class Algorithm;
class RxDataset;
class IRxListener;
class Job;
class RxDataset;
class Rx
{
public:
static bool init(const Job &job, int initThreads, bool hugePages, bool numa, IRxListener *listener);
static bool isReady(const Job &job);
static RxDataset *dataset(const Job &job, uint32_t nodeId);
static std::pair<unsigned, unsigned> hugePages();
static void destroy();
static void init();
static void init(const Job &job, int initThreads, bool hugePages, bool numa);
};

View file

@ -31,14 +31,21 @@
xmrig::Algorithm::Id xmrig::RxAlgo::apply(Algorithm::Id algorithm)
{
randomx_apply_config(*base(algorithm));
return algorithm;
}
const RandomX_ConfigurationBase *xmrig::RxAlgo::base(Algorithm::Id algorithm)
{
switch (algorithm) {
case Algorithm::RX_WOW:
randomx_apply_config(RandomX_WowneroConfig);
break;
return &RandomX_WowneroConfig;
case Algorithm::RX_LOKI:
randomx_apply_config(RandomX_LokiConfig);
return &RandomX_LokiConfig;
break;
case Algorithm::DEFYX:
@ -46,9 +53,32 @@ xmrig::Algorithm::Id xmrig::RxAlgo::apply(Algorithm::Id algorithm)
break;
default:
randomx_apply_config(RandomX_MoneroConfig);
break;
}
return algorithm;
return &RandomX_MoneroConfig;
}
uint32_t xmrig::RxAlgo::version(Algorithm::Id algorithm)
{
return algorithm == Algorithm::RX_WOW ? 103 : 104;
}
uint32_t xmrig::RxAlgo::programCount(Algorithm::Id algorithm)
{
return base(algorithm)->ProgramCount;
}
uint32_t xmrig::RxAlgo::programIterations(Algorithm::Id algorithm)
{
return base(algorithm)->ProgramIterations;
}
uint32_t xmrig::RxAlgo::programSize(Algorithm::Id algorithm)
{
return base(algorithm)->ProgramSize;
}

View file

@ -28,13 +28,16 @@
#define XMRIG_RX_ALGO_H
#include <stddef.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include "crypto/common/Algorithm.h"
struct RandomX_ConfigurationBase;
namespace xmrig
{
@ -43,6 +46,11 @@ class RxAlgo
{
public:
static Algorithm::Id apply(Algorithm::Id algorithm);
static const RandomX_ConfigurationBase *base(Algorithm::Id algorithm);
static uint32_t programCount(Algorithm::Id algorithm);
static uint32_t programIterations(Algorithm::Id algorithm);
static uint32_t programSize(Algorithm::Id algorithm);
static uint32_t version(Algorithm::Id algorithm);
};

View file

@ -34,8 +34,7 @@ static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mism
xmrig::RxCache::RxCache(bool hugePages) :
m_seed()
xmrig::RxCache::RxCache(bool hugePages)
{
if (hugePages) {
m_flags = RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES;
@ -62,22 +61,14 @@ xmrig::RxCache::~RxCache()
}
bool xmrig::RxCache::init(const uint8_t *seed)
bool xmrig::RxCache::init(const Buffer &seed)
{
if (isReady(seed)) {
if (m_seed == seed) {
return false;
}
memcpy(m_seed, seed, sizeof(m_seed));
randomx_init_cache(m_cache, m_seed, sizeof(m_seed));
m_initCount++;
m_seed = seed;
randomx_init_cache(m_cache, m_seed.data(), m_seed.size());
return true;
}
bool xmrig::RxCache::isReady(const uint8_t *seed) const
{
return m_initCount && memcmp(m_seed, seed, sizeof(m_seed)) == 0;
}

View file

@ -28,9 +28,11 @@
#define XMRIG_RX_CACHE_H
#include <stdint.h>
#include <cstdint>
#include "base/tools/Buffer.h"
#include "base/tools/Object.h"
#include "crypto/randomx/configuration.h"
@ -44,26 +46,24 @@ namespace xmrig
class RxCache
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxCache)
RxCache(bool hugePages = true);
~RxCache();
inline bool isHugePages() const { return m_flags & 1; }
inline bool isJIT() const { return m_flags & 8; }
inline const uint8_t *seed() const { return m_seed; }
inline const Buffer &seed() const { return m_seed; }
inline randomx_cache *get() const { return m_cache; }
inline uint64_t initCount() const { return m_initCount; }
bool init(const uint8_t *seed);
bool init(const Buffer &seed);
static inline constexpr size_t size() { return RANDOMX_CACHE_MAX_SIZE; }
static inline constexpr size_t maxSize() { return RANDOMX_CACHE_MAX_SIZE; }
private:
bool isReady(const uint8_t *seed) const;
Buffer m_seed;
int m_flags = 0;
randomx_cache *m_cache = nullptr;
uint64_t m_initCount = 0;
uint8_t m_seed[32];
};

View file

@ -64,7 +64,7 @@ xmrig::RxDataset::~RxDataset()
}
bool xmrig::RxDataset::init(const uint8_t *seed, uint32_t numThreads)
bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads)
{
cache()->init(seed);
@ -72,13 +72,13 @@ bool xmrig::RxDataset::init(const uint8_t *seed, uint32_t numThreads)
return true;
}
const uint32_t datasetItemCount = randomx_dataset_item_count();
const uint64_t datasetItemCount = randomx_dataset_item_count();
if (numThreads > 1) {
std::vector<std::thread> threads;
threads.reserve(numThreads);
for (uint32_t i = 0; i < numThreads; ++i) {
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);
@ -99,16 +99,22 @@ bool xmrig::RxDataset::init(const uint8_t *seed, uint32_t numThreads)
std::pair<size_t, size_t> xmrig::RxDataset::hugePages() const
{
constexpr size_t twoMiB = 2u * 1024u * 1024u;
constexpr const size_t total = (VirtualMemory::align(size(), twoMiB) + VirtualMemory::align(RxCache::size(), twoMiB)) / twoMiB;
constexpr const size_t total = (VirtualMemory::align(maxSize(), twoMiB) + VirtualMemory::align(RxCache::maxSize(), twoMiB)) / twoMiB;
size_t count = 0;
if (isHugePages()) {
count += VirtualMemory::align(size(), twoMiB) / twoMiB;
count += VirtualMemory::align(maxSize(), twoMiB) / twoMiB;
}
if (m_cache->isHugePages()) {
count += VirtualMemory::align(RxCache::size(), twoMiB) / twoMiB;
count += VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB;
}
return std::pair<size_t, size_t>(count, total);
return { count, total };
}
void *xmrig::RxDataset::raw() const
{
return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr;
}

View file

@ -30,6 +30,7 @@
#include "crypto/common/Algorithm.h"
#include "crypto/randomx/configuration.h"
#include "base/tools/Object.h"
struct randomx_dataset;
@ -39,23 +40,28 @@ namespace xmrig
{
class Buffer;
class RxCache;
class RxDataset
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset)
RxDataset(bool hugePages = true);
~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 size_t size() const { return maxSize(); }
bool init(const uint8_t *seed, uint32_t numThreads);
bool init(const Buffer &seed, uint32_t numThreads);
std::pair<size_t, size_t> hugePages() const;
void *raw() const;
static inline constexpr size_t size() { return RANDOMX_DATASET_MAX_SIZE; }
static inline constexpr size_t maxSize() { return RANDOMX_DATASET_MAX_SIZE; }
private:
Algorithm m_algorithm;

View file

@ -28,10 +28,13 @@
#define XMRIG_RX_VM_H
#include <stdint.h>
#include "base/tools/Object.h"
struct randomx_vm;
#include <cstdint>
class randomx_vm;
namespace xmrig
@ -44,6 +47,8 @@ class RxDataset;
class RxVm
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxVm);
RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes);
~RxVm();