314 lines
8.7 KiB
C++
314 lines
8.7 KiB
C++
/*
|
|
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 <atomic>
|
|
#include <list>
|
|
#include <thread>
|
|
|
|
#include <boost/asio.hpp>
|
|
#include <boost/bind.hpp>
|
|
#include <boost/dll.hpp>
|
|
#include <boost/filesystem.hpp>
|
|
#include <boost/process.hpp>
|
|
|
|
#include <jsoncpp/json/json.h>
|
|
|
|
#include <libdevcore/Common.h>
|
|
#include <libdevcore/Worker.h>
|
|
|
|
#include <libethcore/Miner.h>
|
|
|
|
#include <libhwmon/wrapnvml.h>
|
|
#if defined(__linux)
|
|
#include <libhwmon/wrapamdsysfs.h>
|
|
#include <sys/stat.h>
|
|
#else
|
|
#include <libhwmon/wrapadl.h>
|
|
#endif
|
|
|
|
extern boost::asio::io_service g_io_service;
|
|
|
|
namespace dev
|
|
{
|
|
namespace eth
|
|
{
|
|
struct FarmSettings
|
|
{
|
|
unsigned dagLoadMode = 0; // 0 = Parallel; 1 = Serialized
|
|
bool noEval = false; // Whether or not to re-evaluate solutions
|
|
unsigned hwMon = 0; // 0 - No monitor; 1 - Temp and Fan; 2 - Temp Fan Power
|
|
unsigned ergodicity = 0; // 0=default, 1=per session, 2=per job
|
|
unsigned tempStart = 40; // Temperature threshold to restart mining (if paused)
|
|
unsigned tempStop = 0; // Temperature threshold to pause mining (overheating)
|
|
};
|
|
|
|
/**
|
|
* @brief A collective of Miners.
|
|
* Miners ask for work, then submit proofs
|
|
* @threadsafe
|
|
*/
|
|
class Farm : public FarmFace
|
|
{
|
|
public:
|
|
unsigned tstart = 0, tstop = 0;
|
|
|
|
Farm(std::map<std::string, DeviceDescriptor>& _DevicesCollection,
|
|
FarmSettings _settings, CUSettings _CUSettings, CLSettings _CLSettings,
|
|
CPSettings _CPSettings);
|
|
|
|
~Farm();
|
|
|
|
static Farm& f() { return *m_this; }
|
|
|
|
/**
|
|
* @brief Randomizes the nonce scrambler
|
|
*/
|
|
void shuffle();
|
|
|
|
/**
|
|
* @brief Sets the current mining mission.
|
|
* @param _wp The work package we wish to be mining.
|
|
*/
|
|
void setWork(WorkPackage const& _newWp);
|
|
|
|
/**
|
|
* @brief Start a number of miners.
|
|
*/
|
|
bool start();
|
|
|
|
/**
|
|
* @brief All mining activities to a full stop.
|
|
* Implies all mining threads are stopped.
|
|
*/
|
|
void stop();
|
|
|
|
/**
|
|
* @brief Signals all miners to suspend mining
|
|
*/
|
|
void pause();
|
|
|
|
/**
|
|
* @brief Whether or not the whole farm has been paused
|
|
*/
|
|
bool paused();
|
|
|
|
/**
|
|
* @brief Signals all miners to resume mining
|
|
*/
|
|
void resume();
|
|
|
|
/**
|
|
* @brief Stop all mining activities and Starts them again
|
|
*/
|
|
void restart();
|
|
|
|
/**
|
|
* @brief Stop all mining activities and Starts them again (async post)
|
|
*/
|
|
void restart_async();
|
|
|
|
/**
|
|
* @brief Returns whether or not the farm has been started
|
|
*/
|
|
bool isMining() const { return m_isMining.load(std::memory_order_relaxed); }
|
|
|
|
/**
|
|
* @brief Spawn a reboot script (reboot.bat/reboot.sh)
|
|
* @return false if no matching file was found
|
|
*/
|
|
bool reboot(const std::vector<std::string>& args);
|
|
|
|
/**
|
|
* @brief Get information on the progress of mining this work package.
|
|
* @return The progress with mining so far.
|
|
*/
|
|
TelemetryType& Telemetry() { return m_telemetry; }
|
|
|
|
/**
|
|
* @brief Gets current hashrate
|
|
*/
|
|
float HashRate() { return m_telemetry.farm.hashrate; };
|
|
|
|
/**
|
|
* @brief Gets the collection of pointers to miner instances
|
|
*/
|
|
std::vector<std::shared_ptr<Miner>> getMiners() { return m_miners; }
|
|
|
|
/**
|
|
* @brief Gets the number of miner instances
|
|
*/
|
|
unsigned getMinersCount() { return (unsigned)m_miners.size(); };
|
|
|
|
/**
|
|
* @brief Gets the pointer to a miner instance
|
|
*/
|
|
std::shared_ptr<Miner> getMiner(unsigned index)
|
|
{
|
|
try
|
|
{
|
|
return m_miners.at(index);
|
|
}
|
|
catch (const std::exception&)
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Accounts a solution to a miner and, as a consequence, to
|
|
* the whole farm
|
|
*/
|
|
void accountSolution(unsigned _minerIdx, SolutionAccountingEnum _accounting) override;
|
|
|
|
/**
|
|
* @brief Gets the solutions account for the whole farm
|
|
*/
|
|
SolutionAccountType getSolutions();
|
|
|
|
/**
|
|
* @brief Gets the solutions account for single miner
|
|
*/
|
|
SolutionAccountType getSolutions(unsigned _minerIdx);
|
|
|
|
using SolutionFound = std::function<void(const Solution&)>;
|
|
using MinerRestart = std::function<void()>;
|
|
|
|
/**
|
|
* @brief Provides a valid header based upon that received previously with setWork().
|
|
* @param _bi The now-valid header.
|
|
* @return true if the header was good and that the Farm should pause until more work is
|
|
* submitted.
|
|
*/
|
|
void onSolutionFound(SolutionFound const& _handler) { m_onSolutionFound = _handler; }
|
|
|
|
void onMinerRestart(MinerRestart const& _handler) { m_onMinerRestart = _handler; }
|
|
|
|
/**
|
|
* @brief Gets the actual start nonce of the segment picked by the farm
|
|
*/
|
|
uint64_t get_nonce_scrambler() override { return m_nonce_scrambler; }
|
|
|
|
/**
|
|
* @brief Gets the actual width of each subsegment assigned to miners
|
|
*/
|
|
unsigned get_segment_width() override { return m_nonce_segment_with; }
|
|
|
|
/**
|
|
* @brief Sets the actual start nonce of the segment picked by the farm
|
|
*/
|
|
void set_nonce_scrambler(uint64_t n) { m_nonce_scrambler = n; }
|
|
|
|
/**
|
|
* @brief Sets the actual width of each subsegment assigned to miners
|
|
*/
|
|
void set_nonce_segment_width(unsigned n)
|
|
{
|
|
if (!m_currentWp.exSizeBytes)
|
|
m_nonce_segment_with = n;
|
|
}
|
|
|
|
/**
|
|
* @brief Provides the description of segments each miner is working on
|
|
* @return a JsonObject
|
|
*/
|
|
Json::Value get_nonce_scrambler_json();
|
|
|
|
void setTStartTStop(unsigned tstart, unsigned tstop);
|
|
|
|
unsigned get_tstart() override { return m_Settings.tempStart; }
|
|
|
|
unsigned get_tstop() override { return m_Settings.tempStop; }
|
|
|
|
unsigned get_ergodicity() override { return m_Settings.ergodicity; }
|
|
|
|
/**
|
|
* @brief Called from a Miner to note a WorkPackage has a solution.
|
|
* @param _s The solution.
|
|
*/
|
|
void submitProof(Solution const& _s) override;
|
|
|
|
bool getNoEval() { return m_Settings.noEval; }
|
|
|
|
private:
|
|
std::atomic<bool> m_paused = {false};
|
|
|
|
// Async submits solution serializing execution
|
|
// in Farm's strand
|
|
void submitProofAsync(Solution const& _s);
|
|
|
|
// Collects data about hashing and hardware status
|
|
void collectData(const boost::system::error_code& ec);
|
|
|
|
/**
|
|
* @brief Spawn a file - must be located in the directory of progminer binary
|
|
* @return false if file was not found or it is not executeable
|
|
*/
|
|
bool spawn_file_in_bin_dir(const char* filename, const std::vector<std::string>& args);
|
|
|
|
mutable Mutex x_minerWork;
|
|
std::vector<std::shared_ptr<Miner>> m_miners; // Collection of miners
|
|
|
|
WorkPackage m_currentWp;
|
|
EpochContext m_currentEc;
|
|
|
|
std::atomic<bool> m_isMining = {false};
|
|
|
|
TelemetryType m_telemetry; // Holds progress and status info for farm and miners
|
|
|
|
SolutionFound m_onSolutionFound;
|
|
MinerRestart m_onMinerRestart;
|
|
|
|
FarmSettings m_Settings; // Own Farm Settings
|
|
CUSettings m_CUSettings; // Cuda settings passed to CUDA Miner instantiator
|
|
CLSettings m_CLSettings; // OpenCL settings passed to CL Miner instantiator
|
|
CPSettings m_CPSettings; // CPU settings passed to CPU Miner instantiator
|
|
|
|
boost::asio::io_service::strand m_io_strand;
|
|
boost::asio::deadline_timer m_collectTimer;
|
|
static const int m_collectInterval = 5000;
|
|
|
|
string m_pool_addresses;
|
|
|
|
// StartNonce (non-NiceHash Mode) and
|
|
// segment width assigned to each GPU as exponent of 2
|
|
// considering an average block time of 15 seconds
|
|
// a single device GPU should need a speed of 286 Mh/s
|
|
// before it consumes the whole 2^32 segment
|
|
uint64_t m_nonce_scrambler;
|
|
unsigned int m_nonce_segment_with = 32;
|
|
|
|
// Wrappers for hardware monitoring libraries and their mappers
|
|
wrap_nvml_handle* nvmlh = nullptr;
|
|
std::map<string, int> map_nvml_handle = {};
|
|
|
|
#if defined(__linux)
|
|
wrap_amdsysfs_handle* sysfsh = nullptr;
|
|
std::map<string, int> map_amdsysfs_handle = {};
|
|
#else
|
|
wrap_adl_handle* adlh = nullptr;
|
|
std::map<string, int> map_adl_handle = {};
|
|
#endif
|
|
|
|
static Farm* m_this;
|
|
std::map<std::string, DeviceDescriptor>& m_DevicesCollection;
|
|
};
|
|
|
|
} // namespace eth
|
|
} // namespace dev
|