mirror of
https://github.com/monero-project/monero.git
synced 2024-11-18 00:37:43 +00:00
miner: it can now autodetect the optimal number of threads
This commit is contained in:
parent
31bdf7bd11
commit
8298f42e9d
4 changed files with 96 additions and 9 deletions
|
@ -73,6 +73,9 @@
|
||||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||||
#define MONERO_DEFAULT_LOG_CATEGORY "miner"
|
#define MONERO_DEFAULT_LOG_CATEGORY "miner"
|
||||||
|
|
||||||
|
#define AUTODETECT_WINDOW 10 // seconds
|
||||||
|
#define AUTODETECT_GAIN_THRESHOLD 1.02f // 2%
|
||||||
|
|
||||||
using namespace epee;
|
using namespace epee;
|
||||||
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
@ -108,6 +111,7 @@ namespace cryptonote
|
||||||
m_starter_nonce(0),
|
m_starter_nonce(0),
|
||||||
m_last_hr_merge_time(0),
|
m_last_hr_merge_time(0),
|
||||||
m_hashes(0),
|
m_hashes(0),
|
||||||
|
m_total_hashes(0),
|
||||||
m_do_print_hashrate(false),
|
m_do_print_hashrate(false),
|
||||||
m_do_mining(false),
|
m_do_mining(false),
|
||||||
m_current_hash_rate(0),
|
m_current_hash_rate(0),
|
||||||
|
@ -179,6 +183,11 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_autodetect_interval.do_call([&](){
|
||||||
|
update_autodetection();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
@ -209,6 +218,60 @@ namespace cryptonote
|
||||||
m_hashes = 0;
|
m_hashes = 0;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
void miner::update_autodetection()
|
||||||
|
{
|
||||||
|
if (m_threads_autodetect.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t now = epee::misc_utils::get_ns_count();
|
||||||
|
uint64_t dt = now - m_threads_autodetect.back().first;
|
||||||
|
if (dt < AUTODETECT_WINDOW * 1000000000ull)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// work out how many more hashes we got
|
||||||
|
m_threads_autodetect.back().first = dt;
|
||||||
|
uint64_t dh = m_total_hashes - m_threads_autodetect.back().second;
|
||||||
|
m_threads_autodetect.back().second = dh;
|
||||||
|
float hs = dh / (dt / (float)1000000000);
|
||||||
|
MGINFO("Mining autodetection: " << m_threads_autodetect.size() << " threads: " << hs << " H/s");
|
||||||
|
|
||||||
|
// when we don't increase by at least 2%, stop, otherwise check next
|
||||||
|
// if N and N+1 have mostly the same hash rate, we want to "lighter" one
|
||||||
|
bool found = false;
|
||||||
|
if (m_threads_autodetect.size() > 1)
|
||||||
|
{
|
||||||
|
int previdx = m_threads_autodetect.size() - 2;
|
||||||
|
float previous_hs = m_threads_autodetect[previdx].second / (m_threads_autodetect[previdx].first / (float)1000000000);
|
||||||
|
if (previous_hs > 0 && hs / previous_hs < AUTODETECT_GAIN_THRESHOLD)
|
||||||
|
{
|
||||||
|
m_threads_total = m_threads_autodetect.size() - 1;
|
||||||
|
m_threads_autodetect.clear();
|
||||||
|
MGINFO("Optimal number of threads seems to be " << m_threads_total);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
// setup one more thread
|
||||||
|
m_threads_autodetect.push_back({now, m_total_hashes});
|
||||||
|
m_threads_total = m_threads_autodetect.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// restart all threads
|
||||||
|
{
|
||||||
|
CRITICAL_REGION_LOCAL(m_threads_lock);
|
||||||
|
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
|
||||||
|
for(boost::thread& th: m_threads)
|
||||||
|
th.join();
|
||||||
|
m_threads.clear();
|
||||||
|
}
|
||||||
|
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
|
||||||
|
boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
|
||||||
|
for(size_t i = 0; i != m_threads_total; i++)
|
||||||
|
m_threads.push_back(boost::thread(m_attrs, boost::bind(&miner::worker_thread, this)));
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------------
|
||||||
void miner::init_options(boost::program_options::options_description& desc)
|
void miner::init_options(boost::program_options::options_description& desc)
|
||||||
{
|
{
|
||||||
command_line::add_arg(desc, arg_extra_messages);
|
command_line::add_arg(desc, arg_extra_messages);
|
||||||
|
@ -297,6 +360,13 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
m_mine_address = adr;
|
m_mine_address = adr;
|
||||||
m_threads_total = static_cast<uint32_t>(threads_count);
|
m_threads_total = static_cast<uint32_t>(threads_count);
|
||||||
|
if (threads_count == 0)
|
||||||
|
{
|
||||||
|
m_threads_autodetect.clear();
|
||||||
|
m_threads_autodetect.push_back({epee::misc_utils::get_ns_count(), m_total_hashes});
|
||||||
|
m_threads_total = 1;
|
||||||
|
}
|
||||||
|
m_attrs = attrs;
|
||||||
m_starter_nonce = crypto::rand<uint32_t>();
|
m_starter_nonce = crypto::rand<uint32_t>();
|
||||||
CRITICAL_REGION_LOCAL(m_threads_lock);
|
CRITICAL_REGION_LOCAL(m_threads_lock);
|
||||||
if(is_mining())
|
if(is_mining())
|
||||||
|
@ -318,12 +388,15 @@ namespace cryptonote
|
||||||
set_is_background_mining_enabled(do_background);
|
set_is_background_mining_enabled(do_background);
|
||||||
set_ignore_battery(ignore_battery);
|
set_ignore_battery(ignore_battery);
|
||||||
|
|
||||||
for(size_t i = 0; i != threads_count; i++)
|
for(size_t i = 0; i != m_threads_total; i++)
|
||||||
{
|
{
|
||||||
m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
|
m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" );
|
if (threads_count == 0)
|
||||||
|
MINFO("Mining has started, autodetecting optimal number of threads, good luck!" );
|
||||||
|
else
|
||||||
|
MINFO("Mining has started with " << threads_count << " threads, good luck!" );
|
||||||
|
|
||||||
if( get_is_background_mining_enabled() )
|
if( get_is_background_mining_enabled() )
|
||||||
{
|
{
|
||||||
|
@ -360,7 +433,7 @@ namespace cryptonote
|
||||||
|
|
||||||
if (!is_mining())
|
if (!is_mining())
|
||||||
{
|
{
|
||||||
MDEBUG("Not mining - nothing to stop" );
|
MTRACE("Not mining - nothing to stop" );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +454,7 @@ namespace cryptonote
|
||||||
|
|
||||||
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
|
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
|
m_threads_autodetect.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
@ -506,6 +580,7 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
nonce+=m_threads_total;
|
nonce+=m_threads_total;
|
||||||
++m_hashes;
|
++m_hashes;
|
||||||
|
++m_total_hashes;
|
||||||
}
|
}
|
||||||
slow_hash_free_state();
|
slow_hash_free_state();
|
||||||
MGINFO("Miner thread stopped ["<< th_local_index << "]");
|
MGINFO("Miner thread stopped ["<< th_local_index << "]");
|
||||||
|
|
|
@ -103,6 +103,7 @@ namespace cryptonote
|
||||||
bool worker_thread();
|
bool worker_thread();
|
||||||
bool request_block_template();
|
bool request_block_template();
|
||||||
void merge_hr();
|
void merge_hr();
|
||||||
|
void update_autodetection();
|
||||||
|
|
||||||
struct miner_config
|
struct miner_config
|
||||||
{
|
{
|
||||||
|
@ -132,16 +133,20 @@ namespace cryptonote
|
||||||
account_public_address m_mine_address;
|
account_public_address m_mine_address;
|
||||||
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||||
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||||
|
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
|
||||||
std::vector<blobdata> m_extra_messages;
|
std::vector<blobdata> m_extra_messages;
|
||||||
miner_config m_config;
|
miner_config m_config;
|
||||||
std::string m_config_folder_path;
|
std::string m_config_folder_path;
|
||||||
std::atomic<uint64_t> m_last_hr_merge_time;
|
std::atomic<uint64_t> m_last_hr_merge_time;
|
||||||
std::atomic<uint64_t> m_hashes;
|
std::atomic<uint64_t> m_hashes;
|
||||||
|
std::atomic<uint64_t> m_total_hashes;
|
||||||
std::atomic<uint64_t> m_current_hash_rate;
|
std::atomic<uint64_t> m_current_hash_rate;
|
||||||
epee::critical_section m_last_hash_rates_lock;
|
epee::critical_section m_last_hash_rates_lock;
|
||||||
std::list<uint64_t> m_last_hash_rates;
|
std::list<uint64_t> m_last_hash_rates;
|
||||||
bool m_do_print_hashrate;
|
bool m_do_print_hashrate;
|
||||||
bool m_do_mining;
|
bool m_do_mining;
|
||||||
|
std::vector<std::pair<uint64_t, uint64_t>> m_threads_autodetect;
|
||||||
|
boost::thread::attributes m_attrs;
|
||||||
|
|
||||||
// background mining stuffs ..
|
// background mining stuffs ..
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||||
{
|
{
|
||||||
if(!args.size())
|
if(!args.size())
|
||||||
{
|
{
|
||||||
std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>]" << std::endl;
|
std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>|auto]" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,10 +387,17 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||||
}
|
}
|
||||||
|
|
||||||
if(args.size() >= 2)
|
if(args.size() >= 2)
|
||||||
|
{
|
||||||
|
if (args[1] == "auto" || args[1] == "autodetect")
|
||||||
|
{
|
||||||
|
threads_count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
bool ok = epee::string_tools::get_xtype_from_string(threads_count, args[1]);
|
bool ok = epee::string_tools::get_xtype_from_string(threads_count, args[1]);
|
||||||
threads_count = (ok && 0 < threads_count) ? threads_count : 1;
|
threads_count = (ok && 0 < threads_count) ? threads_count : 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery);
|
m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery);
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,8 @@ t_command_server::t_command_server(
|
||||||
m_command_lookup.set_handler(
|
m_command_lookup.set_handler(
|
||||||
"start_mining"
|
"start_mining"
|
||||||
, std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)
|
, std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)
|
||||||
, "start_mining <addr> [<threads>] [do_background_mining] [ignore_battery]"
|
, "start_mining <addr> [<threads>|auto] [do_background_mining] [ignore_battery]"
|
||||||
, "Start mining for specified address. Defaults to 1 thread and no background mining."
|
, "Start mining for specified address. Defaults to 1 thread and no background mining. Use \"auto\" to autodetect optimal number of threads."
|
||||||
);
|
);
|
||||||
m_command_lookup.set_handler(
|
m_command_lookup.set_handler(
|
||||||
"stop_mining"
|
"stop_mining"
|
||||||
|
|
Loading…
Reference in a new issue