Drillbit: --drillbit-auto parameter for tweakable custom tuning of ASIC speeds
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
diff --git a/ASIC-README b/ASIC-README
index ed2edff..dafbfb1 100644
--- a/ASIC-README
+++ b/ASIC-README
@@ -466,12 +466,25 @@ Drillbit Systems Devices
* voltage is ASIC core voltage in millivolts, available values vary per board but
default is 850 and the recommended maximum is 950 (Bitfury) and 1000 (Avalon.)
---drillbit-autotune
+--drillbit-auto <every>:[<gooderr>:<baderr>:<maxerr>]
If supported by firmware and device, this feature allows cgminer to
automatically tweak each ASIC's clock rate up and down in to achieve
optimal performance.
+* every - only required param, check each ASIC after each block of
+ this many work units. Recommended value 100.
+* gooderr - the "Good" threshold is when less hardware errors than
+ this per "every" work units, the clock rate will be increased.
+ Default value 1.
+* baderr - the "Bad" threshold is when more hardware errors than
+ this per "every" work units, the clock rate will be decreased.
+ Default value 3.
+* maxerr - the "Max" threshold is when more hardware errors than
+ this per "every" work units (including pre-empting before
+ "every" work units is up), the clock rate will be decreased and
+ will not be increased again past this point. Default value 10.
+
BlackArrow Bitfury devices
diff --git a/cgminer.c b/cgminer.c
index 39b9d99..d3fce65 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -209,7 +209,7 @@ char *opt_klondike_options = NULL;
#endif
#ifdef USE_DRILLBIT
char *opt_drillbit_options = NULL;
-bool opt_drillbit_autotune = false;
+char *opt_drillbit_auto = NULL;
#endif
char *opt_bab_options = NULL;
#ifdef USE_BITMINE_A1
@@ -1140,6 +1140,14 @@ static char *set_drillbit_options(const char *arg)
return NULL;
}
+
+static char *set_drillbit_auto(const char *arg)
+{
+ opt_set_charp(arg, &opt_drillbit_auto);
+
+ return NULL;
+}
+
#endif
#ifdef USE_BAB
@@ -1341,11 +1349,11 @@ static struct opt_table opt_config_table[] = {
"Automatically disable pools that continually reject shares"),
#ifdef USE_DRILLBIT
OPT_WITH_ARG("--drillbit-options",
- set_drillbit_options, NULL, NULL,
- "Set drillbit options <int|ext>:clock[:clock_divider][:voltage]"),
- OPT_WITHOUT_ARG("--drillbit-autotune",
- opt_set_bool, &opt_drillbit_autotune,
- "Enable drillbit automatic clock speed tuning"),
+ set_drillbit_options, NULL, NULL,
+ "Set drillbit options <int|ext>:clock[:clock_divider][:voltage]"),
+ OPT_WITH_ARG("--drillbit-auto",
+ set_drillbit_auto, NULL, NULL,
+ "Enable drillbit automatic tuning <every>:[<gooderr>:<baderr>:<maxerr>]"),
#endif
OPT_WITH_ARG("--expiry|-E",
set_int_0_to_9999, opt_show_intval, &opt_expiry,
@@ -4783,6 +4791,8 @@ void write_config(FILE *fcfg)
#ifdef USE_DRILLBIT
if (opt_drillbit_options)
fprintf(fcfg, ",\n\"drillbit-options\" : \"%s\"", json_escape(opt_drillbit_options));
+ if (opt_drillbit_auto)
+ fprintf(fcfg, ",\n\"drillbit-auto\" : \"%s\"", json_escape(opt_drillbit_auto));
#endif
if (opt_bab_options)
fprintf(fcfg, ",\n\"bab-options\" : \"%s\"", json_escape(opt_bab_options));
diff --git a/driver-drillbit.c b/driver-drillbit.c
index b2037d7..8f42c53 100644
--- a/driver-drillbit.c
+++ b/driver-drillbit.c
@@ -120,6 +120,12 @@ static config_setting *settings;
static void drillbit_empty_buffer(struct cgpu_info *drillbit);
+/* Automatic tuning parameters */
+static uint32_t auto_every = 100;
+static uint32_t auto_good = 1;
+static uint32_t auto_bad = 3;
+static uint32_t auto_max = 10;
+
/* Return a pointer to the chip_info structure for a given chip id, or NULL otherwise */
static struct drillbit_chip_info *find_chip(struct drillbit_info *info, uint16_t chip_id) {
int i;
@@ -529,6 +535,18 @@ static bool drillbit_parse_options(struct cgpu_info *drillbit)
if (next_opt)
next_opt++;
}
+
+ if(opt_drillbit_auto) {
+ sscanf(opt_drillbit_auto, "%d:%d:%d:%d",
+ &auto_every, &auto_good, &auto_bad, &auto_max);
+ if(auto_max < auto_bad) {
+ quithere(1, "Bad drillbit-auto: MAX limit must be greater than BAD limit");
+ }
+ if(auto_bad < auto_good) {
+ quithere(1, "Bad drillbit-auto: GOOD limit must be greater than BAD limit");
+ }
+ }
+
return true;
}
@@ -565,6 +583,7 @@ static struct cgpu_info *drillbit_detect_one(struct libusb_device *dev, struct u
info->chips = calloc(sizeof(struct drillbit_chip_info), info->num_chips);
for (i = 0; i < info->num_chips; i++) {
info->chips[i].chip_id = i;
+ info->chips[i].auto_max = 999;
}
/* Send reset request */
@@ -654,37 +673,51 @@ static bool drillbit_checkresults(struct thr_info *thr, struct work *work, uint3
}
/* Check if this ASIC should be tweaked up or down in clock speed */
-static void drillbit_check_autotune(struct thr_info *thr, struct drillbit_chip_info *chip)
+static void drillbit_check_auto(struct thr_info *thr, struct drillbit_chip_info *chip)
{
struct cgpu_info *drillbit = thr->cgpu;
AutoTuneRequest request;
char buf[SZ_SERIALISED_AUTOTUNEREQUEST+1];
int amount;
float ratio;
+ bool tune_up, tune_down;
- /* autotune tries to keep ratio of HW errors within these margins:
- every RETUNE_EVERY results (errors and successes totalled, error count should be between
- the low and high limits given.
+ /*
+ Only check automatic tuning every "auto_every" work units,
+ or if the error count exceeds the 'max' count
*/
- const uint32_t TUNE_UP_EVERY = 100;
- const uint32_t ERROR_LOW = 1;
- const uint32_t ERROR_HIGH = 3;
-
- /* Check auto parameters */
- if(chip->success_auto + chip->error_auto < TUNE_UP_EVERY && chip->error_auto < ERROR_HIGH*2)
+ if(chip->success_auto + chip->error_auto < auto_every &&
+ (chip->error_auto < auto_max))
return;
- ratio = 100 * (float)chip->error_auto / (chip->success_auto + chip->error_auto);
- applog(LOG_DEBUG, "Chip id %d has error ratio %3.1f%%", chip->chip_id, ratio);
+ tune_up = chip->error_auto < auto_good && chip->auto_delta < chip->auto_max;
+ tune_down = chip->error_auto > auto_bad;
+
+
+ drvlog(tune_up||tune_down ? LOG_NOTICE : LOG_DEBUG,
+ "Chip id %d has %d/%d error rate %s", chip->chip_id, chip->error_auto,
+ chip->error_auto + chip->success_auto,
+ tune_up ? " - tuning up" : tune_down ? " - tuning down" : " - no change");
- if(chip->error_auto < ERROR_LOW || chip->error_auto > ERROR_HIGH) {
+ if(tune_up || tune_down) {
/* Value should be tweaked */
buf[0] = 'A';
request.chip_id = chip->chip_id;
- request.increase_clock = chip->error_auto < ERROR_LOW;
+ request.increase_clock = tune_up;
serialise_autotune_request(&buf[1], &request);
usb_write_timeout(drillbit, buf, sizeof(buf), &amount, TIMEOUT, C_BF_AUTOTUNE);
usb_read_simple_response(drillbit, 'A', C_BF_AUTOTUNE);
+ if(tune_up) {
+ chip->auto_delta++;
+ } else {
+ chip->auto_delta--;
+ if(chip->error_auto >= auto_max
+ && chip->success_count + chip->error_count > auto_every) {
+ drvlog(LOG_ERR, "Chip id %d capping auto delta at max %d",chip->chip_id,
+ chip->auto_delta);
+ chip->auto_max = chip->auto_delta;
+ }
+ }
}
chip->success_auto = 0;
@@ -799,8 +832,8 @@ static int check_for_results(struct thr_info *thr)
else
chip->state = IDLE; // Uh-oh, we're totally out of work for this ASIC!
- if(opt_drillbit_autotune && info->protocol_version >= 4)
- drillbit_check_autotune(thr, chip);
+ if(opt_drillbit_auto && info->protocol_version >= 4)
+ drillbit_check_auto(thr, chip);
}
cleanup:
diff --git a/driver-drillbit.h b/driver-drillbit.h
index 373a3c7..b386107 100644
--- a/driver-drillbit.h
+++ b/driver-drillbit.h
@@ -49,6 +49,8 @@ struct drillbit_chip_info {
uint32_t work_sent_count;
uint32_t success_auto;
uint32_t error_auto;
+ int auto_delta;
+ int auto_max;
};
#endif /* BITFURY_H */
diff --git a/miner.h b/miner.h
index 40d88ea..4f74f67 100644
--- a/miner.h
+++ b/miner.h
@@ -982,7 +982,7 @@ extern char *opt_klondike_options;
#endif
#ifdef USE_DRILLBIT
extern char *opt_drillbit_options;
-extern bool opt_drillbit_autotune;
+extern char *opt_drillbit_auto;
#endif
#ifdef USE_BAB
extern char *opt_bab_options;