diff --git a/src/3rdparty/cl.h b/src/3rdparty/cl.h index def1e7a5..bd9a46d0 100644 --- a/src/3rdparty/cl.h +++ b/src/3rdparty/cl.h @@ -33,19 +33,4 @@ #endif -namespace xmrig { - - -enum OclVendor { - OCL_VENDOR_UNKNOWN = -2, - OCL_VENDOR_MANUAL = -1, - OCL_VENDOR_AMD = 0, - OCL_VENDOR_NVIDIA = 1, - OCL_VENDOR_INTEL = 2 -}; - - -} // namespace xmrig - - #endif /* XMRIG_CL_H */ diff --git a/src/backend/common/Threads.h b/src/backend/common/Threads.h index 2cb333d6..afae184c 100644 --- a/src/backend/common/Threads.h +++ b/src/backend/common/Threads.h @@ -47,7 +47,13 @@ public: inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); } 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) { m_profiles.insert({ profile, threads }); } + + inline void move(const char *profile, T &&threads) + { + if (!threads.isEmpty()) { + m_profiles.insert({ profile, std::move(threads) }); + } + } const T &get(const String &profileName) const; size_t read(const rapidjson::Value &value); diff --git a/src/backend/opencl/OclConfig.cpp b/src/backend/opencl/OclConfig.cpp index ecc1fb8a..ae0f431a 100644 --- a/src/backend/opencl/OclConfig.cpp +++ b/src/backend/opencl/OclConfig.cpp @@ -24,23 +24,64 @@ #include "backend/opencl/OclConfig.h" +#include "backend/opencl/wrappers/OclLib.h" #include "base/io/json/Json.h" #include "rapidjson/document.h" namespace xmrig { +static const char *kAMD = "AMD"; static const char *kCache = "cache"; +static const char *kCn = "cn"; static const char *kEnabled = "enabled"; +static const char *kINTEL = "INTEL"; 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"; +static const char *kPlatform = "platform"; +static const char *kCn2 = "cn/2"; + + +#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 OclThreads generate(const Algorithm &algorithm, const std::vector &devices) +{ + OclThreads threads; + for (const OclDevice &device : devices) { + device.generate(algorithm, threads); + } + + return threads; +} + + } @@ -139,7 +180,37 @@ void xmrig::OclConfig::read(const rapidjson::Value &value) void xmrig::OclConfig::generate() { + OclLib::init(loader()); + + const auto devices = platform().devices(); + m_shouldSave = true; + + m_threads.disable(Algorithm::CN_0); + m_threads.move(kCn, xmrig::generate(Algorithm::CN_0, devices)); + m_threads.move(kCn2, xmrig::generate(Algorithm::CN_2, devices)); + +# ifdef XMRIG_ALGO_CN_GPU +// m_threads.move(kCnGPU, xmrig::generate(Algorithm::CN_GPU, devices)); +# endif + +# ifdef XMRIG_ALGO_CN_LITE + m_threads.disable(Algorithm::CN_LITE_0); + m_threads.move(kCnLite, xmrig::generate(Algorithm::CN_LITE_1, devices)); +# endif + +# ifdef XMRIG_ALGO_CN_HEAVY + m_threads.move(kCnHeavy, xmrig::generate(Algorithm::CN_HEAVY_0, devices)); +# endif + +# ifdef XMRIG_ALGO_CN_PICO + m_threads.move(kCnPico, xmrig::generate(Algorithm::CN_PICO_0, devices)); +# endif + +# ifdef XMRIG_ALGO_RANDOMX +// m_threads.move(kRx, xmrig::generate(Algorithm::RX_0, devices)); +// m_threads.move(kRxWOW, xmrig::generate(Algorithm::RX_WOW, devices)); +# endif } diff --git a/src/backend/opencl/OclThread.cpp b/src/backend/opencl/OclThread.cpp index 7c5f830e..70fd5725 100644 --- a/src/backend/opencl/OclThread.cpp +++ b/src/backend/opencl/OclThread.cpp @@ -23,36 +23,113 @@ */ +#include + + #include "backend/opencl/OclThread.h" #include "base/io/json/Json.h" #include "rapidjson/document.h" +namespace xmrig { + +static const char *kAffinity = "affinity"; +static const char *kCompMode = "comp_mode"; +static const char *kIndex = "index"; +static const char *kIntensity = "intensity"; +static const char *kMemChunk = "mem_chunk"; +static const char *kStridedIndex = "strided_index"; +static const char *kUnroll = "unroll"; +static const char *kWorksize = "worksize"; + +#ifdef XMRIG_ALGO_RANDOMX +static const char *kBFactor = "bfactor"; +static const char *kGCNAsm = "gcn_asm"; +static const char* kDatasetHost = "dataset_host"; +#endif + +} // namespace xmrig + + xmrig::OclThread::OclThread(const rapidjson::Value &value) { - if (value.IsArray() && value.Size() >= 2) { - m_intensity = value[0].GetInt(); - m_affinity = value[1].GetInt(); + m_index = Json::getUint(value, kIndex); + m_intensity = Json::getUint(value, kIntensity); + m_worksize = Json::getUint(value, kWorksize); + m_affinity = Json::getInt64(value, kAffinity, -1); + m_memChunk = std::max(Json::getUint(value, kMemChunk, m_memChunk), 18u); + m_compMode = Json::getBool(value, kCompMode, m_compMode); + + setUnrollFactor(Json::getUint(value, kUnroll, m_unrollFactor)); + +# ifdef XMRIG_ALGO_RANDOMX + m_bfactor = Json::getUint(value, kBFactor, 6); + m_gcnAsm = Json::getUint(value, kGCNAsm, m_gcnAsm); + m_datasetHost = Json::getInt(value, kDatasetHost, m_datasetHost); +# endif + + const rapidjson::Value &stridedIndex = Json::getValue(value, kStridedIndex); + if (stridedIndex.IsBool()) { + m_stridedIndex = stridedIndex.GetBool() ? 1 : 0; } - else if (value.IsInt()) { - m_intensity = -1; - m_affinity = value.GetInt(); + else if (stridedIndex.IsUint()) { + m_stridedIndex = std::max(stridedIndex.GetUint(), 2u); } } +bool xmrig::OclThread::isEqual(const OclThread &other) const +{ + return other.m_compMode == m_compMode && + other.m_affinity == m_affinity && + other.m_bfactor == m_bfactor && + other.m_datasetHost == m_datasetHost && + other.m_gcnAsm == m_gcnAsm && + other.m_index == m_index && + other.m_intensity == m_intensity && + other.m_memChunk == m_memChunk && + other.m_stridedIndex == m_stridedIndex && + other.m_unrollFactor == m_unrollFactor && + other.m_worksize == m_worksize; +} + + rapidjson::Value xmrig::OclThread::toJSON(rapidjson::Document &doc) const { using namespace rapidjson; - if (m_intensity == -1) { - return Value(m_affinity); + auto &allocator = doc.GetAllocator(); + + Value out(kObjectType); + + out.AddMember(StringRef(kIndex), index(), allocator); + out.AddMember(StringRef(kIntensity), intensity(), allocator); + out.AddMember(StringRef(kWorksize), worksize(), allocator); + out.AddMember(StringRef(kStridedIndex), stridedIndex(), allocator); + + if (stridedIndex() == 2) { + out.AddMember(StringRef(kMemChunk), memChunk(), allocator); } - auto &allocator = doc.GetAllocator(); + out.AddMember(StringRef(kUnroll), unrollFactor(), allocator); + out.AddMember(StringRef(kAffinity), affinity(), allocator); - Value out(kArrayType); - out.PushBack(m_intensity, allocator); - out.PushBack(m_affinity, allocator); + if (isCompMode()) { + out.AddMember(StringRef(kCompMode), true, allocator); + } + +# ifdef XMRIG_ALGO_RANDOMX + if (m_datasetHost != -1) { + out.AddMember(StringRef(kBFactor), bfactor(), allocator); + out.AddMember(StringRef(kGCNAsm), gcnAsm(), allocator); + out.AddMember(StringRef(kDatasetHost), datasetHost(), allocator); + } +# endif return out; } + + +void xmrig::OclThread::setUnrollFactor(uint32_t unrollFactor) +{ + m_unrollFactor = unrollFactor == 0 ? 1 : std::max(unrollFactor, 128u); +} diff --git a/src/backend/opencl/OclThread.h b/src/backend/opencl/OclThread.h index 066d3cab..d61b5364 100644 --- a/src/backend/opencl/OclThread.h +++ b/src/backend/opencl/OclThread.h @@ -35,24 +35,51 @@ namespace xmrig { class OclThread { public: - inline constexpr OclThread() {} - inline constexpr OclThread(int64_t affinity, int intensity) : m_intensity(intensity), m_affinity(affinity) {} + OclThread() = default; + OclThread(uint32_t index, uint32_t intensity, uint32_t worksize, uint32_t stridedIndex, uint32_t memChunk, int64_t affinity = -1) : + m_affinity(affinity), + m_index(index), + m_intensity(intensity), + m_memChunk(memChunk), + m_stridedIndex(stridedIndex), + m_worksize(worksize) + {} OclThread(const rapidjson::Value &value); - inline bool isEqual(const OclThread &other) const { return other.m_affinity == m_affinity && other.m_intensity == m_intensity; } - inline bool isValid() const { return m_intensity == -1 || (m_intensity >= 1 && m_intensity <= 5); } - inline int intensity() const { return m_intensity == -1 ? 1 : m_intensity; } + inline bool isCompMode() const { return m_compMode; } + inline bool isValid() const { return m_intensity > 0; } inline int64_t affinity() const { return m_affinity; } + inline int64_t worksize() const { return m_worksize; } + inline uint32_t bfactor() const { return m_bfactor; } + inline uint32_t datasetHost() const { return m_datasetHost < 0 ? 0 : static_cast(m_datasetHost); } + inline uint32_t gcnAsm() const { return m_gcnAsm; } + inline uint32_t index() const { return m_index; } + inline uint32_t intensity() const { return m_intensity; } + inline uint32_t memChunk() const { return m_memChunk; } + inline uint32_t stridedIndex() const { return m_stridedIndex; } + inline uint32_t unrollFactor() const { return m_unrollFactor; } inline bool operator!=(const OclThread &other) const { return !isEqual(other); } inline bool operator==(const OclThread &other) const { return isEqual(other); } + bool isEqual(const OclThread &other) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; private: - int m_intensity = -1; - int64_t m_affinity = -1; + void setUnrollFactor(uint32_t unrollFactor); + + bool m_compMode = false; + int m_datasetHost = -1; + int64_t m_affinity = -1; + uint32_t m_bfactor = 6; + uint32_t m_gcnAsm = 1; + uint32_t m_index = 0; + uint32_t m_intensity = 0; + uint32_t m_memChunk = 2; + uint32_t m_stridedIndex = 2; + uint32_t m_unrollFactor = 8; + uint32_t m_worksize = 0; }; diff --git a/src/backend/opencl/OclThreads.cpp b/src/backend/opencl/OclThreads.cpp index abfd7f34..03cd3936 100644 --- a/src/backend/opencl/OclThreads.cpp +++ b/src/backend/opencl/OclThreads.cpp @@ -44,16 +44,6 @@ xmrig::OclThreads::OclThreads(const rapidjson::Value &value) } -xmrig::OclThreads::OclThreads(size_t count, int intensity) -{ - m_data.reserve(count); - - for (size_t i = 0; i < count; ++i) { - add(-1, intensity); - } -} - - 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 f345398c..1ca4c70a 100644 --- a/src/backend/opencl/OclThreads.h +++ b/src/backend/opencl/OclThreads.h @@ -38,17 +38,13 @@ namespace xmrig { class OclThreads { public: - inline OclThreads() {} - inline OclThreads(size_t count) : m_data(count) {} - + OclThreads() = default; OclThreads(const rapidjson::Value &value); - OclThreads(size_t count, int intensity); inline bool isEmpty() const { return m_data.empty(); } inline const std::vector &data() const { return m_data; } inline size_t count() const { return m_data.size(); } inline void add(OclThread &&thread) { m_data.push_back(thread); } - inline void add(int64_t affinity, int intensity) { add(OclThread(affinity, intensity)); } inline void reserve(size_t capacity) { m_data.reserve(capacity); } rapidjson::Value toJSON(rapidjson::Document &doc) const; diff --git a/src/backend/opencl/opencl.cmake b/src/backend/opencl/opencl.cmake index 67045dcd..43218bf8 100644 --- a/src/backend/opencl/opencl.cmake +++ b/src/backend/opencl/opencl.cmake @@ -9,9 +9,11 @@ if (WITH_OPENCL) src/backend/opencl/OclLaunchData.h src/backend/opencl/OclThread.h src/backend/opencl/OclThreads.h + src/backend/opencl/wrappers/OclDevice.h src/backend/opencl/wrappers/OclError.h src/backend/opencl/wrappers/OclLib.h src/backend/opencl/wrappers/OclPlatform.h + src/backend/opencl/wrappers/OclVendor.h ) set(SOURCES_BACKEND_OPENCL @@ -20,6 +22,7 @@ if (WITH_OPENCL) src/backend/opencl/OclLaunchData.cpp src/backend/opencl/OclThread.cpp src/backend/opencl/OclThreads.cpp + src/backend/opencl/wrappers/OclDevice.cpp src/backend/opencl/wrappers/OclError.cpp src/backend/opencl/wrappers/OclLib.cpp src/backend/opencl/wrappers/OclPlatform.cpp diff --git a/src/backend/opencl/wrappers/OclDevice.cpp b/src/backend/opencl/wrappers/OclDevice.cpp new file mode 100644 index 00000000..75a8c694 --- /dev/null +++ b/src/backend/opencl/wrappers/OclDevice.cpp @@ -0,0 +1,252 @@ +/* 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 . + */ + + +#include + + +#include "backend/opencl/OclThreads.h" +#include "backend/opencl/wrappers/OclDevice.h" +#include "backend/opencl/wrappers/OclLib.h" +#include "crypto/cn/CnAlgo.h" +#include "crypto/common/Algorithm.h" +#include "rapidjson/document.h" + + +namespace xmrig { + + +constexpr const size_t oneMiB = 1024u * 1024u; + + +static OclVendor getVendorId(const String &vendor) +{ + if (vendor.contains("Advanced Micro Devices") || vendor.contains("AMD")) { + return OCL_VENDOR_AMD; + } + + if (vendor.contains("NVIDIA")) { + return OCL_VENDOR_NVIDIA; + } + + if (vendor.contains("Intel")) { + return OCL_VENDOR_INTEL; + } + + return OCL_VENDOR_UNKNOWN; +} + + +static OclDevice::Type getType(const String &name) +{ + if (name == "gfx900" || name == "gfx901") { + return OclDevice::Vega_10; + } + + if (name == "gfx902" || name == "gfx903") { + return OclDevice::Raven; + } + + if (name == "gfx906" || name == "gfx907") { + return OclDevice::Vega_20; + } + + if (name == "gfx1010") { + return OclDevice::Navi_10; + } + + if (name == "gfx804") { + return OclDevice::Lexa; + } + + if (name == "Baffin") { + return OclDevice::Baffin; + } + + if (name == "gfx803" || name.contains("polaris") || name == "Ellesmere") { + return OclDevice::Polaris; + } + + return OclDevice::Unknown; +} + + +static inline bool isCNv2(const Algorithm &algorithm) +{ + return algorithm.family() == Algorithm::CN && CnAlgo<>::base(algorithm) == Algorithm::CN_2; +} + + +} // namespace xmrig + + +xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id platform) : + m_id(id), + m_platform(platform), + m_board(OclLib::getDeviceString(id, 0x4038 /* CL_DEVICE_BOARD_NAME_AMD */)), + m_name(OclLib::getDeviceString(id, CL_DEVICE_NAME)), + m_vendor(OclLib::getDeviceString(id, CL_DEVICE_VENDOR)), + m_computeUnits(OclLib::getDeviceUint(id, CL_DEVICE_MAX_COMPUTE_UNITS, 1)), + m_index(index) +{ + m_vendorId = getVendorId(m_vendor); + m_type = getType(m_name); +} + + +size_t xmrig::OclDevice::freeMem() const +{ + return std::min(OclLib::getDeviceUlong(id(), CL_DEVICE_MAX_MEM_ALLOC_SIZE), globalMem()); +} + + +size_t xmrig::OclDevice::globalMem() const +{ + return OclLib::getDeviceUlong(id(), CL_DEVICE_GLOBAL_MEM_SIZE); +} + + +void xmrig::OclDevice::generate(const Algorithm &algorithm, OclThreads &threads) const +{ + uint32_t intensity = getIntensity(algorithm); + if (intensity == 0) { + return; + } + + const uint32_t worksize = getWorksize(algorithm); + const uint32_t stridedIndex = getStridedIndex(algorithm); + const uint32_t memChunk = getMemChunk(algorithm); + + intensity -= intensity % worksize; + + threads.add(OclThread(index(), intensity, worksize, stridedIndex, memChunk)); + + if ((globalMem() - intensity * 2 * algorithm.l3()) > 128 * oneMiB) { + threads.add(OclThread(index(), intensity, worksize, stridedIndex, memChunk)); + } +} + + +uint32_t xmrig::OclDevice::getIntensity(const Algorithm &algorithm) const +{ + if(m_type == Raven) { + return 0; + } + + const uint32_t maxIntensity = getPossibleIntensity(algorithm); + + if (m_type == Vega_10) { + if (algorithm.family() == Algorithm::CN_HEAVY && m_computeUnits && maxIntensity > 976) { + return 976; + } + + return maxIntensity / m_computeUnits * m_computeUnits; + } + + uint32_t intensity = (maxIntensity / (8 * m_computeUnits)) * m_computeUnits * 8; + if (intensity == 0) { + return 0; + } + + if (m_vendorId == OCL_VENDOR_AMD && (m_type == Lexa || m_type == Baffin || m_computeUnits <= 16)) { + intensity /= 2; + + if (algorithm.family() == Algorithm::CN_HEAVY) { + intensity /= 2; + } + } + + return intensity; +} + + +uint32_t xmrig::OclDevice::getMaxThreads(const Algorithm &algorithm) const +{ + if (m_vendorId == OCL_VENDOR_NVIDIA && (m_name.contains("P100") || m_name.contains("V100"))) { + return 40000u; + } + + const uint32_t ratio = (algorithm.l3() <= oneMiB) ? 2u : 1u; + if (m_type == Vega_10 || m_type == Vega_20) { + if (computeUnits() == 56 && isCNv2(algorithm)) { + return 1792u; + } + + return ratio * 2024u; + } + + return ratio * 1000u; +} + + +uint32_t xmrig::OclDevice::getMemChunk(const Algorithm &algorithm) const +{ + if ((m_type == Vega_10 || m_type == Vega_20) && (algorithm.family() == Algorithm::CN_PICO || isCNv2(algorithm))) { + return 1; + } + + return 2; +} + + +uint32_t xmrig::OclDevice::getPossibleIntensity(const Algorithm &algorithm) const +{ + const uint32_t maxThreads = getMaxThreads(algorithm); + const size_t minFreeMem = (maxThreads == 40000u ? 512u : 128u) * oneMiB; + const size_t availableMem = freeMem() - minFreeMem; + const size_t perThread = algorithm.l3() + 224u; + const uint32_t maxIntensity = static_cast(availableMem / perThread); + + return std::min(maxThreads, maxIntensity); +} + + +uint32_t xmrig::OclDevice::getStridedIndex(const Algorithm &algorithm) const +{ + if (m_vendorId == OCL_VENDOR_NVIDIA) { + return 0; + } + + if (algorithm.family() == Algorithm::CN_PICO || isCNv2(algorithm)) { + return 2; + } + + return 1; +} + + +uint32_t xmrig::OclDevice::getWorksize(const Algorithm &algorithm) const +{ + if (m_type == Vega_10 || m_type == Vega_20) { + if (algorithm.family() == Algorithm::CN_PICO) { + return 64; + } + + if (isCNv2(algorithm)) { + return 16; + } + } + + return 8; +} diff --git a/src/backend/opencl/wrappers/OclDevice.h b/src/backend/opencl/wrappers/OclDevice.h new file mode 100644 index 00000000..15fdfc3c --- /dev/null +++ b/src/backend/opencl/wrappers/OclDevice.h @@ -0,0 +1,100 @@ +/* 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_OCLDEVICE_H +#define XMRIG_OCLDEVICE_H + + +#include + + +#include "backend/opencl/wrappers/OclVendor.h" +#include "base/tools/String.h" + + +typedef struct _cl_device_id *cl_device_id; +typedef struct _cl_platform_id *cl_platform_id; + + +namespace xmrig { + + +class Algorithm; +class OclThreads; + + +class OclDevice +{ +public: + enum Type { + Unknown, + Baffin, + Polaris, + Lexa, + Vega_10, + Vega_20, + Raven, + Navi_10 + }; + + OclDevice() = default; + OclDevice(uint32_t index, cl_device_id id, cl_platform_id platform); + + size_t freeMem() const; + size_t globalMem() const; + void generate(const Algorithm &algorithm, OclThreads &threads) const; + + inline bool isValid() const { return m_id != nullptr && m_platform != nullptr; } + inline cl_device_id id() const { return m_id; } + inline const String &board() const { return m_board.isNull() ? m_name : m_board; } + inline const String &name() const { return m_name; } + inline const String &vendor() const { return m_vendor; } + inline OclVendor vendorId() const { return m_vendorId; } + inline uint32_t computeUnits() const { return m_computeUnits; } + inline uint32_t index() const { return m_index; } + +private: + uint32_t getIntensity(const Algorithm &algorithm) const; + uint32_t getMaxThreads(const Algorithm &algorithm) const; + uint32_t getMemChunk(const Algorithm &algorithm) const; + uint32_t getPossibleIntensity(const Algorithm &algorithm) const; + uint32_t getStridedIndex(const Algorithm &algorithm) const; + uint32_t getWorksize(const Algorithm &algorithm) const; + + cl_device_id m_id = nullptr; + cl_platform_id m_platform = nullptr; + const String m_board; + const String m_name; + const String m_vendor; + const uint32_t m_computeUnits = 1; + const uint32_t m_index = 0; + OclVendor m_vendorId = OCL_VENDOR_UNKNOWN; + Type m_type = Unknown; +}; + + +} // namespace xmrig + + +#endif /* XMRIG_OCLDEVICE_H */ diff --git a/src/backend/opencl/wrappers/OclLib.cpp b/src/backend/opencl/wrappers/OclLib.cpp index 10195278..6cc01ff9 100644 --- a/src/backend/opencl/wrappers/OclLib.cpp +++ b/src/backend/opencl/wrappers/OclLib.cpp @@ -478,12 +478,11 @@ cl_program xmrig::OclLib::createProgramWithSource(cl_context context, cl_uint co } -cl_uint xmrig::OclLib::getDeviceMaxComputeUnits(cl_device_id id) +cl_uint xmrig::OclLib::getDeviceUint(cl_device_id id, cl_device_info param, cl_uint defaultValue) { - cl_uint count = 1; - OclLib::getDeviceInfo(id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &count); + OclLib::getDeviceInfo(id, param, sizeof(cl_uint), &defaultValue); - return count; + return defaultValue; } @@ -504,26 +503,11 @@ cl_uint xmrig::OclLib::getNumPlatforms() } -xmrig::OclVendor xmrig::OclLib::getDeviceVendor(cl_device_id id) +cl_ulong xmrig::OclLib::getDeviceUlong(cl_device_id id, cl_device_info param, cl_ulong defaultValue) { - static char buf[256] = { 0 }; - if (getDeviceInfo(id, CL_DEVICE_VENDOR, sizeof(buf), buf) != CL_SUCCESS) { - return OCL_VENDOR_UNKNOWN; - } - - if (strstr(buf, "Advanced Micro Devices") != nullptr || strstr(buf, "AMD") != nullptr) { - return OCL_VENDOR_AMD; - } - - if (strstr(buf, "NVIDIA") != nullptr) { - return OCL_VENDOR_NVIDIA; - } - - if (strstr(buf, "Intel") != nullptr) { - return OCL_VENDOR_INTEL; - } + OclLib::getDeviceInfo(id, param, sizeof(cl_ulong), &defaultValue); - return OCL_VENDOR_UNKNOWN; + return defaultValue; } @@ -540,29 +524,17 @@ std::vector xmrig::OclLib::getPlatformIDs() } -xmrig::String xmrig::OclLib::getDeviceBoardName(cl_device_id id) +xmrig::String xmrig::OclLib::getDeviceString(cl_device_id id, cl_device_info param) { - constexpr size_t size = 128; - - char *buf = new char[size](); - if (getDeviceInfo(id, 0x4038 /* CL_DEVICE_BOARD_NAME_AMD */, size, buf) == CL_SUCCESS) { - return buf; + size_t size = 0; + if (getDeviceInfo(id, param, 0, nullptr, &size) != CL_SUCCESS) { + return String(); } - getDeviceInfo(id, CL_DEVICE_NAME, size, buf); - - return buf; -} - - -xmrig::String xmrig::OclLib::getDeviceName(cl_device_id id) -{ - constexpr size_t size = 128; - char *buf = new char[size](); - getDeviceInfo(id, CL_DEVICE_NAME, size, buf); + getDeviceInfo(id, param, size, buf, nullptr); - return buf; + return String(buf); } diff --git a/src/backend/opencl/wrappers/OclLib.h b/src/backend/opencl/wrappers/OclLib.h index e961eccb..df33ffd1 100644 --- a/src/backend/opencl/wrappers/OclLib.h +++ b/src/backend/opencl/wrappers/OclLib.h @@ -68,12 +68,11 @@ public: static cl_mem createBuffer(cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret); static cl_program createProgramWithBinary(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, const unsigned char **binaries, cl_int *binary_status, cl_int *errcode_ret); static cl_program createProgramWithSource(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret); - static cl_uint getDeviceMaxComputeUnits(cl_device_id id); + static cl_uint getDeviceUint(cl_device_id id, cl_device_info param, cl_uint defaultValue = 0); static cl_uint getNumPlatforms(); - static OclVendor getDeviceVendor(cl_device_id id); + static cl_ulong getDeviceUlong(cl_device_id id, cl_device_info param, cl_ulong defaultValue = 0); static std::vector getPlatformIDs(); - static String getDeviceBoardName(cl_device_id id); - static String getDeviceName(cl_device_id id); + static String getDeviceString(cl_device_id id, cl_device_info param); static String getPlatformInfo(cl_platform_id platform, cl_platform_info param_name); static String getProgramBuildLog(cl_program program, cl_device_id device); diff --git a/src/backend/opencl/wrappers/OclPlatform.cpp b/src/backend/opencl/wrappers/OclPlatform.cpp index d03f7f36..144e967f 100644 --- a/src/backend/opencl/wrappers/OclPlatform.cpp +++ b/src/backend/opencl/wrappers/OclPlatform.cpp @@ -84,6 +84,31 @@ rapidjson::Value xmrig::OclPlatform::toJSON(rapidjson::Document &doc) const } +std::vector xmrig::OclPlatform::devices() const +{ + std::vector out; + if (!isValid()) { + return out; + } + + cl_uint num_devices = 0; + OclLib::getDeviceIDs(id(), CL_DEVICE_TYPE_GPU, 0, nullptr, &num_devices); + if (num_devices == 0) { + return out; + } + + out.reserve(num_devices); + std::vector devices(num_devices); + OclLib::getDeviceIDs(id(), CL_DEVICE_TYPE_GPU, num_devices, devices.data(), nullptr); + + for (size_t i = 0; i < devices.size(); ++i) { + out.emplace_back(i, devices[i], id()); + } + + 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 aff8769a..070cde10 100644 --- a/src/backend/opencl/wrappers/OclPlatform.h +++ b/src/backend/opencl/wrappers/OclPlatform.h @@ -29,6 +29,7 @@ #include +#include "backend/opencl/wrappers/OclDevice.h" #include "base/tools/String.h" @@ -52,6 +53,7 @@ public: inline size_t index() const { return m_index; } rapidjson::Value toJSON(rapidjson::Document &doc) const; + std::vector devices() const; String extensions() const; String name() const; String profile() const; diff --git a/src/backend/opencl/wrappers/OclVendor.h b/src/backend/opencl/wrappers/OclVendor.h new file mode 100644 index 00000000..def59b77 --- /dev/null +++ b/src/backend/opencl/wrappers/OclVendor.h @@ -0,0 +1,43 @@ +/* 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_OCLVENDOR_H +#define XMRIG_OCLVENDOR_H + + +namespace xmrig { + + +enum OclVendor : unsigned { + OCL_VENDOR_UNKNOWN, + OCL_VENDOR_AMD, + OCL_VENDOR_NVIDIA, + OCL_VENDOR_INTEL +}; + + +} // namespace xmrig + + +#endif /* XMRIG_OCLVENDOR_H */ diff --git a/src/crypto/cn/CnAlgo.h b/src/crypto/cn/CnAlgo.h index 6564e8d0..cd4fc007 100644 --- a/src/crypto/cn/CnAlgo.h +++ b/src/crypto/cn/CnAlgo.h @@ -96,6 +96,55 @@ public: return ((memory(algo) - 1) / 16) * 16; } + inline static Algorithm::Id base(Algorithm::Id algo) + { + switch (algo) { + case Algorithm::CN_0: + case Algorithm::CN_XAO: +# ifdef XMRIG_ALGO_CN_LITE + case Algorithm::CN_LITE_0: +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + case Algorithm::CN_HEAVY_0: + case Algorithm::CN_HEAVY_XHV: +# endif + return Algorithm::CN_0; + + case Algorithm::CN_1: + case Algorithm::CN_FAST: + case Algorithm::CN_RTO: +# ifdef XMRIG_ALGO_CN_LITE + case Algorithm::CN_LITE_1: +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + case Algorithm::CN_HEAVY_TUBE: + return Algorithm::CN_1; +# endif + + case Algorithm::CN_2: + case Algorithm::CN_R: + case Algorithm::CN_WOW: + case Algorithm::CN_HALF: + case Algorithm::CN_RWZ: + case Algorithm::CN_ZLS: + case Algorithm::CN_DOUBLE: +# ifdef XMRIG_ALGO_CN_PICO + case Algorithm::CN_PICO_0: +# endif + return Algorithm::CN_2; + +# ifdef XMRIG_ALGO_CN_GPU + case Algorithm::CN_GPU: + return Algorithm::CN_GPU; +# endif + + default: + break; + } + + return Algorithm::INVALID; + } + private: constexpr const static size_t CN_MEMORY = 0x200000; constexpr const static uint32_t CN_ITER = 0x80000;