Browse Source

Add a gpu autotune option which adjusts GPU speed to maintain a target temperature within the bounds of the default GPU speed and any overclocking set.

nfactor-troky
Con Kolivas 13 years ago
parent
commit
e9b5885ebe
  1. 125
      adl.c
  2. 4
      main.c
  3. 3
      miner.h

125
adl.c

@ -147,7 +147,7 @@ void init_adl(int nDevs)
return; return;
} }
for ( i = 0; i < iNumberAdapters; i++ ) { for (i = 0; i < iNumberAdapters; i++) {
struct gpu_adl *ga; struct gpu_adl *ga;
int iAdapterIndex; int iAdapterIndex;
int lpAdapterID; int lpAdapterID;
@ -197,7 +197,7 @@ void init_adl(int nDevs)
lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1; lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
/* We're only interested in the top performance level */ /* We're only interested in the top performance level */
lpOdPerformanceLevels = alloca(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel))); lpOdPerformanceLevels = malloc(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel)));
lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev; lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev;
/* Get default performance levels first */ /* Get default performance levels first */
@ -210,11 +210,12 @@ void init_adl(int nDevs)
/* Now get the current performance levels for any existing overclock */ /* Now get the current performance levels for any existing overclock */
ADL_Overdrive5_ODPerformanceLevels_Get(iAdapterIndex, 0, lpOdPerformanceLevels); ADL_Overdrive5_ODPerformanceLevels_Get(iAdapterIndex, 0, lpOdPerformanceLevels);
/* Save these values as the defaults in case we wish to reset to defaults */
ga->DefPerfLev = lpOdPerformanceLevels;
ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock; ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock; ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc; ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
/* Now use any parameters already set outside default as limits */
if (ga->iEngineClock < ga->minspeed) if (ga->iEngineClock < ga->minspeed)
ga->minspeed = ga->iEngineClock; ga->minspeed = ga->iEngineClock;
if (ga->iEngineClock > ga->maxspeed) if (ga->iEngineClock > ga->maxspeed)
@ -225,11 +226,16 @@ void init_adl(int nDevs)
continue; continue;
} }
/* Save the fanspeed values as defaults in case we reset later */
ADL_Overdrive5_FanSpeed_Get(ga->iAdapterIndex, 0, &ga->DefFanSpeedValue);
/* Set some default temperatures for autotune when enabled */ /* Set some default temperatures for autotune when enabled */
ga->targettemp = 75; ga->targettemp = 75;
ga->overtemp = 85; ga->overtemp = 85;
if (opt_autofan) if (opt_autofan)
ga->autofan = true; ga->autofan = true;
if (opt_autoengine)
ga->autoengine = true;
gpus[devices - 1].has_adl = true; gpus[devices - 1].has_adl = true;
} }
@ -386,6 +392,10 @@ static int set_engineclock(int gpu, int iEngineClock)
return 1; return 1;
} }
ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock; ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
if (ga->iEngineClock > ga->maxspeed)
ga->maxspeed = ga->iEngineClock;
if (ga->iEngineClock < ga->minspeed)
ga->minspeed = ga->iEngineClock;
ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock; ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc; ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
return 0; return 0;
@ -555,55 +565,114 @@ static int set_fanspeed(int gpu, int iFanSpeed)
void gpu_autotune(int gpu) void gpu_autotune(int gpu)
{ {
int temp, fanpercent, engine, newpercent, newengine;
bool fan_optimal = true;
struct gpu_adl *ga; struct gpu_adl *ga;
int temp, fanpercent;
if (!gpus[gpu].has_adl || !adl_active) if (!gpus[gpu].has_adl || !adl_active)
return; return;
temp = gpu_temp(gpu); temp = gpu_temp(gpu);
if (!temp) newpercent = fanpercent = gpu_fanpercent(gpu);
return; newengine = engine = gpu_engineclock(gpu) * 100;
fanpercent = gpu_fanpercent(gpu);
if (fanpercent < 0)
return;
ga = &gpus[gpu].adl; ga = &gpus[gpu].adl;
if (temp > ga->overtemp) { if (temp && fanpercent >= 0 && ga->autofan) {
applog(LOG_WARNING, "Overhead detected, increasing fan to 100%"); if (temp > ga->overtemp && fanpercent < 100) {
set_fanspeed(gpu, 100); applog(LOG_WARNING, "Overhead detected, increasing fan to 100%");
return; newpercent = 100;
} } else if (temp > ga->targettemp && fanpercent < 85) {
if (temp > ga->targettemp && fanpercent < 85) { if (opt_debug)
if (opt_debug) applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
applog(LOG_DEBUG, "Temperature over target, increasing fanspeed"); newpercent = fanpercent + 5;
set_fanspeed(gpu, fanpercent + 5); } else if (fanpercent && temp < ga->targettemp - 5) {
return; if (opt_debug)
applog(LOG_DEBUG, "Temperature 5 degrees below target, decreasing fanspeed");
newpercent = fanpercent - 1;
}
if (newpercent > 100)
newpercent = 100;
else if (newpercent < 0)
newpercent = 0;
if (newpercent != fanpercent) {
fan_optimal = false;
applog(LOG_INFO, "Setting GPU %d fan percentage to %d", gpu, newpercent);
set_fanspeed(gpu, newpercent);
}
} }
if (fanpercent && temp < ga->targettemp - 5) {
if (opt_debug) if (engine && ga->autoengine) {
applog(LOG_DEBUG, "Temperature 5 degrees below target, decreasing fanspeed"); if (temp > ga->overtemp && engine > ga->minspeed) {
set_fanspeed(gpu, fanpercent - 1); applog(LOG_WARNING, "Overheat detected, decreasing GPU clock speed");
newengine = ga->minspeed;
} else if (temp > ga->targettemp && engine > ga->minspeed && fan_optimal) {
if (opt_debug)
applog(LOG_DEBUG, "Temperature over target, decreasing clock speed");
newengine = engine - ga->lpOdParameters.sEngineClock.iStep;
} else if (temp < ga->targettemp && engine < ga->maxspeed) {
if (opt_debug)
applog(LOG_DEBUG, "Temperature below target, increasing clock speed");
newengine = engine + ga->lpOdParameters.sEngineClock.iStep;
}
if (newengine > ga->maxspeed)
newengine = ga->maxspeed;
else if (newengine < ga->minspeed)
newengine = ga->minspeed;
if (newengine != engine) {
newengine /= 100;
applog(LOG_INFO, "Setting GPU %d engine clock to %d", gpu, newengine);
set_engineclock(gpu, newengine);
}
} }
} }
void set_defaultfan(int gpu)
{
struct gpu_adl *ga;
if (!gpus[gpu].has_adl || !adl_active)
return;
ga = &gpus[gpu].adl;
ADL_Overdrive5_FanSpeed_Set(ga->iAdapterIndex, 0, &ga->DefFanSpeedValue);
}
void set_defaultengine(int gpu)
{
struct gpu_adl *ga;
if (!gpus[gpu].has_adl || !adl_active)
return;
ga = &gpus[gpu].adl;
ADL_Overdrive5_ODPerformanceLevels_Set(ga->iAdapterIndex, ga->DefPerfLev);
}
void change_autosettings(int gpu) void change_autosettings(int gpu)
{ {
struct gpu_adl *ga = &gpus[gpu].adl; struct gpu_adl *ga = &gpus[gpu].adl;
char input; char input;
wlogprint("Fan autotune is %s\n", ga->autofan ? "enabled" : "disabled"); wlogprint("Fan autotune is %s\n", ga->autofan ? "enabled" : "disabled");
wlogprint("GPU engine clock autotune is %s\n", ga->autoengine ? "enabled" : "disabled");
wlogprint("Target temperature: %d\n", ga->targettemp); wlogprint("Target temperature: %d\n", ga->targettemp);
wlogprint("Overheat temperature: %d\n", ga->overtemp); wlogprint("Overheat temperature: %d\n", ga->overtemp);
wlogprint("Change [F]an [T]arget [O]verheat\n"); wlogprint("Toggle [F]an auto [G]PU auto, change [T]arget [O]verheat\n");
wlogprint("Or press any other key to continue\n"); wlogprint("Or press any other key to continue\n");
input = getch(); input = getch();
if (!strncasecmp(&input, "f", 1)) { if (!strncasecmp(&input, "f", 1)) {
ga->autofan ^= true; ga->autofan ^= true;
wlogprint("Fan autotune is now %s\n", ga->autofan ? "enabled" : "disabled"); wlogprint("Fan autotune is now %s\n", ga->autofan ? "enabled" : "disabled");
if (!ga->autofan) { if (!ga->autofan) {
wlogprint("Setting fan to 85 %% as safety precaution\n"); wlogprint("Resetting fan to startup settings\n");
set_fanspeed(gpu, 85); set_defaultfan(gpu);
}
} else if (!strncasecmp(&input, "g", 1)) {
ga->autoengine ^= true;
wlogprint("GPU engine clock autotune is now %s\n", ga->autoengine ? "enabled" : "disabled");
if (!ga->autoengine) {
wlogprint("Resetting GPU engine clock to startup settings\n");
set_defaultengine(gpu);
} }
} }
} }

