From 166a68244ed353de92b1e0ede74fae4af51401f9 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 19 Aug 2019 22:35:58 +0700 Subject: [PATCH] Added platform option. --- src/backend/opencl/OclBackend.cpp | 40 +++++++++-- src/backend/opencl/OclConfig.cpp | 73 +++++++++++++++++++-- src/backend/opencl/OclConfig.h | 9 +++ src/backend/opencl/wrappers/OclLib.cpp | 46 +++++++++---- src/backend/opencl/wrappers/OclLib.h | 10 ++- src/backend/opencl/wrappers/OclPlatform.cpp | 25 ++++++- src/backend/opencl/wrappers/OclPlatform.h | 2 + src/base/tools/String.cpp | 14 ++++ src/base/tools/String.h | 1 + 9 files changed, 194 insertions(+), 26 deletions(-) diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 7c9fdefe..99de80e7 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -32,6 +32,7 @@ #include "backend/opencl/OclBackend.h" #include "backend/opencl/OclConfig.h" #include "backend/opencl/OclLaunchData.h" +#include "backend/opencl/wrappers/OclLib.h" #include "base/io/log/Log.h" #include "base/net/stratum/Job.h" #include "base/tools/Chrono.h" @@ -52,7 +53,7 @@ namespace xmrig { extern template class Threads; -static const char *tag = MAGENTA_BG_BOLD(" ocl "); +static const char *tag = MAGENTA_BG_BOLD(WHITE_BOLD_S " ocl "); static const String kType = "opencl"; @@ -89,6 +90,30 @@ public: } + bool init(const OclConfig &cl) + { + if (!OclLib::init(cl.loader())) { + LOG_ERR("%s" RED_S " failed to load OpenCL runtime (%s): " RED_BOLD_S "\"%s\"", tag, OclLib::loader().data(), OclLib::lastError()); + + return false; + } + + if (!platform.isValid()) { + platform = cl.platform(); + + if (!platform.isValid()) { + LOG_ERR("%s" RED_S " selected OpenCL platform NOT found.", tag); + + return false; + } + + LOG_INFO("%s use platform " WHITE_BOLD("%s") "/" WHITE_BOLD("%s"), tag, platform.name().data(), platform.version().data()); + } + + return true; + } + + inline void start() { LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"), @@ -123,6 +148,7 @@ public: Algorithm algo; Controller *controller; LaunchStatus status; + OclPlatform platform; std::mutex mutex; std::vector threads; String profileName; @@ -143,6 +169,8 @@ xmrig::OclBackend::OclBackend(Controller *controller) : xmrig::OclBackend::~OclBackend() { delete d_ptr; + + OclLib::close(); } @@ -213,6 +241,9 @@ void xmrig::OclBackend::setJob(const Job &job) } const OclConfig &cl = d_ptr->controller->config()->cl(); + if (!d_ptr->init(cl)) { + return; + } std::vector threads = cl.get(d_ptr->controller->miner(), job.algorithm()); // if (d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) { @@ -271,17 +302,14 @@ void xmrig::OclBackend::tick(uint64_t ticks) rapidjson::Value xmrig::OclBackend::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; - auto &allocator = doc.GetAllocator(); - const CpuConfig &cpu = d_ptr->controller->config()->cpu(); + auto &allocator = doc.GetAllocator(); Value out(kObjectType); out.AddMember("type", type().toJSON(), allocator); out.AddMember("enabled", isEnabled(), allocator); out.AddMember("algo", d_ptr->algo.toJSON(), allocator); out.AddMember("profile", profileName().toJSON(), allocator); - out.AddMember("hw-aes", cpu.isHwAES(), allocator); - out.AddMember("priority", cpu.priority(), allocator); - out.AddMember("memory", static_cast(d_ptr->algo.isValid() ? (d_ptr->ways() * d_ptr->algo.l3()) : 0), allocator); + out.AddMember("platform", d_ptr->platform.toJSON(doc), allocator); if (d_ptr->threads.empty() || !hashrate()) { return out; diff --git a/src/backend/opencl/OclConfig.cpp b/src/backend/opencl/OclConfig.cpp index 59b726ff..ecc1fb8a 100644 --- a/src/backend/opencl/OclConfig.cpp +++ b/src/backend/opencl/OclConfig.cpp @@ -30,7 +30,13 @@ namespace xmrig { -static const char *kEnabled = "enabled"; +static const char *kCache = "cache"; +static const char *kEnabled = "enabled"; +static const char *kLoader = "loader"; +static const char *kPlatform = "platform"; +static const char *kAMD = "AMD"; +static const char *kNVIDIA = "NVIDIA"; +static const char *kINTEL = "INTEL"; extern template class Threads; @@ -38,11 +44,51 @@ extern template class Threads; } -xmrig::OclConfig::OclConfig() +xmrig::OclConfig::OclConfig() : + m_platformVendor(kAMD) { } +xmrig::OclPlatform xmrig::OclConfig::platform() const +{ + const auto platforms = OclPlatform::get(); + if (platforms.empty()) { + return OclPlatform(); + } + + if (!m_platformVendor.isEmpty()) { + String search; + String vendor = m_platformVendor; + vendor.toUpper(); + + if (vendor == kAMD) { + search = "Advanced Micro Devices"; + } + else if (vendor == kNVIDIA) { + search = kNVIDIA; + } + else if (vendor == kINTEL) { + search = "Intel"; + } + else { + search = m_platformVendor; + } + + for (const auto &platform : platforms) { + if (platform.vendor().contains(search)) { + return platform; + } + } + } + else if (m_platformIndex < platforms.size()) { + return platforms[m_platformIndex]; + } + + return OclPlatform(); +} + + rapidjson::Value xmrig::OclConfig::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; @@ -50,7 +96,10 @@ rapidjson::Value xmrig::OclConfig::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); - obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kEnabled), m_enabled, allocator); + obj.AddMember(StringRef(kCache), m_cache, allocator); + obj.AddMember(StringRef(kLoader), m_loader.toJSON(), allocator); + obj.AddMember(StringRef(kPlatform), m_platformVendor.isEmpty() ? Value(m_platformIndex) : m_platformVendor.toJSON(), allocator); m_threads.toJSON(obj, doc); @@ -69,7 +118,11 @@ std::vector xmrig::OclConfig::get(const Miner *miner, cons void xmrig::OclConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { - m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_cache = Json::getBool(value, kCache, m_cache); + m_loader = Json::getString(value, kLoader); + + setPlatform(Json::getValue(value, kPlatform)); if (!m_threads.read(value)) { generate(); @@ -88,3 +141,15 @@ void xmrig::OclConfig::generate() { m_shouldSave = true; } + + +void xmrig::OclConfig::setPlatform(const rapidjson::Value &platform) +{ + if (platform.IsString()) { + m_platformVendor = platform.GetString(); + } + else if (platform.IsUint()) { + m_platformVendor = nullptr; + m_platformIndex = platform.GetUint(); + } +} diff --git a/src/backend/opencl/OclConfig.h b/src/backend/opencl/OclConfig.h index bf7d0abb..d3a97bce 100644 --- a/src/backend/opencl/OclConfig.h +++ b/src/backend/opencl/OclConfig.h @@ -29,6 +29,7 @@ #include "backend/common/Threads.h" #include "backend/opencl/OclLaunchData.h" #include "backend/opencl/OclThreads.h" +#include "backend/opencl/wrappers/OclPlatform.h" namespace xmrig { @@ -39,20 +40,28 @@ class OclConfig public: OclConfig(); + OclPlatform platform() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; std::vector get(const Miner *miner, const Algorithm &algorithm) const; void read(const rapidjson::Value &value); + inline bool isCacheEnabled() const { return m_cache; } inline bool isEnabled() const { return m_enabled; } inline bool isShouldSave() const { return m_shouldSave; } + inline const String &loader() const { return m_loader; } inline const Threads &threads() const { return m_threads; } private: void generate(); + void setPlatform(const rapidjson::Value &platform); + bool m_cache = true; bool m_enabled = true; bool m_shouldSave = false; + String m_loader; + String m_platformVendor; Threads m_threads; + uint32_t m_platformIndex = 0; }; diff --git a/src/backend/opencl/wrappers/OclLib.cpp b/src/backend/opencl/wrappers/OclLib.cpp index f4b4a200..10195278 100644 --- a/src/backend/opencl/wrappers/OclLib.cpp +++ b/src/backend/opencl/wrappers/OclLib.cpp @@ -123,26 +123,36 @@ static setKernelArg_t pSetKernelArg = nu #define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast(&p##x)) == -1) { return false; } +namespace xmrig { + +bool OclLib::m_initialized = false; +bool OclLib::m_ready = false; +String OclLib::m_loader; + +} // namespace xmrig + + bool xmrig::OclLib::init(const char *fileName) { - if (uv_dlopen(fileName == nullptr ? defaultLoader() : fileName, &oclLib) == -1 || !load()) { - LOG_ERR("Failed to load OpenCL runtime: %s", uv_dlerror(&oclLib)); - return false; + if (!m_initialized) { + m_loader = fileName == nullptr ? defaultLoader() : fileName; + m_ready = uv_dlopen(m_loader, &oclLib) == 0 && load(); + m_initialized = true; } - return true; + return m_ready; } -const char *xmrig::OclLib::defaultLoader() +const char *xmrig::OclLib::lastError() { -# if defined(__APPLE__) - return "/System/Library/Frameworks/OpenCL.framework/OpenCL"; -# elif defined(_WIN32) - return "OpenCL.dll"; -# else - return "libOpenCL.so"; -# endif + return uv_dlerror(&oclLib); +} + + +void xmrig::OclLib::close() +{ + uv_dlclose(&oclLib); } @@ -181,6 +191,18 @@ bool xmrig::OclLib::load() } +const char *xmrig::OclLib::defaultLoader() +{ +# if defined(__APPLE__) + return "/System/Library/Frameworks/OpenCL.framework/OpenCL"; +# elif defined(_WIN32) + return "OpenCL.dll"; +# else + return "libOpenCL.so"; +# endif +} + + cl_command_queue xmrig::OclLib::createCommandQueue(cl_context context, cl_device_id device, cl_int *errcode_ret) { cl_command_queue result; diff --git a/src/backend/opencl/wrappers/OclLib.h b/src/backend/opencl/wrappers/OclLib.h index 97bbdeb4..e961eccb 100644 --- a/src/backend/opencl/wrappers/OclLib.h +++ b/src/backend/opencl/wrappers/OclLib.h @@ -40,7 +40,10 @@ class OclLib { public: static bool init(const char *fileName = nullptr); - static const char *defaultLoader(); + static const char *lastError(); + static void close(); + + static inline const String &loader() { return m_loader; } static cl_command_queue createCommandQueue(cl_context context, cl_device_id device, cl_int *errcode_ret); static cl_context createContext(const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), void *user_data, cl_int *errcode_ret); @@ -76,6 +79,11 @@ public: private: static bool load(); + static const char *defaultLoader(); + + static bool m_initialized; + static bool m_ready; + static String m_loader; }; diff --git a/src/backend/opencl/wrappers/OclPlatform.cpp b/src/backend/opencl/wrappers/OclPlatform.cpp index 6a7651a9..d03f7f36 100644 --- a/src/backend/opencl/wrappers/OclPlatform.cpp +++ b/src/backend/opencl/wrappers/OclPlatform.cpp @@ -23,11 +23,9 @@ */ -#include - - #include "backend/opencl/wrappers/OclLib.h" #include "backend/opencl/wrappers/OclPlatform.h" +#include "rapidjson/document.h" std::vector xmrig::OclPlatform::get() @@ -65,6 +63,27 @@ void xmrig::OclPlatform::print() } +rapidjson::Value xmrig::OclPlatform::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + auto &allocator = doc.GetAllocator(); + + if (!isValid()) { + return Value(kNullType); + } + + Value out(kObjectType); + out.AddMember("index", index(), allocator); + out.AddMember("profile", profile().toJSON(doc), allocator); + out.AddMember("version", version().toJSON(doc), allocator); + out.AddMember("name", name().toJSON(doc), allocator); + out.AddMember("vendor", vendor().toJSON(doc), allocator); + out.AddMember("extensions", extensions().toJSON(doc), allocator); + + return out; +} + + xmrig::String xmrig::OclPlatform::extensions() const { return OclLib::getPlatformInfo(id(), CL_PLATFORM_EXTENSIONS); diff --git a/src/backend/opencl/wrappers/OclPlatform.h b/src/backend/opencl/wrappers/OclPlatform.h index 9fd80ecf..aff8769a 100644 --- a/src/backend/opencl/wrappers/OclPlatform.h +++ b/src/backend/opencl/wrappers/OclPlatform.h @@ -47,9 +47,11 @@ public: static std::vector get(); static void print(); + inline bool isValid() const { return m_id != nullptr; } inline cl_platform_id id() const { return m_id; } inline size_t index() const { return m_index; } + rapidjson::Value toJSON(rapidjson::Document &doc) const; String extensions() const; String name() const; String profile() const; diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index 7778c6da..363573c1 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -146,6 +146,20 @@ xmrig::String &xmrig::String::toLower() } +xmrig::String &xmrig::String::toUpper() +{ + if (isNull() || isEmpty()) { + return *this; + } + + for (size_t i = 0; i < size(); ++i) { + m_data[i] = static_cast(toupper(m_data[i])); + } + + return *this; +} + + xmrig::String xmrig::String::join(const std::vector &vec, char sep) { if (vec.empty()) { diff --git a/src/base/tools/String.h b/src/base/tools/String.h index 2c47d850..3e77b6da 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -87,6 +87,7 @@ public: rapidjson::Value toJSON(rapidjson::Document &doc) const; std::vector split(char sep) const; String &toLower(); + String &toUpper(); static String join(const std::vector &vec, char sep);