mirror of
https://github.com/jwinterm/xmr-stak.git
synced 2026-10-26 06:08:32 +01:00
+150
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
#include "jconf.h"
|
||||
#include "console.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
|
||||
// Mask bits between h and l and return the value
|
||||
// This enables us to put in values exactly like in the manual
|
||||
// For example EBX[31:22] is get_masked(cpu_info[1], 31, 22)
|
||||
inline 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");
|
||||
|
||||
if(!detectL3Size())
|
||||
return;
|
||||
|
||||
if(L3KB_size < 1024 || L3KB_size > 102400)
|
||||
{
|
||||
printer::inst()->print_msg(L0, "Autoconf failed: L3 size sanity check failed - %u KB.", L3KB_size);
|
||||
return;
|
||||
}
|
||||
|
||||
printer::inst()->print_msg(L0, "Autoconf L3 size detected at %u KB.", L3KB_size);
|
||||
|
||||
detectCPUConf();
|
||||
|
||||
printer::inst()->print_msg(L0, "Autoconf core count detected as %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 || old_amd)
|
||||
{
|
||||
aff_id += 2;
|
||||
|
||||
if(aff_id >= corecnt)
|
||||
aff_id = 1;
|
||||
}
|
||||
else
|
||||
aff_id++;
|
||||
|
||||
if(double_mode)
|
||||
L3KB_size -= 4096;
|
||||
else
|
||||
L3KB_size -= 2048;
|
||||
}
|
||||
|
||||
printer::inst()->print_str("]\n\n**************** Copy&Paste ****************\n");
|
||||
}
|
||||
|
||||
private:
|
||||
bool detectL3Size()
|
||||
{
|
||||
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_size = ((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_size = get_masked(cpu_info[3], 31, 18) * 512;
|
||||
|
||||
jconf::cpuid(1, 0, cpu_info);
|
||||
if(get_masked(cpu_info[0], 11, 8) < 0x17) //0x17h is Zen
|
||||
old_amd = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printer::inst()->print_msg(L0, "Autoconf failed: Unknown CPU type: %s.", cpustr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void detectCPUConf()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
corecnt = info.dwNumberOfProcessors;
|
||||
linux_layout = false;
|
||||
#else
|
||||
corecnt = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
linux_layout = true;
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
int32_t L3KB_size = 0;
|
||||
uint32_t corecnt;
|
||||
bool old_amd = false;
|
||||
bool linux_layout;
|
||||
};
|
||||
@@ -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();
|
||||
|
||||
+11
-11
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<Add library="crypto" />
|
||||
<Add library="ssl" />
|
||||
</Linker>
|
||||
<Unit filename="autoAdjust.hpp" />
|
||||
<Unit filename="cli-miner.cpp" />
|
||||
<Unit filename="console.cpp" />
|
||||
<Unit filename="console.h" />
|
||||
|
||||
Reference in New Issue
Block a user