diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 476c810c2..65311b019 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -97,11 +97,11 @@ public: if ((arg == "-F" || arg == "--farm") && i + 1 < argc) { mode = OperationMode::Farm; - farmURL = argv[++i]; + m_farmURL = argv[++i]; } else if (arg == "--farm-recheck" && i + 1 < argc) try { - farmRecheckPeriod = stol(argv[++i]); + m_farmRecheckPeriod = stol(argv[++i]); } catch (...) { @@ -110,7 +110,7 @@ public: } else if (arg == "--opencl-platform" && i + 1 < argc) try { - openclPlatform = stol(argv[++i]); + m_openclPlatform = stol(argv[++i]); } catch (...) { @@ -119,8 +119,8 @@ public: } else if (arg == "--opencl-device" && i + 1 < argc) try { - openclDevice = stol(argv[++i]); - miningThreads = 1; + m_openclDevice = stol(argv[++i]); + m_miningThreads = 1; } catch (...) { @@ -128,17 +128,16 @@ public: throw BadArgument(); } else if (arg == "--list-devices") - { - ProofOfWork::GPUMiner::listDevices(); - exit(0); - } + m_shouldListDevices = true; + else if (arg == "--allow-opencl-cpu") + m_clAllowCPU = true; else if (arg == "--phone-home" && i + 1 < argc) { string m = argv[++i]; if (isTrue(m)) - phoneHome = true; + m_phoneHome = true; else if (isFalse(m)) - phoneHome = false; + m_phoneHome = false; else { cerr << "Bad " << arg << " option: " << m << endl; @@ -147,7 +146,7 @@ public: } else if (arg == "--benchmark-warmup" && i + 1 < argc) try { - benchmarkWarmup = stol(argv[++i]); + m_benchmarkWarmup = stol(argv[++i]); } catch (...) { @@ -156,7 +155,7 @@ public: } else if (arg == "--benchmark-trial" && i + 1 < argc) try { - benchmarkTrial = stol(argv[++i]); + m_benchmarkTrial = stol(argv[++i]); } catch (...) { @@ -165,7 +164,7 @@ public: } else if (arg == "--benchmark-trials" && i + 1 < argc) try { - benchmarkTrials = stol(argv[++i]); + m_benchmarkTrials = stol(argv[++i]); } catch (...) { @@ -175,21 +174,10 @@ public: else if (arg == "-C" || arg == "--cpu") m_minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") - { - if (!ProofOfWork::GPUMiner::configureGPU()) - { - cout << "No GPU device with sufficient memory was found. Defaulting to CPU" << endl; - m_minerType = MinerType::CPU; - } - else - { - m_minerType = MinerType::GPU; - miningThreads = 1; - } - } + m_minerType = MinerType::GPU; else if (arg == "--no-precompute") { - precompute = false; + m_precompute = false; } else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) { @@ -197,7 +185,7 @@ public: mode = OperationMode::DAGInit; try { - initDAG = stol(m); + m_initDAG = stol(m); } catch (...) { @@ -247,7 +235,7 @@ public: else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) { try { - miningThreads = stol(argv[++i]); + m_miningThreads = stol(argv[++i]); } catch (...) { @@ -262,20 +250,29 @@ public: void execute() { + if (m_shouldListDevices) + { + ProofOfWork::GPUMiner::listDevices(); + exit(0); + } + if (m_minerType == MinerType::CPU) - ProofOfWork::CPUMiner::setNumInstances(miningThreads); + ProofOfWork::CPUMiner::setNumInstances(m_miningThreads); else if (m_minerType == MinerType::GPU) { - ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); - ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); - ProofOfWork::GPUMiner::setNumInstances(miningThreads); + ProofOfWork::GPUMiner::setNumInstances(m_miningThreads); + if (!ProofOfWork::GPUMiner::configureGPU(m_openclPlatform, m_openclDevice, m_clAllowCPU)) + { + cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; + exit(1); + } } if (mode == OperationMode::DAGInit) - doInitDAG(initDAG); + doInitDAG(m_initDAG); else if (mode == OperationMode::Benchmark) - doBenchmark(m_minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); + doBenchmark(m_minerType, m_phoneHome, m_benchmarkWarmup, m_benchmarkTrial, m_benchmarkTrials); else if (mode == OperationMode::Farm) - doFarm(m_minerType, farmURL, farmRecheckPeriod); + doFarm(m_minerType, m_farmURL, m_farmRecheckPeriod); } static void streamHelp(ostream& _out) @@ -441,7 +438,7 @@ private: cnote << "Grabbing DAG for" << newSeedHash; if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) BOOST_THROW_EXCEPTION(DAGCreationFailure()); - if (precompute) + if (m_precompute) EthashAux::computeFull(sha3(newSeedHash), true); if (hh != current.headerHash) { @@ -490,22 +487,23 @@ private: /// Mining options MinerType m_minerType = MinerType::CPU; - unsigned openclPlatform = 0; - unsigned openclDevice = 0; - unsigned miningThreads = UINT_MAX; - unsigned dagChunks = 1; + unsigned m_openclPlatform = 0; + unsigned m_openclDevice = 0; + unsigned m_miningThreads = UINT_MAX; + bool m_shouldListDevices = false; + bool m_clAllowCPU = false; /// DAG initialisation param. - unsigned initDAG = 0; + unsigned m_initDAG = 0; /// Benchmarking params - bool phoneHome = true; - unsigned benchmarkWarmup = 3; - unsigned benchmarkTrial = 3; - unsigned benchmarkTrials = 5; + bool m_phoneHome = true; + unsigned m_benchmarkWarmup = 3; + unsigned m_benchmarkTrial = 3; + unsigned m_benchmarkTrials = 5; /// Farm params - string farmURL = "http://127.0.0.1:8545"; - unsigned farmRecheckPeriod = 500; - bool precompute = true; + string m_farmURL = "http://127.0.0.1:8545"; + unsigned m_farmRecheckPeriod = 500; + bool m_precompute = true; }; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 1a5eaddc3..db08d10c3 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -51,6 +51,8 @@ using namespace std; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl +// Types of OpenCL devices we are interested in +#define ETHCL_QUERIED_DEVICE_TYPES (CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR) static void addDefinition(string& _source, char const* _id, unsigned _value) { @@ -82,9 +84,8 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) } // get GPU device of the selected platform - vector devices; unsigned platform_num = min(_platformId, platforms.size() - 1); - platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); @@ -99,6 +100,17 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) return "{ \"platform\": \"" + platforms[platform_num].getInfo() + "\", \"device\": \"" + device.getInfo() + "\", \"version\": \"" + device_version + "\" }"; } +std::vector ethash_cl_miner::getDevices(std::vector const& _platforms, unsigned _platformId) +{ + vector devices; + unsigned platform_num = min(_platformId, _platforms.size() - 1); + _platforms[platform_num].getDevices( + s_allowCPU ? CL_DEVICE_TYPE_ALL : ETHCL_QUERIED_DEVICE_TYPES, + &devices + ); + return devices; +} + unsigned ethash_cl_miner::getNumPlatforms() { vector platforms; @@ -116,9 +128,7 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) return 0; } - vector devices; - unsigned platform_num = min(_platformId, platforms.size() - 1); - platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); @@ -127,8 +137,9 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) return devices.size(); } -bool ethash_cl_miner::configureGPU() +bool ethash_cl_miner::configureGPU(bool _allowCPU) { + s_allowCPU = _allowCPU; return searchForAllDevices([](cl::Device const _device) -> bool { cl_ulong result; @@ -152,6 +163,8 @@ bool ethash_cl_miner::configureGPU() ); } +bool ethash_cl_miner::s_allowCPU = false; + bool ethash_cl_miner::searchForAllDevices(function _callback) { vector platforms; @@ -175,8 +188,7 @@ bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, function= platforms.size()) return false; - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); for (cl::Device const& device: devices) if (_callback(device)) return true; @@ -204,8 +216,7 @@ void ethash_cl_miner::doForAllDevices(unsigned _platformId, function= platforms.size()) return; - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); for (cl::Device const& device: devices) _callback(device); } @@ -253,8 +264,7 @@ bool ethash_cl_miner::init( ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo().c_str()); // get GPU device of the default platform - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 4c986053a..44ec7eba9 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -40,7 +40,7 @@ public: static unsigned getNumDevices(unsigned _platformId = 0); static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); static void listDevices(); - static bool configureGPU(); + static bool configureGPU(bool _allowCPU); bool init( uint8_t const* _dag, @@ -56,6 +56,9 @@ public: void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook); private: + + static std::vector getDevices(std::vector const& _platforms, unsigned _platformId); + enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 }; cl::Context m_context; @@ -70,4 +73,5 @@ private: unsigned m_workgroup_size; bool m_opencl_1_1; + static bool s_allowCPU; }; diff --git a/libethash-cl/ethash_cl_miner_kernel.cl b/libethash-cl/ethash_cl_miner_kernel.cl index 8567bb164..2143435ed 100644 --- a/libethash-cl/ethash_cl_miner_kernel.cl +++ b/libethash-cl/ethash_cl_miner_kernel.cl @@ -585,4 +585,4 @@ __kernel void ethash_search_chunks( uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1)); g_output[slot] = gid; } -} \ No newline at end of file +} diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 9ac4474ba..20ba539d1 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -381,9 +381,11 @@ void Ethash::GPUMiner::listDevices() return ethash_cl_miner::listDevices(); } -bool Ethash::GPUMiner::configureGPU() +bool Ethash::GPUMiner::configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU) { - return ethash_cl_miner::configureGPU(); + s_platformId = _platformId; + s_deviceId = _deviceId; + return ethash_cl_miner::configureGPU(_allowCPU); } #endif diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 49a8ae006..ee4c7d008 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -87,11 +87,8 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); - static void setDefaultPlatform(unsigned) {} - static void setDagChunks(unsigned) {} - static void setDefaultDevice(unsigned) {} static void listDevices() {} - static bool configureGPU() { return false; } + static bool configureGPU(unsigned, unsigned, bool) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -120,9 +117,7 @@ public: static std::string platformInfo(); static unsigned getNumDevices(); static void listDevices(); - static bool configureGPU(); - static void setDefaultPlatform(unsigned _id) { s_platformId = _id; } - static void setDefaultDevice(unsigned _id) { s_deviceId = _id; } + static bool configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU); static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } protected: