From 3ad4be7de0acdc1b455cb64949fda490ac980eca Mon Sep 17 00:00:00 2001 From: Tanguy Pruvot Date: Wed, 19 Nov 2014 16:04:14 +0100 Subject: [PATCH] api: export gpu freq on linux too + hwinfo command --- api.cpp | 91 +++++++++++++++++++++++++++++++++----- api/index.php | 4 +- miner.h | 9 +++- nvml.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++------ nvml.h | 4 ++ 5 files changed, 198 insertions(+), 28 deletions(-) diff --git a/api.cpp b/api.cpp index 73d9f31..6f096e6 100644 --- a/api.cpp +++ b/api.cpp @@ -108,7 +108,7 @@ extern int opt_api_listen; /* port */ extern uint64_t global_hashrate; extern uint32_t accepted_count; extern uint32_t rejected_count; - +extern int num_processors; extern int device_map[8]; extern char *device_name[8]; @@ -128,8 +128,8 @@ static void gpustatus(int thr_id) cgpu->gpu_bus = gpu_busid(cgpu); cgpu->gpu_temp = gpu_temp(cgpu); cgpu->gpu_fan = gpu_fanpercent(cgpu); - cgpu->gpu_pstate = gpu_pstate(cgpu); cgpu->gpu_clock = gpu_clock(cgpu); + cgpu->gpu_pstate = gpu_pstate(cgpu); #endif // todo: can be 0 if set by algo (auto) @@ -149,14 +149,14 @@ static void gpustatus(int thr_id) cgpu->khashes = stats_get_speed(cgpu->gpu_id, 0.0) / 1000.0; - snprintf(pstate, sizeof(pstate), "P%u", cgpu->gpu_pstate); + snprintf(pstate, sizeof(pstate), "P%hu", cgpu->gpu_pstate); if (cgpu->gpu_pstate == -1) - *pstate= '\0'; + (*pstate) = '\0'; card = device_name[gpuid]; - snprintf(buf, sizeof(buf), "GPU=%d;BUS=%d;CARD=%s;TEMP=%.1f;FAN=%d;" - "FREQ=%d;PST=%s;KHS=%.2f;HWF=%d;I=%d|", + snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;" + "TEMP=%.1f;FAN=%d;FREQ=%d;PST=%s;KHS=%.2f;HWF=%d;I=%d|", gpuid, cgpu->gpu_bus, card, cgpu->gpu_temp, cgpu->gpu_fan, cgpu->gpu_clock, pstate, cgpu->khashes, cgpu->hw_errors, cgpu->intensity); @@ -166,6 +166,17 @@ static void gpustatus(int thr_id) } } +/** +* Returns gpu/thread specific stats +*/ +static char *getthreads(char *params) +{ + *buffer = '\0'; + for (int i = 0; i < opt_n_threads; i++) + gpustatus(i); + return buffer; +} + /*****************************************************************************/ /** @@ -191,14 +202,71 @@ static char *getsummary(char *params) return buffer; } +/*****************************************************************************/ + +static void gpuhwinfos(int gpu_id) +{ + char buf[256]; + char pstate[8]; + char* card; + struct cgpu_info *cgpu = NULL; + + for (int g = 0; g < opt_n_threads; g++) { + if (device_map[g] == gpu_id) { + cgpu = &thr_info[g].gpu; + break; + } + } + + if (cgpu == NULL) + return; + +#ifdef USE_WRAPNVML + cgpu->has_monitoring = true; + cgpu->gpu_bus = gpu_busid(cgpu); + cgpu->gpu_temp = gpu_temp(cgpu); + cgpu->gpu_fan = gpu_fanpercent(cgpu); + cgpu->gpu_pstate = gpu_pstate(cgpu); + cgpu->gpu_clock = gpu_clock(cgpu); + gpu_info(cgpu); +#endif + + snprintf(pstate, sizeof(pstate), "P%hu", cgpu->gpu_pstate); + if (cgpu->gpu_pstate == -1) + (*pstate) = '\0'; + + card = device_name[gpu_id]; + + snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;" + "TEMP=%.1f;FAN=%d;FREQ=%d;PST=%s;" + "VID=%hx;PID=%hx;BIOS=%s|", + gpu_id, cgpu->gpu_bus, card, + cgpu->gpu_temp, cgpu->gpu_fan, cgpu->gpu_clock, pstate, + cgpu->gpu_vid, cgpu->gpu_pid, cgpu->gpu_desc); + + strcat(buffer, buf); +} + /** -* Returns gpu/thread specific stats -*/ -static char *getthreads(char *params) + * To finish + */ +static void cpuhwinfos() +{ + char buf[256]; + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "CPU=|"); + strcat(buffer, buf); +} + +/** + * Returns gpu and system (todo) informations + */ +static char *gethwinfos(char *params) { *buffer = '\0'; - for (int i = 0; i < opt_n_threads; i++) - gpustatus(i); + for (int i = 0; i < num_processors; i++) + gpuhwinfos(i); + cpuhwinfos(); return buffer; } @@ -251,6 +319,7 @@ struct CMDS { { "threads", getthreads }, { "histo", gethistory }, { "meminfo", getmeminfo }, + { "hwinfo", gethwinfos }, /* keep it the last */ { "help", gethelp }, }; diff --git a/api/index.php b/api/index.php index c344dcd..fb57b9e 100644 --- a/api/index.php +++ b/api/index.php @@ -11,7 +11,7 @@ $configs = array( set_time_limit(3); error_reporting(0); -function getdataFromPears() +function getdataFromPeers() { global $host, $configs; $data = array(); @@ -129,7 +129,7 @@ function displayData($data) return $htm; } -$data = getdataFromPears(); +$data = getdataFromPeers(); ?> diff --git a/miner.h b/miner.h index afc8e6f..7b72642 100644 --- a/miner.h +++ b/miner.h @@ -376,13 +376,18 @@ struct cgpu_info { double khashes; uint8_t intensity; uint8_t has_monitoring; - int gpu_bus; float gpu_temp; int gpu_fan; int gpu_clock; int gpu_memclock; - int gpu_pstate; + uint32_t gpu_usage; double gpu_vddc; + int16_t gpu_pstate; + int16_t gpu_bus; + + uint16_t gpu_vid; + uint16_t gpu_pid; + char gpu_desc[64]; }; struct thr_api { diff --git a/nvml.cpp b/nvml.cpp index c69e1e6..167ad0d 100644 --- a/nvml.cpp +++ b/nvml.cpp @@ -30,7 +30,6 @@ extern wrap_nvml_handle *hnvml; extern int num_processors; // gpus -extern int device_map[8]; static uint32_t device_bus_ids[8] = { 0 }; @@ -175,7 +174,8 @@ wrap_nvml_handle * wrap_nvml_create() nvmlh->devs = (wrap_nvmlDevice_t *) calloc(nvmlh->nvml_gpucount, sizeof(wrap_nvmlDevice_t)); nvmlh->nvml_pci_domain_id = (unsigned int*) calloc(nvmlh->nvml_gpucount, sizeof(unsigned int)); nvmlh->nvml_pci_bus_id = (unsigned int*) calloc(nvmlh->nvml_gpucount, sizeof(unsigned int)); - nvmlh->nvml_pci_device_id = (unsigned int*) calloc(nvmlh->nvml_gpucount, sizeof(unsigned int)); + nvmlh->nvml_pci_device_id = (unsigned int*)calloc(nvmlh->nvml_gpucount, sizeof(unsigned int)); + nvmlh->nvml_pci_subsys_id = (unsigned int*)calloc(nvmlh->nvml_gpucount, sizeof(unsigned int)); nvmlh->nvml_cuda_device_id = (int*) calloc(nvmlh->nvml_gpucount, sizeof(int)); nvmlh->cuda_nvml_device_id = (int*) calloc(nvmlh->cuda_gpucount, sizeof(int)); @@ -192,6 +192,7 @@ wrap_nvml_handle * wrap_nvml_create() nvmlh->nvml_pci_domain_id[i] = pciinfo.domain; nvmlh->nvml_pci_bus_id[i] = pciinfo.bus; nvmlh->nvml_pci_device_id[i] = pciinfo.device; + nvmlh->nvml_pci_subsys_id[i] = pciinfo.pci_subsystem_id; } /* build mapping of NVML device IDs to CUDA IDs */ @@ -340,11 +341,33 @@ int wrap_nvml_get_busid(wrap_nvml_handle *nvmlh, int cudaindex, int *busid) return 0; } +int wrap_nvml_get_info(wrap_nvml_handle *nvmlh, int cudaindex, uint16_t *vid, uint16_t *pid) +{ + uint32_t subids = 0; + int gpuindex = nvmlh->cuda_nvml_device_id[cudaindex]; + if (gpuindex < 0 || gpuindex >= nvmlh->nvml_gpucount) + return -1; + + subids = nvmlh->nvml_pci_subsys_id[gpuindex]; + (*vid) = subids >> 16; + (*pid) = subids & 0xFFFF; + return 0; +} + int wrap_nvml_destroy(wrap_nvml_handle *nvmlh) { nvmlh->nvmlShutdown(); wrap_dlclose(nvmlh->nvml_dll); + + free(nvmlh->nvml_pci_bus_id); + free(nvmlh->nvml_pci_device_id); + free(nvmlh->nvml_pci_domain_id); + free(nvmlh->nvml_pci_subsys_id); + free(nvmlh->nvml_cuda_device_id); + free(nvmlh->cuda_nvml_device_id); + free(nvmlh->devs); + free(nvmlh); return 0; } @@ -455,6 +478,51 @@ int nvapi_getpstate(unsigned int devNum, unsigned int *power) return 0; } +#define UTIL_DOMAIN_GPU 0 +int nvapi_getusage(unsigned int devNum, unsigned int *pct) +{ + NvAPI_Status ret; + + if (devNum >= nvapi_dev_cnt) + return -1; + + NV_GPU_DYNAMIC_PSTATES_INFO_EX info; + info.version = NV_GPU_DYNAMIC_PSTATES_INFO_EX_VER; + ret = NvAPI_GPU_GetDynamicPstatesInfoEx(phys[devNum], &info); + if (ret != NVAPI_OK) { + NvAPI_ShortString string; + NvAPI_GetErrorMessage(ret, string); + if (opt_debug) + applog(LOG_DEBUG, "NVAPI GetDynamicPstatesInfoEx: %s", string); + return -1; + } + else { + if (info.utilization[UTIL_DOMAIN_GPU].bIsPresent) + (*pct) = info.utilization[UTIL_DOMAIN_GPU].percentage; + } + + return 0; +} + +int nvapi_getinfo(unsigned int devNum, char *desc) +{ + NvAPI_Status ret; + + if (devNum >= nvapi_dev_cnt) + return -1; + + // bios rev + ret = NvAPI_GPU_GetVbiosVersionString(phys[devNum], desc); + if (ret != NVAPI_OK) { + NvAPI_ShortString string; + NvAPI_GetErrorMessage(ret, string); + if (opt_debug) + applog(LOG_DEBUG, "NVAPI GetVbiosVersionString: %s", string); + return -1; + } + return 0; +} + int nvapi_getbusid(unsigned int devNum, int *busid) { if (devNum >= 0 && devNum <= 8) { @@ -486,9 +554,10 @@ int wrap_nvapi_init() for (int g = 0; g < num_processors; g++) { cudaDeviceProp props; - if (cudaGetDeviceProperties(&props, g) == cudaSuccess) + if (cudaGetDeviceProperties(&props, g) == cudaSuccess) { device_bus_ids[g] = props.pciBusID; - nvapi_dev_map[g] = g;// default mapping + } + nvapi_dev_map[g] = g; // default mapping } for (NvU8 i = 0; i < nvapi_dev_cnt; i++) { @@ -532,7 +601,7 @@ int gpu_fanpercent(struct cgpu_info *gpu) { unsigned int pct = 0; if (hnvml) { - wrap_nvml_get_fanpcnt(hnvml, device_map[gpu->thr_id], &pct); + wrap_nvml_get_fanpcnt(hnvml, gpu->gpu_id, &pct); } #ifdef WIN32 else { @@ -553,7 +622,7 @@ float gpu_temp(struct cgpu_info *gpu) float tc = 0.0; unsigned int tmp = 0; if (hnvml) { - wrap_nvml_get_tempC(hnvml, device_map[gpu->thr_id], &tmp); + wrap_nvml_get_tempC(hnvml, gpu->gpu_id, &tmp); tc = (float)tmp; } #ifdef WIN32 @@ -570,13 +639,18 @@ int gpu_clock(struct cgpu_info *gpu) unsigned int freq = 0; int support = -1; if (hnvml) { - support = wrap_nvml_get_clock(hnvml, device_map[gpu->thr_id], NVML_CLOCK_GRAPHICS, &freq); + support = wrap_nvml_get_clock(hnvml, gpu->gpu_id, NVML_CLOCK_GRAPHICS, &freq); } -#ifdef WIN32 if (support == -1) { +#ifdef WIN32 nvapi_getclock(nvapi_dev_map[gpu->gpu_id], &freq); - } +#else + cudaDeviceProp props; + if (cudaGetDeviceProperties(&props, gpu->gpu_id) == cudaSuccess) { + freq = props.clockRate; + } #endif + } return (int) freq; } @@ -585,7 +659,7 @@ int gpu_pstate(struct cgpu_info *gpu) int pstate = -1; int support = -1; if (hnvml) { - support = wrap_nvml_get_pstate(hnvml, device_map[gpu->thr_id], &pstate); + support = wrap_nvml_get_pstate(hnvml, gpu->gpu_id, &pstate); } #ifdef WIN32 if (support == -1) { @@ -602,7 +676,7 @@ int gpu_busid(struct cgpu_info *gpu) int busid = -1; int support = -1; if (hnvml) { - support = wrap_nvml_get_busid(hnvml, device_map[gpu->thr_id], &busid); + support = wrap_nvml_get_busid(hnvml, gpu->gpu_id, &busid); } #ifdef WIN32 if (support == -1) { @@ -612,21 +686,39 @@ int gpu_busid(struct cgpu_info *gpu) return busid; } - +/* not used in api (too much variable) */ unsigned int gpu_power(struct cgpu_info *gpu) { unsigned int mw = 0; int support = -1; if (hnvml) { - support = wrap_nvml_get_power_usage(hnvml, device_map[gpu->thr_id], &mw); + support = wrap_nvml_get_power_usage(hnvml, gpu->gpu_id, &mw); + } +#ifdef WIN32 + if (support == -1) { + unsigned int pct = 0; + nvapi_getusage(nvapi_dev_map[gpu->gpu_id], &pct); } +#endif return mw; } +int gpu_info(struct cgpu_info *gpu) +{ + if (hnvml) { + wrap_nvml_get_info(hnvml, gpu->gpu_id, &gpu->gpu_vid, &gpu->gpu_pid); + } +#ifdef WIN32 + nvapi_getinfo(nvapi_dev_map[gpu->gpu_id], &gpu->gpu_desc[0]); +#endif + return 0; +} + #if defined(__cplusplus) } #endif + #endif /* USE_WRAPNVML */ /* strings /usr/lib/nvidia-340/libnvidia-ml.so | grep nvmlDeviceGet | grep -v : | sort | uniq diff --git a/nvml.h b/nvml.h index 186dfa1..3adf4e0 100644 --- a/nvml.h +++ b/nvml.h @@ -60,6 +60,7 @@ typedef struct { unsigned int *nvml_pci_domain_id; unsigned int *nvml_pci_bus_id; unsigned int *nvml_pci_device_id; + unsigned int *nvml_pci_subsys_id; int *nvml_cuda_device_id; /* map NVML dev to CUDA dev */ int *cuda_nvml_device_id; /* map CUDA dev to NVML dev */ wrap_nvmlDevice_t *devs; @@ -144,9 +145,12 @@ int gpu_fanpercent(struct cgpu_info *gpu); float gpu_temp(struct cgpu_info *gpu); int gpu_clock(struct cgpu_info *gpu); unsigned int gpu_power(struct cgpu_info *gpu); +unsigned int gpu_usage(struct cgpu_info *gpu); int gpu_pstate(struct cgpu_info *gpu); int gpu_busid(struct cgpu_info *gpu); +int gpu_info(struct cgpu_info *gpu); + #if defined(__cplusplus) } #endif