Browse Source

api: use MHz for all clocks and show plimit

plimit value is reported in mW like the power, or % on Windows x86 (via nvapi)

+ the monitor thread will no more report 0W if the device doesnt support it

also upgrade nvml and sample php api.

some more changes may come in this temporary API 1.9 (for the final 2.0)
2upstream
Tanguy Pruvot 8 years ago
parent
commit
4da35e0bcf
  1. 25
      api.cpp
  2. 19
      api/index.php
  3. 2
      miner.h
  4. 54
      nvml.cpp
  5. 1
      nvml.h
  6. 1
      util.cpp

25
api.cpp

@ -118,6 +118,8 @@ static void gpustatus(int thr_id)
char* card; char* card;
cuda_gpu_info(cgpu); cuda_gpu_info(cgpu);
cgpu->gpu_plimit = device_plimit[cgpu->gpu_id];
#ifdef USE_WRAPNVML #ifdef USE_WRAPNVML
cgpu->has_monitoring = true; cgpu->has_monitoring = true;
cgpu->gpu_bus = gpu_busid(cgpu); cgpu->gpu_bus = gpu_busid(cgpu);
@ -125,6 +127,7 @@ static void gpustatus(int thr_id)
cgpu->gpu_fan = (uint16_t) gpu_fanpercent(cgpu); cgpu->gpu_fan = (uint16_t) gpu_fanpercent(cgpu);
cgpu->gpu_fan_rpm = (uint16_t) gpu_fanrpm(cgpu); cgpu->gpu_fan_rpm = (uint16_t) gpu_fanrpm(cgpu);
cgpu->gpu_power = gpu_power(cgpu); // mWatts cgpu->gpu_power = gpu_power(cgpu); // mWatts
cgpu->gpu_plimit = gpu_plimit(cgpu); // mW or %
#endif #endif
// todo: per gpu // todo: per gpu
@ -143,13 +146,14 @@ static void gpustatus(int thr_id)
snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;TEMP=%.1f;" snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;TEMP=%.1f;"
"POWER=%u;FAN=%hu;RPM=%hu;" "POWER=%u;FAN=%hu;RPM=%hu;"
"FREQ=%u;CORE=%u;MEM=%u;" "FREQ=%u;MEMFREQ=%u;GPUF=%u;MEMF=%u;"
"KHS=%.2f;KHW=%.5f;" "KHS=%.2f;KHW=%.5f;PLIM=%u;"
"HWF=%d;I=%.1f;THR=%u|", "HWF=%d;I=%.1f;THR=%u|",
gpuid, cgpu->gpu_bus, card, cgpu->gpu_temp, gpuid, cgpu->gpu_bus, card, cgpu->gpu_temp,
cgpu->gpu_power, cgpu->gpu_fan, cgpu->gpu_fan_rpm, cgpu->gpu_power, cgpu->gpu_fan, cgpu->gpu_fan_rpm,
cgpu->gpu_clock, cgpu->monitor.gpu_clock, cgpu->monitor.gpu_memclock, cgpu->gpu_clock/1000, cgpu->gpu_memclock/1000, // base freqs in MHz
cgpu->khashes, khashes_per_watt, cgpu->monitor.gpu_clock, cgpu->monitor.gpu_memclock, // current
cgpu->khashes, khashes_per_watt, cgpu->gpu_plimit,
cgpu->hw_errors, cgpu->intensity, cgpu->throughput); cgpu->hw_errors, cgpu->intensity, cgpu->throughput);
// append to buffer for multi gpus // append to buffer for multi gpus
@ -266,6 +270,8 @@ static void gpuhwinfos(int gpu_id)
return; return;
cuda_gpu_info(cgpu); cuda_gpu_info(cgpu);
cgpu->gpu_plimit = device_plimit[cgpu->gpu_id];
#ifdef USE_WRAPNVML #ifdef USE_WRAPNVML
cgpu->has_monitoring = true; cgpu->has_monitoring = true;
cgpu->gpu_bus = gpu_busid(cgpu); cgpu->gpu_bus = gpu_busid(cgpu);
@ -274,6 +280,7 @@ static void gpuhwinfos(int gpu_id)
cgpu->gpu_fan_rpm = (uint16_t) gpu_fanrpm(cgpu); cgpu->gpu_fan_rpm = (uint16_t) gpu_fanrpm(cgpu);
cgpu->gpu_pstate = (int16_t) gpu_pstate(cgpu); cgpu->gpu_pstate = (int16_t) gpu_pstate(cgpu);
cgpu->gpu_power = gpu_power(cgpu); cgpu->gpu_power = gpu_power(cgpu);
cgpu->gpu_plimit = gpu_plimit(cgpu);
gpu_info(cgpu); gpu_info(cgpu);
#ifdef WIN32 #ifdef WIN32
if (opt_debug) nvapi_pstateinfo(cgpu->gpu_id); if (opt_debug) nvapi_pstateinfo(cgpu->gpu_id);
@ -287,12 +294,14 @@ static void gpuhwinfos(int gpu_id)
card = device_name[gpu_id]; card = device_name[gpu_id];
snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;SM=%hu;MEM=%u;" snprintf(buf, sizeof(buf), "GPU=%d;BUS=%hd;CARD=%s;SM=%hu;MEM=%u;"
"TEMP=%.1f;FAN=%hu;RPM=%hu;FREQ=%d;MEMFREQ=%d;PST=%s;POWER=%u;" "TEMP=%.1f;FAN=%hu;RPM=%hu;FREQ=%u;MEMFREQ=%u;GPUF=%u;MEMF=%u;"
"PST=%s;POWER=%u;PLIM=%u;"
"VID=%hx;PID=%hx;NVML=%d;NVAPI=%d;SN=%s;BIOS=%s|", "VID=%hx;PID=%hx;NVML=%d;NVAPI=%d;SN=%s;BIOS=%s|",
gpu_id, cgpu->gpu_bus, card, cgpu->gpu_arch, (uint32_t) cgpu->gpu_mem, gpu_id, cgpu->gpu_bus, card, cgpu->gpu_arch, (uint32_t) cgpu->gpu_mem,
cgpu->gpu_temp, cgpu->gpu_fan, cgpu->gpu_fan_rpm, cgpu->gpu_temp, cgpu->gpu_fan, cgpu->gpu_fan_rpm,
cgpu->gpu_clock, cgpu->gpu_memclock, cgpu->gpu_clock/1000U, cgpu->gpu_memclock/1000U, // base clocks
pstate, cgpu->gpu_power, cgpu->monitor.gpu_clock, cgpu->monitor.gpu_memclock, // current
pstate, cgpu->gpu_power, cgpu->gpu_plimit,
cgpu->gpu_vid, cgpu->gpu_pid, cgpu->nvml_id, cgpu->nvapi_id, cgpu->gpu_vid, cgpu->gpu_pid, cgpu->nvml_id, cgpu->nvapi_id,
cgpu->gpu_sn, cgpu->gpu_desc); cgpu->gpu_sn, cgpu->gpu_desc);
@ -329,7 +338,7 @@ static void syshwinfos()
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "OS=%s;NVDRIVER=%s;CPUS=%d;CPUTEMP=%d;CPUFREQ=%d|", snprintf(buf, sizeof(buf), "OS=%s;NVDRIVER=%s;CPUS=%d;CPUTEMP=%d;CPUFREQ=%d|",
os_name(), driver_version, num_cpus, cputc, cpuclk); os_name(), driver_version, num_cpus, cputc, cpuclk/1000);
strcat(buffer, buf); strcat(buffer, buf);
} }

