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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
diff --git a/adl.c b/adl.c
index 3b3b55f..ea81123 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 ebf5e44..a4da8a2 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 9035a2b..2cc1871 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,