Skip to content
This repository has been archived by the owner on Apr 24, 2022. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release/0.13
Browse files Browse the repository at this point in the history
# Conflicts:
#	libethash-cuda/CUDAMiner.cpp
  • Loading branch information
chfast committed Jan 7, 2018
2 parents f2049e1 + 37b1de2 commit d74fbf1
Show file tree
Hide file tree
Showing 17 changed files with 849 additions and 383 deletions.
58 changes: 36 additions & 22 deletions ethminer/MinerAux.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,18 @@ class MinerCLI
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if (arg == "--cl-kernel" && i + 1 < argc)
{
try
{
m_openclSelectedKernel = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
BOOST_THROW_EXCEPTION(BadArgument());
}
}
#endif
#if ETH_ETHASHCL || ETH_ETHASHCUDA
else if ((arg == "--cl-global-work" || arg == "--cuda-grid-size") && i + 1 < argc)
Expand Down Expand Up @@ -501,7 +513,9 @@ class MinerCLI
m_miningThreads = m_openclDeviceCount;
}

CLMiner::setCLKernel(m_openclSelectedKernel);
CLMiner::setThreadsPerHash(m_openclThreadsPerHash);

if (!CLMiner::configureGPU(
m_localWorkSize,
m_globalWorkSizeMultiplier,
Expand Down Expand Up @@ -601,11 +615,17 @@ class MinerCLI
<< " sequential - load DAG on GPUs one after another. Use this when the miner crashes during DAG generation" << endl
<< " single <n> - generate DAG on device n, then copy to other devices" << endl
#if ETH_ETHASHCL
<< " OpenCL configuration:" << endl
<< " --cl-kernel <n> Use a different OpenCL kernel (default: use stable kernel)" << endl
<< " 0: stable kernel" << endl
<< " 1: unstable kernel" << endl
// << " 2: experimental kernel" << endl
<< " --cl-local-work Set the OpenCL local work size. Default is " << CLMiner::c_defaultLocalWorkSize << endl
<< " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << CLMiner::c_defaultGlobalWorkSizeMultiplier << " * " << CLMiner::c_defaultLocalWorkSize << endl
<< " --cl-parallel-hash <1 2 ..8> Define how many threads to associate per hash. Default=8" << endl
#endif
#if ETH_ETHASHCUDA
<< " CUDA configuration:" << endl
<< " --cuda-block-size Set the CUDA block work size. Default is " << toString(ethash_cuda_miner::c_defaultBlockSize) << endl
<< " --cuda-grid-size Set the CUDA grid size. Default is " << toString(ethash_cuda_miner::c_defaultGridSize) << endl
<< " --cuda-streams Set the number of CUDA streams. Default is " << toString(ethash_cuda_miner::c_defaultNumStreams) << endl
Expand All @@ -618,6 +638,7 @@ class MinerCLI
<< " --cuda-parallel-hash <1 2 ..8> Define how many hashes to calculate in a kernel, can be scaled to achieve better performance. Default=4" << endl
#endif
#if API_CORE
<< " API core configuration:" << endl
<< " --api-port Set the api port, the miner should listen to. Use 0 to disable. Default=0, use negative numbers to run in readonly mode. for example -3333." << endl
#endif
;
Expand Down Expand Up @@ -856,30 +877,22 @@ class MinerCLI
}
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
}
if (EthashAux::eval(solution.seedHash, solution.headerHash, solution.nonce).value < solution.boundary)
{
bool ok = prpc->eth_submitWork("0x" + toHex(solution.nonce), "0x" + toString(solution.headerHash), "0x" + toString(solution.mixHash));
if (ok) {
cnote << "Solution found; Submitted to" << _remote << "...";
cnote << " Nonce:" << solution.nonce;
cnote << " headerHash:" << solution.headerHash.hex();
cnote << " mixHash:" << solution.mixHash.hex();
cnote << EthLime << "Accepted." << EthReset;
f.acceptedSolution(false);
}
else {
cwarn << "Solution found; Submitted to" << _remote << "...";
cwarn << " Nonce:" << solution.nonce;
cwarn << " headerHash:" << solution.headerHash.hex();
cwarn << " mixHash:" << solution.mixHash.hex();
cwarn << "Not accepted.";
f.rejectedSolution(false);
}
//exit(0);
bool ok = prpc->eth_submitWork("0x" + toHex(solution.nonce), "0x" + toString(solution.headerHash), "0x" + toString(solution.mixHash));
if (ok) {
cnote << "Solution found; Submitted to" << _remote;
cnote << " Nonce:" << solution.nonce;
cnote << " headerHash:" << solution.headerHash.hex();
cnote << " mixHash:" << solution.mixHash.hex();
cnote << EthLime << " Accepted." << EthReset;
f.acceptedSolution(solution.stale);
}
else {
f.failedSolution();
cwarn << "FAILURE: GPU gave incorrect result!";
cwarn << "Solution found; Submitted to" << _remote;
cwarn << " Nonce:" << solution.nonce;
cwarn << " headerHash:" << solution.headerHash.hex();
cwarn << " mixHash:" << solution.mixHash.hex();
cwarn << EthYellow << " Rejected." << EthReset;
f.rejectedSolution(solution.stale);
}
}
catch (jsonrpc::JsonRpcException&)
Expand Down Expand Up @@ -1056,6 +1069,7 @@ class MinerCLI
unsigned m_miningThreads = UINT_MAX;
bool m_shouldListDevices = false;
#if ETH_ETHASHCL
unsigned m_openclSelectedKernel = 0; ///< A numeric value for the selected OpenCL kernel
unsigned m_openclDeviceCount = 0;
unsigned m_openclDevices[16];
unsigned m_openclThreadsPerHash = 8;
Expand Down
204 changes: 195 additions & 9 deletions libethash-cl/CLMiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

