Files
mines/zano/libethcore/Miner.cpp

208 lines
5.4 KiB
C++

/*
This file is part of ethereum.
progminer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with progminer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Miner.h"
namespace dev
{
namespace eth
{
unsigned Miner::s_dagLoadMode = 0;
unsigned Miner::s_dagLoadIndex = 0;
unsigned Miner::s_minersCount = 0;
FarmFace* FarmFace::m_this = nullptr;
DeviceDescriptor Miner::getDescriptor()
{
return m_deviceDescriptor;
}
void Miner::setWork(WorkPackage const& _work)
{
{
boost::mutex::scoped_lock l(x_work);
// Void work if this miner is paused
if (paused())
m_work.header = h256();
else
m_work = _work;
#ifdef DEV_BUILD
m_workSwitchStart = std::chrono::steady_clock::now();
#endif
}
kick_miner();
}
void Miner::pause(MinerPauseEnum what)
{
boost::mutex::scoped_lock l(x_pause);
m_pauseFlags.set(what);
m_work.header = h256();
kick_miner();
}
bool Miner::paused()
{
boost::mutex::scoped_lock l(x_pause);
return m_pauseFlags.any();
}
bool Miner::pauseTest(MinerPauseEnum what)
{
boost::mutex::scoped_lock l(x_pause);
return m_pauseFlags.test(what);
}
std::string Miner::pausedString()
{
boost::mutex::scoped_lock l(x_pause);
std::string retVar;
if (m_pauseFlags.any())
{
for (int i = 0; i < MinerPauseEnum::Pause_MAX; i++)
{
if (m_pauseFlags[(MinerPauseEnum)i])
{
if (!retVar.empty())
retVar.append("; ");
if (i == MinerPauseEnum::PauseDueToOverHeating)
retVar.append("Overheating");
else if (i == MinerPauseEnum::PauseDueToAPIRequest)
retVar.append("Api request");
else if (i == MinerPauseEnum::PauseDueToFarmPaused)
retVar.append("Farm suspended");
else if (i == MinerPauseEnum::PauseDueToInsufficientMemory)
retVar.append("Insufficient GPU memory");
else if (i == MinerPauseEnum::PauseDueToInitEpochError)
retVar.append("Epoch initialization error");
}
}
}
return retVar;
}
void Miner::resume(MinerPauseEnum fromwhat)
{
boost::mutex::scoped_lock l(x_pause);
m_pauseFlags.reset(fromwhat);
//if (!m_pauseFlags.any())
//{
// // TODO Push most recent job from farm ?
// // If we do not push a new job the miner will stay idle
// // till a new job arrives
//}
}
float Miner::RetrieveHashRate() noexcept
{
return m_hashRate.load(std::memory_order_relaxed);
}
void Miner::TriggerHashRateUpdate() noexcept
{
bool b = false;
if (m_hashRateUpdate.compare_exchange_weak(b, true, std::memory_order_relaxed))
return;
// GPU didn't respond to last trigger, assume it's dead.
// This can happen on CUDA if:
// runtime of --cuda-grid-size * --cuda-streams exceeds time of m_collectInterval
m_hashRate = 0.0;
}
bool Miner::initEpoch()
{
// When loading of DAG is sequential wait for
// this instance to become current
if (s_dagLoadMode == DAG_LOAD_MODE_SEQUENTIAL)
{
while (s_dagLoadIndex < m_index)
{
boost::system_time const timeout =
boost::get_system_time() + boost::posix_time::seconds(3);
boost::mutex::scoped_lock l(x_work);
m_dag_loaded_signal.timed_wait(l, timeout);
}
if (shouldStop())
return false;
}
// Run the internal initialization
// specific for miner
bool result = initEpoch_internal();
// Advance to next miner or reset to zero for
// next run if all have processed
if (s_dagLoadMode == DAG_LOAD_MODE_SEQUENTIAL)
{
s_dagLoadIndex = (m_index + 1);
if (s_minersCount == s_dagLoadIndex)
s_dagLoadIndex = 0;
else
m_dag_loaded_signal.notify_all();
}
return result;
}
WorkPackage Miner::work() const
{
boost::mutex::scoped_lock l(x_work);
return m_work;
}
void Miner::updateHashRate(uint32_t _groupSize, uint32_t _increment) noexcept
{
m_groupCount += _increment;
bool b = true;
if (!m_hashRateUpdate.compare_exchange_weak(b, false, std::memory_order_relaxed))
return;
using namespace std::chrono;
auto t = steady_clock::now();
auto us = duration_cast<microseconds>(t - m_hashTime).count();
m_hashTime = t;
m_hashRate.store(
us ? (float(m_groupCount * _groupSize) * 1.0e6f) / us : 0.0f, std::memory_order_relaxed);
m_groupCount = 0;
}
bool Miner::dropThreadPriority()
{
#if defined(__linux__)
// Non Posix hack to lower compile thread's priority. Under POSIX
// the nice value is a process attribute, under Linux it's a thread
// attribute
return nice(5) != -1;
#elif defined(WIN32)
return SetThreadPriority(m_compileThread->native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
#else
return false;
#endif
}
} // namespace eth
} // namespace dev