Improved OpenCL profile generation, don't create unnecessary (equal to main profile) profiles.

This commit is contained in:
XMRig 2019-10-09 11:11:43 +07:00
parent 1d03b942a5
commit 7db7b3727d
6 changed files with 193 additions and 99 deletions

View file

@ -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;

View file

@ -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 <algorithm>
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<OclThreads>;
static size_t generate(const char *key, Threads<OclThreads> &threads, const Algorithm &algorithm, const std::vector<OclDevice> &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<OclDevice> filterDevices(const std::vector<OclDevice> &devices, const std::vector<uint32_t> &hints)
{
std::vector<OclDevice> 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<Algorithm::CN>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, devices);
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, devices);
m_shouldSave = count > 0;
}

View file

@ -0,0 +1,152 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_OCLCONFIG_GEN_H
#define XMRIG_OCLCONFIG_GEN_H
#include "backend/common/Threads.h"
#include "backend/opencl/OclThreads.h"
#include <algorithm>
namespace xmrig {
static inline size_t generate(const char *key, Threads<OclThreads> &threads, const Algorithm &algorithm, const std::vector<OclDevice> &devices)
{
if (threads.isExist(algorithm)) {
return 0;
}
return threads.move(key, OclThreads(devices, algorithm));
}
template<Algorithm::Family FAMILY>
static inline size_t generate(Threads<OclThreads> &, const std::vector<OclDevice> &) { return 0; }
template<>
size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::vector<OclDevice> &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<Algorithm::CN_LITE>(Threads<OclThreads> &threads, const std::vector<OclDevice> &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<Algorithm::CN_HEAVY>(Threads<OclThreads> &threads, const std::vector<OclDevice> &devices)
{
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices);
}
#endif
#ifdef XMRIG_ALGO_CN_PICO
template<>
size_t inline generate<Algorithm::CN_PICO>(Threads<OclThreads> &threads, const std::vector<OclDevice> &devices)
{
return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices);
}
#endif
#ifdef XMRIG_ALGO_RANDOMX
template<>
size_t inline generate<Algorithm::RANDOM_X>(Threads<OclThreads> &threads, const std::vector<OclDevice> &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<OclDevice> filterDevices(const std::vector<OclDevice> &devices, const std::vector<uint32_t> &hints)
{
std::vector<OclDevice> 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 */

View file

@ -44,6 +44,24 @@ xmrig::OclThreads::OclThreads(const rapidjson::Value &value)
}
xmrig::OclThreads::OclThreads(const std::vector<OclDevice> &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;

View file

@ -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<OclDevice> &devices, const Algorithm &algorithm);
inline bool isEmpty() const { return m_data.empty(); }
inline const std::vector<OclThread> &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:

View file

@ -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