diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1a195f6e0..849c1257e 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/README.md b/README.md
index cffb28c7a..fa2e814ad 100644
--- a/README.md
+++ b/README.md
@@ -84,11 +84,13 @@ OpenCL backend:
 CUDA backend:
       --cuda                    enable CUDA mining backend
       --cuda-loader=PATH        path to CUDA plugin (xmrig-cuda.dll or libxmrig-cuda.so)
+      --no-nvml                 disable NVML (NVIDIA Management Library) support
 
 Logging:
   -S, --syslog                  use system log for output messages
   -l, --log-file=FILE           log all output to a file
       --print-time=N            print hashrate report every N seconds
+      --health-print-time=N     print health report every N seconds
       --no-color                disable colored output
 
 Misc:
diff --git a/src/App.cpp b/src/App.cpp
index 7db2ace28..04b054515 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -98,29 +98,12 @@ int xmrig::App::exec()
 
 void xmrig::App::onConsoleCommand(char command)
 {
-    switch (command) {
-    case 'h':
-    case 'H':
-        m_controller->miner()->printHashrate(true);
-        break;
-
-    case 'p':
-    case 'P':
-        m_controller->miner()->setEnabled(false);
-        break;
-
-    case 'r':
-    case 'R':
-        m_controller->miner()->setEnabled(true);
-        break;
-
-    case 3:
+    if (command == 3) {
         LOG_WARN("Ctrl+C received, exiting");
         close();
-        break;
-
-    default:
-        break;
+    }
+    else {
+        m_controller->miner()->execCommand(command);
     }
 }
 
diff --git a/src/Summary.cpp b/src/Summary.cpp
index 2b8939a7a..2055e972a 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -126,9 +126,9 @@ static void print_threads(Config *config)
 static void print_commands(Config *)
 {
     if (Log::colors) {
-        Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS     ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ")
-                                                                     MAGENTA_BOLD("p") WHITE_BOLD("ause, ")
-                                                                     MAGENTA_BOLD("r") WHITE_BOLD("esume"));
+        Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS     ") MAGENTA_BG(WHITE_BOLD_S "h") WHITE_BOLD("ashrate, ")
+                                                                     MAGENTA_BG(WHITE_BOLD_S "p") WHITE_BOLD("ause, ")
+                                                                     MAGENTA_BG(WHITE_BOLD_S "r") WHITE_BOLD("esume"));
     }
     else {
         Log::print(" * COMMANDS     'h' hashrate, 'p' pause, 'r' resume");
diff --git a/src/backend/common/interfaces/IBackend.h b/src/backend/common/interfaces/IBackend.h
index f90732293..c6e05bcfb 100644
--- a/src/backend/common/interfaces/IBackend.h
+++ b/src/backend/common/interfaces/IBackend.h
@@ -53,6 +53,7 @@ public:
     virtual const Hashrate *hashrate() const                            = 0;
     virtual const String &profileName() const                           = 0;
     virtual const String &type() const                                  = 0;
+    virtual void execCommand(char command)                              = 0;
     virtual void prepare(const Job &nextJob)                            = 0;
     virtual void printHashrate(bool details)                            = 0;
     virtual void setJob(const Job &job)                                 = 0;
diff --git a/src/backend/cpu/CpuBackend.h b/src/backend/cpu/CpuBackend.h
index d5d9fbf6c..d0e2267a2 100644
--- a/src/backend/cpu/CpuBackend.h
+++ b/src/backend/cpu/CpuBackend.h
@@ -50,6 +50,8 @@ public:
     ~CpuBackend() override;
 
 protected:
+    inline void execCommand(char) override {}
+
     bool isEnabled() const override;
     bool isEnabled(const Algorithm &algorithm) const override;
     const Hashrate *hashrate() const override;
diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp
index db0d512e3..feb1dd93f 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<CudaThreads>;
 
 
 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,49 @@ 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())) {
+                NvmlLib::assign(devices);
+
+                Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" GREEN_BOLD("%s") " press " MAGENTA_BG(WHITE_BOLD_S "e") " for health report",
+                           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",
@@ -205,6 +233,38 @@ public:
     }
 
 