#include "CLMiner.h"
#include <libethash/internal.h>
#include "CLMiner_kernel.h"
#include "CLMiner_kernel_stable.h"
#include "CLMiner_kernel_unstable.h"

using namespace dev;
using namespace eth;
Expand All @@ -18,6 +19,7 @@ namespace eth
unsigned CLMiner::s_workgroupSize = CLMiner::c_defaultLocalWorkSize;
unsigned CLMiner::s_initialGlobalWorkSize = CLMiner::c_defaultGlobalWorkSizeMultiplier * CLMiner::c_defaultLocalWorkSize;
unsigned CLMiner::s_threadsPerHash = 8;
CLKernelName CLMiner::s_clKernelName = CLMiner::c_defaultKernelName;

constexpr size_t c_maxSearchResults = 1;

Expand All @@ -30,6 +32,172 @@ struct CLChannel: public LogChannel
#define cllog clog(CLChannel)
#define ETHCL_LOG(_contents) cllog << _contents

/**
* Returns the name of a numerical cl_int error
* Takes constants from CL/cl.h and returns them in a readable format
*/
static const char *strClError(cl_int err) {

switch (err) {
case CL_SUCCESS:
return "CL_SUCCESS";
case CL_DEVICE_NOT_FOUND:
return "CL_DEVICE_NOT_FOUND";
case CL_DEVICE_NOT_AVAILABLE:
return "CL_DEVICE_NOT_AVAILABLE";
case CL_COMPILER_NOT_AVAILABLE:
return "CL_COMPILER_NOT_AVAILABLE";
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
case CL_OUT_OF_RESOURCES:
return "CL_OUT_OF_RESOURCES";
case CL_OUT_OF_HOST_MEMORY:
return "CL_OUT_OF_HOST_MEMORY";
case CL_PROFILING_INFO_NOT_AVAILABLE:
return "CL_PROFILING_INFO_NOT_AVAILABLE";
case CL_MEM_COPY_OVERLAP:
return "CL_MEM_COPY_OVERLAP";
case CL_IMAGE_FORMAT_MISMATCH:
return "CL_IMAGE_FORMAT_MISMATCH";
case CL_IMAGE_FORMAT_NOT_SUPPORTED:
return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
case CL_BUILD_PROGRAM_FAILURE:
return "CL_BUILD_PROGRAM_FAILURE";
case CL_MAP_FAILURE:
return "CL_MAP_FAILURE";
case CL_MISALIGNED_SUB_BUFFER_OFFSET:
return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";

#ifdef CL_VERSION_1_2
case CL_COMPILE_PROGRAM_FAILURE:
return "CL_COMPILE_PROGRAM_FAILURE";
case CL_LINKER_NOT_AVAILABLE:
return "CL_LINKER_NOT_AVAILABLE";
case CL_LINK_PROGRAM_FAILURE:
return "CL_LINK_PROGRAM_FAILURE";
case CL_DEVICE_PARTITION_FAILED:
return "CL_DEVICE_PARTITION_FAILED";
case CL_KERNEL_ARG_INFO_NOT_AVAILABLE:
return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE";
#endif // CL_VERSION_1_2

case CL_INVALID_VALUE:
return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE_TYPE:
return "CL_INVALID_DEVICE_TYPE";
case CL_INVALID_PLATFORM:
return "CL_INVALID_PLATFORM";
case CL_INVALID_DEVICE:
return "CL_INVALID_DEVICE";
case CL_INVALID_CONTEXT:
return "CL_INVALID_CONTEXT";
case CL_INVALID_QUEUE_PROPERTIES:
return "CL_INVALID_QUEUE_PROPERTIES";
case CL_INVALID_COMMAND_QUEUE:
return "CL_INVALID_COMMAND_QUEUE";
case CL_INVALID_HOST_PTR:
return "CL_INVALID_HOST_PTR";
case CL_INVALID_MEM_OBJECT:
return "CL_INVALID_MEM_OBJECT";
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
case CL_INVALID_IMAGE_SIZE:
return "CL_INVALID_IMAGE_SIZE";
case CL_INVALID_SAMPLER:
return "CL_INVALID_SAMPLER";
case CL_INVALID_BINARY:
return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS:
return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_PROGRAM:
return "CL_INVALID_PROGRAM";
case CL_INVALID_PROGRAM_EXECUTABLE:
return "CL_INVALID_PROGRAM_EXECUTABLE";
case CL_INVALID_KERNEL_NAME:
return "CL_INVALID_KERNEL_NAME";
case CL_INVALID_KERNEL_DEFINITION:
return "CL_INVALID_KERNEL_DEFINITION";
case CL_INVALID_KERNEL:
return "CL_INVALID_KERNEL";
case CL_INVALID_ARG_INDEX:
return "CL_INVALID_ARG_INDEX";
case CL_INVALID_ARG_VALUE:
return "CL_INVALID_ARG_VALUE";
case CL_INVALID_ARG_SIZE:
return "CL_INVALID_ARG_SIZE";
case CL_INVALID_KERNEL_ARGS:
return "CL_INVALID_KERNEL_ARGS";
case CL_INVALID_WORK_DIMENSION:
return "CL_INVALID_WORK_DIMENSION";
case CL_INVALID_WORK_GROUP_SIZE:
return "CL_INVALID_WORK_GROUP_SIZE";
case CL_INVALID_WORK_ITEM_SIZE:
return "CL_INVALID_WORK_ITEM_SIZE";
case CL_INVALID_GLOBAL_OFFSET:
return "CL_INVALID_GLOBAL_OFFSET";
case CL_INVALID_EVENT_WAIT_LIST:
return "CL_INVALID_EVENT_WAIT_LIST";
case CL_INVALID_EVENT:
return "CL_INVALID_EVENT";
case CL_INVALID_OPERATION:
return "CL_INVALID_OPERATION";
case CL_INVALID_GL_OBJECT:
return "CL_INVALID_GL_OBJECT";
case CL_INVALID_BUFFER_SIZE:
return "CL_INVALID_BUFFER_SIZE";
case CL_INVALID_MIP_LEVEL:
return "CL_INVALID_MIP_LEVEL";
case CL_INVALID_GLOBAL_WORK_SIZE:
return "CL_INVALID_GLOBAL_WORK_SIZE";
case CL_INVALID_PROPERTY:
return "CL_INVALID_PROPERTY";

#ifdef CL_VERSION_1_2
case CL_INVALID_IMAGE_DESCRIPTOR:
return "CL_INVALID_IMAGE_DESCRIPTOR";
case CL_INVALID_COMPILER_OPTIONS:
return "CL_INVALID_COMPILER_OPTIONS";
case CL_INVALID_LINKER_OPTIONS:
return "CL_INVALID_LINKER_OPTIONS";
case CL_INVALID_DEVICE_PARTITION_COUNT:
return "CL_INVALID_DEVICE_PARTITION_COUNT";
#endif // CL_VERSION_1_2

#ifdef CL_VERSION_2_0
case CL_INVALID_PIPE_SIZE:
return "CL_INVALID_PIPE_SIZE";
case CL_INVALID_DEVICE_QUEUE:
return "CL_INVALID_DEVICE_QUEUE";
#endif // CL_VERSION_2_0

#ifdef CL_VERSION_2_2
case CL_INVALID_SPEC_ID:
return "CL_INVALID_SPEC_ID";
case CL_MAX_SIZE_RESTRICTION_EXCEEDED:
return "CL_MAX_SIZE_RESTRICTION_EXCEEDED";
#endif // CL_VERSION_2_2
}

return "Unknown CL error encountered";
}

