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

@ -26,51 +26,43 @@
#include <math.h>
#include <string.h>
#include <stdio.h>
#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<size_t>(data.total_logical_cpus);
m_sockets = std::max<size_t>(threads() / static_cast<size_t>(data.num_logical_cpus), 1);
m_cores = static_cast<size_t>(data.num_cores) * m_sockets;
m_L3 = data.l3_cache > 0 ? static_cast<size_t>(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<size_t>(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<size_t>(std::min<size_t>(count, threads()), 1));
}

View file

@ -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;
};

View file

@ -22,6 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <string.h>
#include <thread>
@ -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<size_t>(threads() / 4, 1));
}
return CpuThreads(std::max<size_t>(threads() / 2, 1));
}

View file

@ -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;
};