+#   ifdef XMRIG_FEATURE_NVML
+    void printHealth()
+    {
+        for (const auto &device : devices) {
+            const auto health = NvmlLib::health(device.nvmlDevice());
+
+            std::string clocks;
+            if (health.clock && health.memClock) {
+                clocks += " " + std::to_string(health.clock) + "/" + std::to_string(health.memClock) + " MHz";
+            }
+
+            std::string fans;
+            if (!health.fanSpeed.empty()) {
+                for (uint32_t i = 0; i < health.fanSpeed.size(); ++i) {
+                    fans += " fan" + std::to_string(i) + ":" CYAN_BOLD_S + std::to_string(health.fanSpeed[i]) + "%" CLEAR;
+                }
+            }
+
+            LOG_INFO(CYAN_BOLD("#%u") YELLOW(" %s") MAGENTA_BOLD("%4uW") CSI "1;%um %2uC" CLEAR WHITE_BOLD("%s") "%s",
+                     device.index(),
+                     device.topology().toString().data(),
+                     health.power,
+                     health.temperature < 60 ? 32 : (health.temperature > 85 ? 31 : 33),
+                     health.temperature,
+                     clocks.c_str(),
+                     fans.c_str()
+                     );
+        }
+    }
+#   endif
+
+
     Algorithm algo;
     Controller *controller;
     CudaLaunchStatus status;
@@ -238,6 +298,10 @@ xmrig::CudaBackend::~CudaBackend()
     delete d_ptr;
 
     CudaLib::close();
+
+#   ifdef XMRIG_FEATURE_NVML
+    NvmlLib::close();
+#   endif
 }
 
 
@@ -271,6 +335,16 @@ const xmrig::String &xmrig::CudaBackend::type() const
 }
 
 
+void xmrig::CudaBackend::execCommand(char command)
+{
+#   ifdef XMRIG_FEATURE_NVML
+    if (command == 'e' || command == 'E') {
+        d_ptr->printHealth();
+    }
+#   endif
+}
+
+
 void xmrig::CudaBackend::prepare(const Job &)
 {
 }
@@ -378,6 +452,13 @@ void xmrig::CudaBackend::stop()
 void xmrig::CudaBackend::tick(uint64_t ticks)
 {
     d_ptr->workers.tick(ticks);
+
+#   ifdef XMRIG_FEATURE_NVML
+    auto seconds = d_ptr->controller->config()->healthPrintTime();
+    if (seconds && ticks && (ticks % (seconds * 2)) == 0) {
+        d_ptr->printHealth();
+    }
+#   endif
 }
 
 
@@ -394,10 +475,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/CudaBackend.h b/src/backend/cuda/CudaBackend.h
index 0d2a2395d..cf0bb6217 100644
--- a/src/backend/cuda/CudaBackend.h
+++ b/src/backend/cuda/CudaBackend.h
@@ -56,6 +56,7 @@ protected:
     const Hashrate *hashrate() const override;
     const String &profileName() const override;
     const String &type() const override;
+    void execCommand(char command) override;
     void prepare(const Job &nextJob) override;
     void printHashrate(bool details) override;
     void setJob(const Job &job) override;
diff --git a/src/backend/cuda/CudaConfig.cpp b/src/backend/cuda/CudaConfig.cpp
index 19817c65b..49a28d114 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<CudaThreads>;
 
