From e9b5885ebed12fb47d1de2d06088980b8d6d1e07 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 3 Sep 2011 22:30:11 +1000 Subject: [PATCH] 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. --- adl.c | 125 +++++++++++++++++++++++++++++++++++++++++++------------- main.c | 4 ++ miner.h | 3 ++ 3 files changed, 104 insertions(+), 28 deletions(-) diff --git a/adl.c b/adl.c index 3b3b55f6..ea811233 100644 --- a/adl.c +++ b/adl.c @@ -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) 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) /* 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) 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) 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) 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); } } } diff --git a/main.c b/main.c index ebf5e441..a4da8a28 100644 --- a/main.c +++ b/main.c @@ -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[] = { 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, diff --git a/miner.h b/miner.h index 9035a2b4..2cc18718 100644 --- a/miner.h +++ b/miner.h @@ -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; 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,