19
api/index.php

@ -1,5 +1,5 @@
<?php <?php
/* ccminer API sample UI (API 1.7) */ /* ccminer API sample UI (API 1.9) */
$host = 'http://localhost/api/'; // 'http://'.$_SERVER['SERVER_NAME'].'/api/'; $host = 'http://localhost/api/'; // 'http://'.$_SERVER['SERVER_NAME'].'/api/';
$configs = array( $configs = array(
@ -65,8 +65,14 @@ function translateField($key)
$intl['TEMP'] = 'T°c'; $intl['TEMP'] = 'T°c';
$intl['FAN'] = 'Fan %'; $intl['FAN'] = 'Fan %';
$intl['FREQ'] = 'Freq.'; $intl['CPUFREQ'] = 'CPU Freq.';
$intl['FREQ'] = 'Base Freq.';
$intl['MEMFREQ'] = 'Mem. Freq.';
$intl['GPUF'] = 'Curr Freq.';
$intl['MEMF'] = 'Mem. Freq.';
$intl['KHW'] = 'Efficiency';
$intl['POWER'] = 'Power'; $intl['POWER'] = 'Power';
$intl['PLIM'] = 'P.Limit';
$intl['PST'] = 'P-State'; $intl['PST'] = 'P-State';
// pool infos // pool infos
@ -98,8 +104,12 @@ function translateValue($key,$val,$data=array())
case 'NAME': case 'NAME':
$val = $data['NAME'].'&nbsp;'.$data['VER']; $val = $data['NAME'].'&nbsp;'.$data['VER'];
break; break;
case 'CPUFREQ':
case 'FREQ': case 'FREQ':
$val = sprintf("%d MHz", round(floatval($val)/1000.0)); case 'MEMFREQ':
case 'GPUF':
case 'MEMF':
$val = sprintf("%d MHz", $val);
break; break;
case 'POWER': case 'POWER':
$val = sprintf("%d W", round(floatval($val)/1000.0)); $val = sprintf("%d W", round(floatval($val)/1000.0));
@ -111,6 +121,9 @@ function translateValue($key,$val,$data=array())
case 'NETKHS': case 'NETKHS':
$val = '<span class="bold">'.$val.'</span> kH/s'; $val = '<span class="bold">'.$val.'</span> kH/s';
break; break;
case 'KHW':
$val = $val.' kH/W';
break;
case 'NAME': case 'NAME':
case 'POOL'; case 'POOL';
case 'USER': case 'USER':

2
miner.h

@ -391,6 +391,7 @@ struct cgpu_info {
uint64_t gpu_mem; uint64_t gpu_mem;
uint64_t gpu_memfree; uint64_t gpu_memfree;
uint32_t gpu_power; uint32_t gpu_power;
uint32_t gpu_plimit;
double gpu_vddc; double gpu_vddc;
int16_t gpu_pstate; int16_t gpu_pstate;
int16_t gpu_bus; int16_t gpu_bus;
@ -521,6 +522,7 @@ extern char* device_name[MAX_GPUS];
extern short device_map[MAX_GPUS]; extern short device_map[MAX_GPUS];
extern short device_mpcount[MAX_GPUS]; extern short device_mpcount[MAX_GPUS];
extern long device_sm[MAX_GPUS]; extern long device_sm[MAX_GPUS];
extern uint32_t device_plimit[MAX_GPUS];
extern uint32_t gpus_intensity[MAX_GPUS]; extern uint32_t gpus_intensity[MAX_GPUS];
extern int opt_cudaschedule; extern int opt_cudaschedule;

54
nvml.cpp

@ -34,7 +34,6 @@ static uint32_t device_bus_ids[MAX_GPUS] = { 0 };
extern uint32_t device_gpu_clocks[MAX_GPUS]; extern uint32_t device_gpu_clocks[MAX_GPUS];
extern uint32_t device_mem_clocks[MAX_GPUS]; extern uint32_t device_mem_clocks[MAX_GPUS];
extern uint32_t device_plimit[MAX_GPUS];
extern uint8_t device_tlimit[MAX_GPUS]; extern uint8_t device_tlimit[MAX_GPUS];
extern int8_t device_pstate[MAX_GPUS]; extern int8_t device_pstate[MAX_GPUS];
extern int32_t device_led[MAX_GPUS]; extern int32_t device_led[MAX_GPUS];
@ -539,6 +538,19 @@ int nvml_set_plimit(nvml_handle *nvmlh, int dev_id)
return 1; return 1;
} }
uint32_t nvml_get_plimit(nvml_handle *nvmlh, int dev_id)
{
uint32_t plimit = 0;
int n = nvmlh ? nvmlh->cuda_nvml_device_id[dev_id] : -1;
if (n < 0 || n >= nvmlh->nvml_gpucount)
return 0;
if (nvmlh->nvmlDeviceGetPowerManagementLimit) {
nvmlh->nvmlDeviceGetPowerManagementLimit(nvmlh->devs[n], &plimit);
}
return plimit;
}
// ccminer -D -n // ccminer -D -n
#define LSTDEV_PFX " " #define LSTDEV_PFX " "
void nvml_print_device_info(int dev_id) void nvml_print_device_info(int dev_id)
@ -1788,7 +1800,7 @@ int nvapi_init_settings()
for (int n=0; n < opt_n_threads; n++) { for (int n=0; n < opt_n_threads; n++) {
int dev_id = device_map[n % MAX_GPUS]; int dev_id = device_map[n % MAX_GPUS];
if (device_plimit[dev_id]) { if (device_plimit[dev_id] && !hnvml) {
if (nvapi_set_plimit(nvapi_dev_map[dev_id], device_plimit[dev_id]) == NVAPI_OK) { if (nvapi_set_plimit(nvapi_dev_map[dev_id], device_plimit[dev_id]) == NVAPI_OK) {
uint32_t res = nvapi_get_plimit(nvapi_dev_map[dev_id]); uint32_t res = nvapi_get_plimit(nvapi_dev_map[dev_id]);
gpulog(LOG_INFO, n, "Power limit is set to %u%%", res); gpulog(LOG_INFO, n, "Power limit is set to %u%%", res);
@ -1952,6 +1964,23 @@ unsigned int gpu_power(struct cgpu_info *gpu)
return mw; return mw;
} }
unsigned int gpu_plimit(struct cgpu_info *gpu)
{
unsigned int mw = 0;
int support = -1;
if (hnvml) {
mw = nvml_get_plimit(hnvml, gpu->gpu_id);
support = (mw > 0);
}
#ifdef WIN32
// NVAPI value is in % (< 100 so)
if (support == -1) {
mw = nvapi_get_plimit(nvapi_dev_map[gpu->gpu_id]);
}
#endif
return mw;
}
static int translate_vendor_id(uint16_t vid, char *vendorname) static int translate_vendor_id(uint16_t vid, char *vendorname)
{ {
struct VENDORS { struct VENDORS {
@ -2116,15 +2145,18 @@ void *monitor_thread(void *userdata)
do { do {
unsigned int tmp_clock=0, tmp_memclock=0; unsigned int tmp_clock=0, tmp_memclock=0;
nvml_get_current_clocks(dev_id, &tmp_clock, &tmp_memclock); nvml_get_current_clocks(dev_id, &tmp_clock, &tmp_memclock);
if (tmp_clock < 200) {
#ifdef WIN32 #ifdef WIN32
// workaround for buggy driver 378.49 (real clock) if (tmp_clock < 200) {
// workaround for buggy drivers 378.x (real clock)
tmp_clock = nvapi_get_gpu_clock(nvapi_dev_map[dev_id]); tmp_clock = nvapi_get_gpu_clock(nvapi_dev_map[dev_id]);
#else }
#endif
if (tmp_clock < 200) {
// some older cards only report a base clock with cuda props. // some older cards only report a base clock with cuda props.
if (cuda_gpu_info(cgpu) == 0) if (cuda_gpu_info(cgpu) == 0) {
tmp_clock = cgpu->gpu_clock/1000; tmp_clock = cgpu->gpu_clock/1000;
#endif tmp_memclock = cgpu->gpu_memclock/1000;
}
} }
clock += tmp_clock; clock += tmp_clock;
mem_clock += tmp_memclock; mem_clock += tmp_memclock;
@ -2148,14 +2180,14 @@ void *monitor_thread(void *userdata)
khs_per_watt = stats_get_speed(thr_id, thr_hashrates[thr_id]); khs_per_watt = stats_get_speed(thr_id, thr_hashrates[thr_id]);
khs_per_watt = khs_per_watt / ((double)power / counter); khs_per_watt = khs_per_watt / ((double)power / counter);
format_hashrate(khs_per_watt * 1000, khw); format_hashrate(khs_per_watt * 1000, khw);
if (strlen(khw)) khw[strlen(khw)-1] = 'W'; if (strlen(khw))
sprintf(&khw[strlen(khw)-1], "W %uW ", cgpu->monitor.gpu_power / 1000);
} }
if (opt_hwmonitor && (time(NULL) - cgpu->monitor.tm_displayed) > 60) { if (opt_hwmonitor && (time(NULL) - cgpu->monitor.tm_displayed) > 60) {
gpulog(LOG_INFO, thr_id, "%u MHz %s %uW %uC FAN %u%%", gpulog(LOG_INFO, thr_id, "%u MHz %s%uC FAN %u%%",
cgpu->monitor.gpu_clock/*, cgpu->monitor.gpu_memclock*/, cgpu->monitor.gpu_clock/*, cgpu->monitor.gpu_memclock*/,
khw, cgpu->monitor.gpu_power / 1000, khw, cgpu->monitor.gpu_temp, cgpu->monitor.gpu_fan
cgpu->monitor.gpu_temp, cgpu->monitor.gpu_fan
); );
cgpu->monitor.tm_displayed = (uint32_t)time(NULL); cgpu->monitor.tm_displayed = (uint32_t)time(NULL);
} }

1
nvml.h

@ -211,6 +211,7 @@ unsigned int gpu_fanpercent(struct cgpu_info *gpu);
unsigned int gpu_fanrpm(struct cgpu_info *gpu); unsigned int gpu_fanrpm(struct cgpu_info *gpu);
float gpu_temp(struct cgpu_info *gpu); float gpu_temp(struct cgpu_info *gpu);
unsigned int gpu_power(struct cgpu_info *gpu); unsigned int gpu_power(struct cgpu_info *gpu);
unsigned int gpu_plimit(struct cgpu_info *gpu);
int gpu_pstate(struct cgpu_info *gpu); int gpu_pstate(struct cgpu_info *gpu);
int gpu_busid(struct cgpu_info *gpu); int gpu_busid(struct cgpu_info *gpu);

1
util.cpp

@ -1627,7 +1627,6 @@ static bool stratum_get_algo(struct stratum_ctx *sctx, json_t *id, json_t *param
#include "nvml.h" #include "nvml.h"
extern char driver_version[32]; extern char driver_version[32];
extern int cuda_arch[MAX_GPUS]; extern int cuda_arch[MAX_GPUS];
extern uint32_t device_plimit[MAX_GPUS];
static bool json_object_set_error(json_t *result, int code, const char *msg) static bool json_object_set_error(json_t *result, int code, const char *msg)
{ {

Loading…
Cancel
Save