From ffa6bda1062cfd1be7fc5075fc2912b0979edd2b Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 26 Jul 2019 15:29:06 +0700 Subject: [PATCH] Added VirtualMemory::bindToNUMANode --- CMakeLists.txt | 1 + src/Summary.cpp | 16 ++++-- src/backend/common/Worker.cpp | 3 ++ src/backend/cpu/platform/HwlocCpuInfo.cpp | 7 +++ src/backend/cpu/platform/HwlocCpuInfo.h | 9 ++++ src/crypto/common/VirtualMemory.cpp | 66 +++++++++++++++++++++++ src/crypto/common/VirtualMemory.h | 1 + 7 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 src/crypto/common/VirtualMemory.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ef608422..42dcdb8d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,7 @@ set(SOURCES_CRYPTO src/crypto/common/Algorithm.cpp src/crypto/common/keccak.cpp src/crypto/common/Nonce.cpp + src/crypto/common/VirtualMemory.cpp ) if (WIN32) diff --git a/src/Summary.cpp b/src/Summary.cpp index 7b22ab348..ab6b7b1ec 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -62,7 +62,7 @@ inline static const char *asmName(Assembly::Id assembly) static void print_memory(Config *) { # ifdef _WIN32 Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s", - "HUGE PAGES", VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("available") : RED_BOLD("unavailable")); + "HUGE PAGES", VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable")); # endif } @@ -71,22 +71,28 @@ static void print_cpu(Config *) { const ICpuInfo *info = Cpu::info(); - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%zu/%zu)") " %sx64 %sAES %sAVX2", + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%zu)") " %sx64 %sAES %sAVX2", "CPU", info->brand(), info->packages(), - info->nodes(), info->isX64() ? GREEN_BOLD_S : RED_BOLD_S "-", info->hasAES() ? GREEN_BOLD_S : RED_BOLD_S "-", info->hasAVX2() ? GREEN_BOLD_S : RED_BOLD_S "-" ); # if defined(XMRIG_FEATURE_LIBCPUID) || defined (XMRIG_FEATURE_HWLOC) - Log::print(WHITE_BOLD(" %-13s") BLACK_BOLD("L2:") WHITE_BOLD("%.1f MB") BLACK_BOLD(" L3:") WHITE_BOLD("%.1f MB") BLACK_BOLD(" cores:") CYAN_BOLD("%zu") BLACK_BOLD(" threads:") CYAN_BOLD("%zu"), - "", + Log::print(WHITE_BOLD(" %-13s") BLACK_BOLD("L2:") WHITE_BOLD("%.1f MB") BLACK_BOLD(" L3:") WHITE_BOLD("%.1f MB") + CYAN_BOLD(" %zu") "C" BLACK_BOLD("/") CYAN_BOLD("%zu") "T" +# ifdef XMRIG_FEATURE_HWLOC + BLACK_BOLD(" NUMA:") CYAN_BOLD("%zu") +# endif + , "", info->L2() / 1048576.0, info->L3() / 1048576.0, info->cores(), info->threads() +# ifdef XMRIG_FEATURE_HWLOC + , info->nodes() +# endif ); # else Log::print(WHITE_BOLD(" %-13s") BLACK_BOLD("threads:") CYAN_BOLD("%zu"), diff --git a/src/backend/common/Worker.cpp b/src/backend/common/Worker.cpp index 5676f2c49..92438b39f 100644 --- a/src/backend/common/Worker.cpp +++ b/src/backend/common/Worker.cpp @@ -27,6 +27,7 @@ #include "backend/common/Worker.h" #include "base/kernel/Platform.h" #include "base/tools/Chrono.h" +#include "crypto/common/VirtualMemory.h" xmrig::Worker::Worker(size_t id, int64_t affinity, int priority) : @@ -36,7 +37,9 @@ xmrig::Worker::Worker(size_t id, int64_t affinity, int priority) : m_timestamp(0), m_count(0) { + VirtualMemory::bindToNUMANode(affinity); Platform::trySetThreadAffinity(affinity); + Platform::setThreadPriority(priority); } diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 13ff1ee67..253d51085 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -38,6 +38,9 @@ namespace xmrig { +uint32_t HwlocCpuInfo::m_features = 0; + + static inline bool isCacheObject(hwloc_obj_t obj) { # if HWLOC_API_VERSION >= 0x20000 @@ -147,6 +150,10 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(), m_cores = countByType(m_topology, HWLOC_OBJ_CORE); m_nodes = std::max(countByType(m_topology, HWLOC_OBJ_NUMANODE), 1); m_packages = countByType(m_topology, HWLOC_OBJ_PACKAGE); + + if (nodes() > 1 && hwloc_topology_get_support(m_topology)->membind->set_thisthread_membind) { + m_features |= SET_THISTHREAD_MEMBIND; + } } diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index 4ba0f2fb1..a5678fa94 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.h +++ b/src/backend/cpu/platform/HwlocCpuInfo.h @@ -39,9 +39,16 @@ namespace xmrig { class HwlocCpuInfo : public BasicCpuInfo { public: + enum Feature : uint32_t { + SET_THISTHREAD_MEMBIND = 1 + }; + + HwlocCpuInfo(); ~HwlocCpuInfo() override; + static inline bool has(Feature feature) { return m_features & feature; } + protected: CpuThreads threads(const Algorithm &algorithm) const override; @@ -55,6 +62,8 @@ protected: private: void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads) const; + static uint32_t m_features; + char m_backend[20]; hwloc_topology_t m_topology; size_t m_cache[5]; diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp new file mode 100644 index 000000000..285bdf80d --- /dev/null +++ b/src/crypto/common/VirtualMemory.cpp @@ -0,0 +1,66 @@ +/* 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 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2018-2019 tevador + * 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 . + */ + + +#ifdef XMRIG_FEATURE_HWLOC +# include +# include "backend/cpu/platform/HwlocCpuInfo.h" +#endif + + +#include "base/io/log/Log.h" +#include "crypto/common/VirtualMemory.h" + + +void xmrig::VirtualMemory::bindToNUMANode(int64_t affinity) +{ +# ifdef XMRIG_FEATURE_HWLOC + if (affinity < 0 || !HwlocCpuInfo::has(HwlocCpuInfo::SET_THISTHREAD_MEMBIND)) { + return; + } + + hwloc_topology_t topology; + hwloc_topology_init(&topology); + hwloc_topology_load(topology); + + const int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); + const unsigned puId = static_cast(affinity); + + for (unsigned i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); i++) { + hwloc_obj_t pu = hwloc_get_obj_by_depth(topology, depth, i); + + if (pu->os_index == puId) { + if (hwloc_set_membind_nodeset(topology, pu->nodeset, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_THREAD) < 0) { + LOG_WARN("CPU #%02u warning: \"can't bind memory\"", puId); + } + + break; + } + } + + hwloc_topology_destroy(topology); +# endif +} diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index 44f77a23d..b6ea680a0 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -54,6 +54,7 @@ public: static void *allocateExecutableMemory(size_t size); static void *allocateLargePagesMemory(size_t size); + static void bindToNUMANode(int64_t affinity); static void flushInstructionCache(void *p, size_t size); static void freeLargePagesMemory(void *p, size_t size); static void init(bool hugePages);