Skip to content
This repository was archived by the owner on Apr 24, 2022. It is now read-only.

Hardware Monitoring for NVML, ADL and AMDGPU SysFS #319

Merged
merged 8 commits into from
Nov 27, 2017
13 changes: 13 additions & 0 deletions libethash-cl/CLMiner.cpp
Original file line number Diff line number Diff line change
@@ -343,6 +343,17 @@ bool CLMiner::configureGPU(
HwMonitor CLMiner::hwmon()
{
HwMonitor hw;
unsigned int tempC = 0, fanpcnt = 0;
if (nvmlh) {
wrap_nvml_get_tempC(nvmlh, index, &tempC);
wrap_nvml_get_fanpcnt(nvmlh, index, &fanpcnt);
}
if (adlh) {
wrap_adl_get_tempC(adlh, index, &tempC);
wrap_adl_get_fanpcnt(adlh, index, &fanpcnt);
}
hw.tempC = tempC;
hw.fanP = fanpcnt;
return hw;
}

@@ -367,10 +378,12 @@ bool CLMiner::init(const h256& seed)
if (platformName == "NVIDIA CUDA")
{
platformId = OPENCL_PLATFORM_NVIDIA;
nvmlh = wrap_nvml_create();
}
else if (platformName == "AMD Accelerated Parallel Processing")
{
platformId = OPENCL_PLATFORM_AMD;
adlh = wrap_adl_create();
}
else if (platformName == "Clover")
{
5 changes: 5 additions & 0 deletions libethash-cl/CLMiner.h
Original file line number Diff line number Diff line change
@@ -8,6 +8,8 @@
#include <libdevcore/Worker.h>
#include <libethcore/EthashAux.h>
#include <libethcore/Miner.h>
#include <libhwmon/wrapnvml.h>
#include <libhwmon/wrapadl.h>

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS true
#define CL_HPP_ENABLE_EXCEPTIONS true
@@ -100,6 +102,9 @@ class CLMiner: public Miner
/// The initial global work size for the searches
static unsigned s_initialGlobalWorkSize;

wrap_nvml_handle *nvmlh = NULL;
wrap_adl_handle *adlh = NULL;

};

}
2 changes: 1 addition & 1 deletion libethash-cl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -30,5 +30,5 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(..)

add_library(ethash-cl ${SOURCES})
target_link_libraries(ethash-cl PUBLIC ethcore ethash)
target_link_libraries(ethash-cl PUBLIC ethcore ethash hwmon)
target_link_libraries(ethash-cl PRIVATE OpenCL::OpenCL)
2 changes: 2 additions & 0 deletions libhwmon/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
set(SOURCES
wraphelper.h
wrapnvml.h wrapnvml.cpp
wrapadl.h wrapadl.cpp
)

add_library(hwmon ${SOURCES})
141 changes: 141 additions & 0 deletions libhwmon/wrapadl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Wrapper for ADL, inspired by wrapnvml from John E. Stone
*
* By Philipp Andreas - [email protected]
*/
#include <stdio.h>
#include <stdlib.h>
#include "wraphelper.h"
#include "wrapadl.h"

