Browse Source

Merge pull request #487 from kanoi/master

ICA optional limit timing with short=N or long=N
nfactor-troky
kanoi 11 years ago
parent
commit
10a1de9a3d
  1. 8
      FPGA-README
  2. 66
      driver-icarus.c

8
FPGA-README

@ -213,8 +213,8 @@ only 1 FPGA actually runs on the board (e.g. like an early CM1 Icarus copy bitst @@ -213,8 +213,8 @@ only 1 FPGA actually runs on the board (e.g. like an early CM1 Icarus copy bitst
--icarus-timing <arg> Set how the Icarus timing is calculated - one setting/value for all or comma separated
default[=N] Use the default Icarus hash time (2.6316ns)
short Calculate the hash time and stop adjusting it at ~315 difficulty 1 shares (~1hr)
long Re-calculate the hash time continuously
short=[N] Calculate the hash time and stop adjusting it at ~315 difficulty 1 shares (~1hr)
long=[N] Re-calculate the hash time continuously
value[=N] Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
If you define fewer comma seperated values than Icarus devices, the last values will be used
@ -236,6 +236,10 @@ Any CPU delays while calculating the hash time will affect the result @@ -236,6 +236,10 @@ Any CPU delays while calculating the hash time will affect the result
'short' mode only requires the computer to be stable until it has completed ~315 difficulty 1 shares
'long' mode requires it to always be stable to ensure accuracy, however, over time it continually
corrects itself
The optional additional =N for 'short' or 'long' specifies the limit to set the timeout to in N * 100ms
thus if the timing code calculation is higher while running, it will instead use N * 100ms
This can be set to the appropriate value to ensure the device never goes idle even if the
calculation is negatively affected by system performance
When in 'short' or 'long' mode, it will report the hash time value each time it is re-calculated
In 'short' or 'long' mode, the scan abort time starts at 5 seconds and uses the default 2.6316ns

66
driver-icarus.c

@ -72,9 +72,17 @@ ASSERT1(sizeof(uint32_t) == 4); @@ -72,9 +72,17 @@ ASSERT1(sizeof(uint32_t) == 4);
// maybe 1ms?
#define ICARUS_READ_TIME(baud) (0.001)
// USB ms timeout to wait
// USB ms timeout to wait - user specified timeouts are multiples of this
#define ICARUS_WAIT_TIMEOUT 100
// Defined in multiples of ICARUS_WAIT_TIMEOUT
// Must of course be greater than ICARUS_READ_COUNT_TIMING/ICARUS_WAIT_TIMEOUT
// There's no need to have this bigger, since the overhead/latency of extra work
// is pretty small once you get beyond a 10s nonce range time and 10s also
// means that nothing slower than 429MH/s can go idle so most icarus devices
// will always mine without idling
#define ICARUS_READ_TIME_LIMIT_MAX 100
// In timing mode: Default starting value until an estimate can be obtained
// 5000 ms allows for up to a ~840MH/s device
#define ICARUS_READ_COUNT_TIMING 5000
@ -160,7 +168,9 @@ enum timing_mode { MODE_DEFAULT, MODE_SHORT, MODE_LONG, MODE_VALUE }; @@ -160,7 +168,9 @@ enum timing_mode { MODE_DEFAULT, MODE_SHORT, MODE_LONG, MODE_VALUE };
static const char *MODE_DEFAULT_STR = "default";
static const char *MODE_SHORT_STR = "short";
static const char *MODE_SHORT_STREQ = "short=";
static const char *MODE_LONG_STR = "long";
static const char *MODE_LONG_STREQ = "long=";
static const char *MODE_VALUE_STR = "value";
static const char *MODE_UNKNOWN_STR = "unknown";
@ -176,6 +186,8 @@ struct ICARUS_INFO { @@ -176,6 +186,8 @@ struct ICARUS_INFO {
double Hs;
// ms til we abort
int read_time;
// ms limit for (short=/long=) read_time
int read_time_limit;
enum timing_mode timing_mode;
bool do_icarus_timing;
@ -536,19 +548,46 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus) @@ -536,19 +548,46 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
}
info->read_time = 0;
info->read_time_limit = 0; // 0 = no limit
// TODO: allow short=N and long=N
if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
// short
info->read_time = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_SHORT;
info->do_icarus_timing = true;
} else if (strncasecmp(buf, MODE_SHORT_STREQ, strlen(MODE_SHORT_STREQ)) == 0) {
// short=limit
info->read_time = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_SHORT;
info->do_icarus_timing = true;
info->read_time_limit = atoi(&buf[strlen(MODE_SHORT_STREQ)]);
if (info->read_time_limit < 0)
info->read_time_limit = 0;
if (info->read_time_limit > ICARUS_READ_TIME_LIMIT_MAX)
info->read_time_limit = ICARUS_READ_TIME_LIMIT_MAX;
} else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
// long
info->read_time = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_LONG;
info->do_icarus_timing = true;
} else if (strncasecmp(buf, MODE_LONG_STREQ, strlen(MODE_LONG_STREQ)) == 0) {
// long=limit
info->read_time = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_LONG;
info->do_icarus_timing = true;
info->read_time_limit = atoi(&buf[strlen(MODE_LONG_STREQ)]);
if (info->read_time_limit < 0)
info->read_time_limit = 0;
if (info->read_time_limit > ICARUS_READ_TIME_LIMIT_MAX)
info->read_time_limit = ICARUS_READ_TIME_LIMIT_MAX;
} else if ((Hs = atof(buf)) != 0) {
// ns[=read_time]
info->Hs = Hs / NANOSEC;
info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
@ -583,10 +622,13 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus) @@ -583,10 +622,13 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
info->min_data_count = MIN_DATA_COUNT;
applog(LOG_DEBUG, "%s: cgid %d Init: mode=%s read_time=%dms Hs=%e",
// All values are in multiples of ICARUS_WAIT_TIMEOUT
info->read_time_limit *= ICARUS_WAIT_TIMEOUT;
applog(LOG_DEBUG, "%s: cgid %d Init: mode=%s read_time=%dms limit=%dms Hs=%e",
icarus->drv->name, icarus->cgminer_id,
timing_mode_str(info->timing_mode),
info->read_time, info->Hs);
info->read_time, info->read_time_limit, info->Hs);
}
static uint32_t mask(int work_division)
@ -866,6 +908,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, @@ -866,6 +908,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
int count;
double Hs, W, fullnonce;
int read_time;
bool limited;
int64_t estimate_hashes;
uint32_t values;
int64_t hash_count_range;
@ -967,7 +1010,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, @@ -967,7 +1010,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
elapsed.tv_sec, elapsed.tv_usec);
}
// ignore possible end condition values ... and hw errors
// Ignore possible end condition values ... and hw errors
// TODO: set limitations on calculated values depending on the device
// to avoid crap values caused by CPU/Task Switching/Swapping/etc
if (info->do_icarus_timing
&& !was_hw_error
&& ((nonce & info->nonce_mask) > END_CONDITION)
@ -1040,6 +1085,11 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, @@ -1040,6 +1085,11 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
fullnonce = W + Hs * (((double)0xffffffff) + 1);
read_time = SECTOMS(fullnonce) - ICARUS_READ_REDUCE;
if (info->read_time_limit > 0 && read_time > info->read_time_limit) {
read_time = info->read_time_limit;
limited = true;
} else
limited = false;
info->Hs = Hs;
info->read_time = read_time;
@ -1055,8 +1105,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, @@ -1055,8 +1105,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
else if (info->timing_mode == MODE_SHORT)
info->do_icarus_timing = false;
applog(LOG_WARNING, "%s%d Re-estimate: Hs=%e W=%e read_time=%dms fullnonce=%.3fs",
icarus->drv->name, icarus->device_id, Hs, W, read_time, fullnonce);
applog(LOG_WARNING, "%s%d Re-estimate: Hs=%e W=%e read_time=%dms%s fullnonce=%.3fs",
icarus->drv->name, icarus->device_id, Hs, W, read_time,
limited ? " (limited)" : "", fullnonce);
}
info->history_count++;
cgtime(&tv_history_finish);
@ -1078,6 +1129,7 @@ static struct api_data *icarus_api_stats(struct cgpu_info *cgpu) @@ -1078,6 +1129,7 @@ static struct api_data *icarus_api_stats(struct cgpu_info *cgpu)
// locking access to displaying API debug 'stats'
// If locking becomes an issue for any of them, use copy_data=true also
root = api_add_int(root, "read_time", &(info->read_time), false);
root = api_add_int(root, "read_time_limit", &(info->read_time_limit), false);
root = api_add_double(root, "fullnonce", &(info->fullnonce), false);
root = api_add_int(root, "count", &(info->count), false);
root = api_add_hs(root, "Hs", &(info->Hs), false);

Loading…
Cancel
Save