Added support for multi-algorithm CPU threads settings.

This commit is contained in:
XMRig 2019-07-02 22:56:28 +07:00
parent 83fdbbf29c
commit b92807e8d8
24 changed files with 595 additions and 109 deletions

View file

@ -18,13 +18,13 @@ option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
include (CheckIncludeFile) include (CheckIncludeFile)
include (cmake/cpu.cmake) include (cmake/cpu.cmake)
include (src/base/base.cmake) include (src/base/base.cmake)
include (src/backend/cpu/cpu.cmake) include (src/backend/backend.cmake)
set(HEADERS set(HEADERS
"${HEADERS_BASE}" "${HEADERS_BASE}"
"${HEADERS_BASE_HTTP}" "${HEADERS_BASE_HTTP}"
"${HEADERS_CPU}" "${HEADERS_BACKEND}"
src/api/interfaces/IApiListener.h src/api/interfaces/IApiListener.h
src/App.h src/App.h
src/common/Platform.h src/common/Platform.h
@ -45,7 +45,7 @@ set(HEADERS
src/net/strategies/DonateStrategy.h src/net/strategies/DonateStrategy.h
src/Summary.h src/Summary.h
src/version.h src/version.h
src/workers/CpuThread.h src/workers/CpuThreadLegacy.h
src/workers/Hashrate.h src/workers/Hashrate.h
src/workers/MultiWorker.h src/workers/MultiWorker.h
src/workers/ThreadHandle.h src/workers/ThreadHandle.h
@ -83,7 +83,7 @@ endif()
set(SOURCES set(SOURCES
"${SOURCES_BASE}" "${SOURCES_BASE}"
"${SOURCES_BASE_HTTP}" "${SOURCES_BASE_HTTP}"
"${SOURCES_CPU}" "${SOURCES_BACKEND}"
src/App.cpp src/App.cpp
src/common/Platform.cpp src/common/Platform.cpp
src/core/config/Config.cpp src/core/config/Config.cpp
@ -94,7 +94,7 @@ set(SOURCES
src/net/NetworkState.cpp src/net/NetworkState.cpp
src/net/strategies/DonateStrategy.cpp src/net/strategies/DonateStrategy.cpp
src/Summary.cpp src/Summary.cpp
src/workers/CpuThread.cpp src/workers/CpuThreadLegacy.cpp
src/workers/Hashrate.cpp src/workers/Hashrate.cpp
src/workers/MultiWorker.cpp src/workers/MultiWorker.cpp
src/workers/ThreadHandle.cpp src/workers/ThreadHandle.cpp

145
src/backend/Threads.cpp Normal file
View file

@ -0,0 +1,145 @@
/* 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/CpuThread.h"
#include "backend/Threads.h"
#include "rapidjson/document.h"
template <class T>
const std::vector<T> &xmrig::Threads<T>::get(const String &profileName) const
{
static std::vector<T> empty;
if (profileName.isNull() || !has(profileName)) {
return empty;
}
return m_profiles.at(profileName);
}
template <class T>
xmrig::String xmrig::Threads<T>::profileName(const Algorithm &algorithm, bool strict) const
{
if (isDisabled(algorithm)) {
return String();
}
const String name = algorithm.shortName();
if (has(name)) {
return name;
}
if (m_aliases.count(algorithm) > 0) {
return m_aliases.at(algorithm);
}
if (!strict && name.contains("/")) {
const String base = name.split('/').at(0);
if (has(base)) {
return base;
}
}
return String();
}
template <class T>
void xmrig::Threads<T>::read(const rapidjson::Value &value)
{
using namespace rapidjson;
for (auto &member : value.GetObject()) {
if (member.value.IsArray()) {
std::vector<T> threads;
for (auto &v : member.value.GetArray()) {
T thread(v);
if (thread.isValid()) {
threads.push_back(std::move(thread));
}
}
if (!threads.empty()) {
move(member.name.GetString(), std::move(threads));
}
continue;
}
const Algorithm algo(member.name.GetString());
if (!algo.isValid()) {
continue;
}
if (member.value.IsBool() && member.value.IsFalse()) {
disable(algo);
continue;
}
if (member.value.IsString()) {
if (has(member.value.GetString())) {
m_aliases.insert({ algo, member.value.GetString() });
}
else {
m_disabled.insert(algo);
}
}
}
}
template <class T>
void xmrig::Threads<T>::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
for (const auto &kv : m_profiles) {
Value arr(kArrayType);
for (const T &thread : kv.second) {
arr.PushBack(thread.toJSON(doc), allocator);
}
out.AddMember(kv.first.toJSON(), arr, allocator);
}
for (const Algorithm &algo : m_disabled) {
out.AddMember(StringRef(algo.shortName()), false, allocator);
}
for (const auto &kv : m_aliases) {
out.AddMember(StringRef(kv.first.shortName()), kv.second.toJSON(), allocator);
}
}
namespace xmrig {
template class Threads<CpuThread>;
} // namespace xmrig

67
src/backend/Threads.h Normal file
View file

@ -0,0 +1,67 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_THREADS_H
#define XMRIG_THREADS_H
#include <map>
#include <set>
#include "base/tools/String.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
template <class T>
class Threads
{
public:
inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; }
inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0; }
inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); }
inline const std::vector<T> &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); }
inline void disable(const Algorithm &algo) { m_disabled.insert(algo); }
inline void move(const char *profile, std::vector<T> &&threads) { m_profiles.insert({ profile, threads }); }
const std::vector<T> &get(const String &profileName) const;
String profileName(const Algorithm &algorithm, bool strict = false) const;
void read(const rapidjson::Value &value);
void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const;
private:
std::map<Algorithm, String> m_aliases;
std::map<String, std::vector<T> > m_profiles;
std::set<Algorithm> m_disabled;
};
} /* namespace xmrig */
#endif /* XMRIG_THREADS_H */

12
src/backend/backend.cmake Normal file
View file

@ -0,0 +1,12 @@
include (src/backend/cpu/cpu.cmake)
set(HEADERS_BACKEND
"${HEADERS_CPU}"
src/backend/Threads.h
)
set(SOURCES_BACKEND
"${SOURCES_CPU}"
src/backend/Threads.cpp
)

View file

@ -31,17 +31,34 @@
namespace xmrig { namespace xmrig {
static const char *kCn = "cn";
static const char *kEnabled = "enabled"; static const char *kEnabled = "enabled";
static const char *kHugePages = "huge-pages"; static const char *kHugePages = "huge-pages";
static const char *kHwAes = "hw-aes"; static const char *kHwAes = "hw-aes";
static const char *kPriority = "priority"; static const char *kPriority = "priority";
#ifdef XMRIG_FEATURE_ASM #ifdef XMRIG_FEATURE_ASM
static const char *kAsm = "asm"; static const char *kAsm = "asm";
#endif #endif
#ifdef XMRIG_ALGO_CN_GPU
static const char *kCnGPU = "cn/gpu";
#endif
#ifdef XMRIG_ALGO_CN_LITE
static const char *kCnLite = "cn-lite";
#endif
#ifdef XMRIG_ALGO_CN_HEAVY
static const char *kCnHeavy = "cn-heavy";
#endif
#ifdef XMRIG_ALGO_CN_PICO
static const char *kCnPico = "cn-pico";
#endif
extern template class Threads<CpuThread>;
} }
@ -59,7 +76,6 @@ bool xmrig::CpuConfig::isHwAES() const
rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
{ {
using namespace rapidjson; using namespace rapidjson;
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
Value obj(kObjectType); Value obj(kObjectType);
@ -73,6 +89,8 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator); obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator);
# endif # endif
m_threads.toJSON(obj, doc);
return obj; return obj;
} }
@ -89,6 +107,34 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value)
# ifdef XMRIG_FEATURE_ASM # ifdef XMRIG_FEATURE_ASM
m_assembly = Json::getValue(value, kAsm); m_assembly = Json::getValue(value, kAsm);
# endif # endif
m_threads.read(value);
}
else if (value.IsBool() && value.IsFalse()) {
m_enabled = false;
}
else {
m_shouldSave = true;
m_threads.disable(Algorithm::CN_0);
m_threads.move(kCn, Cpu::info()->threads(Algorithm::CN_0));
# ifdef XMRIG_ALGO_CN_GPU
m_threads.move(kCnGPU, Cpu::info()->threads(Algorithm::CN_GPU));
# endif
# ifdef XMRIG_ALGO_CN_LITE
m_threads.disable(Algorithm::CN_LITE_0);
m_threads.move(kCnLite, Cpu::info()->threads(Algorithm::CN_LITE_1));
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
m_threads.move(kCnHeavy, Cpu::info()->threads(Algorithm::CN_HEAVY_0));
# endif
# ifdef XMRIG_ALGO_CN_PICO
m_threads.move(kCnPico, Cpu::info()->threads(Algorithm::CN_PICO_0));
# endif
} }
} }