#if defined(__cplusplus)
extern "C" {
#endif

void* __stdcall ADL_Main_Memory_Alloc(int iSize)
{
void* lpBuffer = malloc(iSize);
return lpBuffer;
}

wrap_adl_handle * wrap_adl_create()
{
int i = 0;
wrap_adl_handle *adlh = NULL;

#if defined(_WIN64)
/* 64-bit Windows */
#define libatiadlxx "atiadlxx.dll"
#elif defined(_WIN32) || defined(_MSC_VER)
/* 32-bit Windows */
#define libatiadlxx "atiadlxx.dll"
#elif defined(__linux) && (defined(__i386__) || defined(__ARM_ARCH_7A__))
/* 32-bit linux assumed */
#define libatiadlxx "/usr/lib32/libatiadlxx.so"
#elif defined(__linux)
/* 64-bit linux assumed */
#define libatiadlxx "/usr/lib/libatiadlxx.so"
#else
#error "Unrecognized platform: need NVML DLL path for this platform..."
#endif

#if WIN32
char tmp[512];
ExpandEnvironmentStringsA(libatiadlxx, tmp, sizeof(tmp));
#else
char tmp[512] = libatiadlxx;
#endif

void *adl_dll = wrap_dlopen(tmp);
if (adl_dll == NULL)
return NULL;

adlh = (wrap_adl_handle *)calloc(1, sizeof(wrap_adl_handle));

adlh->adl_dll = adl_dll;

adlh->adlMainControlCreate = (wrap_adlReturn_t(*)(ADL_MAIN_MALLOC_CALLBACK, int))
wrap_dlsym(adlh->adl_dll, "ADL_Main_Control_Create");
adlh->adlAdapterNumberOfAdapters = (wrap_adlReturn_t(*)(int *))
wrap_dlsym(adlh->adl_dll, "ADL_Adapter_NumberOfAdapters_Get");
adlh->adlAdapterAdapterInfoGet = (wrap_adlReturn_t(*)(LPAdapterInfo, int))
wrap_dlsym(adlh->adl_dll, "ADL_Adapter_AdapterInfo_Get");
adlh->adlOverdrive5TemperatureGet = (wrap_adlReturn_t(*)(int, int, ADLTemperature*))
wrap_dlsym(adlh->adl_dll, "ADL_Overdrive5_Temperature_Get");
adlh->adlOverdrive5FanSpeedGet = (wrap_adlReturn_t(*)(int, int, ADLFanSpeedValue*))
wrap_dlsym(adlh->adl_dll, "ADL_Overdrive5_FanSpeed_Get");
adlh->adlMainControlDestory = (wrap_adlReturn_t(*)(void))
wrap_dlsym(adlh->adl_dll, "ADL_Main_Control_Destroy");

if (adlh->adlMainControlCreate == NULL ||
adlh->adlMainControlDestory == NULL ||
adlh->adlAdapterNumberOfAdapters == NULL ||
adlh->adlAdapterAdapterInfoGet == NULL ||
adlh->adlOverdrive5TemperatureGet == NULL ||
adlh->adlOverdrive5FanSpeedGet == NULL
) {
#if 0
printf("Failed to obtain all required ADL function pointers\n");
#endif
wrap_dlclose(adlh->adl_dll);
free(adlh);
return NULL;
}

adlh->adlMainControlCreate(ADL_Main_Memory_Alloc, 1);
adlh->adlAdapterNumberOfAdapters(&adlh->adl_gpucount);
adlh->devs = (wrap_adlDevice_t *)calloc(adlh->adl_gpucount, sizeof(wrap_adlDevice_t));

return adlh;
}

int wrap_adl_destory(wrap_adl_handle *adlh)
{
adlh->adlMainControlDestory();
wrap_dlclose(adlh->adl_dll);
free(adlh);
return 0;
}

int wrap_adl_get_gpucount(wrap_adl_handle *adlh, int *gpucount)
{
*gpucount = adlh->adl_gpucount;
return 0;
}

int wrap_adl_get_tempC(wrap_adl_handle *adlh, int gpuindex, unsigned int *tempC)
{
wrap_adlReturn_t rc;
if (gpuindex < 0 || gpuindex >= adlh->adl_gpucount)
return -1;

ADLTemperature *temperature = new ADLTemperature();
rc = adlh->adlOverdrive5TemperatureGet(gpuindex, 0, temperature);
if (rc != WRAPADL_OK) {
return -1;
}
*tempC = unsigned(temperature->iTemperature / 1000);
free(temperature);
return 0;
}

int wrap_adl_get_fanpcnt(wrap_adl_handle *adlh, int gpuindex, unsigned int *fanpcnt)
{
wrap_adlReturn_t rc;
if (gpuindex < 0 || gpuindex >= adlh->adl_gpucount)
return -1;

ADLFanSpeedValue *fan = new ADLFanSpeedValue();
fan->iSpeedType = 1;
rc = adlh->adlOverdrive5FanSpeedGet(gpuindex, 0, fan);
if (rc != WRAPADL_OK) {
return -1;
}
*fanpcnt = unsigned(fan->iFanSpeed);
free(fan);
return 0;
}

#if defined(__cplusplus)
}
#endif
129 changes: 129 additions & 0 deletions libhwmon/wrapadl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Wrapper for ADL, inspired by wrapnvml from John E. Stone
*
* By Philipp Andreas - [email protected]
*/