@@ -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 4367d8267..77be3dd41 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 764acd0f0..58ba3f5a5 100644
--- a/src/backend/cuda/cuda.cmake
+++ b/src/backend/cuda/cuda.cmake
@@ -30,8 +30,23 @@ 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/NvmlHealth.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/CudaDevice.cpp b/src/backend/cuda/wrappers/CudaDevice.cpp
index 740a063c5..efacc800e 100644
--- a/src/backend/cuda/wrappers/CudaDevice.cpp
+++ b/src/backend/cuda/wrappers/CudaDevice.cpp
@@ -30,6 +30,9 @@
 #include "crypto/common/Algorithm.h"
 #include "rapidjson/document.h"
 
+#ifdef XMRIG_FEATURE_NVML
+#   include "backend/cuda/wrappers/NvmlLib.h"
+#endif
 
 #include <algorithm>
 
@@ -125,5 +128,25 @@ void xmrig::CudaDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc)
     out.AddMember("global_mem",     static_cast<uint64_t>(globalMemSize()), allocator);
     out.AddMember("clock",          clock(), allocator);
     out.AddMember("memory_clock",   memoryClock(), allocator);
+
+#   ifdef XMRIG_FEATURE_NVML
+    if (m_nvmlDevice) {
+        auto data = NvmlLib::health(m_nvmlDevice);
+
+        Value health(kObjectType);
+        health.AddMember("temperature", data.temperature, allocator);
+        health.AddMember("power",       data.power, allocator);
+        health.AddMember("clock",       data.clock, allocator);
+        health.AddMember("mem_clock",   data.memClock, allocator);
+
+        Value fanSpeed(kArrayType);
+        for (auto speed : data.fanSpeed) {
+            fanSpeed.PushBack(speed, allocator);
+        }
+        health.AddMember("fan_speed", fanSpeed, allocator);
+
+        out.AddMember("health", health, allocator);
+    }
+#   endif
 }
 #endif
diff --git a/src/backend/cuda/wrappers/CudaDevice.h b/src/backend/cuda/wrappers/CudaDevice.h
index 07866c82e..8c624c852 100644
--- a/src/backend/cuda/wrappers/CudaDevice.h
+++ b/src/backend/cuda/wrappers/CudaDevice.h
@@ -30,7 +30,8 @@
 #include "base/tools/String.h"
 
 
-using nvid_ctx = struct nvid_ctx;
+using nvid_ctx      = struct nvid_ctx;
+using nvmlDevice_t  = struct nvmlDevice_st *;
 
 
 namespace xmrig {
@@ -57,11 +58,16 @@ public:
     uint32_t smx() const;
     void generate(const Algorithm &algorithm, CudaThreads &threads) const;
 
-    inline bool isValid() const                 { return m_ctx != nullptr; }
-    inline const PciTopology &topology() const  { return m_topology; }
-    inline const String &name() const           { return m_name; }
-    inline uint32_t arch() const                { return (computeCapability(true) * 10) + computeCapability(false); }
-    inline uint32_t index() const               { return m_index; }
+    inline bool isValid() const                     { return m_ctx != nullptr; }
+    inline const PciTopology &topology() const      { return m_topology; }
+    inline const String &name() const               { return m_name; }
+    inline uint32_t arch() const                    { return (computeCapability(true) * 10) + computeCapability(false); }
+    inline uint32_t index() const                   { return m_index; }
+
+#   ifdef XMRIG_FEATURE_NVML
+    inline nvmlDevice_t nvmlDevice() const          { return m_nvmlDevice; }
+    inline void setNvmlDevice(nvmlDevice_t device)  { m_nvmlDevice = device; }
+#   endif
 
 #   ifdef XMRIG_FEATURE_API
     void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const;
@@ -75,6 +81,10 @@ private:
     nvid_ctx *m_ctx                 = nullptr;
     PciTopology m_topology;
     String m_name;
+
+#   ifdef XMRIG_FEATURE_NVML
+    nvmlDevice_t m_nvmlDevice       = nullptr;
+#   endif
 };
 
 