View file

@ -26,6 +26,8 @@
#define XMRIG_CPUCONFIG_H #define XMRIG_CPUCONFIG_H
#include "backend/cpu/CpuThread.h"
#include "backend/Threads.h"
#include "crypto/common/Assembly.h" #include "crypto/common/Assembly.h"
@ -47,11 +49,12 @@ public:
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) 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; }
inline bool isHugePages() const { return m_hugePages; } inline bool isHugePages() const { return m_hugePages; }
inline bool isShouldSave() const { return m_shouldSave; } inline bool isShouldSave() const { return m_shouldSave; }
inline const Assembly &assembly() const { return m_assembly; } inline const Assembly &assembly() const { return m_assembly; }
inline int priority() const { return m_priority; } inline const Threads<CpuThread> &threads() const { return m_threads; }
inline int priority() const { return m_priority; }
private: private:
void setAesMode(const rapidjson::Value &aesMode); void setAesMode(const rapidjson::Value &aesMode);
@ -63,6 +66,7 @@ private:
bool m_hugePages = true; bool m_hugePages = true;
bool m_shouldSave = false; bool m_shouldSave = false;
int m_priority = -1; int m_priority = -1;
Threads<CpuThread> m_threads;
}; };

View file

@ -0,0 +1,71 @@
/* 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/CpuThread.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
namespace xmrig {
static const char *kAffinity = "affinity";
static const char *kIntensity = "intensity";
}
xmrig::CpuThread::CpuThread(const rapidjson::Value &value)
{
if (value.IsObject()) {
m_intensity = Json::getInt(value, kIntensity, -1);
m_affinity = Json::getInt(value, kAffinity, -1);
}
else if (value.IsInt()) {
m_intensity = 1;
m_affinity = value.GetInt();
}
}
rapidjson::Value xmrig::CpuThread::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
if (intensity() > 1) {
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kIntensity), m_intensity, allocator);
obj.AddMember(StringRef(kAffinity), m_affinity, allocator);
return obj;
}
return Value(m_affinity);
}

View file

@ -0,0 +1,63 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CPUTHREADCONFIG_H
#define XMRIG_CPUTHREADCONFIG_H
#include <vector>
#include "rapidjson/fwd.h"
namespace xmrig {
class CpuThread
{
public:
inline constexpr CpuThread(int intensity = 1, int affinity = -1) : m_affinity(affinity), m_intensity(intensity) {}
CpuThread(const rapidjson::Value &value);
inline bool isValid() const { return m_intensity >= 1 && m_intensity <= 5; }
inline int affinity() const { return m_affinity; }
inline int intensity() const { return m_intensity; }
rapidjson::Value toJSON(rapidjson::Document &doc) const;
private:
int m_affinity = -1;
int m_intensity = -1;
};
typedef std::vector<CpuThread> CpuThreads;
} /* namespace xmrig */
#endif /* XMRIG_CPUTHREADCONFIG_H */