#ifndef _WRAPADL_H_
#define _WRAPADL_H_

#if defined(__cplusplus)
extern "C" {
#endif

typedef enum wrap_adlReturn_enum {
WRAPADL_OK= 0
} wrap_adlReturn_t;

typedef void * wrap_adlDevice_t;

// Some ADL defines and structs from adl sdk
typedef void* (__stdcall *ADL_MAIN_MALLOC_CALLBACK)(int);

#define ADL_MAX_PATH 256
typedef struct AdapterInfo
{
/// \ALL_STRUCT_MEM

/// Size of the structure.
int iSize;
/// The ADL index handle. One GPU may be associated with one or two index handles
int iAdapterIndex;
/// The unique device ID associated with this adapter.
char strUDID[ADL_MAX_PATH];
/// The BUS number associated with this adapter.
int iBusNumber;
/// The driver number associated with this adapter.
int iDeviceNumber;
/// The function number.
int iFunctionNumber;
/// The vendor ID associated with this adapter.
int iVendorID;
/// Adapter name.
char strAdapterName[ADL_MAX_PATH];
/// Display name. For example, "\\Display0" for Windows or ":0:0" for Linux.
char strDisplayName[ADL_MAX_PATH];
/// Present or not; 1 if present and 0 if not present.It the logical adapter is present, the display name such as \\.\Display1 can be found from OS
int iPresent;
// @}

#if defined (_WIN32) || defined (_WIN64)
/// \WIN_STRUCT_MEM

/// Exist or not; 1 is exist and 0 is not present.
int iExist;
/// Driver registry path.
char strDriverPath[ADL_MAX_PATH];
/// Driver registry path Ext for.
char strDriverPathExt[ADL_MAX_PATH];
/// PNP string from Windows.
char strPNPString[ADL_MAX_PATH];
/// It is generated from EnumDisplayDevices.
int iOSDisplayIndex;
// @}
#endif /* (_WIN32) || (_WIN64) */

#if defined (LINUX)
/// \LNX_STRUCT_MEM

/// Internal X screen number from GPUMapInfo (DEPRICATED use XScreenInfo)
int iXScreenNum;
/// Internal driver index from GPUMapInfo
int iDrvIndex;
/// \deprecated Internal x config file screen identifier name. Use XScreenInfo instead.
char strXScreenConfigName[ADL_MAX_PATH];

// @}
#endif /* (LINUX) */
} AdapterInfo, *LPAdapterInfo;

typedef struct ADLTemperature
{
/// Must be set to the size of the structure
int iSize;
/// Temperature in millidegrees Celsius.
int iTemperature;
} ADLTemperature;

typedef struct ADLFanSpeedValue
{
/// Must be set to the size of the structure
int iSize;
/// Possible valies: \ref ADL_DL_FANCTRL_SPEED_TYPE_PERCENT or \ref ADL_DL_FANCTRL_SPEED_TYPE_RPM
int iSpeedType;
/// Fan speed value
int iFanSpeed;
/// The only flag for now is: \ref ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED
int iFlags;
} ADLFanSpeedValue;

/*
* Handle to hold the function pointers for the entry points we need,
* and the shared library itself.
*/
typedef struct {
void *adl_dll;
int adl_gpucount;
wrap_adlDevice_t *devs;
wrap_adlReturn_t(*adlMainControlCreate)(ADL_MAIN_MALLOC_CALLBACK, int);
wrap_adlReturn_t(*adlAdapterNumberOfAdapters)(int *);
wrap_adlReturn_t(*adlAdapterAdapterInfoGet)(LPAdapterInfo, int);
wrap_adlReturn_t(*adlOverdrive5TemperatureGet)(int, int, ADLTemperature*);
wrap_adlReturn_t(*adlOverdrive5FanSpeedGet)(int, int, ADLFanSpeedValue*);
wrap_adlReturn_t(*adlMainControlDestory)(void);
} wrap_adl_handle;

wrap_adl_handle * wrap_adl_create();
int wrap_adl_destory(wrap_adl_handle *adlh);

int wrap_adl_get_gpucount(wrap_adl_handle *adlh, int *gpucount);

int wrap_adl_get_tempC(wrap_adl_handle *adlh, int gpuindex, unsigned int *tempC);

int wrap_adl_get_fanpcnt(wrap_adl_handle *adlh, int gpuindex, unsigned int *fanpcnt);

#if defined(__cplusplus)
}
#endif

