diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp index 853d37e9..a7c315ec 100644 --- a/src/backend/cuda/CudaBackend.cpp +++ b/src/backend/cuda/CudaBackend.cpp @@ -34,6 +34,7 @@ #include "backend/common/Workers.h" #include "backend/cuda/CudaConfig.h" #include "backend/cuda/CudaThreads.h" +#include "backend/cuda/wrappers/CudaDevice.h" #include "backend/cuda/wrappers/CudaLib.h" #include "base/io/log/Log.h" #include "base/net/stratum/Job.h" @@ -89,15 +90,32 @@ public: return printDisabled(RED_S " (failed to load CUDA plugin)"); } - if (!CudaLib::runtimeVersion() || !CudaLib::driverVersion() || !CudaLib::deviceCount()) { - return printDisabled(RED_S " (no devices)"); - } - const uint32_t runtimeVersion = CudaLib::runtimeVersion(); const uint32_t driverVersion = CudaLib::driverVersion(); + if (!runtimeVersion || !driverVersion || !CudaLib::deviceCount()) { + return printDisabled(RED_S " (no devices)"); + } + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%u.%u") "/" WHITE_BOLD("%u.%u") BLACK_BOLD("/%s"), "CUDA", runtimeVersion / 1000, runtimeVersion % 100, driverVersion / 1000, driverVersion % 100, CudaLib::pluginVersion()); + + devices = CudaLib::devices(); + + 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", + device.index(), + device.topology().toString().data(), + device.name().data(), + device.clock(), + device.memoryClock(), + device.smx(), + device.computeCapability(true), + device.computeCapability(false), + device.freeMemSize() / oneMiB, + device.globalMemSize() / oneMiB); + } } @@ -108,6 +126,7 @@ public: Algorithm algo; Controller *controller; + std::vector devices; String profileName; }; diff --git a/src/backend/cuda/cuda.cmake b/src/backend/cuda/cuda.cmake index 983e18a9..4cbe9c0d 100644 --- a/src/backend/cuda/cuda.cmake +++ b/src/backend/cuda/cuda.cmake @@ -7,6 +7,7 @@ if (WITH_CUDA) src/backend/cuda/CudaConfig.h src/backend/cuda/CudaThread.h src/backend/cuda/CudaThreads.h + src/backend/cuda/wrappers/CudaDevice.h src/backend/cuda/wrappers/CudaLib.h ) @@ -15,6 +16,7 @@ if (WITH_CUDA) src/backend/cuda/CudaConfig.cpp src/backend/cuda/CudaThread.cpp src/backend/cuda/CudaThreads.cpp + src/backend/cuda/wrappers/CudaDevice.cpp src/backend/cuda/wrappers/CudaLib.cpp ) else() diff --git a/src/backend/cuda/wrappers/CudaDevice.cpp b/src/backend/cuda/wrappers/CudaDevice.cpp new file mode 100644 index 00000000..03646eae --- /dev/null +++ b/src/backend/cuda/wrappers/CudaDevice.cpp @@ -0,0 +1,115 @@ +/* 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 "backend/cuda/wrappers/CudaDevice.h" +#include "backend/cuda/CudaThreads.h" +#include "backend/cuda/wrappers/CudaLib.h" +#include "base/io/log/Log.h" +#include "crypto/common/Algorithm.h" +#include "rapidjson/document.h" + + +#include + + + +xmrig::CudaDevice::CudaDevice(uint32_t index) : + m_index(index) +{ + auto ctx = CudaLib::alloc(index, 0, 0, 0, 0, Algorithm::INVALID); + if (CudaLib::deviceInfo(ctx) != 0) { + CudaLib::release(ctx); + + return; + } + + m_ctx = ctx; + m_name = CudaLib::deviceName(ctx); + m_topology = PciTopology(CudaLib::deviceUint(ctx, CudaLib::DevicePciBusID), CudaLib::deviceUint(ctx, CudaLib::DevicePciDeviceID), 0); +} + + +xmrig::CudaDevice::CudaDevice(CudaDevice &&other) noexcept : + m_index(other.m_index), + m_ctx(other.m_ctx), + m_topology(other.m_topology), + m_name(std::move(other.m_name)) +{ + other.m_ctx = nullptr; +} + + +xmrig::CudaDevice::~CudaDevice() +{ + CudaLib::release(m_ctx); +} + + +size_t xmrig::CudaDevice::freeMemSize() const +{ + return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryFree); +} + + +size_t xmrig::CudaDevice::globalMemSize() const +{ + return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryTotal); +} + + +uint32_t xmrig::CudaDevice::clock() const +{ + return CudaLib::deviceUint(m_ctx, CudaLib::DeviceClockRate) / 1000; +} + + +uint32_t xmrig::CudaDevice::computeCapability(bool major) const +{ + return CudaLib::deviceUint(m_ctx, major ? CudaLib::DeviceArchMajor : CudaLib::DeviceArchMinor); +} + + +uint32_t xmrig::CudaDevice::memoryClock() const +{ + return CudaLib::deviceUint(m_ctx, CudaLib::DeviceMemoryClockRate) / 1000; +} + + +uint32_t xmrig::CudaDevice::smx() const +{ + return CudaLib::deviceUint(m_ctx, CudaLib::DeviceSmx); +} + + +void xmrig::CudaDevice::generate(const Algorithm &algorithm, CudaThreads &threads) const +{ +} + + +#ifdef XMRIG_FEATURE_API +void xmrig::CudaDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const +{ +} +#endif diff --git a/src/backend/cuda/wrappers/CudaDevice.h b/src/backend/cuda/wrappers/CudaDevice.h new file mode 100644 index 00000000..c0df83c8 --- /dev/null +++ b/src/backend/cuda/wrappers/CudaDevice.h @@ -0,0 +1,83 @@ +/* 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_CUDADEVICE_H +#define XMRIG_CUDADEVICE_H + + +#include "backend/common/misc/PciTopology.h" +#include "base/tools/String.h" + + +using nvid_ctx = struct nvid_ctx; + + +namespace xmrig { + + +class Algorithm; +class CudaThreads; + + +class CudaDevice +{ +public: + CudaDevice() = delete; + CudaDevice(const CudaDevice &other) = delete; + CudaDevice(CudaDevice &&other) noexcept; + CudaDevice(uint32_t index); + ~CudaDevice(); + + size_t freeMemSize() const; + size_t globalMemSize() const; + uint32_t clock() const; + uint32_t computeCapability(bool major = true) const; + uint32_t memoryClock() const; + 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 index() const { return m_index; } + +# ifdef XMRIG_FEATURE_API + void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const; +# endif + + CudaDevice &operator=(const CudaDevice &other) = delete; + CudaDevice &operator=(CudaDevice &&other) = delete; + +private: + const uint32_t m_index = 0; + nvid_ctx *m_ctx = nullptr; + PciTopology m_topology; + String m_name; +}; + + +} // namespace xmrig + + +#endif /* XMRIG_CUDADEVICE_H */ diff --git a/src/backend/cuda/wrappers/CudaLib.cpp b/src/backend/cuda/wrappers/CudaLib.cpp index 1d075408..a8ca5601 100644 --- a/src/backend/cuda/wrappers/CudaLib.cpp +++ b/src/backend/cuda/wrappers/CudaLib.cpp @@ -47,14 +47,24 @@ static uv_lib_t cudaLib; static const char *kAlloc = "alloc"; static const char *kDeviceCount = "deviceCount"; +static const char *kDeviceInfo = "deviceInfo"; +static const char *kDeviceInt = "deviceInt"; +static const char *kDeviceName = "deviceName"; +static const char *kDeviceUint = "deviceUint"; +static const char *kDeviceUlong = "deviceUlong"; static const char *kPluginVersion = "pluginVersion"; static const char *kRelease = "release"; static const char *kSymbolNotFound = "symbol not found"; static const char *kVersion = "version"; -using alloc_t = nvid_ctx * (*)(size_t, int, int, int, int, int); -using deviceCount_t = size_t (*)(); +using alloc_t = nvid_ctx * (*)(size_t, int32_t, int32_t, int32_t, int32_t, int32_t); +using deviceCount_t = uint32_t (*)(); +using deviceInfo_t = int32_t (*)(nvid_ctx *); +using deviceInt_t = int32_t (*)(nvid_ctx *, CudaLib::DeviceProperty); +using deviceName_t = const char * (*)(nvid_ctx *); +using deviceUint_t = uint32_t (*)(nvid_ctx *, CudaLib::DeviceProperty); +using deviceUlong_t = uint64_t (*)(nvid_ctx *, CudaLib::DeviceProperty); using pluginVersion_t = const char * (*)(); using release_t = void (*)(nvid_ctx *); using version_t = uint32_t (*)(Version); @@ -62,6 +72,11 @@ using version_t = uint32_t (*)(Version); static alloc_t pAlloc = nullptr; static deviceCount_t pDeviceCount = nullptr; +static deviceInfo_t pDeviceInfo = nullptr; +static deviceInt_t pDeviceInt = nullptr; +static deviceName_t pDeviceName = nullptr; +static deviceUint_t pDeviceUint = nullptr; +static deviceUlong_t pDeviceUlong = nullptr; static pluginVersion_t pPluginVersion = nullptr; static release_t pRelease = nullptr; static version_t pVersion = nullptr; @@ -102,24 +117,69 @@ void xmrig::CudaLib::close() } +const char *xmrig::CudaLib::deviceName(nvid_ctx *ctx) noexcept +{ + return pDeviceName(ctx); +} + + const char *xmrig::CudaLib::pluginVersion() noexcept { return pPluginVersion(); } +int xmrig::CudaLib::deviceInfo(nvid_ctx *ctx) noexcept +{ + return pDeviceInfo(ctx); +} + + +int32_t xmrig::CudaLib::deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept +{ + return pDeviceInt(ctx, property); +} + + nvid_ctx *xmrig::CudaLib::alloc(size_t id, int blocks, int threads, int bfactor, int bsleep, const Algorithm &algorithm) noexcept { return pAlloc(id, blocks, threads, bfactor, bsleep, algorithm); } -size_t xmrig::CudaLib::deviceCount() noexcept +std::vector xmrig::CudaLib::devices() noexcept +{ + const uint32_t count = deviceCount(); + if (!count) { + return {}; + } + + std::vector out; + out.reserve(count); + + for (uint32_t i = 0; i < count; ++i) { + CudaDevice device(i); + if (device.isValid()) { + out.emplace_back(std::move(device)); + } + } + + return out; +} + + +uint32_t xmrig::CudaLib::deviceCount() noexcept { return pDeviceCount(); } +uint32_t xmrig::CudaLib::deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept +{ + return pDeviceUint(ctx, property); +} + + uint32_t xmrig::CudaLib::driverVersion() noexcept { return pVersion(DriverVersion); @@ -132,6 +192,12 @@ uint32_t xmrig::CudaLib::runtimeVersion() noexcept } +uint64_t xmrig::CudaLib::deviceUlong(nvid_ctx *ctx, DeviceProperty property) noexcept +{ + return pDeviceUlong(ctx, property); +} + + void xmrig::CudaLib::release(nvid_ctx *ctx) noexcept { pRelease(ctx); @@ -151,6 +217,11 @@ bool xmrig::CudaLib::load() try { DLSYM(Alloc); DLSYM(DeviceCount); + DLSYM(DeviceInfo); + DLSYM(DeviceInt); + DLSYM(DeviceName); + DLSYM(DeviceUint); + DLSYM(DeviceUlong); DLSYM(PluginVersion); DLSYM(Release); DLSYM(Version); diff --git a/src/backend/cuda/wrappers/CudaLib.h b/src/backend/cuda/wrappers/CudaLib.h index d82447e1..e479102b 100644 --- a/src/backend/cuda/wrappers/CudaLib.h +++ b/src/backend/cuda/wrappers/CudaLib.h @@ -26,14 +26,15 @@ #define XMRIG_CUDALIB_H -#include +using nvid_ctx = struct nvid_ctx; +#include "backend/cuda/wrappers/CudaDevice.h" #include "base/tools/String.h" #include "crypto/common/Algorithm.h" -using nvid_ctx = struct nvid_ctx; +#include namespace xmrig { @@ -42,6 +43,26 @@ namespace xmrig { class CudaLib { public: + enum DeviceProperty : uint32_t + { + DeviceId, + DeviceAlgorithm, + DeviceArchMajor, + DeviceArchMinor, + DeviceSmx, + DeviceBlocks, + DeviceThreads, + DeviceBFactor, + DeviceBSleep, + DeviceClockRate, + DeviceMemoryClockRate, + DeviceMemoryTotal, + DeviceMemoryFree, + DevicePciBusID, + DevicePciDeviceID, + DevicePciDomainID + }; + static bool init(const char *fileName = nullptr); static const char *lastError(); static void close(); @@ -49,11 +70,17 @@ public: static inline bool isInitialized() { return m_initialized; } static inline const String &loader() { return m_loader; } + static const char *deviceName(nvid_ctx *ctx) noexcept; static const char *pluginVersion() noexcept; + static int deviceInfo(nvid_ctx *ctx) noexcept; + static int32_t deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept; static nvid_ctx *alloc(size_t id, int blocks, int threads, int bfactor, int bsleep, const Algorithm &algorithm) noexcept; - static size_t deviceCount() noexcept; + static std::vector devices() noexcept; + static uint32_t deviceCount() noexcept; + static uint32_t deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept; static uint32_t driverVersion() noexcept; static uint32_t runtimeVersion() noexcept; + static uint64_t deviceUlong(nvid_ctx *ctx, DeviceProperty property) noexcept; static void release(nvid_ctx *ctx) noexcept; private: diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 5b078006..e0c197d8 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -153,7 +153,8 @@ public: Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu ") WHITE_BOLD("%s") "/" WHITE_BOLD("%s"), "OPENCL", platform.index(), platform.name().data(), platform.version().data()); for (const OclDevice &device : devices) { - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%uMHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB", "OPENCL GPU", + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%u MHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB", + "OPENCL GPU", device.index(), device.topology().toString().data(), device.printableName().data(), diff --git a/src/backend/opencl/wrappers/OclDevice.h b/src/backend/opencl/wrappers/OclDevice.h index 04577d90..7d081618 100644 --- a/src/backend/opencl/wrappers/OclDevice.h +++ b/src/backend/opencl/wrappers/OclDevice.h @@ -26,14 +26,13 @@ #define XMRIG_OCLDEVICE_H -#include - - #include "backend/common/misc/PciTopology.h" #include "backend/opencl/wrappers/OclVendor.h" #include "base/tools/String.h" #include +#include + using cl_device_id = struct _cl_device_id *; using cl_platform_id = struct _cl_platform_id *;