View file

@ -1,12 +1,14 @@
set(HEADERS_CPU set(HEADERS_CPU
src/backend/cpu/Cpu.h src/backend/cpu/Cpu.h
src/backend/cpu/CpuConfig.h src/backend/cpu/CpuConfig.h
src/backend/cpu/interfaces/ICpuInfo.h src/backend/cpu/CpuThread.h
src/backend/cpu/interfaces/ICpuInfo.h
) )
set(SOURCES_CPU set(SOURCES_CPU
src/backend/cpu/Cpu.cpp src/backend/cpu/Cpu.cpp
src/backend/cpu/CpuConfig.cpp src/backend/cpu/CpuConfig.cpp
src/backend/cpu/CpuThread.cpp
) )

View file

@ -26,11 +26,9 @@
#define XMRIG_CPUINFO_H #define XMRIG_CPUINFO_H
#include <stddef.h> #include "backend/cpu/CpuThread.h"
#include <stdint.h>
#include "crypto/common/Assembly.h" #include "crypto/common/Assembly.h"
#include "crypto/common/Algorithm.h"
namespace xmrig { namespace xmrig {
@ -47,18 +45,19 @@ public:
inline constexpr static bool isX64() { return false; } inline constexpr static bool isX64() { return false; }
# endif # endif
virtual Assembly::Id assembly() const = 0;
virtual bool hasAES() const = 0; virtual bool hasAES() const = 0;
virtual bool hasAVX2() const = 0; virtual bool hasAVX2() const = 0;
virtual bool isSupported() const = 0; virtual bool isSupported() const = 0;
virtual const char *brand() const = 0; virtual const char *brand() const = 0;
virtual int32_t cores() const = 0; virtual CpuThreads threads(const Algorithm &algorithm) const = 0;
virtual int32_t L2() const = 0; virtual size_t cores() const = 0;
virtual int32_t L3() const = 0; virtual size_t L2() const = 0;
virtual int32_t nodes() const = 0; virtual size_t L3() const = 0;
virtual int32_t sockets() const = 0; virtual size_t nodes() const = 0;
virtual int32_t threads() const = 0;
virtual size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const = 0; virtual size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const = 0;
virtual Assembly::Id assembly() const = 0; virtual size_t sockets() const = 0;
virtual size_t threads() const = 0;
}; };

View file