4
main.c

@ -222,6 +222,7 @@ static bool opt_usecpu;
static int opt_shares; static int opt_shares;
static bool opt_fail_only; static bool opt_fail_only;
bool opt_autofan; bool opt_autofan;
bool opt_autoengine;
char *opt_kernel_path; char *opt_kernel_path;
@ -1136,6 +1137,9 @@ static struct opt_table opt_config_table[] = {
OPT_WITHOUT_ARG("--auto-fan", OPT_WITHOUT_ARG("--auto-fan",
opt_set_bool, &opt_autofan, opt_set_bool, &opt_autofan,
"Automatically adjust all GPU fan speeds to maintain a target temperature"), "Automatically adjust all GPU fan speeds to maintain a target temperature"),
OPT_WITHOUT_ARG("--auto-gpu",
opt_set_bool, &opt_autoengine,
"Automatically adjust all GPU engine clock speeds to maintain a target temperature"),
#endif #endif
OPT_WITH_ARG("--bench-algo|-b", OPT_WITH_ARG("--bench-algo|-b",
set_int_0_to_9999, opt_show_intval, &opt_bench_algo, set_int_0_to_9999, opt_show_intval, &opt_bench_algo,

3
miner.h

@ -163,8 +163,10 @@ struct gpu_adl {
int lpStatus; int lpStatus;
ADLPMActivity lpActivity; ADLPMActivity lpActivity;
ADLODParameters lpOdParameters; ADLODParameters lpOdParameters;
ADLODPerformanceLevels *DefPerfLev;
ADLFanSpeedInfo lpFanSpeedInfo; ADLFanSpeedInfo lpFanSpeedInfo;
ADLFanSpeedValue lpFanSpeedValue; ADLFanSpeedValue lpFanSpeedValue;
ADLFanSpeedValue DefFanSpeedValue;
int iEngineClock; int iEngineClock;
int iMemoryClock; int iMemoryClock;
int iVddc; int iVddc;
@ -296,6 +298,7 @@ extern bool opt_protocol;
extern bool opt_log_output; extern bool opt_log_output;
extern char *opt_kernel_path; extern char *opt_kernel_path;
extern bool opt_autofan; extern bool opt_autofan;
extern bool opt_autoengine;
extern const uint32_t sha256_init_state[]; extern const uint32_t sha256_init_state[];
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,

Loading…
Cancel
Save