From 175a7b06b7795061d0fc79289aae90955b0ba5c8 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 30 Oct 2019 15:33:06 +0700 Subject: [PATCH] Added initial NVML stub. --- CMakeLists.txt | 1 + src/backend/cuda/CudaBackend.cpp | 55 +++++++++-- src/backend/cuda/CudaConfig.cpp | 23 +++++ src/backend/cuda/CudaConfig.h | 10 ++ src/backend/cuda/cuda.cmake | 14 +++ src/backend/cuda/wrappers/CudaLib.cpp | 1 - src/backend/cuda/wrappers/NvmlLib.cpp | 136 ++++++++++++++++++++++++++ src/backend/cuda/wrappers/NvmlLib.h | 62 ++++++++++++ src/backend/cuda/wrappers/nvml_lite.h | 38 +++++++ src/crypto/common/Nonce.cpp | 12 +-- 10 files changed, 335 insertions(+), 17 deletions(-) create mode 100644 src/backend/cuda/wrappers/NvmlLib.cpp create mode 100644 src/backend/cuda/wrappers/NvmlLib.h create mode 100644 src/backend/cuda/wrappers/nvml_lite.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a195f6e..849c1257 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ option(WITH_ASM "Enable ASM PoW implementations" ON) option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF) option(WITH_OPENCL "Enable OpenCL backend" ON) option(WITH_CUDA "Enable CUDA backend" ON) +option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (only if CUDA backend enabled)" ON) option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON) option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF) diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp index db0d512e..a8cfa688 100644 --- a/src/backend/cuda/CudaBackend.cpp +++ b/src/backend/cuda/CudaBackend.cpp @@ -51,6 +51,13 @@ #endif +#ifdef XMRIG_FEATURE_NVML +#include "backend/cuda/wrappers/NvmlLib.h" + +namespace xmrig { static const char *kNvmlLabel = "NVML"; } +#endif + + namespace xmrig { @@ -58,15 +65,16 @@ extern template class Threads; constexpr const size_t oneMiB = 1024u * 1024u; +static const char *kLabel = "CUDA"; static const char *tag = GREEN_BG_BOLD(WHITE_BOLD_S " nv "); static const String kType = "cuda"; static std::mutex mutex; -static void printDisabled(const char *reason) +static void printDisabled(const char *label, const char *reason) { - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled") "%s", "CUDA", reason); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled") "%s", label, reason); } @@ -129,29 +137,44 @@ public: void init(const CudaConfig &cuda) { if (!cuda.isEnabled()) { - return printDisabled(""); + return printDisabled(kLabel, ""); } if (!CudaLib::init(cuda.loader())) { - return printDisabled(RED_S " (failed to load CUDA plugin)"); + return printDisabled(kLabel, RED_S " (failed to load CUDA plugin)"); } runtimeVersion = CudaLib::runtimeVersion(); driverVersion = CudaLib::driverVersion(); if (!runtimeVersion || !driverVersion || !CudaLib::deviceCount()) { - return printDisabled(RED_S " (no devices)"); + return printDisabled(kLabel, RED_S " (no devices)"); } if (!devices.empty()) { return; } - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" WHITE_BOLD("%s") BLACK_BOLD("/%s"), "CUDA", + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" WHITE_BOLD("%s") BLACK_BOLD("/%s"), kLabel, CudaLib::version(runtimeVersion).c_str(), CudaLib::version(driverVersion).c_str(), CudaLib::pluginVersion()); devices = CudaLib::devices(cuda.bfactor(), cuda.bsleep()); +# ifdef XMRIG_FEATURE_NVML + if (cuda.isNvmlEnabled()) { + if (NvmlLib::init(cuda.nvmlLoader())) { + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" GREEN_BOLD("%s"), kNvmlLabel, + NvmlLib::version(), NvmlLib::driverVersion()); + } + else { + printDisabled(kLabel, RED_S " (failed to load NVML)"); + } + } + else { + printDisabled(kNvmlLabel, ""); + } +# endif + for (const CudaDevice &device : devices) { Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") GREEN_BOLD(" %s ") WHITE_BOLD("%u/%u MHz") " smx:" WHITE_BOLD("%u") " arch:" WHITE_BOLD("%u%u") " mem:" CYAN("%zu/%zu") " MB", "CUDA GPU", @@ -238,6 +261,10 @@ xmrig::CudaBackend::~CudaBackend() delete d_ptr; CudaLib::close(); + +# ifdef XMRIG_FEATURE_NVML + NvmlLib::close(); +# endif } @@ -394,10 +421,18 @@ rapidjson::Value xmrig::CudaBackend::toJSON(rapidjson::Document &doc) const out.AddMember("profile", profileName().toJSON(), allocator); Value versions(kObjectType); - versions.AddMember("runtime", Value(CudaLib::version(d_ptr->runtimeVersion).c_str(), allocator), allocator); - versions.AddMember("driver", Value(CudaLib::version(d_ptr->driverVersion).c_str(), allocator), allocator); - versions.AddMember("plugin", String(CudaLib::pluginVersion()).toJSON(doc), allocator); - out.AddMember("versions", versions, allocator); + versions.AddMember("cuda-runtime", Value(CudaLib::version(d_ptr->runtimeVersion).c_str(), allocator), allocator); + versions.AddMember("cuda-driver", Value(CudaLib::version(d_ptr->driverVersion).c_str(), allocator), allocator); + versions.AddMember("plugin", String(CudaLib::pluginVersion()).toJSON(doc), allocator); + +# ifdef XMRIG_FEATURE_NVML + if (NvmlLib::isReady()) { + versions.AddMember("nvml", StringRef(NvmlLib::version()), allocator); + versions.AddMember("driver", StringRef(NvmlLib::driverVersion()), allocator); + } +# endif + + out.AddMember("versions", versions, allocator); if (d_ptr->threads.empty() || !hashrate()) { return out; diff --git a/src/backend/cuda/CudaConfig.cpp b/src/backend/cuda/CudaConfig.cpp index 19817c65..49a28d11 100644 --- a/src/backend/cuda/CudaConfig.cpp +++ b/src/backend/cuda/CudaConfig.cpp @@ -40,6 +40,10 @@ static const char *kDevicesHint = "devices-hint"; static const char *kEnabled = "enabled"; static const char *kLoader = "loader"; +#ifdef XMRIG_FEATURE_NVML +static const char *kNvml = "nvml"; +#endif + extern template class Threads; @@ -57,6 +61,15 @@ rapidjson::Value xmrig::CudaConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kEnabled), m_enabled, allocator); obj.AddMember(StringRef(kLoader), m_loader.toJSON(), allocator); +# ifdef XMRIG_FEATURE_NVML + if (m_nvmlLoader.isNull()) { + obj.AddMember(StringRef(kNvml), m_nvml, allocator); + } + else { + obj.AddMember(StringRef(kNvml), m_nvmlLoader.toJSON(), allocator); + } +# endif + m_threads.toJSON(obj, doc); return obj; @@ -95,6 +108,16 @@ void xmrig::CudaConfig::read(const rapidjson::Value &value) setDevicesHint(Json::getString(value, kDevicesHint)); +# ifdef XMRIG_FEATURE_NVML + auto &nvml = Json::getValue(value, kNvml); + if (nvml.IsString()) { + m_nvmlLoader = nvml.GetString(); + } + else if (nvml.IsBool()) { + m_nvml = nvml.GetBool(); + } +# endif + m_threads.read(value); generate(); diff --git a/src/backend/cuda/CudaConfig.h b/src/backend/cuda/CudaConfig.h index 4367d826..77be3dd4 100644 --- a/src/backend/cuda/CudaConfig.h +++ b/src/backend/cuda/CudaConfig.h @@ -50,6 +50,11 @@ public: inline int32_t bfactor() const { return m_bfactor; } inline int32_t bsleep() const { return m_bsleep; } +# ifdef XMRIG_FEATURE_NVML + inline bool isNvmlEnabled() const { return m_nvml; } + inline const String &nvmlLoader() const { return m_nvmlLoader; } +# endif + private: void generate(); void setDevicesHint(const char *devicesHint); @@ -67,6 +72,11 @@ private: int32_t m_bfactor = 0; int32_t m_bsleep = 0; # endif + +# ifdef XMRIG_FEATURE_NVML + bool m_nvml = true; + String m_nvmlLoader; +# endif }; diff --git a/src/backend/cuda/cuda.cmake b/src/backend/cuda/cuda.cmake index 764acd0f..a5dd27b8 100644 --- a/src/backend/cuda/cuda.cmake +++ b/src/backend/cuda/cuda.cmake @@ -30,8 +30,22 @@ if (WITH_CUDA) src/backend/cuda/wrappers/CudaDevice.cpp src/backend/cuda/wrappers/CudaLib.cpp ) + + if (WITH_NVML AND NOT APPLE) + add_definitions(/DXMRIG_FEATURE_NVML) + + list(APPEND HEADERS_BACKEND_CUDA + src/backend/cuda/wrappers/nvml_lite.h + src/backend/cuda/wrappers/NvmlLib.h + ) + + list(APPEND SOURCES_BACKEND_CUDA src/backend/cuda/wrappers/NvmlLib.cpp) + else() + remove_definitions(/DXMRIG_FEATURE_NVML) + endif() else() remove_definitions(/DXMRIG_FEATURE_CUDA) + remove_definitions(/DXMRIG_FEATURE_NVML) set(HEADERS_BACKEND_CUDA "") set(SOURCES_BACKEND_CUDA "") diff --git a/src/backend/cuda/wrappers/CudaLib.cpp b/src/backend/cuda/wrappers/CudaLib.cpp index 5f3018d3..7264d67d 100644 --- a/src/backend/cuda/wrappers/CudaLib.cpp +++ b/src/backend/cuda/wrappers/CudaLib.cpp @@ -28,7 +28,6 @@ #include "backend/cuda/wrappers/CudaLib.h" -#include "base/io/log/Log.h" namespace xmrig { diff --git a/src/backend/cuda/wrappers/NvmlLib.cpp b/src/backend/cuda/wrappers/NvmlLib.cpp new file mode 100644 index 00000000..2eb731cc --- /dev/null +++ b/src/backend/cuda/wrappers/NvmlLib.cpp @@ -0,0 +1,136 @@ +/* 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 + + +#include "backend/cuda/wrappers/NvmlLib.h" +#include "backend/cuda/wrappers/nvml_lite.h" +#include "base/io/log/Log.h" + + + +namespace xmrig { + + +static uv_lib_t nvmlLib; + + +static const char *kNvmlInit = "nvmlInit_v2"; +static const char *kNvmlShutdown = "nvmlShutdown"; +static const char *kNvmlSystemGetDriverVersion = "nvmlSystemGetDriverVersion"; +static const char *kNvmlSystemGetNVMLVersion = "nvmlSystemGetNVMLVersion"; +static const char *kSymbolNotFound = "symbol not found"; + + +static nvmlReturn_t (*pNvmlInit)() = nullptr; +static nvmlReturn_t (*pNvmlShutdown)() = nullptr; +static nvmlReturn_t (*pNvmlSystemGetDriverVersion)(char *version, unsigned int length) = nullptr; +static nvmlReturn_t (*pNvmlSystemGetNVMLVersion)(char *version, unsigned int length) = nullptr; + + +#define DLSYM(x) if (uv_dlsym(&nvmlLib, k##x, reinterpret_cast(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); } + + +bool NvmlLib::m_initialized = false; +bool NvmlLib::m_ready = false; +char NvmlLib::m_driverVersion[80] = { 0 }; +char NvmlLib::m_nvmlVersion[80] = { 0 }; +String NvmlLib::m_loader; + + +} // namespace xmrig + + +bool xmrig::NvmlLib::init(const char *fileName) +{ + if (!m_initialized) { + m_loader = fileName; + m_ready = dlopen() && load(); + m_initialized = true; + } + + return m_ready; +} + + +const char *xmrig::NvmlLib::lastError() noexcept +{ + return uv_dlerror(&nvmlLib); +} + + +void xmrig::NvmlLib::close() +{ + if (m_ready) { + pNvmlShutdown(); + } + + uv_dlclose(&nvmlLib); +} + + +bool xmrig::NvmlLib::dlopen() +{ + if (!m_loader.isNull()) { + return uv_dlopen(m_loader, &nvmlLib) == 0; + } + +# ifdef _WIN32 + if (uv_dlopen("nvml.dll", &nvmlLib) == 0) { + return true; + } + + char path[MAX_PATH] = { 0 }; + ExpandEnvironmentStringsA("%PROGRAMFILES%\\NVIDIA Corporation\\NVSMI\\nvml.dll", path, sizeof(path)); + + return uv_dlopen(path, &nvmlLib) == 0; +# else + return uv_dlopen("libnvidia-ml.so", &nvmlLib) == 0; +# endif +} + + +bool xmrig::NvmlLib::load() +{ + try { + DLSYM(NvmlInit); + DLSYM(NvmlShutdown); + DLSYM(NvmlSystemGetDriverVersion); + DLSYM(NvmlSystemGetNVMLVersion); + } catch (std::exception &ex) { + return false; + } + + if (pNvmlInit() != NVML_SUCCESS) { + return false; + } + + pNvmlSystemGetDriverVersion(m_driverVersion, sizeof(m_driverVersion)); + pNvmlSystemGetNVMLVersion(m_nvmlVersion, sizeof(m_nvmlVersion)); + + return true; +} diff --git a/src/backend/cuda/wrappers/NvmlLib.h b/src/backend/cuda/wrappers/NvmlLib.h new file mode 100644 index 00000000..395858f5 --- /dev/null +++ b/src/backend/cuda/wrappers/NvmlLib.h @@ -0,0 +1,62 @@ +/* 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_NVMLLIB_H +#define XMRIG_NVMLLIB_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +class NvmlLib +{ +public: + static bool init(const char *fileName = nullptr); + static const char *lastError() noexcept; + static void close(); + + static inline bool isInitialized() noexcept { return m_initialized; } + static inline bool isReady() noexcept { return m_ready; } + static inline const char *driverVersion() noexcept { return m_driverVersion; } + static inline const char *version() noexcept { return m_nvmlVersion; } + +private: + static bool dlopen(); + static bool load(); + + static bool m_initialized; + static bool m_ready; + static char m_driverVersion[80]; + static char m_nvmlVersion[80]; + static String m_loader; +}; + + +} // namespace xmrig + + +#endif /* XMRIG_NVMLLIB_H */ diff --git a/src/backend/cuda/wrappers/nvml_lite.h b/src/backend/cuda/wrappers/nvml_lite.h new file mode 100644 index 00000000..1de6e657 --- /dev/null +++ b/src/backend/cuda/wrappers/nvml_lite.h @@ -0,0 +1,38 @@ +/* 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_NVML_LITE_H +#define XMRIG_NVML_LITE_H + + +#include + + +#define NVML_SUCCESS 0 + + +using nvmlReturn_t = uint32_t; + + +#endif /* XMRIG_NVML_LITE_H */ diff --git a/src/crypto/common/Nonce.cpp b/src/crypto/common/Nonce.cpp index e79cb310..897045ca 100644 --- a/src/crypto/common/Nonce.cpp +++ b/src/crypto/common/Nonce.cpp @@ -48,8 +48,8 @@ xmrig::Nonce::Nonce() { m_paused = true; - for (int i = 0; i < MAX; ++i) { - m_sequence[i] = 1; + for (auto &i : m_sequence) { + i = 1; } } @@ -85,15 +85,15 @@ void xmrig::Nonce::stop() { pause(false); - for (int i = 0; i < MAX; ++i) { - m_sequence[i] = 0; + for (auto &i : m_sequence) { + i = 0; } } void xmrig::Nonce::touch() { - for (int i = 0; i < MAX; ++i) { - m_sequence[i]++; + for (auto &i : m_sequence) { + i++; } }