summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfireice-uk <fireice-uk@users.noreply.github.com>2017-05-24 14:43:39 +0100
committerGitHub <noreply@github.com>2017-05-24 14:43:39 +0100
commitee2a2d77ecf5e20cd323443497de38d45ebb580c (patch)
tree6e48f3fe18fe53780c8a3537b7dff86f64013489
parent8f51236e6743849bd3737d633f9716607b7427d1 (diff)
parente8a8cca0fb9663761d67ae3f2ed159f3701b4f50 (diff)
downloadxmr-stak-ee2a2d77ecf5e20cd323443497de38d45ebb580c.zip
xmr-stak-ee2a2d77ecf5e20cd323443497de38d45ebb580c.tar.gz
Merge pull request #108 from psychocrypt/topic-hwloc
hwloc autoadjust
-rw-r--r--CMakeLists.txt23
-rw-r--r--README.md9
-rw-r--r--autoAdjustHwloc.hpp209
-rw-r--r--cli-miner.cpp6
4 files changed, 243 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2373d85..876d68d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,6 +78,29 @@ else()
endif()
################################################################################
+# Find hwloc
+################################################################################
+
+option(HWLOC_ENABLE "Enable or disable the requirement of hwloc" ON)
+if(HWLOC_ENABLE)
+ find_path(HWLOC_INCLUDE_DIR hwloc.h
+ $ENV{HWLOC_ROOT}/inlcude
+ /opt/local/include
+ /usr/local/include
+ /usr/include
+ )
+ find_library(HWLOC NAMES hwloc)
+ if("${HWLOC}" STREQUAL "MHTD-NOTFOUND" OR ${HWLOC_INCLUDE_DIR} STREQUAL "HWLOC_INCLUDE_DIR-NOTFOUND")
+ message(FATAL_ERROR "hwloc NOT found: use `-DHWLOC_ENABLE=OFF` to build without hwloc support")
+ else()
+ set(LIBS ${LIBS} ${HWLOC})
+ include_directories(AFTER ${HWLOC_INCLUDE_DIR})
+ endif()
+else()
+ add_definitions("-DCONF_NO_HWLOC")
+endif()
+
+################################################################################
# Compile & Link
################################################################################
diff --git a/README.md b/README.md
index 4c202f6..977e779 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ xXl2Nm/u3cPP/eQVrZz5H8eACwIv+LL1EV+9uLanWUa+IO5hHr3KElvKNKD6vN0=
### GNU Compiler
```
- sudo apt-get install libmicrohttpd-dev libssl-dev cmake build-essential
+ sudo apt-get install libmicrohttpd-dev libssl-dev cmake build-essential libhwloc-dev
cmake .
make install
```
@@ -171,9 +171,12 @@ and install.
- `MICROHTTPD_ENABLE` allow to disable/enable the dependency *microhttpd*
- by default enabled
- there is no *http* interface available if option is disabled: `cmake . -DMICROHTTPD_ENABLE=OFF`
-- `OpenSSL_ENABLE`allow to disable/enable the dependency *OpenSSL*
+- `OpenSSL_ENABLE` allow to disable/enable the dependency *OpenSSL*
- by default enabled
- - it is not possible to connect to a *https* secured pool if optin is disabled: `cmake . -DOpenSSL_ENABLE=OFF`
+ - it is not possible to connect to a *https* secured pool if option is disabled: `cmake . -DOpenSSL_ENABLE=OFF`
+- `HWLOC_ENABLE` allow to disable/enable the dependency *hwloc*
+ - by default enabled
+ - the config suggestion is not optimal if option is disabled: `cmake . -DHWLOC_ENABLE=OFF`
## PGP Key
```
diff --git a/autoAdjustHwloc.hpp b/autoAdjustHwloc.hpp
new file mode 100644
index 0000000..07c3b4a
--- /dev/null
+++ b/autoAdjustHwloc.hpp
@@ -0,0 +1,209 @@
+#pragma once
+
+#include "console.h"
+#include <hwloc.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif // _WIN32
+
+class autoAdjust
+{
+public:
+
+ autoAdjust()
+ {
+ }
+
+ void printConfig()
+ {
+ printer::inst()->print_str("The configuration for 'cpu_threads_conf' in your config file is 'null'.\n");
+ printer::inst()->print_str("The miner evaluates your system and prints a suggestion for the section `cpu_threads_conf` to the terminal.\n");
+ printer::inst()->print_str("The values are not optimal, please try to tweak the values based on notes in config.txt.\n");
+ printer::inst()->print_str("Please copy & paste the block within the asterisks to your config.\n\n");
+ printer::inst()->print_str("\n**************** Copy&Paste ****************\n\n");
+ printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
+
+ int depth;
+ hwloc_topology_t topology;
+ hwloc_obj_t socket;
+
+
+ hwloc_topology_init(&topology);
+ hwloc_topology_load(topology);
+
+ depth = hwloc_get_type_depth(topology, HWLOC_OBJ_SOCKET);
+ if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
+ {
+ printf("*** The number of sockets is unknown\n");
+ }
+
+ for (int i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); i++)
+ {
+ socket = hwloc_get_obj_by_depth(topology, depth, i);
+
+ // search cacheprinter::inst()->print_str("\n**************** Copy&Paste ****************\n\n");
+ for (int j = 0; j < socket->arity; j++)
+ {
+ hwloc_obj_t nextLvl = socket->children[j];
+ findCache(topology, nextLvl);
+ }
+ }
+
+ /* Destroy topology object. */
+ hwloc_topology_destroy(topology);
+
+ printer::inst()->print_str("],\n\n**************** Copy&Paste ****************\n");
+ }
+
+private:
+
+ /** count bits with ones */
+ template<typename T>
+ int compat_popcnt(T x)
+ {
+ int count = 0;
+ for( int i = 0; i < sizeof(T) - 1; ++i )
+ if( ( ( x >> i ) & 1 ) == 1 )
+ ++count;
+ return count;
+ }
+
+ int rightZeros(size_t v)
+ {
+ int c;
+ if (v)
+ {
+ v = (v ^ (v - 1)) >> 1;
+ for (c = 0; v; c++)
+ {
+ v >>= 1;
+ }
+ }
+ else
+ {
+ c = CHAR_BIT * sizeof (v);
+ }
+ return c;
+ }
+
+ inline void getConfig(hwloc_topology_t topology, hwloc_obj_t obj, size_t& numHashes, int& numCachesLeft)
+ {
+ if (obj->type == HWLOC_OBJ_CORE)
+ {
+ if (obj)
+ {
+ hwloc_cpuset_t cpuset;
+ /* Get a copy of its cpuset that we may modify. */
+ cpuset = hwloc_bitmap_dup(obj->cpuset);
+ size_t allcpu = hwloc_bitmap_to_ulong(cpuset);
+ /* Get only one logical processor (in case the core is
+ SMT/hyperthreaded). */
+ hwloc_bitmap_singlify(cpuset);
+
+
+ size_t cpu = hwloc_bitmap_to_ulong(cpuset);
+ // move bit mask to right to allow to compare always the first bit
+ cpu >>= rightZeros(allcpu);
+
+
+ int nativeCores = compat_popcnt(cpu);
+ int numPus = obj->arity;
+ for (int i = 0; i < numPus && numHashes != 0; i++)
+ {
+ hwloc_obj_t pu = obj->children[i];
+ // only use native pu's
+ if (pu->type == HWLOC_OBJ_PU && cpu & 1)
+ {
+ // if no cache is available we give each native core a hash
+ int numUnit = numCachesLeft != 0 ? numCachesLeft : nativeCores;
+
+ // two hashes per native pu if number of hashes if larger than compute units
+ int power = numHashes > numUnit ? 2 : 1;
+ char strbuf[256];
+ //printf("------------------------------core %i -> %i mpu=%i %lu\n", pu->os_index, power, nativeCores, numHashes);
+ snprintf(strbuf, sizeof(strbuf), " { \"low_power_mode\" : %s, \"no_prefetch\" : true, \"affine_to_cpu\" : %u },\n",
+ power == 2 ? "true" : "false", pu->os_index);
+ printer::inst()->print_str(strbuf);
+
+ // update number of free hashes
+ numHashes -= power;
+ cpu >>= 1;
+
+ // one cache is filled with hashes
+ if (numCachesLeft != 0) numCachesLeft--;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < obj->arity; i++)
+ getConfig(topology, obj->children[i], numHashes, numCachesLeft);
+ }
+ }
+
+ inline void findCache(hwloc_topology_t topology, hwloc_obj_t obj)
+ {
+ if (obj->type == HWLOC_OBJ_CACHE)
+ {
+ size_t cacheSize = obj->attr->cache.size;
+ size_t numHashL3 = ( cacheSize + m_scratchPadMemSize/ 2llu ) / m_scratchPadMemSize;
+
+ /* check cache is exclusive or inclusive */
+ const char* value = hwloc_obj_get_info_by_name(obj, "Inclusive");
+
+
+ bool doL3 = true;
+ if (value == NULL || value[0] != 49 || cacheSize == 0)
+ {
+ size_t numHashes = 0;
+ int numL2 = obj->arity;
+ for (int k = 0; k < numL2; k++)
+ {
+ hwloc_obj_t l3Cache = obj->children[k];
+ size_t l2Cache = 0;
+
+ if (obj->type == HWLOC_OBJ_CACHE)
+ l2Cache = l3Cache->attr->cache.size;
+ else
+ break;
+
+ if (l2Cache < m_scratchPadMemSize)
+ {
+ // we need to start from L3
+ break;
+ }
+
+ // start from L2
+
+ /* if more hashes available than objects in the current depth of the topology
+ * than divide with round down else round up
+ */
+ int extraHash = numHashL3 > numL2 ? numHashL3 / numL2 : (numHashL3 + numL2 - 1) / numL2;
+ numHashL3 -= extraHash;
+ if (numHashL3 < 0)
+ numHashL3 = 0;
+ numHashes += extraHash;
+ //add L2 hashes
+ numHashes += ( l2Cache + m_scratchPadMemSize / 2llu ) / m_scratchPadMemSize;
+ int numCachesLeft = numL2;
+ getConfig(topology, l3Cache, numHashes, numCachesLeft);
+ doL3 = false;
+ }
+ }
+ if (doL3)
+ {
+ int numCachesLeft = obj->arity;
+ getConfig(topology, obj, numHashL3, numCachesLeft);
+ }
+ }
+ else
+ for (int j = 0; j < obj->arity; j++)
+ findCache(topology, obj->children[j]);
+ }
+
+ static constexpr size_t m_scratchPadMemSize = ( 2llu * 1024llu * 1024llu );
+};
diff --git a/cli-miner.cpp b/cli-miner.cpp
index 70a5228..2cbe6d9 100644
--- a/cli-miner.cpp
+++ b/cli-miner.cpp
@@ -26,7 +26,11 @@
#include "jconf.h"
#include "console.h"
#include "donate-level.h"
-#include "autoAdjust.hpp"
+#ifndef CONF_NO_HWLOC
+# include "autoAdjustHwloc.hpp"
+#else
+# include "autoAdjust.hpp"
+#endif
#include "version.h"
#ifndef CONF_NO_HTTPD
OpenPOWER on IntegriCloud