summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--autoAdjust.hpp138
-rw-r--r--cli-miner.cpp9
-rw-r--r--config.txt22
-rw-r--r--jconf.cpp88
-rw-r--r--jconf.h3
5 files changed, 210 insertions, 50 deletions
diff --git a/autoAdjust.hpp b/autoAdjust.hpp
new file mode 100644
index 0000000..8414b3e
--- /dev/null
+++ b/autoAdjust.hpp
@@ -0,0 +1,138 @@
+#pragma once
+#include "jconf.h"
+#include "console.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif // _WIN32
+
+int32_t get_masked(int32_t val, int32_t h, int32_t l)
+{
+ val &= (0x7FFFFFFF >> (31-(h-l))) << l;
+ return val >> l;
+}
+
+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");
+
+ int32_t L3KB_size = 0;
+
+ if(!detectL3Size(L3KB_size))
+ return;
+
+ if(L3KB_size < 1024 || L3KB_size > 102400)
+ {
+ printer::inst()->print_msg(L0, "Autoconf failed: L3 size sanity check failed %u.", L3KB_size);
+ return;
+ }
+
+ printer::inst()->print_msg(L0, "Autoconf L3 size detected at %u.", L3KB_size);
+
+ uint32_t corecnt;
+ bool linux_layout;
+
+ detectCPUConf(corecnt, linux_layout);
+
+ printer::inst()->print_msg(L0, "Autoconf cores detected at %u on %s.", corecnt,
+ linux_layout ? "Linux" : "Windows");
+
+ printer::inst()->print_str("\n**************** Copy&Paste ****************\n\n");
+ printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
+
+ uint32_t aff_id = 0;
+ char strbuf[256];
+ for(uint32_t i=0; i < corecnt; i++)
+ {
+ bool double_mode;
+
+ if(L3KB_size < 0)
+ break;
+
+ double_mode = L3KB_size / 2048 > (int32_t)(corecnt-i);
+
+ snprintf(strbuf, sizeof(strbuf), " { \"low_power_mode\" : %s, \"no_prefetch\" : true, \"affine_to_cpu\" : %u },\n",
+ double_mode ? "true" : "false", aff_id);
+ printer::inst()->print_str(strbuf);
+
+ if(linux_layout)
+ aff_id++;
+ else
+ aff_id += 2;
+
+ if(double_mode)
+ L3KB_size -= 4096;
+ else
+ L3KB_size -= 2048;
+ }
+
+ printer::inst()->print_str("]\n\n**************** Copy&Paste ****************\n");
+ }
+
+private:
+ bool detectL3Size(int32_t &l3kb)
+ {
+ int32_t cpu_info[4];
+ char cpustr[13] = {0};
+
+ jconf::cpuid(0, 0, cpu_info);
+ memcpy(cpustr, &cpu_info[1], 4);
+ memcpy(cpustr+4, &cpu_info[3], 4);
+ memcpy(cpustr+8, &cpu_info[2], 4);
+
+ if(strcmp(cpustr, "GenuineIntel") == 0)
+ {
+ jconf::cpuid(4, 3, cpu_info);
+
+ if(get_masked(cpu_info[0], 7, 5) != 3)
+ {
+ printer::inst()->print_msg(L0, "Autoconf failed: Couln't find L3 cache page.");
+ return false;
+ }
+
+ l3kb = ((get_masked(cpu_info[1], 31, 22) + 1) * (get_masked(cpu_info[1], 21, 12) + 1) *
+ (get_masked(cpu_info[1], 11, 0) + 1) * (cpu_info[2] + 1)) / 1024;
+
+ return true;
+ }
+ else if(strcmp(cpustr, "AuthenticAMD") == 0)
+ {
+ jconf::cpuid(0x80000006, 0, cpu_info);
+
+ l3kb = get_masked(cpu_info[3], 31, 18) * 512;
+
+ return true;
+ }
+ else
+ {
+ printer::inst()->print_msg(L0, "Autoconf failed: Unknown CPU type: %s.", cpustr);
+ return false;
+ }
+ }
+
+ void detectCPUConf(uint32_t &corecnt, bool &linux_layout)
+ {
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ corecnt = info.dwNumberOfProcessors;
+ linux_layout = false;
+#else
+ corecnt = sysconf(_SC_NPROCESSORS_ONLN);
+ linux_layout = true;
+#endif // _WIN32
+ }
+};
diff --git a/cli-miner.cpp b/cli-miner.cpp
index deb462e..38fb720 100644
--- a/cli-miner.cpp
+++ b/cli-miner.cpp
@@ -26,6 +26,7 @@
#include "jconf.h"
#include "console.h"
#include "donate-level.h"
+#include "autoAdjust.hpp"
#ifndef CONF_NO_HTTPD
# include "httpd.h"
@@ -99,6 +100,14 @@ int main(int argc, char *argv[])
return 0;
}
+ if(jconf::inst()->NeedsAutoconf())
+ {
+ autoAdjust adjust;
+ adjust.printConfig();
+ win_exit();
+ return 0;
+ }
+
if (!minethd::self_test())
{
win_exit();
diff --git a/config.txt b/config.txt
index 1530809..0dcb9e9 100644
--- a/config.txt
+++ b/config.txt
@@ -1,10 +1,3 @@
-/*
- * Number of threads. You can configure them below. Cryptonight uses 2MB of memory, so the optimal setting
- * here is the size of your L3 cache divided by 2. Intel mid-to-high end desktop processors have 2MB of L3
- * cache per physical core. Low end cpus can have 1.5 or 1 MB while Xeons can have 2, 2.5 or 3MB per core.
- */
-"cpu_thread_num" : 2,
-
/*
* Thread configuration for each thread. Make sure it matches the number above.
* low_power_mode - This mode will double the cache usage, and double the single thread performance. It will
@@ -19,11 +12,18 @@
* even or odd numbered cpu numbers. For Linux it will be usually the lower CPU numbers, so for a 4
* physical core CPU you should select cpu numbers 0-3.
*
+ * On the first run the miner will look at your system and suggest a basic configuration that will work,
+ * you can try to tweak it from there to get the best performance.
+ *
+ * A filled out configuration should look like this:
+ * "cpu_threads_conf" :
+ * [
+ * { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 0 },
+ * { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 1 },
+ * ],
*/
-"cpu_threads_conf" : [
- { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 0 },
- { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 1 },
-],
+"cpu_threads_conf" :
+null,
/*
* LARGE PAGE SUPPORT
diff --git a/jconf.cpp b/jconf.cpp
index 3e3a1d5..82750cc 100644
--- a/jconf.cpp
+++ b/jconf.cpp
@@ -45,7 +45,7 @@ using namespace rapidjson;
/*
* This enum needs to match index in oConfigValues, otherwise we will get a runtime error
*/
-enum configEnum { iCpuThreadNum, aCpuThreadsConf, sUseSlowMem, bNiceHashMode,
+enum configEnum { aCpuThreadsConf, sUseSlowMem, bNiceHashMode,
bTlsMode, bTlsSecureAlgo, sTlsFingerprint, sPoolAddr, sWalletAddr, sPoolPwd,
iCallTimeout, iNetRetry, iGiveUpLimit, iVerboseLevel, iAutohashTime,
sOutputFile, iHttpdPort, bPreferIpv4 };
@@ -56,10 +56,10 @@ struct configVal {
Type iType;
};
-//Same order as in configEnum, as per comment above
+// Same order as in configEnum, as per comment above
+// kNullType means any type
configVal oConfigValues[] = {
- { iCpuThreadNum, "cpu_thread_num", kNumberType },
- { aCpuThreadsConf, "cpu_threads_conf", kArrayType },
+ { aCpuThreadsConf, "cpu_threads_conf", kNullType },
{ sUseSlowMem, "use_slow_memory", kStringType },
{ bNiceHashMode, "nicehash_nonce", kTrueType },
{ bTlsMode, "use_tls", kTrueType },
@@ -84,6 +84,8 @@ inline bool checkType(Type have, Type want)
{
if(want == have)
return true;
+ else if(want == kNullType)
+ return true;
else if(want == kTrueType && have == kFalseType)
return true;
else if(want == kFalseType && have == kTrueType)
@@ -111,6 +113,9 @@ jconf::jconf()
bool jconf::GetThreadConfig(size_t id, thd_cfg &cfg)
{
+ if(!prv->configValues[aCpuThreadsConf]->IsArray())
+ return false;
+
if(id >= prv->configValues[aCpuThreadsConf]->Size())
return false;
@@ -206,7 +211,15 @@ bool jconf::PreferIpv4()
size_t jconf::GetThreadCount()
{
- return prv->configValues[aCpuThreadsConf]->Size();
+ if(prv->configValues[aCpuThreadsConf]->IsArray())
+ return prv->configValues[aCpuThreadsConf]->Size();
+ else
+ return 0;
+}
+
+bool jconf::NeedsAutoconf()
+{
+ return !prv->configValues[aCpuThreadsConf]->IsArray();
}
uint64_t jconf::GetCallTimeout()
@@ -249,38 +262,34 @@ const char* jconf::GetOutputFile()
return prv->configValues[sOutputFile]->GetString();
}
+void jconf::cpuid(uint32_t eax, int32_t ecx, int32_t val[4])
+{
+ memset(val, 0, sizeof(int32_t)*4);
+
+#ifdef _WIN32
+ __cpuidex(val, eax, ecx);
+#else
+ __cpuid_count(eax, ecx, val[0], val[1], val[2], val[3]);
+#endif
+}
+
bool jconf::check_cpu_features()
{
constexpr int AESNI_BIT = 1 << 25;
constexpr int SSE2_BIT = 1 << 26;
constexpr int BMI2_BIT = 1 << 8;
-
- int cpu_info[4];
+ int32_t cpu_info[4];
bool bHaveSse2;
-#ifdef _WIN32
- __cpuid(cpu_info, 1);
-#else
- __cpuid(1, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
-#endif
+ cpuid(1, 0, cpu_info);
bHaveAes = (cpu_info[2] & AESNI_BIT) != 0;
bHaveSse2 = (cpu_info[3] & SSE2_BIT) != 0;
-#ifdef _WIN32
- __cpuidex(cpu_info, 7, 0);
-#else
- __cpuid_count(7, 0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
-#endif
+ cpuid(7, 0, cpu_info);
bHaveBmi2 = (cpu_info[1] & BMI2_BIT) != 0;
- if(!bHaveAes)
- printer::inst()->print_msg(L0, "Your CPU doesn't support hardware AES. Don't expect high hashrates.");
-
- if(bHaveBmi2)
- printer::inst()->print_msg(L0, "CPU supports BMI2 instructions. Faster multiplication enabled.");
-
return bHaveSse2;
}
@@ -384,23 +393,8 @@ bool jconf::parse_config(const char* sFilename)
}
}
- size_t n_thd = prv->configValues[aCpuThreadsConf]->Size();
- if(prv->configValues[iCpuThreadNum]->GetUint64() != n_thd)
- {
- printer::inst()->print_msg(L0,
- "Invalid config file. Your CPU config array has %llu members, while you want to use %llu threads.",
- int_port(n_thd), int_port(prv->configValues[iCpuThreadNum]->GetUint64()));
- return false;
- }
-
- if(NiceHashMode() && n_thd >= 32)
- {
- printer::inst()->print_msg(L0, "You need to use less than 32 threads in NiceHash mode.");
- return false;
- }
-
thd_cfg c;
- for(size_t i=0; i < n_thd; i++)
+ for(size_t i=0; i < GetThreadCount(); i++)
{
if(!GetThreadConfig(i, c))
{
@@ -409,6 +403,12 @@ bool jconf::parse_config(const char* sFilename)
}
}
+ if(NiceHashMode() && GetThreadCount() >= 32)
+ {
+ printer::inst()->print_msg(L0, "You need to use less than 32 threads in NiceHash mode.");
+ return false;
+ }
+
if(GetSlowMemSetting() == unknown_value)
{
printer::inst()->print_msg(L0,
@@ -457,5 +457,15 @@ bool jconf::parse_config(const char* sFilename)
#endif // _WIN32
printer::inst()->set_verbose_level(prv->configValues[iVerboseLevel]->GetUint64());
+
+ if(!NeedsAutoconf())
+ {
+ if(!bHaveAes)
+ printer::inst()->print_msg(L0, "Your CPU doesn't support hardware AES. Don't expect high hashrates.");
+
+ if(bHaveBmi2)
+ printer::inst()->print_msg(L0, "CPU supports BMI2 instructions. Faster multiplication enabled.");
+ }
+
return true;
}
diff --git a/jconf.h b/jconf.h
index 7444a01..08e2124 100644
--- a/jconf.h
+++ b/jconf.h
@@ -29,6 +29,7 @@ public:
size_t GetThreadCount();
bool GetThreadConfig(size_t id, thd_cfg &cfg);
+ bool NeedsAutoconf();
slow_mem_cfg GetSlowMemSetting();
@@ -58,6 +59,8 @@ public:
inline bool HaveHardwareAes() { return bHaveAes; }
inline bool HaveMulx() { return bHaveBmi2; }
+ static void cpuid(uint32_t eax, int32_t ecx, int32_t val[4]);
+
private:
jconf();
static jconf* oInst;
OpenPOWER on IntegriCloud