From 7db7b3727d5f506c0546da9dd8ae05e5b94eff09 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 9 Oct 2019 11:11:43 +0700 Subject: [PATCH] Improved OpenCL profile generation, don't create unnecessary (equal to main profile) profiles. --- src/backend/common/Threads.h | 10 +- src/backend/opencl/OclConfig.cpp | 105 ++------------------ src/backend/opencl/OclConfig_gen.h | 152 +++++++++++++++++++++++++++++ src/backend/opencl/OclThreads.cpp | 18 ++++ src/backend/opencl/OclThreads.h | 6 ++ src/backend/opencl/opencl.cmake | 1 + 6 files changed, 193 insertions(+), 99 deletions(-) create mode 100644 src/backend/opencl/OclConfig_gen.h diff --git a/src/backend/common/Threads.h b/src/backend/common/Threads.h index f73b22a00..7a01bad7d 100644 --- a/src/backend/common/Threads.h +++ b/src/backend/common/Threads.h @@ -49,11 +49,19 @@ public: inline const T &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); } inline void disable(const Algorithm &algo) { m_disabled.insert(algo); } - inline void move(const char *profile, T &&threads) + inline size_t move(const char *profile, T &&threads) { + if (has(profile)) { + return 0; + } + + const size_t count = threads.count(); + if (!threads.isEmpty()) { m_profiles.insert({ profile, std::move(threads) }); } + + return count; } const T &get(const String &profileName) const; diff --git a/src/backend/opencl/OclConfig.cpp b/src/backend/opencl/OclConfig.cpp index bdefcaae3..71a669d6d 100644 --- a/src/backend/opencl/OclConfig.cpp +++ b/src/backend/opencl/OclConfig.cpp @@ -24,21 +24,18 @@ #include "backend/opencl/OclConfig.h" +#include "backend/opencl/OclConfig_gen.h" #include "backend/opencl/wrappers/OclLib.h" #include "base/io/json/Json.h" #include "base/io/log/Log.h" #include "rapidjson/document.h" -#include - - namespace xmrig { + static const char *kAMD = "AMD"; static const char *kCache = "cache"; -static const char *kCn = "cn"; -static const char *kCn2 = "cn/2"; static const char *kDevicesHint = "devices-hint"; static const char *kEnabled = "enabled"; static const char *kINTEL = "INTEL"; @@ -47,69 +44,9 @@ static const char *kNVIDIA = "NVIDIA"; static const char *kPlatform = "platform"; -#ifdef XMRIG_ALGO_CN_GPU -static const char *kCnGPU = "cn/gpu"; -#endif - -#ifdef XMRIG_ALGO_CN_LITE -static const char *kCnLite = "cn-lite"; -#endif - -#ifdef XMRIG_ALGO_CN_HEAVY -static const char *kCnHeavy = "cn-heavy"; -#endif - -#ifdef XMRIG_ALGO_CN_PICO -static const char *kCnPico = "cn-pico"; -#endif - -#ifdef XMRIG_ALGO_RANDOMX -static const char *kRx = "rx"; -static const char *kRxWOW = "rx/wow"; -#endif - -#ifdef XMRIG_ALGO_ARGON2 -//static const char *kArgon2 = "argon2"; -#endif - - extern template class Threads; -static size_t generate(const char *key, Threads &threads, const Algorithm &algorithm, const std::vector &devices) -{ - if (threads.has(key) || threads.isExist(algorithm)) { - return 0; - } - - OclThreads profile; - for (const OclDevice &device : devices) { - device.generate(algorithm, profile); - } - - const size_t count = profile.count(); - threads.move(key, std::move(profile)); - - return count; -} - - -static inline std::vector filterDevices(const std::vector &devices, const std::vector &hints) -{ - std::vector out; - out.reserve(std::min(devices.size(), hints.size())); - - for (const auto &device : devices) { - auto it = std::find(hints.begin(), hints.end(), device.index()); - if (it != hints.end()) { - out.emplace_back(device); - } - } - - return out; -} - - } @@ -251,39 +188,11 @@ void xmrig::OclConfig::generate() size_t count = 0; - count += xmrig::generate(kCn, m_threads, Algorithm::CN_0, devices); - count += xmrig::generate(kCn2, m_threads, Algorithm::CN_2, devices); - - if (!m_threads.isExist(Algorithm::CN_0)) { - m_threads.disable(Algorithm::CN_0); - count++; - } - -# ifdef XMRIG_ALGO_CN_GPU - count += xmrig::generate(kCnGPU, m_threads, Algorithm::CN_GPU, devices); -# endif - -# ifdef XMRIG_ALGO_CN_LITE - count += xmrig::generate(kCnLite, m_threads, Algorithm::CN_LITE_1, devices); - - if (!m_threads.isExist(Algorithm::CN_LITE_0)) { - m_threads.disable(Algorithm::CN_LITE_0); - count++; - } -# endif - -# ifdef XMRIG_ALGO_CN_HEAVY - count += xmrig::generate(kCnHeavy, m_threads, Algorithm::CN_HEAVY_0, devices); -# endif - -# ifdef XMRIG_ALGO_CN_PICO - count += xmrig::generate(kCnPico, m_threads, Algorithm::CN_PICO_0, devices); -# endif - -# ifdef XMRIG_ALGO_RANDOMX - count += xmrig::generate(kRx, m_threads, Algorithm::RX_0, devices); - count += xmrig::generate(kRxWOW, m_threads, Algorithm::RX_WOW, devices); -# endif + count += xmrig::generate(m_threads, devices); + count += xmrig::generate(m_threads, devices); + count += xmrig::generate(m_threads, devices); + count += xmrig::generate(m_threads, devices); + count += xmrig::generate(m_threads, devices); m_shouldSave = count > 0; } diff --git a/src/backend/opencl/OclConfig_gen.h b/src/backend/opencl/OclConfig_gen.h new file mode 100644 index 000000000..593b43a0c --- /dev/null +++ b/src/backend/opencl/OclConfig_gen.h @@ -0,0 +1,152 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_OCLCONFIG_GEN_H +#define XMRIG_OCLCONFIG_GEN_H + + +#include "backend/common/Threads.h" +#include "backend/opencl/OclThreads.h" + + +#include + + +namespace xmrig { + + +static inline size_t generate(const char *key, Threads &threads, const Algorithm &algorithm, const std::vector &devices) +{ + if (threads.isExist(algorithm)) { + return 0; + } + + return threads.move(key, OclThreads(devices, algorithm)); +} + + +template +static inline size_t generate(Threads &, const std::vector &) { return 0; } + + +template<> +size_t inline generate(Threads &threads, const std::vector &devices) +{ + size_t count = 0; + + count += generate("cn", threads, Algorithm::CN_0, devices); + count += generate("cn/2", threads, Algorithm::CN_2, devices); + + if (!threads.isExist(Algorithm::CN_0)) { + threads.disable(Algorithm::CN_0); + count++; + } + +# ifdef XMRIG_ALGO_CN_GPU + count += generate("cn/gpu", threads, Algorithm::CN_GPU, devices); +# endif + + return count; +} + + +#ifdef XMRIG_ALGO_CN_LITE +template<> +size_t inline generate(Threads &threads, const std::vector &devices) +{ + size_t count = generate("cn-lite", threads, Algorithm::CN_LITE_1, devices); + + if (!threads.isExist(Algorithm::CN_LITE_0)) { + threads.disable(Algorithm::CN_LITE_0); + ++count; + } + + return count; +} +#endif + + +#ifdef XMRIG_ALGO_CN_HEAVY +template<> +size_t inline generate(Threads &threads, const std::vector &devices) +{ + return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices); +} +#endif + + +#ifdef XMRIG_ALGO_CN_PICO +template<> +size_t inline generate(Threads &threads, const std::vector &devices) +{ + return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices); +} +#endif + + +#ifdef XMRIG_ALGO_RANDOMX +template<> +size_t inline generate(Threads &threads, const std::vector &devices) +{ + size_t count = 0; + + auto rx = OclThreads(devices, Algorithm::RX_0); + auto wow = OclThreads(devices, Algorithm::RX_WOW); + auto arq = OclThreads(devices, Algorithm::RX_ARQ); + + if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) { + count += threads.move("rx/wow", std::move(wow)); + } + + if (!threads.isExist(Algorithm::RX_ARQ) && arq != rx) { + count += threads.move("rx/arq", std::move(arq)); + } + + count += threads.move("rx", std::move(rx)); + + return count; +} +#endif + + +static inline std::vector filterDevices(const std::vector &devices, const std::vector &hints) +{ + std::vector out; + out.reserve(std::min(devices.size(), hints.size())); + + for (const auto &device : devices) { + auto it = std::find(hints.begin(), hints.end(), device.index()); + if (it != hints.end()) { + out.emplace_back(device); + } + } + + return out; +} + + +} /* namespace xmrig */ + + +#endif /* XMRIG_OCLCONFIG_GEN_H */ diff --git a/src/backend/opencl/OclThreads.cpp b/src/backend/opencl/OclThreads.cpp index 03cd3936a..167ccfc0b 100644 --- a/src/backend/opencl/OclThreads.cpp +++ b/src/backend/opencl/OclThreads.cpp @@ -44,6 +44,24 @@ xmrig::OclThreads::OclThreads(const rapidjson::Value &value) } +xmrig::OclThreads::OclThreads(const std::vector &devices, const Algorithm &algorithm) +{ + for (const OclDevice &device : devices) { + device.generate(algorithm, *this); + } +} + + +bool xmrig::OclThreads::isEqual(const OclThreads &other) const +{ + if (isEmpty() && other.isEmpty()) { + return true; + } + + return count() == other.count() && std::equal(m_data.begin(), m_data.end(), other.m_data.begin()); +} + + rapidjson::Value xmrig::OclThreads::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; diff --git a/src/backend/opencl/OclThreads.h b/src/backend/opencl/OclThreads.h index 1ca4c70a1..ed3ad18db 100644 --- a/src/backend/opencl/OclThreads.h +++ b/src/backend/opencl/OclThreads.h @@ -30,6 +30,7 @@ #include "backend/opencl/OclThread.h" +#include "backend/opencl/wrappers/OclDevice.h" namespace xmrig { @@ -40,6 +41,7 @@ class OclThreads public: OclThreads() = default; OclThreads(const rapidjson::Value &value); + OclThreads(const std::vector &devices, const Algorithm &algorithm); inline bool isEmpty() const { return m_data.empty(); } inline const std::vector &data() const { return m_data; } @@ -47,6 +49,10 @@ public: inline void add(OclThread &&thread) { m_data.push_back(thread); } inline void reserve(size_t capacity) { m_data.reserve(capacity); } + inline bool operator!=(const OclThreads &other) const { return !isEqual(other); } + inline bool operator==(const OclThreads &other) const { return isEqual(other); } + + bool isEqual(const OclThreads &other) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; private: diff --git a/src/backend/opencl/opencl.cmake b/src/backend/opencl/opencl.cmake index 376757170..48a92649d 100644 --- a/src/backend/opencl/opencl.cmake +++ b/src/backend/opencl/opencl.cmake @@ -13,6 +13,7 @@ if (WITH_OPENCL) src/backend/opencl/OclBackend.h src/backend/opencl/OclCache.h src/backend/opencl/OclConfig.h + src/backend/opencl/OclConfig_gen.h src/backend/opencl/OclGenerator.h src/backend/opencl/OclLaunchData.h src/backend/opencl/OclThread.h