diff --git a/hwlocMemory.hpp b/hwlocMemory.hpp new file mode 100644 index 0000000..b9972ce --- /dev/null +++ b/hwlocMemory.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "console.h" + +#ifndef CONF_NO_HWLOC + +#include + +/** pin memory to NUMA node + * + * Set the default memory policy for the current thread to bind memory to the + * NUMA node. + * + * @param puId core id + */ +void bindMemoryToNUMANode( int puId ) +{ + int depth; + hwloc_topology_t topology; + hwloc_obj_t obj; + + hwloc_topology_init(&topology); + hwloc_topology_load(topology); + + depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); + + for( int 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( 0 > hwloc_set_membind_nodeset( + topology, + pu->nodeset, + HWLOC_MEMBIND_BIND, + HWLOC_MEMBIND_THREAD) + ) + printer::inst()->print_msg(L0, "hwloc: can't bind memory"); + else + { + printer::inst()->print_msg(L0, "hwloc: memory pinned"); + break; + } + } +} +#else + +void bindMemoryToNUMANode( int ) +{ +} + +#endif diff --git a/minethd.cpp b/minethd.cpp index 199779e..a4f9ef7 100644 --- a/minethd.cpp +++ b/minethd.cpp @@ -64,6 +64,7 @@ void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id) #include "minethd.h" #include "jconf.h" #include "crypto/cryptonight_aesni.h" +#include "hwlocMemory.hpp" telemetry::telemetry(size_t iThd) { @@ -140,7 +141,7 @@ void telemetry::push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTime iBucketTop[iThd] = (iTop + 1) & iBucketMask; } -minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch) +minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch, int affinity) { oWork = pWork; bQuit = 0; @@ -149,6 +150,7 @@ minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefet iHashCount = 0; iTimestamp = 0; bNoPrefetch = no_prefetch; + this->affinity = affinity; if(double_work) oWorkThd = std::thread(&minethd::double_work_main, this); @@ -295,7 +297,7 @@ std::vector* minethd::thread_starter(miner_work& pWork) { jconf::inst()->GetThreadConfig(i, cfg); - minethd* thd = new minethd(pWork, i, cfg.bDoubleMode, cfg.bNoPrefetch); + minethd* thd = new minethd(pWork, i, cfg.bDoubleMode, cfg.bNoPrefetch, cfg.iCpuAff); if(cfg.iCpuAff >= 0) { @@ -361,6 +363,9 @@ minethd::cn_hash_fun minethd::func_selector(bool bHaveAes, bool bNoPrefetch) void minethd::work_main() { + // pin memory to NUMA node + bindMemoryToNUMANode(this->affinity); + cn_hash_fun hash_fun; cryptonight_ctx* ctx; uint64_t iCount = 0; @@ -448,6 +453,9 @@ minethd::cn_hash_fun_dbl minethd::func_dbl_selector(bool bHaveAes, bool bNoPrefe void minethd::double_work_main() { + // pin memory to NUMA node + bindMemoryToNUMANode(this->affinity); + cn_hash_fun_dbl hash_fun; cryptonight_ctx* ctx0; cryptonight_ctx* ctx1; diff --git a/minethd.h b/minethd.h index 6ba269e..3543b85 100644 --- a/minethd.h +++ b/minethd.h @@ -97,11 +97,13 @@ public: std::atomic iHashCount; std::atomic iTimestamp; + int affinity; + private: typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*); typedef void (*cn_hash_fun_dbl)(const void*, size_t, void*, cryptonight_ctx* __restrict, cryptonight_ctx* __restrict); - minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch); + minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch, int affinity); // We use the top 10 bits of the nonce for thread and resume // This allows us to resume up to 128 threads 4 times before