diff --git a/api.cpp b/api.cpp index c7e579d..1433886 100644 --- a/api.cpp +++ b/api.cpp @@ -128,7 +128,7 @@ static void gpustatus(int thr_id) cgpu->gpu_temp = gpu_temp(cgpu); cgpu->gpu_fan = gpu_fanpercent(cgpu); cgpu->gpu_power = gpu_power(cgpu); - //cgpu->gpu_clock = gpu_clock(cgpu); + cgpu->gpu_clock = gpu_clock(cgpu); } #endif @@ -149,9 +149,10 @@ static void gpustatus(int thr_id) cgpu->khashes = stats_get_speed(thr_id) / 1000.0; - sprintf(buf, "GPU=%d;TEMP=%.1f;FAN=%d;POWER=%d;KHS=%.2f;" + sprintf(buf, "GPU=%d;TEMP=%.1f;FAN=%d;FREQ=%d;POWER=%d;KHS=%.2f;" "HWF=%d;I=%d|", - thr_id, cgpu->gpu_temp, cgpu->gpu_fan, cgpu->gpu_power, cgpu->khashes, + thr_id, cgpu->gpu_temp, cgpu->gpu_fan, + cgpu->gpu_clock, cgpu->gpu_power, cgpu->khashes, cgpu->hw_errors, cgpu->intensity); strcat(buffer, buf); @@ -457,9 +458,11 @@ static void api() connectaddr, addrok ? "Accepted" : "Ignored"); if (addrok) { + bool fail; n = recv(c, &buf[0], SOCK_REC_BUFSZ, 0); - if (SOCKETFAIL(n)) + fail = SOCKETFAIL(n); + if (fail) buf[0] = '\0'; else if (n > 0 && buf[n-1] == '\n') { /* telnet compat \r\n */ @@ -469,10 +472,10 @@ static void api() } buf[n] = '\0'; - if (opt_debug && opt_protocol) + if (opt_debug && opt_protocol && n > 0) applog(LOG_DEBUG, "API: recv command: (%d) '%s'+char(%x)", n, buf, buf[n-1]); - if (!SOCKETFAIL(n)) { + if (!fail) { params = strchr(buf, '|'); if (params != NULL) *(params++) = '\0'; diff --git a/api/index.php b/api/index.php index e49a006..c062574 100644 --- a/api/index.php +++ b/api/index.php @@ -35,6 +35,7 @@ function translateField($key) $intl['TEMP'] = 'T°c'; $intl['FAN'] = 'Fan %'; + $intl['FREQ'] = 'Freq.'; if (isset($intl[$key])) return $intl[$key]; @@ -160,4 +161,4 @@ li span.algo { display: inline-block; width: 50px; max-width: 120px; } - \ No newline at end of file + diff --git a/ccminer.cpp b/ccminer.cpp index 6cb0d39..5a3ef8e 100644 --- a/ccminer.cpp +++ b/ccminer.cpp @@ -2131,7 +2131,7 @@ int main(int argc, char *argv[]) if (hnvml) applog(LOG_INFO, "NVML GPU monitoring enabled."); #ifdef WIN32 /* _WIN32 = x86 only, WIN32 for both _WIN32 & _WIN64 */ - else if (wrap_nvapi_init() == -1) + else if (wrap_nvapi_init() == 0) applog(LOG_INFO, "NVAPI GPU monitoring enabled."); #endif else diff --git a/nvml.cpp b/nvml.cpp index 6b61af8..7442d3c 100644 --- a/nvml.cpp +++ b/nvml.cpp @@ -280,8 +280,8 @@ int wrap_nvml_get_clock(wrap_nvml_handle *nvmlh, int cudaindex, int type, unsign wrap_nvmlReturn_t res = nvmlh->nvmlDeviceGetClockInfo(nvmlh->devs[gpuindex], (wrap_nvmlClockType_t) type, freq); if (res != WRAPNVML_SUCCESS) { - if (opt_debug) - applog(LOG_DEBUG, "nvmlDeviceGetClockInfo: %s", nvmlh->nvmlErrorString(res)); + //if (opt_debug) + // applog(LOG_DEBUG, "nvmlDeviceGetClockInfo: %s", nvmlh->nvmlErrorString(res)); return -1; } @@ -297,8 +297,8 @@ int wrap_nvml_get_power_usage(wrap_nvml_handle *nvmlh, int cudaindex, unsigned i wrap_nvmlReturn_t res = nvmlh->nvmlDeviceGetPowerUsage(nvmlh->devs[gpuindex], milliwatts); if (res != WRAPNVML_SUCCESS) { - if (opt_debug) - applog(LOG_DEBUG, "nvmlDeviceGetPowerUsage: %s", nvmlh->nvmlErrorString(res)); + //if (opt_debug) + // applog(LOG_DEBUG, "nvmlDeviceGetPowerUsage: %s", nvmlh->nvmlErrorString(res)); return -1; } @@ -365,7 +365,6 @@ int nvapi_temperature(unsigned int devNum, unsigned int *temperature) return 0; } - int nvapi_fanspeed(unsigned int devNum, unsigned int *speed) { NvAPI_Status ret; @@ -388,6 +387,55 @@ int nvapi_fanspeed(unsigned int devNum, unsigned int *speed) return 0; } +int nvapi_getclock(unsigned int devNum, unsigned int *freq) +{ + NvAPI_Status ret; + + if (devNum >= nvapi_dev_cnt) + return -1; + + NV_GPU_CLOCK_FREQUENCIES_V2 clocks; + clocks.version = NV_GPU_CLOCK_FREQUENCIES_VER_2; + clocks.ClockType = NV_GPU_CLOCK_FREQUENCIES_CURRENT_FREQ; // CURRENT/BASE/BOOST + ret = NvAPI_GPU_GetAllClockFrequencies(phys[devNum], &clocks); + if (ret != NVAPI_OK) { + NvAPI_ShortString string; + NvAPI_GetErrorMessage(ret, string); + if (opt_debug) + applog(LOG_DEBUG, "NVAPI NvAPI_GPU_GetAllClockFrequencies: %s", string); + return -1; + } else { + // GRAPHICS/MEMORY + (*freq) = (unsigned int)clocks.domain[NVAPI_GPU_PUBLIC_CLOCK_GRAPHICS].frequency; + } + + return 0; +} + +int nvapi_getpower(unsigned int devNum, unsigned int *power) +{ + NvAPI_Status ret; + + if (devNum >= nvapi_dev_cnt) + return -1; + + NV_GPU_PERF_PSTATE_ID CurrentPstate = NVAPI_GPU_PERF_PSTATE_UNDEFINED; /* 16 */ + ret = NvAPI_GPU_GetCurrentPstate(phys[devNum], &CurrentPstate); + if (ret != NVAPI_OK) { + NvAPI_ShortString string; + NvAPI_GetErrorMessage(ret, string); + if (opt_debug) + applog(LOG_DEBUG, "NVAPI NvAPI_GPU_GetCurrentPstate: %s", string); + return -1; + } + else { + // get pstate for the moment... often 0 = P0 + (*power) = (unsigned int)CurrentPstate; + } + + return 0; +} + int wrap_nvapi_init() { NvAPI_Status ret = NvAPI_Initialize(); @@ -426,8 +474,10 @@ int wrap_nvapi_init() } #endif -/* api functions */ -static unsigned int fan_speed_max = 2000; /* assume 2000 rpm as default, auto-updated */ +/* api functions -------------------------------------- */ + +// assume 2500 rpm as default, auto-updated if more +static unsigned int fan_speed_max = 2500; unsigned int gpu_fanpercent(struct cgpu_info *gpu) { @@ -469,18 +519,33 @@ double gpu_temp(struct cgpu_info *gpu) unsigned int gpu_clock(struct cgpu_info *gpu) { unsigned int freq = 0; + int support = -1; if (hnvml) { - wrap_nvml_get_clock(hnvml, device_map[gpu->thr_id], NVML_CLOCK_SM, &freq); + support = wrap_nvml_get_clock(hnvml, device_map[gpu->thr_id], NVML_CLOCK_SM, &freq); } +#ifdef WIN32 + if (support == -1) { + nvapi_getclock(device_map[gpu->thr_id], &freq); + } +#endif return freq; } unsigned int gpu_power(struct cgpu_info *gpu) { unsigned int mw = 0; + int support = -1; if (hnvml) { - wrap_nvml_get_power_usage(hnvml, device_map[gpu->thr_id], &mw); + support = wrap_nvml_get_power_usage(hnvml, device_map[gpu->thr_id], &mw); } +#ifdef WIN32 + if (support == -1) { + unsigned int pstate = 0; + nvapi_getpower(device_map[gpu->thr_id], &pstate); + //todo : convert ? + mw = pstate; + } +#endif return mw; }