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) @@ -147,7 +147,7 @@ void init_adl(int nDevs)
return;
}
for ( i = 0; i < iNumberAdapters; i++ ) {
for (i = 0; i < iNumberAdapters; i++) {
struct gpu_adl *ga;
int iAdapterIndex;
int lpAdapterID;
@ -197,7 +197,7 @@ void init_adl(int nDevs) @@ -197,7 +197,7 @@ void init_adl(int nDevs)
lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
/* 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;
/* Get default performance levels first */
@ -210,11 +210,12 @@ void init_adl(int nDevs) @@ -210,11 +210,12 @@ void init_adl(int nDevs)
/* Now get the current performance levels for any existing overclock */
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->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
/* Now use any parameters already set outside default as limits */
if (ga->iEngineClock < ga->minspeed)
ga->minspeed = ga->iEngineClock;
if (ga->iEngineClock > ga->maxspeed)
@ -225,11 +226,16 @@ void init_adl(int nDevs) @@ -225,11 +226,16 @@ void init_adl(int nDevs)
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 */
ga->targettemp = 75;
ga->overtemp = 85;
if (opt_autofan)
ga->autofan = true;
if (opt_autoengine)
ga->autoengine = true;
gpus[devices - 1].has_adl = true;
}
@ -386,6 +392,10 @@ static int set_engineclock(int gpu, int iEngineClock) @@ -386,6 +392,10 @@ static int set_engineclock(int gpu, int iEngineClock)
return 1;
}
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->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
return 0;
@ -555,55 +565,114 @@ static int set_fanspeed(int gpu, int iFanSpeed) @@ -555,55 +565,114 @@ static int set_fanspeed(int gpu, int iFanSpeed)
void gpu_autotune(int gpu)
{
int temp, fanpercent, engine, newpercent, newengine;
bool fan_optimal = true;
struct gpu_adl *ga;
int temp, fanpercent;
if (!gpus[gpu].has_adl || !adl_active)
return;
temp = gpu_temp(gpu);
if (!temp)
return;
fanpercent = gpu_fanpercent(gpu);
if (fanpercent < 0)
return;
newpercent = fanpercent = gpu_fanpercent(gpu);
newengine = engine = gpu_engineclock(gpu) * 100;
ga = &gpus[gpu].adl;
if (temp > ga->overtemp) {
applog(LOG_WARNING, "Overhead detected, increasing fan to 100%");
set_fanspeed(gpu, 100);
return;
}
if (temp > ga->targettemp && fanpercent < 85) {
if (opt_debug)
applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
set_fanspeed(gpu, fanpercent + 5);
return;
if (temp && fanpercent >= 0 && ga->autofan) {
if (temp > ga->overtemp && fanpercent < 100) {
applog(LOG_WARNING, "Overhead detected, increasing fan to 100%");
newpercent = 100;
} else if (temp > ga->targettemp && fanpercent < 85) {
if (opt_debug)
applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
newpercent = fanpercent + 5;
} else if (fanpercent && temp < ga->targettemp - 5) {
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)
applog(LOG_DEBUG, "Temperature 5 degrees below target, decreasing fanspeed");
set_fanspeed(gpu, fanpercent - 1);
if (engine && ga->autoengine) {
if (temp > ga->overtemp && engine > ga->minspeed) {
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)
{
struct gpu_adl *ga = &gpus[gpu].adl;
char input;
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("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");
input = getch();
if (!strncasecmp(&input, "f", 1)) {
ga->autofan ^= true;
if (!strncasecmp(&input, "f", 1)) {
ga->autofan ^= true;
wlogprint("Fan autotune is now %s\n", ga->autofan ? "enabled" : "disabled");
if (!ga->autofan) {
wlogprint("Setting fan to 85 %% as safety precaution\n");
set_fanspeed(gpu, 85);
wlogprint("Resetting fan to startup settings\n");
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; @@ -222,6 +222,7 @@ static bool opt_usecpu;
static int opt_shares;
static bool opt_fail_only;
bool opt_autofan;
bool opt_autoengine;
char *opt_kernel_path;
@ -1136,6 +1137,9 @@ static struct opt_table opt_config_table[] = { @@ -1136,6 +1137,9 @@ static struct opt_table opt_config_table[] = {
OPT_WITHOUT_ARG("--auto-fan",
opt_set_bool, &opt_autofan,
"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
OPT_WITH_ARG("--bench-algo|-b",
set_int_0_to_9999, opt_show_intval, &opt_bench_algo,

3
miner.h

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

Loading…
Cancel
Save