diff --git a/CMakeLists.txt b/CMakeLists.txt index 7320b63d..ef4f8cee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,13 +18,13 @@ option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF) include (CheckIncludeFile) include (cmake/cpu.cmake) include (src/base/base.cmake) -include (src/backend/cpu/cpu.cmake) +include (src/backend/backend.cmake) set(HEADERS "${HEADERS_BASE}" "${HEADERS_BASE_HTTP}" - "${HEADERS_CPU}" + "${HEADERS_BACKEND}" src/api/interfaces/IApiListener.h src/App.h src/common/Platform.h @@ -45,7 +45,7 @@ set(HEADERS src/net/strategies/DonateStrategy.h src/Summary.h src/version.h - src/workers/CpuThread.h + src/workers/CpuThreadLegacy.h src/workers/Hashrate.h src/workers/MultiWorker.h src/workers/ThreadHandle.h @@ -83,7 +83,7 @@ endif() set(SOURCES "${SOURCES_BASE}" "${SOURCES_BASE_HTTP}" - "${SOURCES_CPU}" + "${SOURCES_BACKEND}" src/App.cpp src/common/Platform.cpp src/core/config/Config.cpp @@ -94,7 +94,7 @@ set(SOURCES src/net/NetworkState.cpp src/net/strategies/DonateStrategy.cpp src/Summary.cpp - src/workers/CpuThread.cpp + src/workers/CpuThreadLegacy.cpp src/workers/Hashrate.cpp src/workers/MultiWorker.cpp src/workers/ThreadHandle.cpp diff --git a/src/backend/Threads.cpp b/src/backend/Threads.cpp new file mode 100644 index 00000000..11e1ec15 --- /dev/null +++ b/src/backend/Threads.cpp @@ -0,0 +1,145 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + + +#include "backend/cpu/CpuThread.h" +#include "backend/Threads.h" +#include "rapidjson/document.h" + + +template +const std::vector &xmrig::Threads::get(const String &profileName) const +{ + static std::vector empty; + if (profileName.isNull() || !has(profileName)) { + return empty; + } + + return m_profiles.at(profileName); +} + + +template +xmrig::String xmrig::Threads::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 +void xmrig::Threads::read(const rapidjson::Value &value) +{ + using namespace rapidjson; + + for (auto &member : value.GetObject()) { + if (member.value.IsArray()) { + std::vector 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 +void xmrig::Threads::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; + +} // namespace xmrig diff --git a/src/backend/Threads.h b/src/backend/Threads.h new file mode 100644 index 00000000..70bc02a4 --- /dev/null +++ b/src/backend/Threads.h @@ -0,0 +1,67 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + +#ifndef XMRIG_THREADS_H +#define XMRIG_THREADS_H + + +#include +#include + + +#include "base/tools/String.h" +#include "crypto/common/Algorithm.h" +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +template +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 &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 &&threads) { m_profiles.insert({ profile, threads }); } + + const std::vector &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 m_aliases; + std::map > m_profiles; + std::set m_disabled; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_THREADS_H */ diff --git a/src/backend/backend.cmake b/src/backend/backend.cmake new file mode 100644 index 00000000..750cc9cb --- /dev/null +++ b/src/backend/backend.cmake @@ -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 + ) diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 5284d607..34dcff44 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -31,17 +31,34 @@ namespace xmrig { - +static const char *kCn = "cn"; static const char *kEnabled = "enabled"; static const char *kHugePages = "huge-pages"; static const char *kHwAes = "hw-aes"; static const char *kPriority = "priority"; - #ifdef XMRIG_FEATURE_ASM static const char *kAsm = "asm"; #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; + } @@ -59,7 +76,6 @@ bool xmrig::CpuConfig::isHwAES() const rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; - auto &allocator = doc.GetAllocator(); Value obj(kObjectType); @@ -73,6 +89,8 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator); # endif + m_threads.toJSON(obj, doc); + return obj; } @@ -89,6 +107,34 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value) # ifdef XMRIG_FEATURE_ASM m_assembly = Json::getValue(value, kAsm); # 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 } } diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 04dd9175..66da3a5f 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -26,6 +26,8 @@ #define XMRIG_CPUCONFIG_H +#include "backend/cpu/CpuThread.h" +#include "backend/Threads.h" #include "crypto/common/Assembly.h" @@ -47,11 +49,12 @@ public: rapidjson::Value toJSON(rapidjson::Document &doc) const; void read(const rapidjson::Value &value); - inline bool isEnabled() const { return m_enabled; } - inline bool isHugePages() const { return m_hugePages; } - inline bool isShouldSave() const { return m_shouldSave; } - inline const Assembly &assembly() const { return m_assembly; } - inline int priority() const { return m_priority; } + inline bool isEnabled() const { return m_enabled; } + inline bool isHugePages() const { return m_hugePages; } + inline bool isShouldSave() const { return m_shouldSave; } + inline const Assembly &assembly() const { return m_assembly; } + inline const Threads &threads() const { return m_threads; } + inline int priority() const { return m_priority; } private: void setAesMode(const rapidjson::Value &aesMode); @@ -63,6 +66,7 @@ private: bool m_hugePages = true; bool m_shouldSave = false; int m_priority = -1; + Threads m_threads; }; diff --git a/src/backend/cpu/CpuThread.cpp b/src/backend/cpu/CpuThread.cpp new file mode 100644 index 00000000..e7132cfa --- /dev/null +++ b/src/backend/cpu/CpuThread.cpp @@ -0,0 +1,71 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + + +#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); +} diff --git a/src/backend/cpu/CpuThread.h b/src/backend/cpu/CpuThread.h new file mode 100644 index 00000000..444b2709 --- /dev/null +++ b/src/backend/cpu/CpuThread.h @@ -0,0 +1,63 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * 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 . + */ + +#ifndef XMRIG_CPUTHREADCONFIG_H +#define XMRIG_CPUTHREADCONFIG_H + + +#include + + +#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 CpuThreads; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_CPUTHREADCONFIG_H */ diff --git a/src/backend/cpu/cpu.cmake b/src/backend/cpu/cpu.cmake index 03ca7075..df9b7cea 100644 --- a/src/backend/cpu/cpu.cmake +++ b/src/backend/cpu/cpu.cmake @@ -1,12 +1,14 @@ set(HEADERS_CPU - src/backend/cpu/Cpu.h - src/backend/cpu/CpuConfig.h - src/backend/cpu/interfaces/ICpuInfo.h + src/backend/cpu/Cpu.h + src/backend/cpu/CpuConfig.h + src/backend/cpu/CpuThread.h + src/backend/cpu/interfaces/ICpuInfo.h ) set(SOURCES_CPU src/backend/cpu/Cpu.cpp src/backend/cpu/CpuConfig.cpp + src/backend/cpu/CpuThread.cpp ) diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index abff7a6c..74f6baee 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -26,11 +26,9 @@ #define XMRIG_CPUINFO_H -#include -#include - - +#include "backend/cpu/CpuThread.h" #include "crypto/common/Assembly.h" +#include "crypto/common/Algorithm.h" namespace xmrig { @@ -47,18 +45,19 @@ public: inline constexpr static bool isX64() { return false; } # endif + virtual Assembly::Id assembly() const = 0; virtual bool hasAES() const = 0; virtual bool hasAVX2() const = 0; virtual bool isSupported() const = 0; virtual const char *brand() const = 0; - virtual int32_t cores() const = 0; - virtual int32_t L2() const = 0; - virtual int32_t L3() const = 0; - virtual int32_t nodes() const = 0; - virtual int32_t sockets() const = 0; - virtual int32_t threads() const = 0; + virtual CpuThreads threads(const Algorithm &algorithm) const = 0; + virtual size_t cores() const = 0; + virtual size_t L2() const = 0; + virtual size_t L3() const = 0; + virtual size_t nodes() 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; }; diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.cpp b/src/backend/cpu/platform/AdvancedCpuInfo.cpp index fc7f734d..4c3b30ab 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.cpp +++ b/src/backend/cpu/platform/AdvancedCpuInfo.cpp @@ -26,51 +26,43 @@ #include #include +#include + #include "backend/cpu/platform/AdvancedCpuInfo.h" xmrig::AdvancedCpuInfo::AdvancedCpuInfo() : - m_aes(false), - m_avx2(false), - m_L2_exclusive(false), - m_brand(), - m_cores(0), - m_L2(0), - m_L3(0), - m_sockets(1), - m_threads(0) + m_brand() { - struct cpu_raw_data_t raw = { 0 }; - struct cpu_id_t data = { 0 }; + struct cpu_raw_data_t raw = {}; + struct cpu_id_t data = {}; cpuid_get_raw_data(&raw); cpu_identify(&raw, &data); strncpy(m_brand, data.brand_str, sizeof(m_brand)); - m_threads = data.total_logical_cpus; - m_sockets = threads() / data.num_logical_cpus; - if (m_sockets == 0) { - m_sockets = 1; - } + m_threads = static_cast(data.total_logical_cpus); + m_sockets = std::max(threads() / static_cast(data.num_logical_cpus), 1); + m_cores = static_cast(data.num_cores) * m_sockets; + m_L3 = data.l3_cache > 0 ? static_cast(data.l3_cache) * m_sockets : 0; - m_cores = data.num_cores * m_sockets; - m_L3 = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0; + const size_t l2 = static_cast(data.l2_cache); // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 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; } // 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. 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; - m_L2 = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; + size_t l2_count_per_socket = cores() > 1 ? cores() / 2 : 1; + m_L2 = data.l2_cache > 0 ? l2 * l2_count_per_socket * m_sockets : 0; } 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]) { @@ -125,3 +117,43 @@ size_t xmrig::AdvancedCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsa 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(std::min(count, threads()), 1)); +} diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.h b/src/backend/cpu/platform/AdvancedCpuInfo.h index 83c3d8e5..9852f6bd 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.h +++ b/src/backend/cpu/platform/AdvancedCpuInfo.h @@ -39,30 +39,31 @@ public: protected: 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 bool hasAES() const override { return m_aes; } inline bool hasAVX2() const override { return m_avx2; } inline bool isSupported() const override { return true; } inline const char *brand() const override { return m_brand; } - inline int32_t cores() const override { return m_cores; } - inline int32_t L2() const override { return m_L2; } - inline int32_t L3() const override { return m_L3; } - inline int32_t nodes() const override { return -1; } - inline int32_t sockets() const override { return m_sockets; } - inline int32_t threads() const override { return m_threads; } + inline size_t cores() const override { return m_cores; } + inline size_t L2() const override { return m_L2; } + inline size_t L3() const override { return m_L3; } + inline size_t nodes() const override { return 0; } + inline size_t sockets() const override { return m_sockets; } + inline size_t threads() const override { return m_threads; } private: Assembly m_assembly; - bool m_aes; - bool m_avx2; - bool m_L2_exclusive; + bool m_aes = false; + bool m_avx2 = false; + bool m_L2_exclusive = false; char m_brand[64]; - int32_t m_cores; - int32_t m_L2; - int32_t m_L3; - int32_t m_sockets; - int32_t m_threads; + size_t m_cores = 0; + size_t m_L2 = 0; + size_t m_L3 = 0; + size_t m_sockets = 1; + size_t m_threads = 0; }; diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index 04ff589b..26237468 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -22,6 +22,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -123,9 +124,9 @@ static inline bool has_ossave() xmrig::BasicCpuInfo::BasicCpuInfo() : m_assembly(Assembly::NONE), + m_brand(), m_aes(has_aes_ni()), m_avx2(has_avx2() && has_ossave()), - m_brand(), m_threads(std::thread::hardware_concurrency()) { cpu_brand_string(m_brand); @@ -158,3 +159,27 @@ size_t xmrig::BasicCpuInfo::optimalThreadsCount(size_t memSize, int maxCpuUsage) 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(threads() / 4, 1)); + } + + return CpuThreads(std::max(threads() / 2, 1)); +} diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index 4d4a5163..12c275dd 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -39,25 +39,26 @@ public: protected: 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 bool hasAES() const override { return m_aes; } inline bool hasAVX2() const override { return m_avx2; } inline bool isSupported() const override { return true; } inline const char *brand() const override { return m_brand; } - inline int32_t cores() const override { return -1; } - inline int32_t L2() const override { return -1; } - inline int32_t L3() const override { return -1; } - inline int32_t nodes() const override { return -1; } - inline int32_t sockets() const override { return 1; } - inline int32_t threads() const override { return m_threads; } + inline size_t cores() const override { return 0; } + inline size_t L2() const override { return 0; } + inline size_t L3() const override { return 0; } + inline size_t nodes() const override { return 0; } + inline size_t sockets() const override { return 1; } + inline size_t threads() const override { return m_threads; } private: Assembly m_assembly; - bool m_aes; - bool m_avx2; - char m_brand[64]; - int32_t m_threads; + char m_brand[64 + 6]; + const bool m_aes; + const bool m_avx2; + const size_t m_threads; }; diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index 33f4cc44..87abbb91 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -36,7 +36,7 @@ #include "rapidjson/document.h" #include "rapidjson/filewritestream.h" #include "rapidjson/prettywriter.h" -#include "workers/CpuThread.h" +#include "workers/CpuThreadLegacy.h" xmrig::Config::Config() : @@ -125,7 +125,7 @@ bool xmrig::Config::finalize() 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_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; @@ -134,7 +134,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; // FIXME MEMORY + const size_t size = CpuThreadLegacy::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; // FIXME MEMORY if (!m_threads.count) { 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) { - 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; @@ -175,7 +175,7 @@ void xmrig::Config::setThreads(const rapidjson::Value &threads) } if (value.HasMember("low_power_mode")) { - auto data = CpuThread::parse(value); + auto data = CpuThreadLegacy::parse(value); if (data.valid) { m_threads.cpu.push_back(std::move(data)); diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 76720889..7b765892 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -34,7 +34,7 @@ #include "base/kernel/config/BaseConfig.h" #include "common/xmrig.h" #include "rapidjson/fwd.h" -#include "workers/CpuThread.h" +#include "workers/CpuThreadLegacy.h" namespace xmrig { @@ -59,7 +59,7 @@ public: void getJSON(rapidjson::Document &doc) const override; 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 std::vector &threads() const { return m_threads.list; } inline int threadsCount() const { return static_cast(m_threads.list.size()); } @@ -81,7 +81,7 @@ private: int64_t mask; size_t count; - std::vector cpu; + std::vector cpu; std::vector list; ThreadsMode mode; }; diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index 66b3ddda..81ee6655 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -30,6 +30,7 @@ #include +#include "crypto/cn/CnAlgo.h" #include "crypto/common/Algorithm.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) { switch (id) { diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h index 92c6f405..08d1c4cd 100644 --- a/src/crypto/common/Algorithm.h +++ b/src/crypto/common/Algorithm.h @@ -94,11 +94,14 @@ public: inline Family family() const { return family(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==(Algorithm::Id id) const { return m_id == id; } inline bool operator==(const Algorithm &other) const { return isEqual(other); } inline operator Algorithm::Id() const { return m_id; } rapidjson::Value toJSON() const; + size_t memory() const; static Family family(Id id); static Id parse(const char *name); diff --git a/src/crypto/common/Assembly.h b/src/crypto/common/Assembly.h index 0b3f29b3..afd8a536 100644 --- a/src/crypto/common/Assembly.h +++ b/src/crypto/common/Assembly.h @@ -59,10 +59,10 @@ public: 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::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::Id &id) const { return m_id == id; } inline operator Assembly::Id() const { return m_id; } private: diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThreadLegacy.cpp similarity index 78% rename from src/workers/CpuThread.cpp rename to src/workers/CpuThreadLegacy.cpp index 7011da12..df9b9904 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThreadLegacy.cpp @@ -31,14 +31,14 @@ #include "crypto/common/VirtualMemory.h" #include "Mem.h" #include "rapidjson/document.h" -#include "workers/CpuThread.h" +#include "workers/CpuThreadLegacy.h" 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_av(av), 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); } -bool xmrig::CpuThread::isSoftAES(AlgoVariant av) +bool xmrig::CpuThreadLegacy::isSoftAES(AlgoVariant av) { 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); @@ -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; 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); - return new CpuThread(index, algorithm, static_cast(av), multiway, data.affinity, priority, softAES, false, data.assembly); + return new CpuThreadLegacy(index, algorithm, static_cast(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; @@ -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) { case AV_SINGLE: @@ -172,7 +172,7 @@ xmrig::IThread::Multiway xmrig::CpuThread::multiway(AlgoVariant av) #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") ",", index(), static_cast(multiway()), static_cast(m_av)); @@ -187,7 +187,7 @@ void xmrig::CpuThread::print() const #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; @@ -206,7 +206,7 @@ rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const #endif -rapidjson::Value xmrig::CpuThread::toConfig(rapidjson::Document &doc) const +rapidjson::Value xmrig::CpuThreadLegacy::toConfig(rapidjson::Document &doc) const { using namespace rapidjson; diff --git a/src/workers/CpuThread.h b/src/workers/CpuThreadLegacy.h similarity index 83% rename from src/workers/CpuThread.h rename to src/workers/CpuThreadLegacy.h index a43a0c09..ed69d8ac 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThreadLegacy.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef XMRIG_CPUTHREAD_H -#define XMRIG_CPUTHREAD_H +#ifndef XMRIG_CPUTHREADLEGACY_H +#define XMRIG_CPUTHREADLEGACY_H #include "common/xmrig.h" @@ -37,7 +37,7 @@ struct cryptonight_ctx; namespace xmrig { -class CpuThread : public IThread +class CpuThreadLegacy : public IThread { public: 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; static bool isSoftAES(AlgoVariant av); - static CpuThread *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 *createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly); + 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 Multiway multiway(AlgoVariant av); @@ -106,4 +106,4 @@ private: } /* namespace xmrig */ -#endif /* XMRIG_CPUTHREAD_H */ +#endif /* XMRIG_CPUTHREADLEGACY_H */ diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 52e98e0a..0ac026bc 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -28,7 +28,7 @@ #include "crypto/cn/CryptoNight_test.h" -#include "workers/CpuThread.h" +#include "workers/CpuThreadLegacy.h" #include "workers/MultiWorker.h" #include "workers/Workers.h" diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index c6ea6d9a..4f69d905 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -26,7 +26,7 @@ #include "backend/cpu/Cpu.h" #include "common/Platform.h" -#include "workers/CpuThread.h" +#include "workers/CpuThreadLegacy.h" #include "workers/ThreadHandle.h" #include "workers/Worker.h" @@ -39,7 +39,7 @@ Worker::Worker(ThreadHandle *handle) : m_timestamp(0), m_count(0), m_sequence(0), - m_thread(static_cast(handle->config())) + m_thread(static_cast(handle->config())) { if (xmrig::Cpu::info()->threads() > 1 && m_thread->affinity() != -1L) { Platform::setThreadAffinity(m_thread->affinity()); diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 4710bcc5..3d40257d 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -37,7 +37,7 @@ class ThreadHandle; namespace xmrig { - class CpuThread; + class CpuThreadLegacy; } @@ -62,7 +62,7 @@ protected: std::atomic m_timestamp; uint64_t m_count; uint64_t m_sequence; - xmrig::CpuThread *m_thread; + xmrig::CpuThreadLegacy *m_thread; };