Added support for threads restart if config changed.

This commit is contained in:
XMRig 2019-07-18 19:11:45 +07:00
parent 871bc3e180
commit f590cf58fb
12 changed files with 105 additions and 62 deletions

View file

@ -78,13 +78,6 @@ const xmrig::Hashrate *xmrig::Workers<T>::hashrate() const
} }
template<class T>
void xmrig::Workers<T>::add(const T &data)
{
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), data));
}
template<class T> template<class T>
void xmrig::Workers<T>::setBackend(IBackend *backend) void xmrig::Workers<T>::setBackend(IBackend *backend)
{ {
@ -93,8 +86,12 @@ void xmrig::Workers<T>::setBackend(IBackend *backend)
template<class T> template<class T>
void xmrig::Workers<T>::start() void xmrig::Workers<T>::start(const std::vector<T> &data)
{ {
for (const T &item : data) {
m_workers.push_back(new Thread<T>(d_ptr->backend, m_workers.size(), item));
}
d_ptr->hashrate = new Hashrate(m_workers.size()); d_ptr->hashrate = new Hashrate(m_workers.size());
for (Thread<T> *worker : m_workers) { for (Thread<T> *worker : m_workers) {

View file

@ -46,9 +46,8 @@ public:
~Workers(); ~Workers();
const Hashrate *hashrate() const; const Hashrate *hashrate() const;
void add(const T &data);
void setBackend(IBackend *backend); void setBackend(IBackend *backend);
void start(); void start(const std::vector<T> &data);
void stop(); void stop();
void tick(uint64_t ticks); void tick(uint64_t ticks);

View file

@ -32,6 +32,7 @@
namespace xmrig { namespace xmrig {
class Algorithm;
class Hashrate; class Hashrate;
class IWorker; class IWorker;
class Job; class Job;
@ -43,13 +44,14 @@ class IBackend
public: public:
virtual ~IBackend() = default; virtual ~IBackend() = default;
virtual const Hashrate *hashrate() const = 0; virtual bool isEnabled(const Algorithm &algorithm) const = 0;
virtual const String &profileName() const = 0; virtual const Hashrate *hashrate() const = 0;
virtual void printHashrate(bool details) = 0; virtual const String &profileName() const = 0;
virtual void setJob(const Job &job) = 0; virtual void printHashrate(bool details) = 0;
virtual void start(IWorker *worker) = 0; virtual void setJob(const Job &job) = 0;
virtual void stop() = 0; virtual void start(IWorker *worker) = 0;
virtual void tick(uint64_t ticks) = 0; virtual void stop() = 0;
virtual void tick(uint64_t ticks) = 0;
}; };

View file

@ -85,40 +85,8 @@ public:
} }
inline bool isReady(const Algorithm &nextAlgo) const inline void start()
{ {
if (!algo.isValid()) {
return false;
}
if (nextAlgo == algo) {
return true;
}
const CpuThreads &nextThreads = controller->config()->cpu().threads().get(nextAlgo);
return algo.memory() == nextAlgo.memory()
&& threads.size() == nextThreads.size()
&& std::equal(threads.begin(), threads.end(), nextThreads.begin());
}
inline void start(const Job &job)
{
const CpuConfig &cpu = controller->config()->cpu();
algo = job.algorithm();
profileName = cpu.threads().profileName(job.algorithm());
threads = cpu.threads().get(profileName);
if (profileName.isNull() || threads.empty()) {
workers.stop();
LOG_WARN(YELLOW_BOLD_S "CPU disabled, no suitable configuration for algo %s", job.algorithm().shortName());
return;
}
LOG_INFO(GREEN_BOLD("CPU") " use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"), LOG_INFO(GREEN_BOLD("CPU") " use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
profileName.data(), profileName.data(),
threads.size(), threads.size(),
@ -131,20 +99,18 @@ public:
status.memory = algo.memory(); status.memory = algo.memory();
status.threads = threads.size(); status.threads = threads.size();
for (const CpuThread &thread : threads) { for (const CpuLaunchData &data : threads) {
workers.add(CpuLaunchData(controller->miner(), algo, cpu, thread)); status.ways += static_cast<size_t>(data.intensity);
status.ways += static_cast<size_t>(thread.intensity());
} }
workers.start(); workers.start(threads);
} }
Algorithm algo; Algorithm algo;
Controller *controller; Controller *controller;
CpuThreads threads;
LaunchStatus status; LaunchStatus status;
std::vector<CpuLaunchData> threads;
String profileName; String profileName;
uv_mutex_t mutex; uv_mutex_t mutex;
Workers<CpuLaunchData> workers; Workers<CpuLaunchData> workers;
@ -167,6 +133,12 @@ xmrig::CpuBackend::~CpuBackend()
} }
bool xmrig::CpuBackend::isEnabled(const Algorithm &algorithm) const
{
return !d_ptr->controller->config()->cpu().threads().get(algorithm).empty();
}
const xmrig::Hashrate *xmrig::CpuBackend::hashrate() const const xmrig::Hashrate *xmrig::CpuBackend::hashrate() const
{ {
return d_ptr->workers.hashrate(); return d_ptr->workers.hashrate();
@ -190,10 +162,10 @@ void xmrig::CpuBackend::printHashrate(bool details)
Log::print(WHITE_BOLD_S "| CPU THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |"); Log::print(WHITE_BOLD_S "| CPU THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
size_t i = 0; size_t i = 0;
for (const CpuThread &thread : d_ptr->threads) { for (const CpuLaunchData &data : d_ptr->threads) {
Log::print("| %13zu | %8" PRId64 " | %7s | %7s | %7s |", Log::print("| %13zu | %8" PRId64 " | %7s | %7s | %7s |",
i, i,
thread.affinity(), data.affinity,
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3), Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3), Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3) Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3)
@ -206,11 +178,26 @@ void xmrig::CpuBackend::printHashrate(bool details)
void xmrig::CpuBackend::setJob(const Job &job) void xmrig::CpuBackend::setJob(const Job &job)
{ {
if (d_ptr->isReady(job.algorithm())) { const CpuConfig &cpu = d_ptr->controller->config()->cpu();
std::vector<CpuLaunchData> threads = cpu.get(d_ptr->controller->miner(), job.algorithm());
if (d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
return; return;
} }
d_ptr->start(job); d_ptr->algo = job.algorithm();
d_ptr->profileName = cpu.threads().profileName(job.algorithm());
if (d_ptr->profileName.isNull() || threads.empty()) {
d_ptr->workers.stop();
LOG_WARN(YELLOW_BOLD_S "CPU disabled, no suitable configuration for algo %s", job.algorithm().shortName());
return;
}
d_ptr->threads = std::move(threads);
d_ptr->start();
} }

View file

@ -44,6 +44,7 @@ public:
~CpuBackend() override; ~CpuBackend() override;
protected: protected:
bool isEnabled(const Algorithm &algorithm) const override;
const Hashrate *hashrate() const override; const Hashrate *hashrate() const override;
const String &profileName() const override; const String &profileName() const override;
void printHashrate(bool details) override; void printHashrate(bool details) override;

View file

@ -100,6 +100,25 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
} }
std::vector<xmrig::CpuLaunchData> xmrig::CpuConfig::get(const Miner *miner, const Algorithm &algorithm) const
{
std::vector<CpuLaunchData> out;
const std::vector<CpuThread> &threads = m_threads.get(algorithm);
if (threads.empty()) {
return out;
}
out.reserve(threads.size());
for (const CpuThread &thread : threads) {
out.push_back(CpuLaunchData(miner, algorithm, *this, thread));
}
return out;
}
void xmrig::CpuConfig::read(const rapidjson::Value &value) void xmrig::CpuConfig::read(const rapidjson::Value &value)
{ {
if (value.IsObject()) { if (value.IsObject()) {

View file

@ -27,6 +27,7 @@
#include "backend/common/Threads.h" #include "backend/common/Threads.h"
#include "backend/cpu/CpuLaunchData.h"
#include "backend/cpu/CpuThread.h" #include "backend/cpu/CpuThread.h"
#include "crypto/common/Assembly.h" #include "crypto/common/Assembly.h"
@ -47,6 +48,7 @@ public:
bool isHwAES() const; bool isHwAES() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<CpuLaunchData> get(const Miner *miner, const Algorithm &algorithm) const;
void read(const rapidjson::Value &value); void read(const rapidjson::Value &value);
inline bool isEnabled() const { return m_enabled; } inline bool isEnabled() const { return m_enabled; }

View file

@ -41,6 +41,19 @@ xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorit
} }
bool xmrig::CpuLaunchData::isEqual(const CpuLaunchData &other) const
{
return (algorithm.memory() == other.algorithm.memory()
&& assembly == other.assembly
&& hugePages == other.hugePages
&& hwAES == other.hwAES
&& intensity == other.intensity
&& priority == other.priority
&& affinity == other.affinity
);
}
xmrig::CnHash::AlgoVariant xmrig::CpuLaunchData::av() const xmrig::CnHash::AlgoVariant xmrig::CpuLaunchData::av() const
{ {
if (intensity <= 2) { if (intensity <= 2) {

View file

@ -46,10 +46,14 @@ class CpuLaunchData
public: public:
CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread); CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread);
bool isEqual(const CpuLaunchData &other) const;
CnHash::AlgoVariant av() const; CnHash::AlgoVariant av() const;
inline constexpr static Nonce::Backend backend() { return Nonce::CPU; } inline constexpr static Nonce::Backend backend() { return Nonce::CPU; }
inline bool operator!=(const CpuLaunchData &other) const { return !isEqual(other); }
inline bool operator==(const CpuLaunchData &other) const { return isEqual(other); }
const Algorithm algorithm; const Algorithm algorithm;
const Assembly assembly; const Assembly assembly;
const bool hugePages; const bool hugePages;

View file

@ -192,7 +192,8 @@ bool xmrig::Pool::isEqual(const Pool &other) const
&& m_rigId == other.m_rigId && m_rigId == other.m_rigId
&& m_url == other.m_url && m_url == other.m_url
&& m_user == other.m_user && m_user == other.m_user
&& m_pollInterval == other.m_pollInterval); && m_pollInterval == other.m_pollInterval
);
} }

View file

@ -99,6 +99,8 @@ public:
xmrig::Miner::Miner(Controller *controller) xmrig::Miner::Miner(Controller *controller)
: d_ptr(new MinerPrivate(controller)) : d_ptr(new MinerPrivate(controller))
{ {
controller->addListener(this);
d_ptr->timer = new Timer(this); d_ptr->timer = new Timer(this);
d_ptr->backends.push_back(new CpuBackend(controller)); d_ptr->backends.push_back(new CpuBackend(controller));
@ -218,6 +220,20 @@ void xmrig::Miner::stop()
} }
void xmrig::Miner::onConfigChanged(Config *config, Config *previousConfig)
{
if (config->pools() != previousConfig->pools() && config->pools().active() > 0) {
return;
}
const Job job = this->job();
for (IBackend *backend : d_ptr->backends) {
backend->setJob(job);
}
}
void xmrig::Miner::onTimer(const Timer *) void xmrig::Miner::onTimer(const Timer *)
{ {
double maxHashrate = 0.0; double maxHashrate = 0.0;

View file

@ -29,6 +29,7 @@
#include <vector> #include <vector>
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/ITimerListener.h" #include "base/kernel/interfaces/ITimerListener.h"
@ -41,7 +42,7 @@ class MinerPrivate;
class IBackend; class IBackend;
class Miner : public ITimerListener class Miner : public ITimerListener, public IBaseListener
{ {
public: public:
Miner(Controller *controller); Miner(Controller *controller);
@ -57,6 +58,7 @@ public:
void stop(); void stop();
protected: protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
void onTimer(const Timer *timer) override; void onTimer(const Timer *timer) override;
private: private: