Skip to content

Commit

Permalink
Drillbit: --drillbit-auto parameter for tweakable custom tuning of AS…
Browse files Browse the repository at this point in the history
…IC speeds
  • Loading branch information
projectgus authored and kanoi committed Mar 12, 2014
1 parent 0be3987 commit 47a42f9
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 24 deletions.
15 changes: 14 additions & 1 deletion ASIC-README
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
22 changes: 16 additions & 6 deletions cgminer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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));
Expand Down
65 changes: 49 additions & 16 deletions driver-drillbit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions driver-drillbit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
2 changes: 1 addition & 1 deletion miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 47a42f9

Please sign in to comment.