diff --git a/src/backend/cuda/wrappers/CudaLib.cpp b/src/backend/cuda/wrappers/CudaLib.cpp
index 5f3018d36..7264d67d5 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/NvmlHealth.h b/src/backend/cuda/wrappers/NvmlHealth.h
new file mode 100644
index 000000000..58c1d3eb1
--- /dev/null
+++ b/src/backend/cuda/wrappers/NvmlHealth.h
@@ -0,0 +1,43 @@
+/* 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_NVMLHEALTH_H
+#define XMRIG_NVMLHEALTH_H
+
+
+#include <cstdint>
+#include <vector>
+
+
+struct NvmlHealth
+{
+    std::vector<uint32_t> fanSpeed;
+    uint32_t clock          = 0;
+    uint32_t memClock       = 0;
+    uint32_t power          = 0;
+    uint32_t temperature    = 0;
+};
+
+
+#endif /* XMRIG_NVMLHEALTH_H */
diff --git a/src/backend/cuda/wrappers/NvmlLib.cpp b/src/backend/cuda/wrappers/NvmlLib.cpp
new file mode 100644
index 000000000..cb05bdc17
--- /dev/null
+++ b/src/backend/cuda/wrappers/NvmlLib.cpp
@@ -0,0 +1,227 @@
+/* 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/>.
+ */
+
+
+#include <stdexcept>
+#include <uv.h>
+
+
+#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 *kNvmlDeviceGetClockInfo                          = "nvmlDeviceGetClockInfo";
+static const char *kNvmlDeviceGetCount                              = "nvmlDeviceGetCount_v2";
+static const char *kNvmlDeviceGetFanSpeed                           = "nvmlDeviceGetFanSpeed";
+static const char *kNvmlDeviceGetFanSpeed_v2                        = "nvmlDeviceGetFanSpeed_v2";
+static const char *kNvmlDeviceGetHandleByIndex                      = "nvmlDeviceGetHandleByIndex_v2";
+static const char *kNvmlDeviceGetPciInfo                            = "nvmlDeviceGetPciInfo_v2";
+static const char *kNvmlDeviceGetPowerUsage                         = "nvmlDeviceGetPowerUsage";
+static const char *kNvmlDeviceGetTemperature                        = "nvmlDeviceGetTemperature";
+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 (*pNvmlDeviceGetClockInfo)(nvmlDevice_t device, uint32_t type, uint32_t *clock)                         = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetCount)(uint32_t *deviceCount)                                                           = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetFanSpeed_v2)(nvmlDevice_t device, uint32_t fan, uint32_t *speed)                        = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetFanSpeed)(nvmlDevice_t device, uint32_t *speed)                                         = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetHandleByIndex)(uint32_t index, nvmlDevice_t *device)                                    = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetPciInfo)(nvmlDevice_t device, nvmlPciInfo_t *pci)                                       = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetPowerUsage)(nvmlDevice_t device, uint32_t *power)                                       = nullptr;
+static nvmlReturn_t (*pNvmlDeviceGetTemperature)(nvmlDevice_t device, uint32_t sensorType, uint32_t *temp)                  = nullptr;
+static nvmlReturn_t (*pNvmlInit)()                                                                                          = nullptr;
+static nvmlReturn_t (*pNvmlShutdown)()                                                                                      = nullptr;
+static nvmlReturn_t (*pNvmlSystemGetDriverVersion)(char *version, uint32_t length)                                          = nullptr;
+static nvmlReturn_t (*pNvmlSystemGetNVMLVersion)(char *version, uint32_t length)                                            = nullptr;
+
+
+#define DLSYM(x) if (uv_dlsym(&nvmlLib, k##x, reinterpret_cast<void**>(&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::assign(std::vector<CudaDevice> &devices)
+{
+    uint32_t count = 0;
+    if (pNvmlDeviceGetCount(&count) != NVML_SUCCESS) {
+        return false;
+    }
+
+    for (uint32_t i = 0; i < count; i++) {
+        nvmlDevice_t nvmlDevice;
+        if (pNvmlDeviceGetHandleByIndex(i, &nvmlDevice) != NVML_SUCCESS) {
+            continue;
+        }
+
+        nvmlPciInfo_t pci;
+        if (pNvmlDeviceGetPciInfo(nvmlDevice, &pci) != NVML_SUCCESS) {
+            continue;
+        }
+
+        for (auto &device : devices) {
+            if (device.topology().bus() == pci.bus && device.topology().device() == pci.device) {
+                device.setNvmlDevice(nvmlDevice);
+            }
+        }
+    }
+
+    return true;
+}
+
+
+NvmlHealth xmrig::NvmlLib::health(nvmlDevice_t device)
+{
+    if (!device) {
+        return {};
+    }
+
+    NvmlHealth health;
+    pNvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &health.temperature);
+    pNvmlDeviceGetPowerUsage(device, &health.power);
+    pNvmlDeviceGetClockInfo(device, NVML_CLOCK_SM, &health.clock);
+    pNvmlDeviceGetClockInfo(device, NVML_CLOCK_MEM, &health.memClock);
+
+    if (health.power) {
+        health.power /= 1000;
+    }
+
+    uint32_t speed = 0;
+
+    if (pNvmlDeviceGetFanSpeed_v2) {
+        uint32_t i = 0;
+
+        while (pNvmlDeviceGetFanSpeed_v2(device, i, &speed) == NVML_SUCCESS) {
+            health.fanSpeed.push_back(speed);
+            ++i;
+        }
+
+    }
+    else {
+        pNvmlDeviceGetFanSpeed(device, &speed);
+
+        health.fanSpeed.push_back(speed);
+    }
+
+    return health;
+}
+
+
+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(NvmlDeviceGetClockInfo);
+        DLSYM(NvmlDeviceGetCount);
+        DLSYM(NvmlDeviceGetFanSpeed);
+        DLSYM(NvmlDeviceGetHandleByIndex);
+        DLSYM(NvmlDeviceGetPciInfo);
+        DLSYM(NvmlDeviceGetPowerUsage);
+        DLSYM(NvmlDeviceGetTemperature);
+        DLSYM(NvmlInit);
+        DLSYM(NvmlShutdown);
+        DLSYM(NvmlSystemGetDriverVersion);
+        DLSYM(NvmlSystemGetNVMLVersion);
+    } catch (std::exception &ex) {
+        return false;
+    }
+
+    uv_dlsym(&nvmlLib, kNvmlDeviceGetFanSpeed_v2, reinterpret_cast<void**>(&pNvmlDeviceGetFanSpeed_v2));
+
+    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 000000000..85b80d0ca
--- /dev/null
+++ b/src/backend/cuda/wrappers/NvmlLib.h
@@ -0,0 +1,66 @@
+/* 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_NVMLLIB_H
+#define XMRIG_NVMLLIB_H
+
+
+#include "backend/cuda/wrappers/CudaDevice.h"
+#include "backend/cuda/wrappers/NvmlHealth.h"
+
+
+namespace xmrig {
+
+
+class NvmlLib
+{
+public:
+    static bool init(const char *fileName = nullptr);
+    static const char *lastError() noexcept;
+    static void close();
+
+    static bool assign(std::vector<CudaDevice> &devices);
+    static NvmlHealth health(nvmlDevice_t device);
+
+    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 000000000..4472847c3
--- /dev/null
+++ b/src/backend/cuda/wrappers/nvml_lite.h
@@ -0,0 +1,55 @@
+/* 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_NVML_LITE_H
+#define XMRIG_NVML_LITE_H
+
+
+#include <cstdint>
+
+
+#define NVML_SUCCESS         0
+#define NVML_TEMPERATURE_GPU 0
+#define NVML_CLOCK_SM        1
+#define NVML_CLOCK_MEM       2
+
+
+using nvmlReturn_t = uint32_t;
+using nvmlDevice_t = struct nvmlDevice_st *;
+
+
+struct nvmlPciInfo_t
+{
+    char busIdLegacy[16]{};
+    unsigned int domain         = 0;
+    unsigned int bus            = 0;
+    unsigned int device         = 0;
+    unsigned int pciDeviceId    = 0;
+    unsigned int pciSubSystemId = 0;
+
+    char busId[32]{};
+};
+
+
+#endif /* XMRIG_NVML_LITE_H */
diff --git a/src/backend/opencl/OclBackend.h b/src/backend/opencl/OclBackend.h
index 57f5db38d..59bea0aa5 100644
--- a/src/backend/opencl/OclBackend.h
+++ b/src/backend/opencl/OclBackend.h
@@ -51,6 +51,8 @@ public:
     ~OclBackend() override;
 
 protected:
+    inline void execCommand(char) override {}
+
     bool isEnabled() const override;
     bool isEnabled(const Algorithm &algorithm) const override;
     const Hashrate *hashrate() const override;
diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h
index ccee47c67..7167e0bb7 100644
--- a/src/base/kernel/interfaces/IConfig.h
+++ b/src/base/kernel/interfaces/IConfig.h
@@ -135,7 +135,9 @@ public:
         CudaAffinityKey      = 1205,
         CudaMaxUsageKey      = 1206,
         CudaKey              = 1207,
-        CudaLoaderKey        = 1208
+        CudaLoaderKey        = 1208,
+        NvmlKey              = 1209,
+        HealthPrintTimeKey   = 1210,
     };
 
     virtual ~IConfig() = default;
diff --git a/src/config.json b/src/config.json
index 9c6d459e2..fbc60474a 100644
--- a/src/config.json
+++ b/src/config.json
@@ -41,6 +41,9 @@
     "cuda": {
         "enabled": false,
         "loader": null,
+        "nvml": true,
+        "cn/0": false,
+        "cn-lite/0": false
     },
     "donate-level": 5,
     "donate-over-proxy": 1,
@@ -63,6 +66,7 @@
         }
     ],
     "print-time": 60,
+    "health-print-time": 60,
     "retries": 5,
     "retry-pause": 5,
     "syslog": false,
diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp
index 0caf298f8..20ff3fd73 100644
--- a/src/core/Miner.cpp
+++ b/src/core/Miner.cpp
@@ -328,6 +328,34 @@ xmrig::Job xmrig::Miner::job() const
 }
 
 
+void xmrig::Miner::execCommand(char command)
+{
+    switch (command) {
+    case 'h':
+    case 'H':
+        printHashrate(true);
+        break;
+
+    case 'p':
+    case 'P':
+        setEnabled(false);
+        break;
+
+    case 'r':
+    case 'R':
+        setEnabled(true);
+        break;
+
+    default:
+        break;
+    }
+
+    for (auto backend : d_ptr->backends) {
+        backend->execCommand(command);
+    }
+}
+
+
 void xmrig::Miner::pause()
 {
     d_ptr->active = false;
@@ -393,7 +421,7 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
     }
 
 #   ifdef XMRIG_ALGO_RANDOMX
-    if (d_ptr->algorithm.family() == Algorithm::RANDOM_X && job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) {
+    if (job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) {
         stop();
     }
 #   endif
@@ -466,7 +494,8 @@ void xmrig::Miner::onTimer(const Timer *)
 
     d_ptr->maxHashrate[d_ptr->algorithm] = std::max(d_ptr->maxHashrate[d_ptr->algorithm], maxHashrate);
 
-    if ((d_ptr->ticks % (d_ptr->controller->config()->printTime() * 2)) == 0) {
+    auto seconds = d_ptr->controller->config()->printTime();
+    if (seconds && (d_ptr->ticks % (seconds * 2)) == 0) {
         printHashrate(false);
     }
 
diff --git a/src/core/Miner.h b/src/core/Miner.h
index 6f4149c30..f40e37f69 100644
--- a/src/core/Miner.h
+++ b/src/core/Miner.h
@@ -59,6 +59,7 @@ public:
     const Algorithms &algorithms() const;
     const std::vector<IBackend *> &backends() const;
     Job job() const;
+    void execCommand(char command);
     void pause();
     void printHashrate(bool details);
     void setEnabled(bool enabled);
diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp
index 4fd88b90e..a445961f1 100644
--- a/src/core/config/Config.cpp
+++ b/src/core/config/Config.cpp
@@ -70,6 +70,11 @@ static const char *kCuda    = "cuda";
 #endif
 
 
+#if defined(XMRIG_FEATURE_NVML)
+static const char *kHealthPrintTime = "health-print-time";
+#endif
+
+
 class ConfigPrivate
 {
 public:
@@ -86,6 +91,10 @@ public:
 #   ifdef XMRIG_FEATURE_CUDA
     CudaConfig cuda;
 #   endif
+
+#   if defined(XMRIG_FEATURE_NVML)
+    uint32_t healthPrintTime = 60;
+#   endif
 };
 
 }
@@ -133,6 +142,14 @@ const xmrig::RxConfig &xmrig::Config::rx() const
 #endif
 
 
+#if defined(XMRIG_FEATURE_NVML)
+uint32_t xmrig::Config::healthPrintTime() const
+{
+    return d_ptr->healthPrintTime;
+}
+#endif
+
+
 bool xmrig::Config::isShouldSave() const
 {
     if (!isAutoSave()) {
@@ -177,6 +194,10 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
     d_ptr->cuda.read(reader.getValue(kCuda));
 #   endif
 
+#   ifdef XMRIG_FEATURE_NVML
+    d_ptr->healthPrintTime = reader.getUint(kHealthPrintTime, d_ptr->healthPrintTime);
+#   endif
+
     return true;
 }
 
@@ -213,14 +234,17 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
     doc.AddMember(StringRef(kCuda),    cuda().toJSON(doc), allocator);
 #   endif
 
-    doc.AddMember("donate-level",      m_pools.donateLevel(), allocator);
-    doc.AddMember("donate-over-proxy", m_pools.proxyDonate(), allocator);
-    doc.AddMember("log-file",          m_logFile.toJSON(), allocator);
-    doc.AddMember("pools",             m_pools.toJSON(doc), allocator);
-    doc.AddMember("print-time",        printTime(), allocator);
-    doc.AddMember("retries",           m_pools.retries(), allocator);
-    doc.AddMember("retry-pause",       m_pools.retryPause(), allocator);
-    doc.AddMember("syslog",            isSyslog(), allocator);
-    doc.AddMember("user-agent",        m_userAgent.toJSON(), allocator);
-    doc.AddMember("watch",             m_watch, allocator);
+    doc.AddMember("donate-level",               m_pools.donateLevel(), allocator);
+    doc.AddMember("donate-over-proxy",          m_pools.proxyDonate(), allocator);
+    doc.AddMember("log-file",                   m_logFile.toJSON(), allocator);
+    doc.AddMember("pools",                      m_pools.toJSON(doc), allocator);
+    doc.AddMember("print-time",                 printTime(), allocator);
+#   if defined(XMRIG_FEATURE_NVML)
+    doc.AddMember(StringRef(kHealthPrintTime),  healthPrintTime(), allocator);
+#   endif
+    doc.AddMember("retries",                    m_pools.retries(), allocator);
+    doc.AddMember("retry-pause",                m_pools.retryPause(), allocator);
+    doc.AddMember("syslog",                     isSyslog(), allocator);
+    doc.AddMember("user-agent",                 m_userAgent.toJSON(), allocator);
+    doc.AddMember("watch",                      m_watch, allocator);
 }
diff --git a/src/core/config/Config.h b/src/core/config/Config.h
index 8becc0b80..5eb91ecae 100644
--- a/src/core/config/Config.h
+++ b/src/core/config/Config.h
@@ -67,6 +67,10 @@ public:
     const RxConfig &rx() const;
 #   endif
 
+#   if defined(XMRIG_FEATURE_NVML)
+    uint32_t healthPrintTime() const;
+#   endif
+
     bool isShouldSave() const;
     bool read(const IJsonReader &reader, const char *fileName) override;
     void getJSON(rapidjson::Document &doc) const override;
diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp
index 51f594e8b..ffd3fbd8e 100644
--- a/src/core/config/ConfigTransform.cpp
+++ b/src/core/config/ConfigTransform.cpp
@@ -193,6 +193,14 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
         return set(doc, kCuda, "loader", arg);
 #   endif
 
+#   ifdef XMRIG_FEATURE_NVML
+    case IConfig::NvmlKey: /* --no-nvml */
+        return set(doc, kCuda, "nvml", false);
+
+    case IConfig::HealthPrintTimeKey: /* --health-print-time */
+        return set(doc, "health-print-time", static_cast<uint64_t>(strtol(arg, nullptr, 10)));
+#   endif
+
     default:
         break;
     }
diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h
index e7d39299f..afd3638bb 100644
--- a/src/core/config/Config_default.h
+++ b/src/core/config/Config_default.h
@@ -75,6 +75,9 @@ R"===(
     "cuda": {
         "enabled": false,
         "loader": null,
+        "nvml": true,
+        "cn/0": false,
+        "cn-lite/0": false
     },
     "donate-level": 5,
     "donate-over-proxy": 1,
@@ -97,6 +100,7 @@ R"===(
         }
     ],
     "print-time": 60,
+    "health-print-time": 60,
     "retries": 5,
     "retry-pause": 5,
     "syslog": false,
diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h
index 371e58fa8..3309bebaf 100644
--- a/src/core/config/Config_platform.h
+++ b/src/core/config/Config_platform.h
@@ -107,6 +107,10 @@ static const option options[] = {
 #   ifdef XMRIG_FEATURE_CUDA
     { "cuda",                  0, nullptr, IConfig::CudaKey               },
     { "cuda-loader",           1, nullptr, IConfig::CudaLoaderKey         },
+#   endif
+#   ifdef XMRIG_FEATURE_NVML
+    { "no-nvml",               0, nullptr, IConfig::NvmlKey               },
+    { "health-print-time",     1, nullptr, IConfig::HealthPrintTimeKey    },
 #   endif
     { nullptr,                 0, nullptr, 0 }
 };
