|
|
@ -52,11 +52,11 @@ 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 |
|
|
|
|
|
|
|
static void add_definition(std::string& source, char const* id, unsigned value) |
|
|
|
static void addDefinition(string& _source, char const* _id, unsigned _value) |
|
|
|
{ |
|
|
|
char buf[256]; |
|
|
|
sprintf(buf, "#define %s %uu\n", id, value); |
|
|
|
source.insert(source.begin(), buf, buf + strlen(buf)); |
|
|
|
sprintf(buf, "#define %s %uu\n", _id, _value); |
|
|
|
_source.insert(_source.begin(), buf, buf + strlen(buf)); |
|
|
|
} |
|
|
|
|
|
|
|
ethash_cl_miner::search_hook::~search_hook() {} |
|
|
@ -71,44 +71,44 @@ ethash_cl_miner::~ethash_cl_miner() |
|
|
|
finish(); |
|
|
|
} |
|
|
|
|
|
|
|
std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) |
|
|
|
string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (platforms.empty()) |
|
|
|
{ |
|
|
|
ETHCL_LOG("No OpenCL platforms found."); |
|
|
|
return std::string(); |
|
|
|
return string(); |
|
|
|
} |
|
|
|
|
|
|
|
// get GPU device of the selected platform
|
|
|
|
std::vector<cl::Device> devices; |
|
|
|
unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
vector<cl::Device> devices; |
|
|
|
unsigned platform_num = min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
|
|
if (devices.empty()) |
|
|
|
{ |
|
|
|
ETHCL_LOG("No OpenCL devices found."); |
|
|
|
return std::string(); |
|
|
|
return string(); |
|
|
|
} |
|
|
|
|
|
|
|
// use selected default device
|
|
|
|
unsigned device_num = std::min<unsigned>(_deviceId, devices.size() - 1); |
|
|
|
unsigned device_num = min<unsigned>(_deviceId, devices.size() - 1); |
|
|
|
cl::Device& device = devices[device_num]; |
|
|
|
std::string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
|
|
|
string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
|
|
|
|
|
|
|
return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }"; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned ethash_cl_miner::getNumPlatforms() |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
return platforms.size(); |
|
|
|
} |
|
|
|
|
|
|
|
unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (platforms.empty()) |
|
|
|
{ |
|
|
@ -116,8 +116,8 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<cl::Device> devices; |
|
|
|
unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
vector<cl::Device> devices; |
|
|
|
unsigned platform_num = min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
|
|
if (devices.empty()) |
|
|
|
{ |
|
|
@ -152,9 +152,9 @@ bool ethash_cl_miner::configureGPU() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
bool ethash_cl_miner::searchForAllDevices(std::function<bool(cl::Device const&)> _callback) |
|
|
|
bool ethash_cl_miner::searchForAllDevices(function<bool(cl::Device const&)> _callback) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (platforms.empty()) |
|
|
|
{ |
|
|
@ -168,14 +168,14 @@ bool ethash_cl_miner::searchForAllDevices(std::function<bool(cl::Device const&)> |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, std::function<bool(cl::Device const&)> _callback) |
|
|
|
bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, function<bool(cl::Device const&)> _callback) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (_platformId >= platforms.size()) |
|
|
|
return false; |
|
|
|
|
|
|
|
std::vector<cl::Device> devices; |
|
|
|
vector<cl::Device> devices; |
|
|
|
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
|
|
for (cl::Device const& device: devices) |
|
|
|
if (_callback(device)) |
|
|
@ -184,9 +184,9 @@ bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, std::function<bo |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
void ethash_cl_miner::doForAllDevices(std::function<void(cl::Device const&)> _callback) |
|
|
|
void ethash_cl_miner::doForAllDevices(function<void(cl::Device const&)> _callback) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (platforms.empty()) |
|
|
|
{ |
|
|
@ -197,14 +197,14 @@ void ethash_cl_miner::doForAllDevices(std::function<void(cl::Device const&)> _ca |
|
|
|
doForAllDevices(i, _callback); |
|
|
|
} |
|
|
|
|
|
|
|
void ethash_cl_miner::doForAllDevices(unsigned _platformId, std::function<void(cl::Device const&)> _callback) |
|
|
|
void ethash_cl_miner::doForAllDevices(unsigned _platformId, function<void(cl::Device const&)> _callback) |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (_platformId >= platforms.size()) |
|
|
|
return; |
|
|
|
|
|
|
|
std::vector<cl::Device> devices; |
|
|
|
vector<cl::Device> devices; |
|
|
|
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
|
|
for (cl::Device const& device: devices) |
|
|
|
_callback(device); |
|
|
@ -212,7 +212,7 @@ void ethash_cl_miner::doForAllDevices(unsigned _platformId, std::function<void(c |
|
|
|
|
|
|
|
void ethash_cl_miner::listDevices() |
|
|
|
{ |
|
|
|
std::string outString ="\nListing OpenCL devices.\nFORMAT: [deviceID] deviceName\n"; |
|
|
|
string outString ="\nListing OpenCL devices.\nFORMAT: [deviceID] deviceName\n"; |
|
|
|
unsigned int i = 0; |
|
|
|
doForAllDevices([&outString, &i](cl::Device const _device) |
|
|
|
{ |
|
|
@ -240,7 +240,7 @@ bool ethash_cl_miner::init( |
|
|
|
// get all platforms
|
|
|
|
try |
|
|
|
{ |
|
|
|
std::vector<cl::Platform> platforms; |
|
|
|
vector<cl::Platform> platforms; |
|
|
|
cl::Platform::get(&platforms); |
|
|
|
if (platforms.empty()) |
|
|
|
{ |
|
|
@ -249,11 +249,11 @@ bool ethash_cl_miner::init( |
|
|
|
} |
|
|
|
|
|
|
|
// use selected platform
|
|
|
|
_platformId = std::min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
_platformId = min<unsigned>(_platformId, platforms.size() - 1); |
|
|
|
ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str()); |
|
|
|
|
|
|
|
// get GPU device of the default platform
|
|
|
|
std::vector<cl::Device> devices; |
|
|
|
vector<cl::Device> devices; |
|
|
|
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
|
|
if (devices.empty()) |
|
|
|
{ |
|
|
@ -262,8 +262,8 @@ bool ethash_cl_miner::init( |
|
|
|
} |
|
|
|
|
|
|
|
// use selected device
|
|
|
|
cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)]; |
|
|
|
std::string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
|
|
|
cl::Device& device = devices[min<unsigned>(_deviceId, devices.size() - 1)]; |
|
|
|
string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
|
|
|
ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")"); |
|
|
|
|
|
|
|
// configure chunk number depending on max allocateable memory
|
|
|
@ -279,7 +279,7 @@ bool ethash_cl_miner::init( |
|
|
|
m_opencl_1_1 = true; |
|
|
|
|
|
|
|
// create context
|
|
|
|
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1)); |
|
|
|
m_context = cl::Context(vector<cl::Device>(&device, &device + 1)); |
|
|
|
m_queue = cl::CommandQueue(m_context, device); |
|
|
|
|
|
|
|
// use requested workgroup size, but we require multiple of 8
|
|
|
@ -288,11 +288,11 @@ bool ethash_cl_miner::init( |
|
|
|
// patch source code
|
|
|
|
// note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled
|
|
|
|
// into a byte array by bin2h.cmake. There is no need to load the file by hand in runtime
|
|
|
|
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE); |
|
|
|
add_definition(code, "GROUP_SIZE", m_workgroup_size); |
|
|
|
add_definition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES)); |
|
|
|
add_definition(code, "ACCESSES", ETHASH_ACCESSES); |
|
|
|
add_definition(code, "MAX_OUTPUTS", c_max_search_results); |
|
|
|
string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE); |
|
|
|
addDefinition(code, "GROUP_SIZE", m_workgroup_size); |
|
|
|
addDefinition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES)); |
|
|
|
addDefinition(code, "ACCESSES", ETHASH_ACCESSES); |
|
|
|
addDefinition(code, "MAX_OUTPUTS", c_max_search_results); |
|
|
|
//debugf("%s", code.c_str());
|
|
|
|
|
|
|
|
// create miner OpenCL program
|
|
|
@ -392,7 +392,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook |
|
|
|
uint64_t start_nonce; |
|
|
|
unsigned buf; |
|
|
|
}; |
|
|
|
std::queue<pending_batch> pending; |
|
|
|
queue<pending_batch> pending; |
|
|
|
|
|
|
|
static uint32_t const c_zero = 0; |
|
|
|
|
|
|
@ -418,8 +418,8 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook |
|
|
|
m_search_kernel.setArg(argPos + 2, ~0u); |
|
|
|
|
|
|
|
unsigned buf = 0; |
|
|
|
std::random_device engine; |
|
|
|
uint64_t start_nonce = std::uniform_int_distribution<uint64_t>()(engine); |
|
|
|
random_device engine; |
|
|
|
uint64_t start_nonce = uniform_int_distribution<uint64_t>()(engine); |
|
|
|
for (;; start_nonce += c_search_batch_size) |
|
|
|
{ |
|
|
|
// supply output buffer to kernel
|
|
|
@ -442,7 +442,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook |
|
|
|
|
|
|
|
// could use pinned host pointer instead
|
|
|
|
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1 + c_max_search_results) * sizeof(uint32_t)); |
|
|
|
unsigned num_found = std::min<unsigned>(results[0], c_max_search_results); |
|
|
|
unsigned num_found = min<unsigned>(results[0], c_max_search_results); |
|
|
|
|
|
|
|
uint64_t nonces[c_max_search_results]; |
|
|
|
for (unsigned i = 0; i != num_found; ++i) |
|
|
|