|
|
@ -1,25 +1,25 @@ |
|
|
|
/*
|
|
|
|
This file is part of cpp-ethereum. |
|
|
|
This file is part of cpp-ethereum. |
|
|
|
|
|
|
|
cpp-ethereum 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. |
|
|
|
cpp-ethereum 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. |
|
|
|
|
|
|
|
cpp-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. |
|
|
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
You should have received a copy of the GNU General Public License |
|
|
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/ |
|
|
|
/** @file EthashCUDAMiner.cpp
|
|
|
|
* @author Gav Wood <i@gavwood.com> |
|
|
|
* @date 2014 |
|
|
|
* |
|
|
|
* Determines the PoW algorithm. |
|
|
|
*/ |
|
|
|
/** @file EthashGPUMiner.cpp
|
|
|
|
* @author Gav Wood <i@gavwood.com> |
|
|
|
* @date 2014 |
|
|
|
* |
|
|
|
* Determines the PoW algorithm. |
|
|
|
*/ |
|
|
|
|
|
|
|
#if ETH_ETHASHCU || !ETH_TRUE |
|
|
|
|
|
|
@ -33,71 +33,71 @@ using namespace eth; |
|
|
|
|
|
|
|
namespace dev |
|
|
|
{ |
|
|
|
namespace eth |
|
|
|
{ |
|
|
|
|
|
|
|
class EthashCUHook: public ethash_cu_miner::search_hook |
|
|
|
{ |
|
|
|
public: |
|
|
|
EthashCUHook(EthashCUDAMiner* _owner): m_owner(_owner) {} |
|
|
|
EthashCUHook(EthashCUHook const&) = delete; |
|
|
|
|
|
|
|
void abort() |
|
|
|
namespace eth |
|
|
|
{ |
|
|
|
|
|
|
|
class EthashCUHook : public ethash_cu_miner::search_hook |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
if (m_aborted) |
|
|
|
return; |
|
|
|
// cdebug << "Attempting to abort";
|
|
|
|
public: |
|
|
|
EthashCUHook(EthashCUDAMiner* _owner) : m_owner(_owner) {} |
|
|
|
EthashCUHook(EthashCUHook const&) = delete; |
|
|
|
|
|
|
|
m_abort = true; |
|
|
|
} |
|
|
|
// m_abort is true so now searched()/found() will return true to abort the search.
|
|
|
|
// we hang around on this thread waiting for them to point out that they have aborted since
|
|
|
|
// otherwise we may end up deleting this object prior to searched()/found() being called.
|
|
|
|
m_aborted.wait(true); |
|
|
|
// for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
|
|
|
|
// std::this_thread::sleep_for(chrono::milliseconds(30));
|
|
|
|
// if (!m_aborted)
|
|
|
|
// cwarn << "Couldn't abort. Abandoning OpenCL process.";
|
|
|
|
} |
|
|
|
void abort() |
|
|
|
{ |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
if (m_aborted) |
|
|
|
return; |
|
|
|
// cdebug << "Attempting to abort";
|
|
|
|
|
|
|
|
void reset() |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
m_aborted = m_abort = false; |
|
|
|
} |
|
|
|
m_abort = true; |
|
|
|
} |
|
|
|
// m_abort is true so now searched()/found() will return true to abort the search.
|
|
|
|
// we hang around on this thread waiting for them to point out that they have aborted since
|
|
|
|
// otherwise we may end up deleting this object prior to searched()/found() being called.
|
|
|
|
m_aborted.wait(true); |
|
|
|
// for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
|
|
|
|
// std::this_thread::sleep_for(chrono::milliseconds(30));
|
|
|
|
// if (!m_aborted)
|
|
|
|
// cwarn << "Couldn't abort. Abandoning OpenCL process.";
|
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
virtual bool found(uint64_t const* _nonces, uint32_t _count) override |
|
|
|
{ |
|
|
|
// dev::operator <<(std::cerr << "Found nonces: ", vector<uint64_t>(_nonces, _nonces + _count)) << std::endl;
|
|
|
|
for (uint32_t i = 0; i < _count; ++i) |
|
|
|
if (m_owner->report(_nonces[i])) |
|
|
|
return (m_aborted = true); |
|
|
|
return m_owner->shouldStop(); |
|
|
|
} |
|
|
|
void reset() |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
m_aborted = m_abort = false; |
|
|
|
} |
|
|
|
|
|
|
|
virtual bool searched(uint64_t _startNonce, uint32_t _count) override |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
// std::cerr << "Searched " << _count << " from " << _startNonce << std::endl;
|
|
|
|
m_owner->accumulateHashes(_count); |
|
|
|
m_last = _startNonce + _count; |
|
|
|
if (m_abort || m_owner->shouldStop()) |
|
|
|
return (m_aborted = true); |
|
|
|
return false; |
|
|
|
} |
|
|
|
protected: |
|
|
|
virtual bool found(uint64_t const* _nonces, uint32_t _count) override |
|
|
|
{ |
|
|
|
// dev::operator <<(std::cerr << "Found nonces: ", vector<uint64_t>(_nonces, _nonces + _count)) << std::endl;
|
|
|
|
for (uint32_t i = 0; i < _count; ++i) |
|
|
|
if (m_owner->report(_nonces[i])) |
|
|
|
return (m_aborted = true); |
|
|
|
return m_owner->shouldStop(); |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
Mutex x_all; |
|
|
|
uint64_t m_last; |
|
|
|
bool m_abort = false; |
|
|
|
Notified<bool> m_aborted = {true}; |
|
|
|
EthashCUDAMiner* m_owner = nullptr; |
|
|
|
}; |
|
|
|
virtual bool searched(uint64_t _startNonce, uint32_t _count) override |
|
|
|
{ |
|
|
|
UniqueGuard l(x_all); |
|
|
|
// std::cerr << "Searched " << _count << " from " << _startNonce << std::endl;
|
|
|
|
m_owner->accumulateHashes(_count); |
|
|
|
m_last = _startNonce + _count; |
|
|
|
if (m_abort || m_owner->shouldStop()) |
|
|
|
return (m_aborted = true); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
private: |
|
|
|
Mutex x_all; |
|
|
|
uint64_t m_last; |
|
|
|
bool m_abort = false; |
|
|
|
Notified<bool> m_aborted = { true }; |
|
|
|
EthashCUDAMiner* m_owner = nullptr; |
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
unsigned EthashCUDAMiner::s_platformId = 0; |
|
|
@ -105,9 +105,9 @@ unsigned EthashCUDAMiner::s_deviceId = 0; |
|
|
|
unsigned EthashCUDAMiner::s_numInstances = 0; |
|
|
|
|
|
|
|
EthashCUDAMiner::EthashCUDAMiner(ConstructionInfo const& _ci) : |
|
|
|
GenericMiner<EthashProofOfWork>(_ci), |
|
|
|
Worker("cudaminer" + toString(index())), |
|
|
|
m_hook(new EthashCUDAMiner(this)) |
|
|
|
GenericMiner<EthashProofOfWork>(_ci), |
|
|
|
Worker("cudaminer" + toString(index())), |
|
|
|
m_hook( new EthashCUHook(this)) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
@ -123,7 +123,7 @@ bool EthashCUDAMiner::report(uint64_t _nonce) |
|
|
|
Nonce n = (Nonce)(u64)_nonce; |
|
|
|
EthashProofOfWork::Result r = EthashAux::eval(work().seedHash, work().headerHash, n); |
|
|
|
if (r.value < work().boundary) |
|
|
|
return submitProof(Solution{n, r.mixHash}); |
|
|
|
return submitProof(Solution{ n, r.mixHash }); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
@ -170,11 +170,11 @@ void EthashCUDAMiner::workLoop() |
|
|
|
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); |
|
|
|
m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook); |
|
|
|
} |
|
|
|
catch (cl::Error const& _e) |
|
|
|
catch (std::runtime_error const& _e) |
|
|
|
{ |
|
|
|
delete m_miner; |
|
|
|
m_miner = nullptr; |
|
|
|
cwarn << "Error GPU mining: " << _e.what() << "(" << _e.err() << ")"; |
|
|
|
cwarn << "Error CUDA mining: " << _e.what(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -186,17 +186,17 @@ void EthashCUDAMiner::pause() |
|
|
|
|
|
|
|
std::string EthashCUDAMiner::platformInfo() |
|
|
|
{ |
|
|
|
return ethash_cl_miner::platform_info(s_platformId, s_deviceId); |
|
|
|
return ethash_cu_miner::platform_info(s_deviceId); |
|
|
|
} |
|
|
|
|
|
|
|
unsigned EthashCUDAMiner::getNumDevices() |
|
|
|
{ |
|
|
|
return ethash_cl_miner::getNumDevices(s_platformId); |
|
|
|
return ethash_cu_miner::getNumDevices(); |
|
|
|
} |
|
|
|
|
|
|
|
void EthashCUDAMiner::listDevices() |
|
|
|
{ |
|
|
|
return ethash_cl_miner::listDevices(); |
|
|
|
return ethash_cu_miner::listDevices(); |
|
|
|
} |
|
|
|
|
|
|
|
bool EthashCUDAMiner::configureGPU( |
|
|
@ -208,7 +208,7 @@ bool EthashCUDAMiner::configureGPU( |
|
|
|
bool _allowCPU, |
|
|
|
unsigned _extraGPUMemory, |
|
|
|
uint64_t _currentBlock |
|
|
|
) |
|
|
|
) |
|
|
|
{ |
|
|
|
s_platformId = _platformId; |
|
|
|
s_deviceId = _deviceId; |
|
|
@ -220,14 +220,14 @@ bool EthashCUDAMiner::configureGPU( |
|
|
|
} |
|
|
|
|
|
|
|
if (!ethash_cu_miner::configureGPU( |
|
|
|
_platformId, |
|
|
|
_localWorkSize, |
|
|
|
_globalWorkSizeMultiplier * _localWorkSize, |
|
|
|
_msPerBatch, |
|
|
|
_allowCPU, |
|
|
|
_extraGPUMemory, |
|
|
|
_currentBlock) |
|
|
|
) |
|
|
|
_platformId, |
|
|
|
_localWorkSize, |
|
|
|
_globalWorkSizeMultiplier * _localWorkSize, |
|
|
|
_msPerBatch, |
|
|
|
_allowCPU, |
|
|
|
_extraGPUMemory, |
|
|
|
_currentBlock) |
|
|
|
) |
|
|
|
{ |
|
|
|
cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; |
|
|
|
return false; |
|
|
|