/**
* Prints cl::Errors in a uniform way
* @param msg text prepending the error message
* @param clerr cl:Error object
*
* Prints errors in the format:
* msg: what(), string err() (numeric err())
*/
static std::string ethCLErrorHelper(const char *msg, cl::Error const &clerr) {
std::ostringstream osstream;
osstream << msg << ": " << clerr.what() << ": " << strClError(clerr.err())
<< " (" << clerr.err() << ")";
return osstream.str();
}

namespace
{

Expand Down Expand Up @@ -103,9 +271,11 @@ void CLMiner::report(uint64_t _nonce, WorkPackage const& _w)
// TODO: Why re-evaluating?
Result r = EthashAux::eval(_w.seed, _w.header, _nonce);
if (r.value < _w.boundary)
farm.submitProof(Solution{_nonce, r.mixHash, _w.header, _w.seed, _w.boundary});
else
cwarn << "Invalid solution";
farm.submitProof(Solution{_nonce, r.mixHash, _w.header, _w.seed, _w.boundary, _w.job, false});
else {
farm.failedSolution();
cwarn << "FAILURE: GPU gave incorrect result!";
}
}

void CLMiner::kickOff()
Expand Down Expand Up @@ -229,7 +399,7 @@ void CLMiner::workLoop()
}
catch (cl::Error const& _e)
{
cwarn << "OpenCL Error:" << _e.what() << _e.err();
cwarn << ethCLErrorHelper("OpenCL Error", _e);
}
}

