Bubbling opencl configuration upward.

This commit is contained in:
clemahieu 2016-04-06 23:18:36 -05:00
commit 52ec609079
13 changed files with 131 additions and 104 deletions

View file

@ -19,7 +19,7 @@ TEST (node, block_store_path_failure)
auto service (boost::make_shared <boost::asio::io_service> ());
rai::alarm alarm (*service);
rai::logging logging;
rai::work_pool work (false);
rai::work_pool work (nullptr);
auto node (std::make_shared <rai::node> (init, *service, 0, rai::unique_path (), alarm, logging, work));
ASSERT_TRUE (node->wallets.items.empty ());
node->stop ();
@ -31,7 +31,7 @@ TEST (node, inactive_supply)
auto service (boost::make_shared <boost::asio::io_service> ());
rai::alarm alarm (*service);
rai::node_config config;
rai::work_pool work (false);
rai::work_pool work (nullptr);
config.inactive_supply = 10;
auto node (std::make_shared <rai::node> (init, *service, rai::unique_path (), alarm, config, work));
ASSERT_EQ (10, node->ledger.inactive_supply);
@ -43,7 +43,7 @@ TEST (node, password_fanout)
auto service (boost::make_shared <boost::asio::io_service> ());
rai::alarm alarm (*service);
rai::node_config config;
rai::work_pool work (false);
rai::work_pool work (nullptr);
config.password_fanout = 10;
auto node (std::make_shared <rai::node> (init, *service, rai::unique_path (), alarm, config, work));
auto wallet (node->wallets.create (100));

View file