@ -26,51 +26,43 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include "backend/cpu/platform/AdvancedCpuInfo.h" #include "backend/cpu/platform/AdvancedCpuInfo.h"
xmrig::AdvancedCpuInfo::AdvancedCpuInfo() : xmrig::AdvancedCpuInfo::AdvancedCpuInfo() :
m_aes(false), m_brand()
m_avx2(false),
m_L2_exclusive(false),
m_brand(),
m_cores(0),
m_L2(0),
m_L3(0),
m_sockets(1),
m_threads(0)
{ {
struct cpu_raw_data_t raw = { 0 }; struct cpu_raw_data_t raw = {};
struct cpu_id_t data = { 0 }; struct cpu_id_t data = {};
cpuid_get_raw_data(&raw); cpuid_get_raw_data(&raw);
cpu_identify(&raw, &data); cpu_identify(&raw, &data);
strncpy(m_brand, data.brand_str, sizeof(m_brand)); strncpy(m_brand, data.brand_str, sizeof(m_brand));
m_threads = data.total_logical_cpus; m_threads = static_cast<size_t>(data.total_logical_cpus);
m_sockets = threads() / data.num_logical_cpus; m_sockets = std::max<size_t>(threads() / static_cast<size_t>(data.num_logical_cpus), 1);
if (m_sockets == 0) { m_cores = static_cast<size_t>(data.num_cores) * m_sockets;
m_sockets = 1; m_L3 = data.l3_cache > 0 ? static_cast<size_t>(data.l3_cache) * m_sockets : 0;
}
m_cores = data.num_cores * m_sockets; const size_t l2 = static_cast<size_t>(data.l2_cache);
m_L3 = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) { if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) {
m_L2 = data.l2_cache * (cores() / 2) * m_sockets; m_L2 = l2 * (cores() / 2) * m_sockets;
m_L2_exclusive = true; m_L2_exclusive = true;
} }
// Workaround for Intel Pentium Dual-Core, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue // Workaround for Intel Pentium Dual-Core, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue
// These processors have L2 cache shared by 2 cores. // These processors have L2 cache shared by 2 cores.
else if (data.vendor == VENDOR_INTEL && data.ext_family == 0x06 && (data.ext_model == 0x0E || data.ext_model == 0x0F || data.ext_model == 0x17)) { else if (data.vendor == VENDOR_INTEL && data.ext_family == 0x06 && (data.ext_model == 0x0E || data.ext_model == 0x0F || data.ext_model == 0x17)) {
int l2_count_per_socket = cores() > 1 ? cores() / 2 : 1; size_t l2_count_per_socket = cores() > 1 ? cores() / 2 : 1;
m_L2 = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; m_L2 = data.l2_cache > 0 ? l2 * l2_count_per_socket * m_sockets : 0;
} }
else{ else{
m_L2 = data.l2_cache > 0 ? data.l2_cache * cores() * m_sockets : 0; m_L2 = data.l2_cache > 0 ? l2 * cores() * m_sockets : 0;
} }
if (data.flags[CPU_FEATURE_AES]) { if (data.flags[CPU_FEATURE_AES]) {
@ -125,3 +117,43 @@ size_t xmrig::AdvancedCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsa
return count < 1 ? 1 : count; return count < 1 ? 1 : count;
} }
xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) const
{
if (threads() == 1) {
return CpuThreads(1);
}
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return CpuThreads(threads());
}
# endif
size_t cache = 0;
size_t count = 0;
if (m_L3) {
cache = m_L2_exclusive ? (m_L2 + m_L3) : m_L3;
}
else {
cache = m_L2;
}
if (cache) {
cache *= 1024;
const size_t memory = algorithm.memory();
count = cache / memory;
if (cache % memory >= memory / 2) {
count++;
}
}
else {
count = threads() / 2;
}
return CpuThreads(std::max<size_t>(std::min<size_t>(count, threads()), 1));
}

View file

