Merge branch 'evo' into feature-per-pool-algo
This commit is contained in:
@ -1,3 +1,8 @@
|
||||
# v2.16.0-beta
|
||||
- [#1036](https://github.com/xmrig/xmrig/pull/1036) Added RandomWOW (RandomX with different preferences) algorithm support for [Wownero](http://wownero.org/).
|
||||
- Algorithm name used by miner is `randomx/wow` or `rx/wow`.
|
||||
- Currently runtime algorithm switching NOT supported with other algorithms.
|
||||
|
||||
# v2.15.4-beta
|
||||
- Added global uptime and extended connection information in API.
|
||||
- API now return current algorithm instead of global algorithm specified in config.
|
||||
|
@ -6,6 +6,7 @@ option(WITH_CN_LITE "CryptoNight-Lite support" ON)
|
||||
option(WITH_CN_HEAVY "CryptoNight-Heavy support" ON)
|
||||
option(WITH_CN_PICO "CryptoNight-Pico support" ON)
|
||||
option(WITH_CN_GPU "CryptoNight-GPU support" ON)
|
||||
option(WITH_RANDOMX "RandomX support" ON)
|
||||
option(WITH_HTTP "HTTP protocol support (client/server)" ON)
|
||||
option(WITH_DEBUG_LOG "Enable debug log output" OFF)
|
||||
option(WITH_TLS "Enable OpenSSL support" ON)
|
||||
@ -161,6 +162,17 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
find_package(UV REQUIRED)
|
||||
|
||||
if (WITH_RANDOMX)
|
||||
find_package(RandomX REQUIRED)
|
||||
include_directories(${RANDOMX_INCLUDE_DIR})
|
||||
|
||||
add_definitions(/DXMRIG_ALGO_RANDOMX)
|
||||
else()
|
||||
set(RANDOMX_LIBRARIES "")
|
||||
|
||||
remove_definitions(/DXMRIG_ALGO_RANDOMX)
|
||||
endif()
|
||||
|
||||
include(cmake/flags.cmake)
|
||||
|
||||
if (WITH_LIBCPUID)
|
||||
@ -231,4 +243,4 @@ if (WITH_DEBUG_LOG)
|
||||
endif()
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${RANDOMX_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||
|
25
cmake/FindRandomX.cmake
Normal file
25
cmake/FindRandomX.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
find_path(
|
||||
RANDOMX_INCLUDE_DIR
|
||||
NAMES randomx.h
|
||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
||||
PATH_SUFFIXES "include"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_path(RANDOMX_INCLUDE_DIR NAMES randomx.h)
|
||||
|
||||
find_library(
|
||||
RANDOMX_LIBRARY
|
||||
NAMES librandomx.a randomx librandomx
|
||||
PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS"
|
||||
PATH_SUFFIXES "lib"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_library(RANDOMX_LIBRARY NAMES librandomx.a randomx librandomx)
|
||||
|
||||
set(RANDOMX_LIBRARIES ${RANDOMX_LIBRARY})
|
||||
set(RANDOMX_INCLUDE_DIRS ${RANDOMX_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(RANDOMX DEFAULT_MSG RANDOMX_LIBRARY RANDOMX_INCLUDE_DIR)
|
@ -69,6 +69,10 @@ MemInfo Mem::create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, si
|
||||
|
||||
void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info)
|
||||
{
|
||||
if (info.memory == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
release(info);
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
|
@ -39,11 +39,11 @@ struct cryptonight_ctx;
|
||||
|
||||
struct MemInfo
|
||||
{
|
||||
alignas(16) uint8_t *memory;
|
||||
alignas(16) uint8_t *memory = nullptr;
|
||||
|
||||
size_t hugePages;
|
||||
size_t pages;
|
||||
size_t size;
|
||||
size_t hugePages = 0;
|
||||
size_t pages = 0;
|
||||
size_t size = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "base/io/json/Json.h"
|
||||
#include "base/io/json/JsonRequest.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/kernel/interfaces/IClientListener.h"
|
||||
@ -333,13 +334,8 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
job.setAlgorithm(params["algo"].GetString());
|
||||
}
|
||||
|
||||
if (params.HasMember("height")) {
|
||||
const rapidjson::Value &variant = params["height"];
|
||||
|
||||
if (variant.IsUint64()) {
|
||||
job.setHeight(variant.GetUint64());
|
||||
}
|
||||
}
|
||||
job.setSeedHash(Json::getString(params, "seed_hash"));
|
||||
job.setHeight(Json::getUint64(params, "height"));
|
||||
|
||||
if (!verifyAlgorithm(job.algorithm())) {
|
||||
*code = 6;
|
||||
|
@ -220,6 +220,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
return false;
|
||||
}
|
||||
|
||||
job.setSeedHash(Json::getString(params, "seed_hash"));
|
||||
job.setHeight(Json::getUint64(params, kHeight));
|
||||
job.setDiff(Json::getUint64(params, "difficulty"));
|
||||
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
|
||||
|
@ -40,7 +40,8 @@ xmrig::Job::Job() :
|
||||
m_diff(0),
|
||||
m_height(0),
|
||||
m_target(0),
|
||||
m_blob()
|
||||
m_blob(),
|
||||
m_seedHash()
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,7 +55,8 @@ xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const Str
|
||||
m_diff(0),
|
||||
m_height(0),
|
||||
m_target(0),
|
||||
m_blob()
|
||||
m_blob(),
|
||||
m_seedHash()
|
||||
{
|
||||
}
|
||||
|
||||
@ -103,6 +105,20 @@ bool xmrig::Job::setBlob(const char *blob)
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Job::setSeedHash(const char *hash)
|
||||
{
|
||||
if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
m_rawSeedHash = hash;
|
||||
# endif
|
||||
|
||||
return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash);
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Job::setTarget(const char *target)
|
||||
{
|
||||
if (!target) {
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
|
||||
bool isEqual(const Job &other) const;
|
||||
bool setBlob(const char *blob);
|
||||
bool setSeedHash(const char *hash);
|
||||
bool setTarget(const char *target);
|
||||
void setDiff(uint64_t diff);
|
||||
|
||||
@ -63,6 +64,7 @@ public:
|
||||
inline const String &id() const { return m_id; }
|
||||
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
|
||||
inline const uint8_t *blob() const { return m_blob; }
|
||||
inline const uint8_t *seedHash() const { return m_seedHash; }
|
||||
inline int poolId() const { return m_poolId; }
|
||||
inline size_t size() const { return m_size; }
|
||||
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
|
||||
@ -77,9 +79,10 @@ public:
|
||||
inline void setPoolId(int poolId) { m_poolId = poolId; }
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
inline char *rawBlob() { return m_rawBlob; }
|
||||
inline const char *rawBlob() const { return m_rawBlob; }
|
||||
inline const char *rawTarget() const { return m_rawTarget; }
|
||||
inline char *rawBlob() { return m_rawBlob; }
|
||||
inline const char *rawBlob() const { return m_rawBlob; }
|
||||
inline const char *rawTarget() const { return m_rawTarget; }
|
||||
inline const String &rawSeedHash() const { return m_rawSeedHash; }
|
||||
# endif
|
||||
|
||||
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
|
||||
@ -99,10 +102,12 @@ private:
|
||||
uint64_t m_height;
|
||||
uint64_t m_target;
|
||||
uint8_t m_blob[kMaxBlobSize];
|
||||
uint8_t m_seedHash[32];
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
char m_rawBlob[kMaxBlobSize * 2 + 8];
|
||||
char m_rawTarget[24];
|
||||
String m_rawSeedHash;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
@ -55,6 +55,12 @@ xmrig::Config::Config() :
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Config::isHwAES() const
|
||||
{
|
||||
return (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_HW;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
|
||||
{
|
||||
if (!BaseConfig::read(reader, fileName)) {
|
||||
@ -146,11 +152,10 @@ bool xmrig::Config::finalize()
|
||||
Algorithm algorithm(Algorithm::CN_0); // FIXME algo
|
||||
|
||||
if (!m_threads.cpu.empty()) {
|
||||
m_threads.mode = Advanced;
|
||||
const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
|
||||
m_threads.mode = Advanced;
|
||||
|
||||
for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
|
||||
m_threads.list.push_back(CpuThread::createFromData(i, algorithm, m_threads.cpu[i], m_priority, softAES));
|
||||
m_threads.list.push_back(CpuThread::createFromData(i, algorithm, m_threads.cpu[i], m_priority, !isHwAES()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -159,7 +164,7 @@ bool xmrig::Config::finalize()
|
||||
const AlgoVariant av = getAlgoVariant();
|
||||
m_threads.mode = m_threads.count ? Simple : Automatic;
|
||||
|
||||
const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024;
|
||||
const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; // FIXME MEMORY
|
||||
|
||||
if (!m_threads.count) {
|
||||
m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
|
||||
|
@ -67,10 +67,10 @@ public:
|
||||
|
||||
Config();
|
||||
|
||||
bool isHwAES() const;
|
||||
bool read(const IJsonReader &reader, const char *fileName) override;
|
||||
void getJSON(rapidjson::Document &doc) const override;
|
||||
|
||||
inline AesMode aesMode() const { return m_aesMode; }
|
||||
inline AlgoVariant algoVariant() const { return m_algoVariant; }
|
||||
inline Assembly assembly() const { return m_assembly; }
|
||||
inline bool isHugePages() const { return m_hugePages; }
|
||||
|
@ -127,6 +127,7 @@ private:
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
CN_MEMORY / 8, // CN_PICO_0
|
||||
0, // RX_WOW
|
||||
# endif
|
||||
};
|
||||
|
||||
@ -156,7 +157,8 @@ private:
|
||||
CN_ITER / 2, // CN_HEAVY_XHV
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
CN_ITER / 8, // CN_PICO_0
|
||||
CN_ITER / 8, // CN_PICO_0,
|
||||
0, // RX_WOW
|
||||
# endif
|
||||
};
|
||||
|
||||
@ -186,7 +188,8 @@ private:
|
||||
Algorithm::CN_0, // CN_HEAVY_XHV
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
Algorithm::CN_2, // CN_PICO_0
|
||||
Algorithm::CN_2, // CN_PICO_0,
|
||||
Algorithm::INVALID, // RX_WOW
|
||||
# endif
|
||||
};
|
||||
};
|
||||
|
@ -106,6 +106,10 @@ static AlgoName const algorithm_names[] = {
|
||||
{ "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 },
|
||||
{ "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 },
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
{ "randomx/wow", "rx/wow", Algorithm::RX_WOW },
|
||||
{ "randomx", "rx", Algorithm::RX_WOW },
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
@ -133,6 +137,7 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
|
||||
case CN_XAO:
|
||||
case CN_RTO:
|
||||
case CN_RWZ:
|
||||
case CN_ZLS:
|
||||
case CN_DOUBLE:
|
||||
# ifdef XMRIG_ALGO_CN_GPU
|
||||
case CN_GPU:
|
||||
@ -153,10 +158,15 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
case Algorithm::CN_PICO_0:
|
||||
case CN_PICO_0:
|
||||
return CN_PICO;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
case RX_WOW:
|
||||
return RANDOM_X;
|
||||
# endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -67,6 +67,9 @@ public:
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL)
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
RX_WOW, // "rx/wow" RandomWOW
|
||||
# endif
|
||||
MAX
|
||||
};
|
||||
@ -76,7 +79,8 @@ public:
|
||||
CN,
|
||||
CN_LITE,
|
||||
CN_HEAVY,
|
||||
CN_PICO
|
||||
CN_PICO,
|
||||
RANDOM_X
|
||||
};
|
||||
|
||||
inline Algorithm() {}
|
||||
|
@ -28,15 +28,15 @@
|
||||
#define APP_ID "xmrig"
|
||||
#define APP_NAME "XMRig"
|
||||
#define APP_DESC "XMRig CPU miner"
|
||||
#define APP_VERSION "2.99.0-evo"
|
||||
#define APP_VERSION "2.16.1-evo"
|
||||
#define APP_DOMAIN "xmrig.com"
|
||||
#define APP_SITE "www.xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"
|
||||
#define APP_KIND "cpu"
|
||||
|
||||
#define APP_VER_MAJOR 2
|
||||
#define APP_VER_MINOR 99
|
||||
#define APP_VER_PATCH 0
|
||||
#define APP_VER_MINOR 16
|
||||
#define APP_VER_PATCH 1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# if (_MSC_VER >= 1920)
|
||||
|
@ -37,7 +37,9 @@ template<size_t N>
|
||||
xmrig::MultiWorker<N>::MultiWorker(ThreadHandle *handle)
|
||||
: Worker(handle)
|
||||
{
|
||||
m_memory = Mem::create(m_ctx, m_thread->algorithm(), N);
|
||||
if (m_thread->algorithm().family() != Algorithm::RANDOM_X) {
|
||||
m_memory = Mem::create(m_ctx, m_thread->algorithm(), N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,9 +47,34 @@ template<size_t N>
|
||||
xmrig::MultiWorker<N>::~MultiWorker()
|
||||
{
|
||||
Mem::release(m_ctx, N, m_memory);
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (m_rx_vm) {
|
||||
randomx_destroy_vm(m_rx_vm);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
template<size_t N>
|
||||
void xmrig::MultiWorker<N>::allocateRandomX_VM()
|
||||
{
|
||||
if (!m_rx_vm) {
|
||||
int flags = RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT;
|
||||
if (!m_thread->isSoftAES()) {
|
||||
flags |= RANDOMX_FLAG_HARD_AES;
|
||||
}
|
||||
|
||||
m_rx_vm = randomx_create_vm(static_cast<randomx_flags>(flags), nullptr, Workers::getDataset());
|
||||
if (!m_rx_vm) {
|
||||
m_rx_vm = randomx_create_vm(static_cast<randomx_flags>(flags - RANDOMX_FLAG_LARGE_PAGES), nullptr, Workers::getDataset());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<size_t N>
|
||||
bool xmrig::MultiWorker<N>::selfTest()
|
||||
{
|
||||
@ -97,6 +124,12 @@ bool xmrig::MultiWorker<N>::selfTest()
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (m_thread->algorithm().family() == Algorithm::RANDOM_X) {
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -123,7 +156,17 @@ void xmrig::MultiWorker<N>::start()
|
||||
storeStats();
|
||||
}
|
||||
|
||||
m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (m_state.job.algorithm().family() == Algorithm::RANDOM_X) {
|
||||
allocateRandomX_VM();
|
||||
Workers::updateDataset(m_state.job.seedHash(), m_totalWays);
|
||||
randomx_calculate_hash(m_rx_vm, m_state.blob, m_state.job.size(), m_hash);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < m_state.job.target()) {
|
||||
|
@ -27,6 +27,11 @@
|
||||
#define XMRIG_MULTIWORKER_H
|
||||
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
# include <randomx.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "base/net/stratum/Job.h"
|
||||
#include "Mem.h"
|
||||
#include "net/JobResult.h"
|
||||
@ -48,6 +53,10 @@ protected:
|
||||
void start() override;
|
||||
|
||||
private:
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
void allocateRandomX_VM();
|
||||
# endif
|
||||
|
||||
bool resume(const Job &job);
|
||||
bool verify(const Algorithm &algorithm, const uint8_t *referenceValue);
|
||||
bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue);
|
||||
@ -70,6 +79,10 @@ private:
|
||||
State m_pausedState;
|
||||
State m_state;
|
||||
uint8_t m_hash[N * 32];
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
randomx_vm *m_rx_vm = nullptr;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -59,6 +59,14 @@ uv_rwlock_t Workers::m_rwlock;
|
||||
uv_timer_t *Workers::m_timer = nullptr;
|
||||
xmrig::Controller *Workers::m_controller = nullptr;
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
uv_rwlock_t Workers::m_rx_dataset_lock;
|
||||
randomx_cache *Workers::m_rx_cache = nullptr;
|
||||
randomx_dataset *Workers::m_rx_dataset = nullptr;
|
||||
uint8_t Workers::m_rx_seed_hash[32] = {};
|
||||
std::atomic<uint32_t> Workers::m_rx_dataset_init_thread_counter = {};
|
||||
#endif
|
||||
|
||||
|
||||
xmrig::Job Workers::job()
|
||||
{
|
||||
@ -183,6 +191,10 @@ void Workers::start(xmrig::Controller *controller)
|
||||
uv_mutex_init(&m_mutex);
|
||||
uv_rwlock_init(&m_rwlock);
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
uv_rwlock_init(&m_rx_dataset_lock);
|
||||
# endif
|
||||
|
||||
m_sequence = 1;
|
||||
m_paused = 1;
|
||||
|
||||
@ -341,13 +353,90 @@ void Workers::start(IWorker *worker)
|
||||
const double percent = (double) m_status.hugePages / m_status.pages * 100.0;
|
||||
const size_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo) / 1024;
|
||||
|
||||
LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "",
|
||||
m_status.threads, m_status.ways,
|
||||
(m_status.hugePages == m_status.pages ? GREEN_BOLD_S : (m_status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
m_status.hugePages, m_status.pages, percent, memory);
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (m_status.algo.family() == xmrig::Algorithm::RANDOM_X) {
|
||||
LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " memory " CYAN_BOLD("%zu KB") "",
|
||||
m_status.threads, m_status.ways, memory);
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "",
|
||||
m_status.threads, m_status.ways,
|
||||
(m_status.hugePages == m_status.pages ? GREEN_BOLD_S : (m_status.hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)),
|
||||
m_status.hugePages, m_status.pages, percent, memory);
|
||||
}
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&m_mutex);
|
||||
|
||||
worker->start();
|
||||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
void Workers::updateDataset(const uint8_t* seed_hash, const uint32_t num_threads)
|
||||
{
|
||||
// Check if we need to update cache and dataset
|
||||
if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) == 0)
|
||||
return;
|
||||
|
||||
const uint32_t thread_id = m_rx_dataset_init_thread_counter++;
|
||||
LOG_DEBUG("Thread %u started updating RandomX dataset", thread_id);
|
||||
|
||||
// Wait for all threads to get here
|
||||
do {
|
||||
if (m_sequence.load(std::memory_order_relaxed) == 0) {
|
||||
// Exit immediately if workers were stopped
|
||||
return;
|
||||
}
|
||||
std::this_thread::yield();
|
||||
} while (m_rx_dataset_init_thread_counter.load() != num_threads);
|
||||
|
||||
// One of the threads updates cache
|
||||
uv_rwlock_wrlock(&m_rx_dataset_lock);
|
||||
if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) != 0) {
|
||||
memcpy(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash));
|
||||
randomx_init_cache(m_rx_cache, m_rx_seed_hash, sizeof(m_rx_seed_hash));
|
||||
}
|
||||
uv_rwlock_wrunlock(&m_rx_dataset_lock);
|
||||
|
||||
// All threads update dataset
|
||||
const uint32_t a = (randomx_dataset_item_count() * thread_id) / num_threads;
|
||||
const uint32_t b = (randomx_dataset_item_count() * (thread_id + 1)) / num_threads;
|
||||
randomx_init_dataset(m_rx_dataset, m_rx_cache, a, b - a);
|
||||
|
||||
LOG_DEBUG("Thread %u finished updating RandomX dataset", thread_id);
|
||||
|
||||
// Wait for all threads to complete
|
||||
--m_rx_dataset_init_thread_counter;
|
||||
do {
|
||||
if (m_sequence.load(std::memory_order_relaxed) == 0) {
|
||||
// Exit immediately if workers were stopped
|
||||
return;
|
||||
}
|
||||
std::this_thread::yield();
|
||||
} while (m_rx_dataset_init_thread_counter.load() != 0);
|
||||
}
|
||||
|
||||
randomx_dataset* Workers::getDataset()
|
||||
{
|
||||
if (m_rx_dataset)
|
||||
return m_rx_dataset;
|
||||
|
||||
uv_rwlock_wrlock(&m_rx_dataset_lock);
|
||||
if (!m_rx_dataset) {
|
||||
randomx_dataset* dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (!dataset) {
|
||||
dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
|
||||
}
|
||||
m_rx_cache = randomx_alloc_cache(static_cast<randomx_flags>(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES));
|
||||
if (!m_rx_cache) {
|
||||
m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT);
|
||||
}
|
||||
m_rx_dataset = dataset;
|
||||
}
|
||||
uv_rwlock_wrunlock(&m_rx_dataset_lock);
|
||||
|
||||
return m_rx_dataset;
|
||||
}
|
||||
#endif
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include <uv.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
# include <randomx.h>
|
||||
#endif
|
||||
|
||||
#include "base/net/stratum/Job.h"
|
||||
#include "net/JobResult.h"
|
||||
#include "rapidjson/fwd.h"
|
||||
@ -72,6 +76,11 @@ public:
|
||||
static void threadsSummary(rapidjson::Document &doc);
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
static void updateDataset(const uint8_t* seed_hash, uint32_t num_threads);
|
||||
static randomx_dataset* getDataset();
|
||||
# endif
|
||||
|
||||
private:
|
||||
static void onReady(void *arg);
|
||||
static void onResult(uv_async_t *handle);
|
||||
@ -113,6 +122,14 @@ private:
|
||||
static uv_rwlock_t m_rwlock;
|
||||
static uv_timer_t *m_timer;
|
||||
static xmrig::Controller *m_controller;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
static uv_rwlock_t m_rx_dataset_lock;
|
||||
static randomx_cache *m_rx_cache;
|
||||
static randomx_dataset *m_rx_dataset;
|
||||
static uint8_t m_rx_seed_hash[32];
|
||||
static std::atomic<uint32_t> m_rx_dataset_init_thread_counter;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user