From 732b0e4115cf882d5c17479d36b9b37fa8fcdce1 Mon Sep 17 00:00:00 2001 From: psychocrypt <psychocryptHPC@gmail.com> Date: Thu, 11 Oct 2018 10:30:51 +0200 Subject: [PATCH] NVIDIA: support for multiple CUDA libs Allow to ship the miner with multiple cuda backends those depends on different driver versions. This will allow to support Turing/Volta and old Fermi GPU within one release. - add support to search for the first working CUDA backend - add some more messages to support better debugging (if a user has some issues) --- xmrstak/backend/backendConnector.cpp | 46 +++++++++++++++++++++++----- xmrstak/backend/nvidia/minethd.cpp | 4 +++ xmrstak/backend/plugin.hpp | 31 +++++++++++-------- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/xmrstak/backend/backendConnector.cpp b/xmrstak/backend/backendConnector.cpp index 525413f..92bb015 100644 --- a/xmrstak/backend/backendConnector.cpp +++ b/xmrstak/backend/backendConnector.cpp @@ -63,10 +63,35 @@ std::vector<iBackend*>* BackendConnector::thread_starter(miner_work& pWork) #ifndef CONF_NO_CUDA if(params::inst().useNVIDIA) { - plugin nvidiaplugin("NVIDIA", "xmrstak_cuda_backend"); - std::vector<iBackend*>* nvidiaThreads = nvidiaplugin.startBackend(static_cast<uint32_t>(pvThreads->size()), pWork, environment::inst()); - pvThreads->insert(std::end(*pvThreads), std::begin(*nvidiaThreads), std::end(*nvidiaThreads)); - if(nvidiaThreads->size() == 0) + plugin nvidiaplugin; + std::vector<iBackend*>* nvidiaThreads; + std::vector<std::string> libNames = {"xmrstak_cuda_backend_cuda10_0", "xmrstak_cuda_backend_cuda9_2", "xmrstak_cuda_backend"}; + size_t numWorkers = 0u; + + for( const auto & name : libNames) + { + printer::inst()->print_msg(L0, "NVIDIA: try to load library '%s'", name.c_str()); + nvidiaplugin.load("NVIDIA", name); + std::vector<iBackend*>* nvidiaThreads = nvidiaplugin.startBackend(static_cast<uint32_t>(pvThreads->size()), pWork, environment::inst()); + if(nvidiaThreads != nullptr) + { + pvThreads->insert(std::end(*pvThreads), std::begin(*nvidiaThreads), std::end(*nvidiaThreads)); + numWorkers = nvidiaThreads->size(); + delete nvidiaThreads; + } + else + { + // remove the plugin if we have found no GPUs + nvidiaplugin.unload(); + } + // we found at leat one working GPU + if(numWorkers != 0) + { + printer::inst()->print_msg(L0, "NVIDIA: use library '%s'", name.c_str()); + break; + } + } + if(numWorkers == 0) printer::inst()->print_msg(L0, "WARNING: backend NVIDIA disabled."); } #endif @@ -75,10 +100,17 @@ std::vector<iBackend*>* BackendConnector::thread_starter(miner_work& pWork) if(params::inst().useAMD) { const std::string backendName = xmrstak::params::inst().openCLVendor; - plugin amdplugin(backendName, "xmrstak_opencl_backend"); + plugin amdplugin; + amdplugin.load(backendName, "xmrstak_opencl_backend"); std::vector<iBackend*>* amdThreads = amdplugin.startBackend(static_cast<uint32_t>(pvThreads->size()), pWork, environment::inst()); - pvThreads->insert(std::end(*pvThreads), std::begin(*amdThreads), std::end(*amdThreads)); - if(amdThreads->size() == 0) + size_t numWorkers = 0u; + if(amdThreads != nullptr) + { + pvThreads->insert(std::end(*pvThreads), std::begin(*amdThreads), std::end(*amdThreads)); + numWorkers = amdThreads->size(); + delete amdThreads; + } + if(numWorkers == 0) printer::inst()->print_msg(L0, "WARNING: backend %s (OpenCL) disabled.", backendName.c_str()); } #endif diff --git a/xmrstak/backend/nvidia/minethd.cpp b/xmrstak/backend/nvidia/minethd.cpp index e82ec91..6460628 100644 --- a/xmrstak/backend/nvidia/minethd.cpp +++ b/xmrstak/backend/nvidia/minethd.cpp @@ -165,6 +165,10 @@ std::vector<iBackend*>* minethd::thread_starter(uint32_t threadOffset, miner_wor std::cout<<"WARNING: NVIDIA no device found"<<std::endl; return pvThreads; } + else + { + std::cout<<"NVIDIA: found "<< deviceCount <<" potential device's"<<std::endl; + } size_t i, n = jconf::inst()->GetGPUThreadCount(); pvThreads->reserve(n); diff --git a/xmrstak/backend/plugin.hpp b/xmrstak/backend/plugin.hpp index 1811af2..5c7dfe1 100644 --- a/xmrstak/backend/plugin.hpp +++ b/xmrstak/backend/plugin.hpp @@ -27,8 +27,11 @@ namespace xmrstak struct plugin { - plugin(const std::string backendName, const std::string libName) : fn_startBackend(nullptr), m_backendName(backendName) + plugin() = default; + + void load(const std::string backendName, const std::string libName) { + m_backendName = backendName; #ifdef WIN32 libBackend = LoadLibrary(TEXT((libName + ".dll").c_str())); if(!libBackend) @@ -81,32 +84,36 @@ struct plugin if(fn_startBackend == nullptr) { std::vector<iBackend*>* pvThreads = new std::vector<iBackend*>(); - std::cerr << "WARNING: " << m_backendName << " Backend disabled"<< std::endl; return pvThreads; } return fn_startBackend(threadOffset, pWork, env); } + void unload() + { + if(libBackend) + { +#ifdef WIN32 + FreeLibrary(libBackend); +#else + dlclose(libBackend); +#endif + } + fn_startBackend = nullptr; + } + std::string m_backendName; typedef std::vector<iBackend*>* (*startBackend_t)(uint32_t threadOffset, miner_work& pWork, environment& env); - startBackend_t fn_startBackend; + startBackend_t fn_startBackend = nullptr; #ifdef WIN32 HINSTANCE libBackend; #else - void *libBackend; -#endif - -/* \todo add unload to destructor and change usage of plugin that libs kept open until the miner ends -#ifdef WIN32 - FreeLibrary(libBackend); -#else - dlclose(libBackend); + void *libBackend = nullptr; #endif - * */ }; } // namespace xmrstak -- GitLab