@ -39,30 +39,31 @@ public:
protected: protected:
size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override; size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override;
CpuThreads threads(const Algorithm &algorithm) const override;
inline Assembly::Id assembly() const override { return m_assembly; } inline Assembly::Id assembly() const override { return m_assembly; }
inline bool hasAES() const override { return m_aes; } inline bool hasAES() const override { return m_aes; }
inline bool hasAVX2() const override { return m_avx2; } inline bool hasAVX2() const override { return m_avx2; }
inline bool isSupported() const override { return true; } inline bool isSupported() const override { return true; }
inline const char *brand() const override { return m_brand; } inline const char *brand() const override { return m_brand; }
inline int32_t cores() const override { return m_cores; } inline size_t cores() const override { return m_cores; }
inline int32_t L2() const override { return m_L2; } inline size_t L2() const override { return m_L2; }
inline int32_t L3() const override { return m_L3; } inline size_t L3() const override { return m_L3; }
inline int32_t nodes() const override { return -1; } inline size_t nodes() const override { return 0; }
inline int32_t sockets() const override { return m_sockets; } inline size_t sockets() const override { return m_sockets; }
inline int32_t threads() const override { return m_threads; } inline size_t threads() const override { return m_threads; }
private: private:
Assembly m_assembly; Assembly m_assembly;
bool m_aes; bool m_aes = false;
bool m_avx2; bool m_avx2 = false;
bool m_L2_exclusive; bool m_L2_exclusive = false;
char m_brand[64]; char m_brand[64];
int32_t m_cores; size_t m_cores = 0;
int32_t m_L2; size_t m_L2 = 0;
int32_t m_L3; size_t m_L3 = 0;
int32_t m_sockets; size_t m_sockets = 1;
int32_t m_threads; size_t m_threads = 0;
}; };

View file

@ -22,6 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <string.h> #include <string.h>
#include <thread> #include <thread>
@ -123,9 +124,9 @@ static inline bool has_ossave()
xmrig::BasicCpuInfo::BasicCpuInfo() : xmrig::BasicCpuInfo::BasicCpuInfo() :
m_assembly(Assembly::NONE), m_assembly(Assembly::NONE),
m_brand(),
m_aes(has_aes_ni()), m_aes(has_aes_ni()),
m_avx2(has_avx2() && has_ossave()), m_avx2(has_avx2() && has_ossave()),
m_brand(),
m_threads(std::thread::hardware_concurrency()) m_threads(std::thread::hardware_concurrency())
{ {
cpu_brand_string(m_brand); cpu_brand_string(m_brand);
@ -158,3 +159,27 @@ size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage)
return count < 1 ? 1 : count; return count < 1 ? 1 : count;
} }
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const
{
if (threads() == 1) {
return CpuThreads(1);
}
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return CpuThreads(threads());
}
# endif
if (algorithm.family() == Algorithm::CN_LITE || algorithm.family() == Algorithm::CN_PICO) {
return CpuThreads(threads());
}
if (algorithm.family() == Algorithm::CN_HEAVY) {
return CpuThreads(std::max<size_t>(threads() / 4, 1));
}
return CpuThreads(std::max<size_t>(threads() / 2, 1));
}

View file

@ -39,25 +39,26 @@ public:
protected: protected:
size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override; size_t optimalThreadsCount(size_t memSize, int maxCpuUsage) const override;
CpuThreads threads(const Algorithm &algorithm) const override;
inline Assembly::Id assembly() const override { return m_assembly; } inline Assembly::Id assembly() const override { return m_assembly; }
inline bool hasAES() const override { return m_aes; } inline bool hasAES() const override { return m_aes; }
inline bool hasAVX2() const override { return m_avx2; } inline bool hasAVX2() const override { return m_avx2; }
inline bool isSupported() const override { return true; } inline bool isSupported() const override { return true; }
inline const char *brand() const override { return m_brand; } inline const char *brand() const override { return m_brand; }
inline int32_t cores() const override { return -1; } inline size_t cores() const override { return 0; }
inline int32_t L2() const override { return -1; } inline size_t L2() const override { return 0; }
inline int32_t L3() const override { return -1; } inline size_t L3() const override { return 0; }
inline int32_t nodes() const override { return -1; } inline size_t nodes() const override { return 0; }
inline int32_t sockets() const override { return 1; } inline size_t sockets() const override { return 1; }
inline int32_t threads() const override { return m_threads; } inline size_t threads() const override { return m_threads; }
private: private:
Assembly m_assembly; Assembly m_assembly;
bool m_aes; char m_brand[64 + 6];
bool m_avx2; const bool m_aes;
char m_brand[64]; const bool m_avx2;
int32_t m_threads; const size_t m_threads;
}; };

View file