#endif
28 changes: 28 additions & 0 deletions libhwmon/wraphelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Wrappers to emulate dlopen() on other systems like Windows
*/
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
#include <windows.h>
static void *wrap_dlopen(const char *filename) {
return (void *)LoadLibrary(filename);
}
static void *wrap_dlsym(void *h, const char *sym) {
return (void *)GetProcAddress((HINSTANCE)h, sym);
}
static int wrap_dlclose(void *h) {
/* FreeLibrary returns nonzero on success */
return (!FreeLibrary((HINSTANCE)h));
}
#else
/* assume we can use dlopen itself... */
#include <dlfcn.h>
static void *wrap_dlopen(const char *filename) {
return dlopen(filename, RTLD_NOW);
}
static void *wrap_dlsym(void *h, const char *sym) {
return dlsym(h, sym);
}
static int wrap_dlclose(void *h) {
return dlclose(h);
}
#endif
33 changes: 4 additions & 29 deletions libhwmon/wrapnvml.cpp
Original file line number Diff line number Diff line change
@@ -12,44 +12,19 @@
*
* John E. Stone - john.stone@gmail.com
*
* Modified to work with ethminer by
*
* Philipp Andreas - github@smurfy.de
*/

#include <stdio.h>
#include <stdlib.h>
#include "wraphelper.h"
#include "wrapnvml.h"
#if ETH_ETHASHCUDA
#include "cuda_runtime.h"
#endif

/*
* Wrappers to emulate dlopen() on other systems like Windows
*/
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
#include <windows.h>
static void *wrap_dlopen(const char *filename) {
return (void *)LoadLibrary(filename);
}
static void *wrap_dlsym(void *h, const char *sym) {
return (void *)GetProcAddress((HINSTANCE)h, sym);
}
static int wrap_dlclose(void *h) {
/* FreeLibrary returns nonzero on success */
return (!FreeLibrary((HINSTANCE)h));
}
#else
/* assume we can use dlopen itself... */
#include <dlfcn.h>
static void *wrap_dlopen(const char *filename) {
return dlopen(filename, RTLD_NOW);
}
static void *wrap_dlsym(void *h, const char *sym) {
return dlsym(h, sym);
}
static int wrap_dlclose(void *h) {
return dlclose(h);
}
#endif

#if defined(__cplusplus)
extern "C" {
#endif
4 changes: 4 additions & 0 deletions libhwmon/wrapnvml.h
Original file line number Diff line number Diff line change
@@ -14,6 +14,9 @@
*
*/

#ifndef _WRAPNVML_H_
#define _WRAPNVML_H_

#if defined(__cplusplus)
extern "C" {
#endif
@@ -121,3 +124,4 @@ int wrap_nvml_get_power_usage(wrap_nvml_handle *nvmlh,
}
#endif

#endif