diff --git a/nano/core_test/work_pool.cpp b/nano/core_test/work_pool.cpp index a04b5921..7d632047 100644 --- a/nano/core_test/work_pool.cpp +++ b/nano/core_test/work_pool.cpp @@ -85,7 +85,7 @@ TEST (work, opencl) nano::logger_mt logger; bool error (false); nano::opencl_environment environment (error); - ASSERT_FALSE (error); + ASSERT_TRUE (!error || !nano::opencl_loaded); if (!environment.platforms.empty () && !environment.platforms.begin ()->devices.empty ()) { nano::opencl_config config (0, 0, 16 * 1024); diff --git a/nano/node/openclwork.cpp b/nano/node/openclwork.cpp index 39c3d466..b71e0ede 100644 --- a/nano/node/openclwork.cpp +++ b/nano/node/openclwork.cpp @@ -11,6 +11,8 @@ #include #include +bool nano::opencl_loaded{ false }; + namespace { std::string opencl_program = R"%%%( @@ -389,111 +391,125 @@ void printstate (blake2b_state * S) nano::opencl_environment::opencl_environment (bool & error_a) { - cl_uint platformIdCount = 0; - clGetPlatformIDs (0, nullptr, &platformIdCount); - std::vector platformIds (platformIdCount); - clGetPlatformIDs (platformIdCount, platformIds.data (), nullptr); - for (auto i (platformIds.begin ()), n (platformIds.end ()); i != n; ++i) + if (nano::opencl_loaded) { - nano::opencl_platform platform; - platform.platform = *i; - cl_uint deviceIdCount = 0; - clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, 0, nullptr, &deviceIdCount); - std::vector deviceIds (deviceIdCount); - clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, deviceIdCount, deviceIds.data (), nullptr); - for (auto j (deviceIds.begin ()), m (deviceIds.end ()); j != m; ++j) + cl_uint platformIdCount = 0; + clGetPlatformIDs (0, nullptr, &platformIdCount); + std::vector platformIds (platformIdCount); + clGetPlatformIDs (platformIdCount, platformIds.data (), nullptr); + for (auto i (platformIds.begin ()), n (platformIds.end ()); i != n; ++i) { - platform.devices.push_back (*j); + nano::opencl_platform platform; + platform.platform = *i; + cl_uint deviceIdCount = 0; + clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, 0, nullptr, &deviceIdCount); + std::vector deviceIds (deviceIdCount); + clGetDeviceIDs (*i, CL_DEVICE_TYPE_ALL, deviceIdCount, deviceIds.data (), nullptr); + for (auto j (deviceIds.begin ()), m (deviceIds.end ()); j != m; ++j) + { + platform.devices.push_back (*j); + } + platforms.push_back (platform); } - platforms.push_back (platform); + } + else + { + error_a = true; } } void nano::opencl_environment::dump (std::ostream & stream) { - auto index (0); - size_t device_count (0); - for (auto & i : platforms) + if (nano::opencl_loaded) { - device_count += i.devices.size (); - } - stream << boost::str (boost::format ("OpenCL 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 queries = { CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS }; - stream << "Platform: " << index << std::endl; - for (auto j (queries.begin ()), m (queries.end ()); j != m; ++j) + auto index (0); + size_t device_count (0); + for (auto & i : platforms) { - size_t platformInfoCount = 0; - clGetPlatformInfo (i->platform, *j, 0, nullptr, &platformInfoCount); - std::vector info (platformInfoCount); - clGetPlatformInfo (i->platform, *j, info.size (), info.data (), nullptr); - stream << info.data () << std::endl; + device_count += i.devices.size (); } - for (auto j (i->devices.begin ()), m (i->devices.end ()); j != m; ++j) + stream << boost::str (boost::format ("OpenCL 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 queries = { CL_DEVICE_NAME, CL_DEVICE_VENDOR, CL_DEVICE_PROFILE }; - stream << "Device: " << j - i->devices.begin () << std::endl; - for (auto k (queries.begin ()), o (queries.end ()); k != o; ++k) + std::vector queries = { CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS }; + stream << "Platform: " << index << std::endl; + for (auto j (queries.begin ()), m (queries.end ()); j != m; ++j) { size_t platformInfoCount = 0; - clGetDeviceInfo (*j, *k, 0, nullptr, &platformInfoCount); + clGetPlatformInfo (i->platform, *j, 0, nullptr, &platformInfoCount); std::vector info (platformInfoCount); - clGetDeviceInfo (*j, *k, info.size (), info.data (), nullptr); - stream << '\t' << info.data () << std::endl; + clGetPlatformInfo (i->platform, *j, info.size (), info.data (), nullptr); + stream << info.data () << std::endl; } - size_t deviceTypeCount = 0; - clGetDeviceInfo (*j, CL_DEVICE_TYPE, 0, nullptr, &deviceTypeCount); - std::vector deviceTypeInfo (deviceTypeCount); - clGetDeviceInfo (*j, CL_DEVICE_TYPE, deviceTypeCount, deviceTypeInfo.data (), 0); - std::string device_type_string; - switch (deviceTypeInfo[0]) + for (auto j (i->devices.begin ()), m (i->devices.end ()); j != m; ++j) { - case CL_DEVICE_TYPE_ACCELERATOR: - device_type_string = "ACCELERATOR"; - break; - case CL_DEVICE_TYPE_CPU: - device_type_string = "CPU"; - break; - case CL_DEVICE_TYPE_CUSTOM: - device_type_string = "CUSTOM"; - break; - case CL_DEVICE_TYPE_DEFAULT: - device_type_string = "DEFAULT"; - break; - case CL_DEVICE_TYPE_GPU: - device_type_string = "GPU"; - break; - default: - device_type_string = "Unknown"; - break; + std::vector queries = { CL_DEVICE_NAME, CL_DEVICE_VENDOR, CL_DEVICE_PROFILE }; + stream << "Device: " << j - i->devices.begin () << std::endl; + for (auto k (queries.begin ()), o (queries.end ()); k != o; ++k) + { + size_t platformInfoCount = 0; + clGetDeviceInfo (*j, *k, 0, nullptr, &platformInfoCount); + std::vector info (platformInfoCount); + clGetDeviceInfo (*j, *k, info.size (), info.data (), nullptr); + stream << '\t' << info.data () << std::endl; + } + size_t deviceTypeCount = 0; + clGetDeviceInfo (*j, CL_DEVICE_TYPE, 0, nullptr, &deviceTypeCount); + std::vector deviceTypeInfo (deviceTypeCount); + clGetDeviceInfo (*j, CL_DEVICE_TYPE, deviceTypeCount, deviceTypeInfo.data (), 0); + std::string device_type_string; + switch (deviceTypeInfo[0]) + { + case CL_DEVICE_TYPE_ACCELERATOR: + device_type_string = "ACCELERATOR"; + break; + case CL_DEVICE_TYPE_CPU: + device_type_string = "CPU"; + break; + case CL_DEVICE_TYPE_CUSTOM: + device_type_string = "CUSTOM"; + break; + case CL_DEVICE_TYPE_DEFAULT: + device_type_string = "DEFAULT"; + break; + case CL_DEVICE_TYPE_GPU: + device_type_string = "GPU"; + break; + default: + device_type_string = "Unknown"; + break; + } + stream << '\t' << device_type_string << std::endl; + size_t compilerAvailableCount = 0; + clGetDeviceInfo (*j, CL_DEVICE_COMPILER_AVAILABLE, 0, nullptr, &compilerAvailableCount); + std::vector compilerAvailableInfo (compilerAvailableCount); + clGetDeviceInfo (*j, CL_DEVICE_COMPILER_AVAILABLE, compilerAvailableCount, compilerAvailableInfo.data (), 0); + stream << "\tCompiler available: " << (compilerAvailableInfo[0] ? "true" : "false") << std::endl; + size_t computeUnitsAvailableCount = 0; + clGetDeviceInfo (*j, CL_DEVICE_MAX_COMPUTE_UNITS, 0, nullptr, &computeUnitsAvailableCount); + std::vector computeUnitsAvailableInfo (computeUnitsAvailableCount); + clGetDeviceInfo (*j, CL_DEVICE_MAX_COMPUTE_UNITS, computeUnitsAvailableCount, computeUnitsAvailableInfo.data (), 0); + uint64_t computeUnits (computeUnitsAvailableInfo[0] | (computeUnitsAvailableInfo[1] << 8) | (computeUnitsAvailableInfo[2] << 16) | (computeUnitsAvailableInfo[3] << 24)); + stream << "\tCompute units available: " << computeUnits << std::endl; + cl_ulong size{ 0 }; + clGetDeviceInfo (*j, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof (cl_ulong), &size, 0); + stream << "\tMemory size" << std::endl; + stream << "\t\tConstant buffer: " << size << std::endl; + clGetDeviceInfo (*j, CL_DEVICE_LOCAL_MEM_SIZE, sizeof (cl_ulong), &size, 0); + stream << "\t\tLocal memory : " << size << std::endl; + clGetDeviceInfo (*j, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof (cl_ulong), &size, 0); + stream << "\t\tGlobal memory : " << size << std::endl; + clGetDeviceInfo (*j, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof (cl_ulong), &size, 0); + stream << "\t\tGlobal cache : " << size << std::endl; + clGetDeviceInfo (*j, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof (cl_ulong), &size, 0); + stream << "\t\tMax allocation : " << size << std::endl; } - stream << '\t' << device_type_string << std::endl; - size_t compilerAvailableCount = 0; - clGetDeviceInfo (*j, CL_DEVICE_COMPILER_AVAILABLE, 0, nullptr, &compilerAvailableCount); - std::vector compilerAvailableInfo (compilerAvailableCount); - clGetDeviceInfo (*j, CL_DEVICE_COMPILER_AVAILABLE, compilerAvailableCount, compilerAvailableInfo.data (), 0); - stream << "\tCompiler available: " << (compilerAvailableInfo[0] ? "true" : "false") << std::endl; - size_t computeUnitsAvailableCount = 0; - clGetDeviceInfo (*j, CL_DEVICE_MAX_COMPUTE_UNITS, 0, nullptr, &computeUnitsAvailableCount); - std::vector computeUnitsAvailableInfo (computeUnitsAvailableCount); - clGetDeviceInfo (*j, CL_DEVICE_MAX_COMPUTE_UNITS, computeUnitsAvailableCount, computeUnitsAvailableInfo.data (), 0); - uint64_t computeUnits (computeUnitsAvailableInfo[0] | (computeUnitsAvailableInfo[1] << 8) | (computeUnitsAvailableInfo[2] << 16) | (computeUnitsAvailableInfo[3] << 24)); - stream << "\tCompute units available: " << computeUnits << std::endl; - cl_ulong size{ 0 }; - clGetDeviceInfo (*j, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof (cl_ulong), &size, 0); - stream << "\tMemory size" << std::endl; - stream << "\t\tConstant buffer: " << size << std::endl; - clGetDeviceInfo (*j, CL_DEVICE_LOCAL_MEM_SIZE, sizeof (cl_ulong), &size, 0); - stream << "\t\tLocal memory : " << size << std::endl; - clGetDeviceInfo (*j, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof (cl_ulong), &size, 0); - stream << "\t\tGlobal memory : " << size << std::endl; - clGetDeviceInfo (*j, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof (cl_ulong), &size, 0); - stream << "\t\tGlobal cache : " << size << std::endl; - clGetDeviceInfo (*j, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof (cl_ulong), &size, 0); - stream << "\t\tMax allocation : " << size << std::endl; } } + else + { + stream << boost::str (boost::format ("OpenCL library could not be found\n")); + } } nano::opencl_work::opencl_work (bool & error_a, nano::opencl_config const & config_a, nano::opencl_environment & environment_a, nano::logger_mt & logger_a) : diff --git a/nano/node/openclwork.hpp b/nano/node/openclwork.hpp index 2b1de604..c06f977c 100644 --- a/nano/node/openclwork.hpp +++ b/nano/node/openclwork.hpp @@ -20,6 +20,7 @@ namespace nano { +extern bool opencl_loaded; class logger_mt; class opencl_platform { diff --git a/nano/node/plat/posix/openclapi.cpp b/nano/node/plat/posix/openclapi.cpp index 35f78860..6429cd73 100644 --- a/nano/node/plat/posix/openclapi.cpp +++ b/nano/node/plat/posix/openclapi.cpp @@ -31,12 +31,14 @@ public: clEnqueueNDRangeKernel = reinterpret_cast (dlsym (opencl_library, "clEnqueueNDRangeKernel")); clEnqueueReadBuffer = reinterpret_cast (dlsym (opencl_library, "clEnqueueReadBuffer")); clFinish = reinterpret_cast (dlsym (opencl_library, "clFinish")); + nano::opencl_loaded = true; } } ~opencl_initializer () { if (opencl_library != nullptr) { + nano::opencl_loaded = false; dlclose (opencl_library); } } diff --git a/nano/node/plat/windows/openclapi.cpp b/nano/node/plat/windows/openclapi.cpp index 8cb8098d..8b71e268 100644 --- a/nano/node/plat/windows/openclapi.cpp +++ b/nano/node/plat/windows/openclapi.cpp @@ -31,12 +31,14 @@ public: clEnqueueNDRangeKernel = reinterpret_cast (GetProcAddress (opencl_library, "clEnqueueNDRangeKernel")); clEnqueueReadBuffer = reinterpret_cast (GetProcAddress (opencl_library, "clEnqueueReadBuffer")); clFinish = reinterpret_cast (GetProcAddress (opencl_library, "clFinish")); + nano::opencl_loaded = true; } } ~opencl_initializer () { if (opencl_library != nullptr) { + nano::opencl_loaded = false; FreeLibrary (opencl_library); } }