@ -36,7 +36,7 @@
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/filewritestream.h" #include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h" #include "rapidjson/prettywriter.h"
#include "workers/CpuThread.h" #include "workers/CpuThreadLegacy.h"
xmrig::Config::Config() : xmrig::Config::Config() :
@ -125,7 +125,7 @@ bool xmrig::Config::finalize()
m_threads.mode = Advanced; m_threads.mode = Advanced;
for (size_t i = 0; i < m_threads.cpu.size(); ++i) { 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_cpu.priority(), !m_cpu.isHwAES())); m_threads.list.push_back(CpuThreadLegacy::createFromData(i, algorithm, m_threads.cpu[i], m_cpu.priority(), !m_cpu.isHwAES()));
} }
return true; return true;
@ -134,7 +134,7 @@ bool xmrig::Config::finalize()
const AlgoVariant av = getAlgoVariant(); const AlgoVariant av = getAlgoVariant();
m_threads.mode = m_threads.count ? Simple : Automatic; m_threads.mode = m_threads.count ? Simple : Automatic;
const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; // FIXME MEMORY const size_t size = CpuThreadLegacy::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; // FIXME MEMORY
if (!m_threads.count) { if (!m_threads.count) {
m_threads.count = Cpu::info()->optimalThreadsCount(size, 100); m_threads.count = Cpu::info()->optimalThreadsCount(size, 100);
@ -147,7 +147,7 @@ bool xmrig::Config::finalize()
// } // }
for (size_t i = 0; i < m_threads.count; ++i) { for (size_t i = 0; i < m_threads.count; ++i) {
m_threads.list.push_back(CpuThread::createFromAV(i, algorithm, av, m_threads.mask, m_cpu.priority(), m_cpu.assembly())); m_threads.list.push_back(CpuThreadLegacy::createFromAV(i, algorithm, av, m_threads.mask, m_cpu.priority(), m_cpu.assembly()));
} }
m_shouldSave = m_threads.mode == Automatic; m_shouldSave = m_threads.mode == Automatic;
@ -175,7 +175,7 @@ void xmrig::Config::setThreads(const rapidjson::Value &threads)
} }
if (value.HasMember("low_power_mode")) { if (value.HasMember("low_power_mode")) {
auto data = CpuThread::parse(value); auto data = CpuThreadLegacy::parse(value);
if (data.valid) { if (data.valid) {
m_threads.cpu.push_back(std::move(data)); m_threads.cpu.push_back(std::move(data));

View file

@ -34,7 +34,7 @@
#include "base/kernel/config/BaseConfig.h" #include "base/kernel/config/BaseConfig.h"
#include "common/xmrig.h" #include "common/xmrig.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
#include "workers/CpuThread.h" #include "workers/CpuThreadLegacy.h"
namespace xmrig { namespace xmrig {
@ -59,7 +59,7 @@ public:
void getJSON(rapidjson::Document &doc) const override; void getJSON(rapidjson::Document &doc) const override;
inline AlgoVariant algoVariant() const { return m_algoVariant; } inline AlgoVariant algoVariant() const { return m_algoVariant; }
inline bool isShouldSave() const { return (m_shouldSave || m_upgrade) && isAutoSave(); } inline bool isShouldSave() const { return (m_shouldSave || m_upgrade || m_cpu.isShouldSave()) && isAutoSave(); }
inline const CpuConfig &cpu() const { return m_cpu; } inline const CpuConfig &cpu() const { return m_cpu; }
inline const std::vector<IThread *> &threads() const { return m_threads.list; } inline const std::vector<IThread *> &threads() const { return m_threads.list; }
inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); } inline int threadsCount() const { return static_cast<int>(m_threads.list.size()); }
@ -81,7 +81,7 @@ private:
int64_t mask; int64_t mask;
size_t count; size_t count;
std::vector<CpuThread::Data> cpu; std::vector<CpuThreadLegacy::Data> cpu;
std::vector<IThread *> list; std::vector<IThread *> list;
ThreadsMode mode; ThreadsMode mode;
}; };

View file

@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include "crypto/cn/CnAlgo.h"
#include "crypto/common/Algorithm.h" #include "crypto/common/Algorithm.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
@ -123,6 +124,20 @@ rapidjson::Value xmrig::Algorithm::toJSON() const
} }
size_t xmrig::Algorithm::memory() const
{
if (family() < RANDOM_X) {
return CnAlgo<>::memory(m_id);
}
if (m_id == RX_WOW) {
return 0x100000;
}
return 0;
}
xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
{ {
switch (id) { switch (id) {

View file

@ -94,11 +94,14 @@ public:
inline Family family() const { return family(m_id); } inline Family family() const { return family(m_id); }
inline Id id() const { return m_id; } inline Id id() const { return m_id; }
inline bool operator!=(Algorithm::Id id) const { return m_id != id; }
inline bool operator!=(const Algorithm &other) const { return !isEqual(other); } inline bool operator!=(const Algorithm &other) const { return !isEqual(other); }
inline bool operator==(Algorithm::Id id) const { return m_id == id; }
inline bool operator==(const Algorithm &other) const { return isEqual(other); } inline bool operator==(const Algorithm &other) const { return isEqual(other); }
inline operator Algorithm::Id() const { return m_id; } inline operator Algorithm::Id() const { return m_id; }
rapidjson::Value toJSON() const; rapidjson::Value toJSON() const;
size_t memory() const;
static Family family(Id id); static Family family(Id id);
static Id parse(const char *name); static Id parse(const char *name);

View file

@ -59,10 +59,10 @@ public:
inline bool isEqual(const Assembly &other) const { return m_id == other.m_id; } inline bool isEqual(const Assembly &other) const { return m_id == other.m_id; }
inline bool operator!=(Assembly::Id id) const { return m_id != id; }
inline bool operator!=(const Assembly &other) const { return !isEqual(other); } inline bool operator!=(const Assembly &other) const { return !isEqual(other); }
inline bool operator!=(const Assembly::Id &id) const { return m_id != id; } inline bool operator==(Assembly::Id id) const { return m_id == id; }
inline bool operator==(const Assembly &other) const { return isEqual(other); } inline bool operator==(const Assembly &other) const { return isEqual(other); }
inline bool operator==(const Assembly::Id &id) const { return m_id == id; }
inline operator Assembly::Id() const { return m_id; } inline operator Assembly::Id() const { return m_id; }
private: private:

View file

@ -31,14 +31,14 @@
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
#include "Mem.h" #include "Mem.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "workers/CpuThread.h" #include "workers/CpuThreadLegacy.h"
static const xmrig::CnHash cnHash; static const xmrig::CnHash cnHash;
xmrig::CpuThread::CpuThread(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly) : xmrig::CpuThreadLegacy::CpuThreadLegacy(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly) :
m_algorithm(algorithm), m_algorithm(algorithm),
m_av(av), m_av(av),
m_assembly(assembly), m_assembly(assembly),
@ -52,20 +52,20 @@ xmrig::CpuThread::CpuThread(size_t index, Algorithm algorithm, AlgoVariant av, M
} }
xmrig::cn_hash_fun xmrig::CpuThread::fn(const Algorithm &algorithm) const xmrig::cn_hash_fun xmrig::CpuThreadLegacy::fn(const Algorithm &algorithm) const
{ {
return cnHash.fn(algorithm, m_av, m_assembly); return cnHash.fn(algorithm, m_av, m_assembly);
} }
bool xmrig::CpuThread::isSoftAES(AlgoVariant av) bool xmrig::CpuThreadLegacy::isSoftAES(AlgoVariant av)
{ {
return av == AV_SINGLE_SOFT || av == AV_DOUBLE_SOFT || av > AV_PENTA; return av == AV_SINGLE_SOFT || av == AV_DOUBLE_SOFT || av > AV_PENTA;
} }
xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly) xmrig::CpuThreadLegacy *xmrig::CpuThreadLegacy::createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly)
{ {
assert(av > AV_AUTO && av < AV_MAX); assert(av > AV_AUTO && av < AV_MAX);
@ -88,11 +88,11 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, const Algorithm &
} }
} }
return new CpuThread(index, algorithm, av, multiway(av), cpuId, priority, isSoftAES(av), false, assembly); return new CpuThreadLegacy(index, algorithm, av, multiway(av), cpuId, priority, isSoftAES(av), false, assembly);
} }
xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, const Algorithm &algorithm, const CpuThread::Data &data, int priority, bool softAES) xmrig::CpuThreadLegacy *xmrig::CpuThreadLegacy::createFromData(size_t index, const Algorithm &algorithm, const CpuThreadLegacy::Data &data, int priority, bool softAES)
{ {
int av = AV_AUTO; int av = AV_AUTO;
const Multiway multiway = data.multiway; const Multiway multiway = data.multiway;
@ -106,11 +106,11 @@ xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, const Algorithm
assert(av > AV_AUTO && av < AV_MAX); assert(av > AV_AUTO && av < AV_MAX);
return new CpuThread(index, algorithm, static_cast<AlgoVariant>(av), multiway, data.affinity, priority, softAES, false, data.assembly); return new CpuThreadLegacy(index, algorithm, static_cast<AlgoVariant>(av), multiway, data.affinity, priority, softAES, false, data.assembly);
} }
xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object) xmrig::CpuThreadLegacy::Data xmrig::CpuThreadLegacy::parse(const rapidjson::Value &object)
{ {
Data data; Data data;
@ -140,7 +140,7 @@ xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object)
} }
xmrig::IThread::Multiway xmrig::CpuThread::multiway(AlgoVariant av) xmrig::IThread::Multiway xmrig::CpuThreadLegacy::multiway(AlgoVariant av)
{ {
switch (av) { switch (av) {
case AV_SINGLE: case AV_SINGLE:
@ -172,7 +172,7 @@ xmrig::IThread::Multiway xmrig::CpuThread::multiway(AlgoVariant av)
#ifdef APP_DEBUG #ifdef APP_DEBUG
void xmrig::CpuThread::print() const void xmrig::CpuThreadLegacy::print() const
{ {
LOG_DEBUG(GREEN_BOLD("CPU thread: ") " index " WHITE_BOLD("%zu") ", multiway " WHITE_BOLD("%d") ", av " WHITE_BOLD("%d") ",", LOG_DEBUG(GREEN_BOLD("CPU thread: ") " index " WHITE_BOLD("%zu") ", multiway " WHITE_BOLD("%d") ", av " WHITE_BOLD("%d") ",",
index(), static_cast<int>(multiway()), static_cast<int>(m_av)); index(), static_cast<int>(multiway()), static_cast<int>(m_av));
@ -187,7 +187,7 @@ void xmrig::CpuThread::print() const
#ifdef XMRIG_FEATURE_API #ifdef XMRIG_FEATURE_API
rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const rapidjson::Value xmrig::CpuThreadLegacy::toAPI(rapidjson::Document &doc) const
{ {
using namespace rapidjson; using namespace rapidjson;
@ -206,7 +206,7 @@ rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
#endif #endif
rapidjson::Value xmrig::CpuThread::toConfig(rapidjson::Document &doc) const rapidjson::Value xmrig::CpuThreadLegacy::toConfig(rapidjson::Document &doc) const
{ {
using namespace rapidjson; using namespace rapidjson;

View file

@ -22,8 +22,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef XMRIG_CPUTHREAD_H #ifndef XMRIG_CPUTHREADLEGACY_H
#define XMRIG_CPUTHREAD_H #define XMRIG_CPUTHREADLEGACY_H
#include "common/xmrig.h" #include "common/xmrig.h"
@ -37,7 +37,7 @@ struct cryptonight_ctx;
namespace xmrig { namespace xmrig {
class CpuThread : public IThread class CpuThreadLegacy : public IThread
{ {
public: public:
struct Data struct Data
@ -59,13 +59,13 @@ public:
}; };
CpuThread(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly); CpuThreadLegacy(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly);
cn_hash_fun fn(const Algorithm &algorithm) const; cn_hash_fun fn(const Algorithm &algorithm) const;
static bool isSoftAES(AlgoVariant av); static bool isSoftAES(AlgoVariant av);
static CpuThread *createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly); static CpuThreadLegacy *createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly);
static CpuThread *createFromData(size_t index, const Algorithm &algorithm, const CpuThread::Data &data, int priority, bool softAES); static CpuThreadLegacy *createFromData(size_t index, const Algorithm &algorithm, const CpuThreadLegacy::Data &data, int priority, bool softAES);
static Data parse(const rapidjson::Value &object); static Data parse(const rapidjson::Value &object);
static Multiway multiway(AlgoVariant av); static Multiway multiway(AlgoVariant av);
@ -106,4 +106,4 @@ private:
} /* namespace xmrig */ } /* namespace xmrig */
#endif /* XMRIG_CPUTHREAD_H */ #endif /* XMRIG_CPUTHREADLEGACY_H */

View file

@ -28,7 +28,7 @@
#include "crypto/cn/CryptoNight_test.h" #include "crypto/cn/CryptoNight_test.h"
#include "workers/CpuThread.h" #include "workers/CpuThreadLegacy.h"
#include "workers/MultiWorker.h" #include "workers/MultiWorker.h"
#include "workers/Workers.h" #include "workers/Workers.h"

View file

@ -26,7 +26,7 @@
#include "backend/cpu/Cpu.h" #include "backend/cpu/Cpu.h"
#include "common/Platform.h" #include "common/Platform.h"
#include "workers/CpuThread.h" #include "workers/CpuThreadLegacy.h"
#include "workers/ThreadHandle.h" #include "workers/ThreadHandle.h"
#include "workers/Worker.h" #include "workers/Worker.h"
@ -39,7 +39,7 @@ Worker::Worker(ThreadHandle *handle) :
m_timestamp(0), m_timestamp(0),
m_count(0), m_count(0),
m_sequence(0), m_sequence(0),
m_thread(static_cast<xmrig::CpuThread *>(handle->config())) m_thread(static_cast<xmrig::CpuThreadLegacy *>(handle->config()))
{ {
if (xmrig::Cpu::info()->threads() > 1 && m_thread->affinity() != -1L) { if (xmrig::Cpu::info()->threads() > 1 && m_thread->affinity() != -1L) {
Platform::setThreadAffinity(m_thread->affinity()); Platform::setThreadAffinity(m_thread->affinity());

View file

@ -37,7 +37,7 @@ class ThreadHandle;
namespace xmrig { namespace xmrig {
class CpuThread; class CpuThreadLegacy;
} }
@ -62,7 +62,7 @@ protected:
std::atomic<uint64_t> m_timestamp; std::atomic<uint64_t> m_timestamp;
uint64_t m_count; uint64_t m_count;
uint64_t m_sequence; uint64_t m_sequence;
xmrig::CpuThread *m_thread; xmrig::CpuThreadLegacy *m_thread;
}; };