diff --git a/src/core/config/usage.h b/src/core/config/usage.h
index c95526f78..d9ef23169 100644
--- a/src/core/config/usage.h
+++ b/src/core/config/usage.h
@@ -113,6 +113,9 @@ static inline const std::string &usage()
     u += "      --cuda                    enable CUDA mining backend\n";
     u += "      --cuda-loader=PATH        path to CUDA plugin (xmrig-cuda.dll or libxmrig-cuda.so)\n";
 #   endif
+#   ifdef XMRIG_FEATURE_NVML
+    u += "      --no-nvml                 disable NVML (NVIDIA Management Library) support\n";
+#   endif
 
     u += "\nLogging:\n";
 
@@ -122,6 +125,9 @@ static inline const std::string &usage()
 
     u += "  -l, --log-file=FILE           log all output to a file\n";
     u += "      --print-time=N            print hashrate report every N seconds\n";
+#   ifdef XMRIG_FEATURE_NVML
+    u += "      --health-print-time=N     print health report every N seconds\n";
+#   endif
     u += "      --no-color                disable colored output\n";
 
     u += "\nMisc:\n";
diff --git a/src/crypto/common/Nonce.cpp b/src/crypto/common/Nonce.cpp
index e79cb310e..897045caf 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++;
     }
 }