Expand Down Expand Up @@ -464,10 +634,26 @@ bool CLMiner::init(const h256& seed)
uint32_t lightSize64 = (unsigned)(light->data().size() / sizeof(node));

// patch source code
// note: CLMiner_kernel is simply ethash_cl_miner_kernel.cl compiled
// note: The kernels here are simply compiled version of the respective .cl kernels
// into a byte array by bin2h.cmake. There is no need to load the file by hand in runtime
// See libethash-cl/CMakeLists.txt: add_custom_command()
// TODO: Just use C++ raw string literal.
string code(CLMiner_kernel, CLMiner_kernel + sizeof(CLMiner_kernel));
string code;

if ( s_clKernelName == CLKernelName::Unstable ) {
cllog << "OpenCL kernel: Unstable kernel";
code = string(CLMiner_kernel_unstable, CLMiner_kernel_unstable + sizeof(CLMiner_kernel_unstable));
}
else { //if(s_clKernelName == CLKernelName::Stable)
cllog << "OpenCL kernel: Stable kernel";

//CLMiner_kernel_stable.cl will do a #undef THREADS_PER_HASH
if(s_threadsPerHash != 8) {
cwarn << "The current stable OpenCL kernel only supports exactly 8 threads. Thread parameter will be ignored.";
}

code = string(CLMiner_kernel_stable, CLMiner_kernel_stable + sizeof(CLMiner_kernel_stable));
}
addDefinition(code, "GROUP_SIZE", m_workgroupSize);
addDefinition(code, "DAG_SIZE", dagSize128);
addDefinition(code, "LIGHT_SIZE", lightSize64);
Expand Down Expand Up @@ -506,7 +692,7 @@ bool CLMiner::init(const h256& seed)
}
catch (cl::Error const& err)
{
cwarn << "Creating DAG buffer failed:" << err.what() << err.err();
cwarn << ethCLErrorHelper("Creating DAG buffer failed", err);
return false;
}
// create buffer for header
Expand Down Expand Up @@ -543,7 +729,7 @@ bool CLMiner::init(const h256& seed)
}
catch (cl::Error const& err)
{
cwarn << err.what() << "(" << err.err() << ")";
cwarn << ethCLErrorHelper("OpenCL init failed", err);
return false;
}
return true;
Expand Down
Loading

0 comments on commit d74fbf1

Please sign in to comment.