@ -4,7 +4,7 @@
TEST (work, one)
{
rai::work_pool pool (false);
rai::work_pool pool (nullptr);
rai::change_block block (1, 1, rai::keypair ().prv, 3, 4);
block.block_work_set (pool.generate (block.root ()));
ASSERT_FALSE (pool.work_validate (block));
@ -12,7 +12,7 @@ TEST (work, one)
TEST (work, validate)
{
rai::work_pool pool (false);
rai::work_pool pool (nullptr);
rai::send_block send_block (1, 1, 2, rai::keypair ().prv, 4, 6);
ASSERT_TRUE (pool.work_validate (send_block));
send_block.block_work_set (pool.generate (send_block.root ()));
@ -21,7 +21,7 @@ TEST (work, validate)
TEST (work, cancel)
{
rai::work_pool pool (false);
rai::work_pool pool (nullptr);
rai::uint256_union key (1);
bool exited (false);
std::thread thread ([&pool, &key, &exited] ()
@ -41,7 +41,9 @@ TEST (work, cancel)
TEST (work, opencl)
{
rai::work_pool pool (true);
auto work (rai::opencl_work::create (true, 0, 1));
ASSERT_NE (nullptr, work);
rai::work_pool pool (std::move (work));
ASSERT_NE (nullptr, pool.opencl);
rai::uint256_union root;
for (auto i (0); i < 1; ++i)

View file

@ -2968,7 +2968,7 @@ bool rai::handle_node_options (boost::program_options::variables_map & vm)
rai::inactive_node::inactive_node () :
service (boost::make_shared <boost::asio::io_service> ()),
alarm (*service),
work (false)
work (nullptr)
{
auto working (rai::working_path ());
boost::filesystem::create_directories (working);

View file

@ -308,6 +308,8 @@ public:
unsigned io_threads;
unsigned work_threads;
bool opencl_work;
unsigned opencl_platform;
unsigned opencl_device;
static std::chrono::seconds constexpr keepalive_period = std::chrono::seconds (60);
static std::chrono::seconds constexpr keepalive_cutoff = keepalive_period * 5;
static std::chrono::minutes constexpr wallet_backup_interval = std::chrono::minutes (5);

View file

@ -396,15 +396,16 @@ rai::opencl_environment::opencl_environment (bool & error_a)
clGetPlatformIDs (platformIdCount, platformIds.data(), nullptr);
for (auto i (platformIds.begin ()), n (platformIds.end ()); i != n; ++i)
{
auto & devices_container (devices [*i]);
rai::opencl_platform platform;
cl_uint deviceIdCount = 0;
clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, 0, nullptr, &deviceIdCount);
std::vector <cl_device_id> deviceIds (deviceIdCount);
clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, deviceIdCount, deviceIds.data (), nullptr);
for (auto j (deviceIds.begin ()), m (deviceIds.end ()); j != m; ++j)
{
devices_container.push_back (*j);
platform.devices.push_back (*j);
}
platforms.push_back (platform);
}
}
@ -412,27 +413,27 @@ void rai::opencl_environment::dump ()
{
auto index (0);
auto device_count (0);
for (auto & i: devices)
for (auto & i: platforms)
{
device_count += i.second.size ();
device_count += i.devices.size ();
}
std::cout << boost::str (boost::format ("Found %1% platforms and %2% devices\n") % devices.size () % device_count);
for (auto i (devices.begin ()), n (devices.end ()); i != n; ++i, ++index)
std::cout << boost::str (boost::format ("Found %1% platforms and %2% devices\n") % platforms.size () % device_count);
for (auto i (platforms.begin ()), n (platforms.end ()); i != n; ++i, ++index)
{
std::vector <unsigned> queries = {CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS};
std::cout << "Platform: " << index << std::endl;
for (auto j (queries.begin ()), m (queries.end ()); j != m; ++j)
{
size_t platformInfoCount = 0;
clGetPlatformInfo(i->first, *j, 0, nullptr, &platformInfoCount);
clGetPlatformInfo(i->platform, *j, 0, nullptr, &platformInfoCount);
std::vector <char> info (platformInfoCount);
clGetPlatformInfo(i->first, *j, info.size (), info.data (), nullptr);
clGetPlatformInfo(i->platform, *j, info.size (), info.data (), nullptr);
std::cout << info.data () << std::endl;
}
for (auto j (i->second.begin ()), m (i->second.end ()); j != m; ++j)
for (auto j (i->devices.begin ()), m (i->devices.end ()); j != m; ++j)
{
std::vector <unsigned> queries = {CL_DEVICE_NAME, CL_DEVICE_VENDOR, CL_DEVICE_PROFILE};
std::cout << "Device: " << j - i->second.begin () << std::endl;
std::cout << "Device: " << j - i->devices.begin () << std::endl;
for (auto k (queries.begin ()), o (queries.end ()); k != o; ++k)
{
size_t platformInfoCount = 0;
@ -483,95 +484,101 @@ void rai::opencl_environment::dump ()
}
}
rai::opencl_work::opencl_work (bool & error_a, rai::opencl_environment & environment_a, rai::work_pool & pool_a) :
rai::opencl_work::opencl_work (bool & error_a, unsigned platform_a, unsigned device_a, rai::opencl_environment & environment_a) :
context (0),
attempt_buffer (0),
result_buffer (0),
item_buffer (0),
program (0),
kernel (0),
queue (0),
pool (pool_a)
queue (0)
{
rai::random_pool.GenerateBlock (reinterpret_cast <uint8_t *> (rand.s.data ()), rand.s.size () * sizeof (decltype (rand.s)::value_type));
auto i (environment_a.devices.begin ());
auto selected_platform (i->first);
std::array <cl_device_id, 1> selected_devices;
selected_devices [0] = i->second [0];
cl_context_properties contextProperties [] =
{
CL_CONTEXT_PLATFORM,
reinterpret_cast<cl_context_properties> (selected_platform),
0, 0
};
cl_int createContextError (0);
context = clCreateContext (contextProperties, selected_devices.size (), selected_devices.data (), nullptr, nullptr, &createContextError);
error_a |= createContextError != CL_SUCCESS;
error_a |= platform_a >= environment_a.platforms.size ();
if (!error_a)
{
cl_int queue_error (0);
queue = clCreateCommandQueue (context, selected_devices [0], 0, &queue_error);
error_a |= queue_error != CL_SUCCESS;
if (!error_a)
auto & platform (environment_a.platforms [platform_a]);
error_a |= device_a >= platform.devices.size ();
if (error_a)
{
cl_int attempt_error (0);
attempt_buffer = clCreateBuffer (context, 0, sizeof (uint64_t), nullptr, &attempt_error);
error_a |= attempt_error != CL_SUCCESS;
rai::random_pool.GenerateBlock (reinterpret_cast <uint8_t *> (rand.s.data ()), rand.s.size () * sizeof (decltype (rand.s)::value_type));
std::array <cl_device_id, 1> selected_devices;
selected_devices [0] = platform.devices [device_a];
cl_context_properties contextProperties [] =
{
CL_CONTEXT_PLATFORM,
reinterpret_cast<cl_context_properties> (platform.platform),
0, 0
};
cl_int createContextError (0);
context = clCreateContext (contextProperties, selected_devices.size (), selected_devices.data (), nullptr, nullptr, &createContextError);
error_a |= createContextError != CL_SUCCESS;
if (!error_a)
{
cl_int result_error (0);
result_buffer = clCreateBuffer (context, 0, sizeof (uint64_t), nullptr, &result_error);
error_a |= result_error != CL_SUCCESS;
cl_int queue_error (0);
queue = clCreateCommandQueue (context, selected_devices [0], 0, &queue_error);
error_a |= queue_error != CL_SUCCESS;
if (!error_a)
{
cl_int item_error (0);
size_t item_size (sizeof (rai::uint256_union));
item_buffer = clCreateBuffer (context, 0, item_size, nullptr, &item_error);
error_a |= item_error != CL_SUCCESS;
cl_int attempt_error (0);
attempt_buffer = clCreateBuffer (context, 0, sizeof (uint64_t), nullptr, &attempt_error);
error_a |= attempt_error != CL_SUCCESS;
if (!error_a)
{
cl_int program_error (0);
char const * program_data (opencl_program.data ());
size_t program_length (opencl_program.size ());
program = clCreateProgramWithSource (context, 1, &program_data, &program_length, &program_error);
error_a |= program_error != CL_SUCCESS;
cl_int result_error (0);
result_buffer = clCreateBuffer (context, 0, sizeof (uint64_t), nullptr, &result_error);
error_a |= result_error != CL_SUCCESS;
if (!error_a)
{
auto clBuildProgramError(clBuildProgram(program, selected_devices.size(), selected_devices.data(), "-D __APPLE__", nullptr, nullptr));
error_a |= clBuildProgramError != CL_SUCCESS;
cl_int item_error (0);
size_t item_size (sizeof (rai::uint256_union));
item_buffer = clCreateBuffer (context, 0, item_size, nullptr, &item_error);
error_a |= item_error != CL_SUCCESS;
if (!error_a)
{
cl_int kernel_error (0);
kernel = clCreateKernel (program, "raiblocks_work", &kernel_error);
error_a |= kernel_error != CL_SUCCESS;
cl_int program_error (0);
char const * program_data (opencl_program.data ());
size_t program_length (opencl_program.size ());
program = clCreateProgramWithSource (context, 1, &program_data, &program_length, &program_error);
error_a |= program_error != CL_SUCCESS;
if (!error_a)
{
cl_int arg0_error (clSetKernelArg (kernel, 0, sizeof (attempt_buffer), &attempt_buffer));
error_a |= arg0_error != CL_SUCCESS;
auto clBuildProgramError(clBuildProgram(program, selected_devices.size(), selected_devices.data(), "-D __APPLE__", nullptr, nullptr));
error_a |= clBuildProgramError != CL_SUCCESS;
if (!error_a)
{
cl_int arg1_error (clSetKernelArg (kernel, 1, sizeof (result_buffer), &result_buffer));
error_a |= arg1_error != CL_SUCCESS;
cl_int kernel_error (0);
kernel = clCreateKernel (program, "raiblocks_work", &kernel_error);
error_a |= kernel_error != CL_SUCCESS;
if (!error_a)
{
cl_int arg2_error (clSetKernelArg (kernel, 2, sizeof (item_buffer), &item_buffer));
error_a |= arg2_error != CL_SUCCESS;
cl_int arg0_error (clSetKernelArg (kernel, 0, sizeof (attempt_buffer), &attempt_buffer));
error_a |= arg0_error != CL_SUCCESS;
if (!error_a)
{
cl_int arg1_error (clSetKernelArg (kernel, 1, sizeof (result_buffer), &result_buffer));
error_a |= arg1_error != CL_SUCCESS;
if (!error_a)
{
cl_int arg2_error (clSetKernelArg (kernel, 2, sizeof (item_buffer), &item_buffer));
error_a |= arg2_error != CL_SUCCESS;
}
}
}
}
else
{
/*
for (auto i (selected_devices.begin ()), n (selected_devices.end ()); i != n; ++i)
{
size_t log_size (0);
clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
std::vector <char> log (log_size);
clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, log.size (), log.data (), nullptr);
std::cout << log.data () << std::endl;
}*/
}
}
}
else
{
/*
for (auto i (selected_devices.begin ()), n (selected_devices.end ()); i != n; ++i)
{
size_t log_size (0);
clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
std::vector <char> log (log_size);
clGetProgramBuildInfo (program, *i, CL_PROGRAM_BUILD_LOG, log.size (), log.data (), nullptr);
std::cout << log.data () << std::endl;
}*/
}
}
}
}
@ -587,13 +594,13 @@ rai::opencl_work::~opencl_work ()
clReleaseContext (context);
}
uint64_t rai::opencl_work::generate_work (rai::uint256_union const & root_a)
uint64_t rai::opencl_work::generate_work (rai::work_pool & pool_a, rai::uint256_union const & root_a)
{
std::lock_guard <std::mutex> lock (mutex);
uint64_t result (0);
unsigned thread_count (rai::rai_network == rai::rai_networks::rai_test_network ? 128 : 1024 * 1024);
size_t work_size [] = { thread_count, 0, 0 };
while (pool.work_validate (root_a, result))
while (pool_a.work_validate (root_a, result))
{
result = rand.next ();
cl_int write_error1 = clEnqueueWriteBuffer (queue, attempt_buffer, false, 0, sizeof (uint64_t), &result, 0, nullptr, nullptr);
@ -604,3 +611,22 @@ uint64_t rai::opencl_work::generate_work (rai::uint256_union const & root_a)
}
return result;
}
std::unique_ptr <rai::opencl_work> rai::opencl_work::create (bool create_a, unsigned platform_a, unsigned device_a)
{
std::unique_ptr <rai::opencl_work> result;
if (create_a)
{
auto error (false);
rai::opencl_environment environment (error);
if (!error)
{
result.reset (new rai::opencl_work (error, platform_a, device_a, environment));
if (error)
{
result.reset ();
}
}
}
return result;
}

View file

@ -14,21 +14,28 @@
namespace rai
{
class opencl_platform
{
public:
cl_platform_id platform;
std::vector <cl_device_id> devices;
};
class opencl_environment
{
public:
opencl_environment (bool &);
void dump ();
std::map <cl_platform_id, std::vector <cl_device_id>> devices;
std::vector <rai::opencl_platform> platforms;
};
union uint256_union;
class work_pool;
class opencl_work
{
public:
opencl_work (bool &, rai::opencl_environment &, rai::work_pool &);
opencl_work (bool &, unsigned, unsigned, rai::opencl_environment &);
~opencl_work ();
uint64_t generate_work (rai::uint256_union const &);
uint64_t generate_work (rai::work_pool &, rai::uint256_union const &);
static std::unique_ptr <opencl_work> create (bool, unsigned, unsigned);
std::mutex mutex;
cl_context context;
cl_mem attempt_buffer;
@ -38,6 +45,5 @@ public:
cl_kernel kernel;
cl_command_queue queue;
rai::xorshift1024star rand;
rai::work_pool & pool;
};
}

View file

@ -6,7 +6,7 @@
rai::system::system (uint16_t port_a, size_t count_a) :
service (new boost::asio::io_service),
alarm (*service),
work (false)
work (nullptr)
{
nodes.reserve (count_a);
for (size_t i (0); i < count_a; ++i)

View file

@ -12,10 +12,11 @@
#include <future>
rai::work_pool::work_pool (bool opencl_work_a) :
rai::work_pool::work_pool (std::unique_ptr <rai::opencl_work> opencl_a) :
current (0),
ticket (0),
done (false)
done (false),
opencl (std::move (opencl_a))
{
static_assert (ATOMIC_INT_LOCK_FREE == 2, "Atomic int needed");
auto count (std::max (1u, std::thread::hardware_concurrency ()));
@ -28,16 +29,6 @@ done (false)
}));
threads.push_back (std::move (thread));
}
if (opencl_work_a)
{
auto error (false);
rai::opencl_environment environment (error);
opencl.reset (new rai::opencl_work (error, environment, *this));
if (error)
{
opencl.reset();
}
}
}
rai::work_pool::~work_pool ()
@ -170,7 +161,7 @@ boost::optional <uint64_t> rai::work_pool::generate_maybe (rai::uint256_union co
boost::optional <uint64_t> result;
if (opencl != nullptr)
{
result = opencl->generate_work (root_a);
result = opencl->generate_work (*this, root_a);
}
else
{

View file

@ -16,7 +16,7 @@ namespace rai
class work_pool
{
public:
work_pool (bool);
work_pool (std::unique_ptr <rai::opencl_work>);
~work_pool ();
void loop (uint64_t);
void stop ();

View file

@ -101,7 +101,7 @@ int main (int argc, char * const * argv)
{
rai::node_init init;
auto service (boost::make_shared <boost::asio::io_service> ());
rai::work_pool work (config.node.opencl_work);
rai::work_pool work (rai::opencl_work::create (config.node.opencl_work, 0, 1));
rai::alarm alarm (*service);
auto node (std::make_shared <rai::node> (init, *service, working, alarm, config.node, work));
if (!init.error ())

View file

@ -62,7 +62,7 @@ void rai_daemon::daemon::run ()
if (!error)
{
auto service (boost::make_shared <boost::asio::io_service> ());
rai::work_pool work (config.node.opencl_work);
rai::work_pool work (std::move (rai::opencl_work::create (config.node.opencl_work, 0, 1)));
rai::alarm alarm (*service);
rai::node_init init;
auto node (std::make_shared <rai::node> (init, *service, working, alarm, config.node, work));

View file

@ -148,7 +148,7 @@ int main (int argc, char * const * argv)
if (!key.decode_hex (vm ["key"].as <std::string> ()))
{
rai::keypair genesis (key.to_string ());
rai::work_pool work (false);
rai::work_pool work (nullptr);
std::cout << "Genesis: " << genesis.prv.data.to_string () << std::endl << "Public: " << genesis.pub.to_string () << std::endl << "Account: " << genesis.pub.to_account () << std::endl;
rai::keypair landing;
std::cout << "Landing: " << landing.prv.data.to_string () << std::endl << "Public: " << landing.pub.to_string () << std::endl << "Account: " << landing.pub.to_account () << std::endl;
@ -215,7 +215,7 @@ int main (int argc, char * const * argv)
}
else if (vm.count ("debug_profile_generate"))
{
rai::work_pool work (false);
rai::work_pool work (nullptr);
rai::change_block block (0, 0, rai::keypair ().prv, 0, 0);
std::cerr << "Starting generation profiling\n";
for (uint64_t i (0); true; ++i)
@ -229,7 +229,7 @@ int main (int argc, char * const * argv)
}
else if (vm.count ("debug_profile_verify"))
{
rai::work_pool work (false);
rai::work_pool work (nullptr);
rai::change_block block (0, 0, rai::keypair ().prv, 0, 0);
std::cerr << "Starting verification profiling\n";
for (uint64_t i (0); true; ++i)

View file

@ -149,7 +149,7 @@ int run_wallet (int argc, char * const * argv)
QApplication application (argc, const_cast <char **> (argv));
rai::set_application_icon (application);
auto service (boost::make_shared <boost::asio::io_service> ());
rai::work_pool work (config.node.opencl_work);
rai::work_pool work (rai::opencl_work::create (config.node.opencl_work, 0, 1));
rai::alarm alarm (*service);
rai::node_init init;
auto node (std::make_shared <rai::node> (init, *service, working, alarm, config.node, work));