progminer zano miner fork https://github.com/hyle-team/progminer
This commit is contained in:
485
zano/libethcore/Miner.h
Normal file
485
zano/libethcore/Miner.h
Normal file
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
This file is part of progminer.
|
||||
|
||||
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.
|
||||
|
||||
progminer 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <list>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
#include "EthashAux.h"
|
||||
#include <libdevcore/Common.h>
|
||||
#include <libdevcore/Log.h>
|
||||
#include <libdevcore/Worker.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
|
||||
#define DAG_LOAD_MODE_PARALLEL 0
|
||||
#define DAG_LOAD_MODE_SEQUENTIAL 1
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern boost::asio::io_service g_io_service;
|
||||
|
||||
namespace dev
|
||||
{
|
||||
namespace eth
|
||||
{
|
||||
enum class DeviceTypeEnum
|
||||
{
|
||||
Unknown,
|
||||
Cpu,
|
||||
Gpu,
|
||||
Accelerator
|
||||
};
|
||||
|
||||
enum class DeviceSubscriptionTypeEnum
|
||||
{
|
||||
None,
|
||||
OpenCL,
|
||||
Cuda,
|
||||
Cpu
|
||||
|
||||
};
|
||||
|
||||
enum class MinerType
|
||||
{
|
||||
Mixed,
|
||||
CL,
|
||||
CUDA,
|
||||
CPU
|
||||
};
|
||||
|
||||
enum class HwMonitorInfoType
|
||||
{
|
||||
UNKNOWN,
|
||||
NVIDIA,
|
||||
AMD,
|
||||
CPU
|
||||
};
|
||||
|
||||
enum class ClPlatformTypeEnum
|
||||
{
|
||||
Unknown,
|
||||
Amd,
|
||||
Clover,
|
||||
Nvidia
|
||||
};
|
||||
|
||||
enum class SolutionAccountingEnum
|
||||
{
|
||||
Accepted,
|
||||
Rejected,
|
||||
Wasted,
|
||||
Failed
|
||||
};
|
||||
|
||||
struct MinerSettings
|
||||
{
|
||||
vector<unsigned> devices;
|
||||
};
|
||||
|
||||
// Holds settings for CUDA Miner
|
||||
struct CUSettings : public MinerSettings
|
||||
{
|
||||
unsigned streams = 2;
|
||||
unsigned schedule = 4;
|
||||
unsigned gridSize = 256;
|
||||
unsigned blockSize = 512;
|
||||
unsigned parallelHash = 4;
|
||||
};
|
||||
|
||||
// Holds settings for OpenCL Miner
|
||||
struct CLSettings : public MinerSettings
|
||||
{
|
||||
bool noBinary = false;
|
||||
unsigned globalWorkSize = 0;
|
||||
unsigned globalWorkSizeMultiplier = 32768;
|
||||
unsigned localWorkSize = 256;
|
||||
};
|
||||
|
||||
// Holds settings for CPU Miner
|
||||
struct CPSettings : public MinerSettings
|
||||
{
|
||||
};
|
||||
|
||||
struct SolutionAccountType
|
||||
{
|
||||
unsigned accepted = 0;
|
||||
unsigned rejected = 0;
|
||||
unsigned wasted = 0;
|
||||
unsigned failed = 0;
|
||||
std::chrono::steady_clock::time_point tstamp = std::chrono::steady_clock::now();
|
||||
string str()
|
||||
{
|
||||
string _ret = "A" + to_string(accepted);
|
||||
if (wasted)
|
||||
_ret.append(":W" + to_string(wasted));
|
||||
if (rejected)
|
||||
_ret.append(":R" + to_string(rejected));
|
||||
if (failed)
|
||||
_ret.append(":F" + to_string(failed));
|
||||
return _ret;
|
||||
};
|
||||
};
|
||||
|
||||
struct HwSensorsType
|
||||
{
|
||||
int tempC = 0;
|
||||
int fanP = 0;
|
||||
double powerW = 0.0;
|
||||
string str()
|
||||
{
|
||||
string _ret = to_string(tempC) + "C " + to_string(fanP) + "%";
|
||||
if (powerW)
|
||||
_ret.append(boost::str(boost::format("%f") % powerW));
|
||||
return _ret;
|
||||
};
|
||||
};
|
||||
|
||||
struct TelemetryAccountType
|
||||
{
|
||||
string prefix = "";
|
||||
float hashrate = 0.0f;
|
||||
bool paused = false;
|
||||
HwSensorsType sensors;
|
||||
SolutionAccountType solutions;
|
||||
};
|
||||
|
||||
struct DeviceDescriptor
|
||||
{
|
||||
DeviceTypeEnum type = DeviceTypeEnum::Unknown;
|
||||
DeviceSubscriptionTypeEnum subscriptionType = DeviceSubscriptionTypeEnum::None;
|
||||
|
||||
string uniqueId; // For GPUs this is the PCI ID
|
||||
size_t totalMemory; // Total memory available by device
|
||||
string name; // Device Name
|
||||
|
||||
bool clDetected; // For OpenCL detected devices
|
||||
string clName;
|
||||
unsigned int clPlatformId;
|
||||
string clPlatformName;
|
||||
ClPlatformTypeEnum clPlatformType = ClPlatformTypeEnum::Unknown;
|
||||
string clPlatformVersion;
|
||||
unsigned int clPlatformVersionMajor;
|
||||
unsigned int clPlatformVersionMinor;
|
||||
unsigned int clDeviceOrdinal;
|
||||
unsigned int clDeviceIndex;
|
||||
string clDeviceVersion;
|
||||
unsigned int clDeviceVersionMajor;
|
||||
unsigned int clDeviceVersionMinor;
|
||||
string clBoardName;
|
||||
size_t clMaxMemAlloc;
|
||||
size_t clMaxWorkGroup;
|
||||
unsigned int clMaxComputeUnits;
|
||||
string clNvCompute;
|
||||
unsigned int clNvComputeMajor;
|
||||
unsigned int clNvComputeMinor;
|
||||
|
||||
bool cuDetected; // For CUDA detected devices
|
||||
string cuName;
|
||||
unsigned int cuDeviceOrdinal;
|
||||
unsigned int cuDeviceIndex;
|
||||
string cuCompute;
|
||||
unsigned int cuComputeMajor;
|
||||
unsigned int cuComputeMinor;
|
||||
|
||||
int cpCpuNumer; // For CPU
|
||||
};
|
||||
|
||||
struct HwMonitorInfo
|
||||
{
|
||||
HwMonitorInfoType deviceType = HwMonitorInfoType::UNKNOWN;
|
||||
string devicePciId;
|
||||
int deviceIndex = -1;
|
||||
};
|
||||
|
||||
/// Pause mining
|
||||
enum MinerPauseEnum
|
||||
{
|
||||
PauseDueToOverHeating,
|
||||
PauseDueToAPIRequest,
|
||||
PauseDueToFarmPaused,
|
||||
PauseDueToInsufficientMemory,
|
||||
PauseDueToInitEpochError,
|
||||
Pause_MAX // Must always be last as a placeholder of max count
|
||||
};
|
||||
|
||||
/// Keeps track of progress for farm and miners
|
||||
struct TelemetryType
|
||||
{
|
||||
bool hwmon = false;
|
||||
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
|
||||
|
||||
TelemetryAccountType farm;
|
||||
std::vector<TelemetryAccountType> miners;
|
||||
std::string str()
|
||||
{
|
||||
std::stringstream _ret;
|
||||
|
||||
/*
|
||||
|
||||
Output is formatted as
|
||||
|
||||
Run <h:mm> <Solutions> <Speed> [<miner> ...]
|
||||
where
|
||||
- Run h:mm Duration of the batch
|
||||
- Solutions Detailed solutions (A+R+F) per farm
|
||||
- Speed Actual hashing rate
|
||||
|
||||
each <miner> reports
|
||||
- speed Actual speed at the same level of
|
||||
magnitude for farm speed
|
||||
- sensors Values of sensors (temp, fan, power)
|
||||
- solutions Optional (LOG_PER_GPU) Solutions detail per GPU
|
||||
*/
|
||||
|
||||
/*
|
||||
Calculate duration
|
||||
*/
|
||||
auto duration = std::chrono::steady_clock::now() - start;
|
||||
auto hours = std::chrono::duration_cast<std::chrono::hours>(duration);
|
||||
int hoursSize = (hours.count() > 9 ? (hours.count() > 99 ? 3 : 2) : 1);
|
||||
duration -= hours;
|
||||
auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration);
|
||||
_ret << EthGreen << setw(hoursSize) << hours.count() << ":" << setfill('0') << setw(2)
|
||||
<< minutes.count() << EthReset << EthWhiteBold << " " << farm.solutions.str()
|
||||
<< EthReset << " ";
|
||||
|
||||
/*
|
||||
Github : @AndreaLanfranchi
|
||||
I whish I could simply make use of getFormattedHashes but in this case
|
||||
this would be misleading as total hashrate could be of a different order
|
||||
of magnitude than the hashrate expressed by single devices.
|
||||
Thus I need to set the vary same scaling index on the farm and on devices
|
||||
*/
|
||||
static string suffixes[] = {"h", "Kh", "Mh", "Gh"};
|
||||
float hr = farm.hashrate;
|
||||
int magnitude = 0;
|
||||
while (hr > 1000.0f && magnitude <= 3)
|
||||
{
|
||||
hr /= 1000.0f;
|
||||
magnitude++;
|
||||
}
|
||||
|
||||
_ret << EthTealBold << std::fixed << std::setprecision(2) << hr << " "
|
||||
<< suffixes[magnitude] << EthReset << " - ";
|
||||
|
||||
int i = -1; // Current miner index
|
||||
int m = miners.size() - 1; // Max miner index
|
||||
for (TelemetryAccountType miner : miners)
|
||||
{
|
||||
i++;
|
||||
hr = miner.hashrate;
|
||||
if (hr > 0.0f)
|
||||
hr /= pow(1000.0f, magnitude);
|
||||
|
||||
_ret << (miner.paused ? EthRed : "") << miner.prefix << i << " " << EthTeal
|
||||
<< std::fixed << std::setprecision(2) << hr << EthReset;
|
||||
|
||||
if (hwmon)
|
||||
_ret << " " << EthTeal << miner.sensors.str() << EthReset;
|
||||
|
||||
// Eventually push also solutions per single GPU
|
||||
if (g_logOptions & LOG_PER_GPU)
|
||||
_ret << " " << EthTeal << miner.solutions.str() << EthReset;
|
||||
|
||||
// Separator if not the last miner index
|
||||
if (i < m)
|
||||
_ret << ", ";
|
||||
}
|
||||
|
||||
return _ret.str();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for hosting one or more Miners.
|
||||
* @warning Must be implemented in a threadsafe manner since it will be called from multiple
|
||||
* miner threads.
|
||||
*/
|
||||
class FarmFace
|
||||
{
|
||||
public:
|
||||
FarmFace() { m_this = this; }
|
||||
static FarmFace& f() { return *m_this; };
|
||||
|
||||
virtual ~FarmFace() = default;
|
||||
virtual unsigned get_tstart() = 0;
|
||||
virtual unsigned get_tstop() = 0;
|
||||
virtual unsigned get_ergodicity() = 0;
|
||||
|
||||
/**
|
||||
* @brief Called from a Miner to note a WorkPackage has a solution.
|
||||
* @param _p The solution.
|
||||
* @return true iff the solution was good (implying that mining should be .
|
||||
*/
|
||||
virtual void submitProof(Solution const& _p) = 0;
|
||||
virtual void accountSolution(unsigned _minerIdx, SolutionAccountingEnum _accounting) = 0;
|
||||
virtual uint64_t get_nonce_scrambler() = 0;
|
||||
virtual unsigned get_segment_width() = 0;
|
||||
|
||||
private:
|
||||
static FarmFace* m_this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A miner - a member and adoptee of the Farm.
|
||||
* @warning Not threadsafe. It is assumed Farm will synchronise calls to/from this class.
|
||||
*/
|
||||
|
||||
class Miner : public Worker
|
||||
{
|
||||
public:
|
||||
Miner(std::string const& _name, unsigned _index)
|
||||
: Worker(_name + std::to_string(_index)), m_index(_index)
|
||||
{}
|
||||
|
||||
~Miner() override = default;
|
||||
|
||||
// Sets basic info for eventual serialization of DAG load
|
||||
static void setDagLoadInfo(unsigned _mode, unsigned _devicecount)
|
||||
{
|
||||
s_dagLoadMode = _mode;
|
||||
s_dagLoadIndex = 0;
|
||||
s_minersCount = _devicecount;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Gets the device descriptor assigned to this instance
|
||||
*/
|
||||
DeviceDescriptor getDescriptor();
|
||||
|
||||
/**
|
||||
* @brief Assigns hashing work to this instance
|
||||
*/
|
||||
void setWork(WorkPackage const& _work);
|
||||
|
||||
/**
|
||||
* @brief Assigns Epoch context to this instance
|
||||
*/
|
||||
void setEpoch(EpochContext const& _ec) { m_epochContext = _ec; }
|
||||
|
||||
unsigned Index() { return m_index; };
|
||||
|
||||
HwMonitorInfo hwmonInfo() { return m_hwmoninfo; }
|
||||
|
||||
void setHwmonDeviceIndex(int i) { m_hwmoninfo.deviceIndex = i; }
|
||||
|
||||
/**
|
||||
* @brief Kick an asleep miner.
|
||||
*/
|
||||
virtual void kick_miner() = 0;
|
||||
|
||||
/**
|
||||
* @brief Pauses mining setting a reason flag
|
||||
*/
|
||||
void pause(MinerPauseEnum what);
|
||||
|
||||
/**
|
||||
* @brief Whether or not this miner is paused for any reason
|
||||
*/
|
||||
bool paused();
|
||||
|
||||
/**
|
||||
* @brief Checks if the given reason for pausing is currently active
|
||||
*/
|
||||
bool pauseTest(MinerPauseEnum what);
|
||||
|
||||
/**
|
||||
* @brief Returns the human readable reason for this miner being paused
|
||||
*/
|
||||
std::string pausedString();
|
||||
|
||||
/**
|
||||
* @brief Cancels a pause flag.
|
||||
* @note Miner can be paused for multiple reasons at a time.
|
||||
*/
|
||||
void resume(MinerPauseEnum fromwhat);
|
||||
|
||||
/**
|
||||
* @brief Retrieves currrently collected hashrate
|
||||
*/
|
||||
float RetrieveHashRate() noexcept;
|
||||
|
||||
void TriggerHashRateUpdate() noexcept;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Initializes miner's device.
|
||||
*/
|
||||
virtual bool initDevice() = 0;
|
||||
|
||||
/**
|
||||
* @brief Initializes miner to current (or changed) epoch.
|
||||
*/
|
||||
bool initEpoch();
|
||||
|
||||
/**
|
||||
* @brief Miner's specific initialization to current (or changed) epoch.
|
||||
*/
|
||||
virtual bool initEpoch_internal() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns current workpackage this miner is working on
|
||||
*/
|
||||
WorkPackage work() const;
|
||||
|
||||
void updateHashRate(uint32_t _groupSize, uint32_t _increment) noexcept;
|
||||
|
||||
bool dropThreadPriority();
|
||||
|
||||
static unsigned s_minersCount; // Total Number of Miners
|
||||
static unsigned s_dagLoadMode; // Way dag should be loaded
|
||||
static unsigned s_dagLoadIndex; // In case of serialized load of dag this is the index of miner
|
||||
// which should load next
|
||||
|
||||
const unsigned m_index = 0; // Ordinal index of the Instance (not the device)
|
||||
DeviceDescriptor m_deviceDescriptor; // Info about the device
|
||||
|
||||
EpochContext m_epochContext;
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
std::chrono::steady_clock::time_point m_workSwitchStart;
|
||||
#endif
|
||||
|
||||
HwMonitorInfo m_hwmoninfo;
|
||||
mutable boost::mutex x_work;
|
||||
mutable boost::mutex x_pause;
|
||||
boost::condition_variable m_new_work_signal;
|
||||
boost::condition_variable m_dag_loaded_signal;
|
||||
uint64_t m_nextProgpowPeriod = 0;
|
||||
boost::thread* m_compileThread = nullptr;
|
||||
|
||||
private:
|
||||
bitset<MinerPauseEnum::Pause_MAX> m_pauseFlags;
|
||||
|
||||
WorkPackage m_work;
|
||||
|
||||
std::chrono::steady_clock::time_point m_hashTime = std::chrono::steady_clock::now();
|
||||
std::atomic<float> m_hashRate = {0.0};
|
||||
uint64_t m_groupCount = 0;
|
||||
atomic<bool> m_hashRateUpdate = {false};
|
||||
};
|
||||
|
||||
} // namespace eth
|
||||
} // namespace dev
|
Reference in New Issue
Block a user