Dynamically adjust time spent hashing current work unit, to meet target
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
diff --git a/cpu-miner.c b/cpu-miner.c
index 8895d50..847e74b 100644
--- a/cpu-miner.c
+++ b/cpu-miner.c
@@ -60,6 +60,7 @@ bool opt_debug = false;
bool opt_protocol = false;
bool opt_quiet = false;
static int opt_retries = 10;
+static int opt_scantime = 5;
static const bool opt_time = true;
static enum sha256_algos opt_algo = ALGO_C;
static int opt_n_threads = 1;
@@ -104,6 +105,10 @@ static struct option_help options_help[] = {
"(-r N) Number of times to retry, if JSON-RPC call fails\n"
"\t(default: 10; use -1 for \"never\")" },
+ { "scantime N",
+ "(-s N) Upper bound on time spent scanning current work,\n"
+ "\tin seconds. (default: 5)" },
+
{ "threads N",
"(-t N) Number of miner threads (default: 1)" },
@@ -124,6 +129,7 @@ static struct option options[] = {
{ "protocol-dump", 0, NULL, 'P' },
{ "threads", 1, NULL, 't' },
{ "retries", 1, NULL, 'r' },
+ { "scantime", 1, NULL, 's' },
{ "url", 1, NULL, 1001 },
{ "userpass", 1, NULL, 1002 },
{ }
@@ -255,6 +261,7 @@ static void *miner_thread(void *thr_id_int)
struct work work __attribute__((aligned(128)));
unsigned long hashes_done;
struct timeval tv_start, tv_end, diff;
+ uint32_t max_nonce = 0xffffff;
json_t *val;
bool rc;
@@ -302,7 +309,7 @@ static void *miner_thread(void *thr_id_int)
case ALGO_C:
rc = scanhash_c(work.midstate, work.data + 64,
work.hash1, work.hash,
- 0xffffff, &hashes_done);
+ max_nonce, &hashes_done);
break;
#ifdef WANT_SSE2_4WAY
@@ -310,7 +317,7 @@ static void *miner_thread(void *thr_id_int)
unsigned int rc4 =
ScanHash_4WaySSE2(work.midstate, work.data + 64,
work.hash1, work.hash,
- 0xffffff, &hashes_done);
+ max_nonce, &hashes_done);
rc = (rc4 == -1) ? false : true;
}
break;
@@ -318,20 +325,20 @@ static void *miner_thread(void *thr_id_int)
#ifdef WANT_VIA_PADLOCK
case ALGO_VIA:
- rc = scanhash_via(work.data, 0xffffff, &hashes_done);
+ rc = scanhash_via(work.data, max_nonce, &hashes_done);
break;
#endif
case ALGO_CRYPTOPP:
rc = scanhash_cryptopp(work.midstate, work.data + 64,
work.hash1, work.hash,
- 0xffffff, &hashes_done);
+ max_nonce, &hashes_done);
break;
#ifdef WANT_CRYPTOPP_ASM32
case ALGO_CRYPTOPP_ASM32:
rc = scanhash_asm32(work.midstate, work.data + 64,
work.hash1, work.hash,
- 0xffffff, &hashes_done);
+ max_nonce, &hashes_done);
break;
#endif
@@ -340,11 +347,24 @@ static void *miner_thread(void *thr_id_int)
return NULL;
}
+ /* record scanhash elapsed time */
gettimeofday(&tv_end, NULL);
timeval_subtract(&diff, &tv_end, &tv_start);
hashmeter(thr_id, &diff, hashes_done);
+ /* adjust max_nonce to meet target scan time */
+ if (diff.tv_sec > (opt_scantime * 2))
+ max_nonce /= 2; /* large decrease */
+ else if (diff.tv_sec > opt_scantime)
+ max_nonce -= 1000; /* small decrease */
+ else if (diff.tv_sec < (opt_scantime - 1))
+ max_nonce += 1000; /* small increase */
+
+ /* catch stupidly slow cases, such as simulators */
+ if (max_nonce < 1000)
+ max_nonce = 1000;
+
/* if nonce found, submit work */
if (rc)
submit_work(&work);
@@ -403,6 +423,13 @@ static void parse_arg (int key, char *arg)
opt_retries = v;
break;
+ case 's':
+ v = atoi(arg);
+ if (v < 1 || v > 9999) /* sanity check */
+ show_usage();
+
+ opt_scantime = v;
+ break;
case 't':
v = atoi(arg);
if (v < 1 || v > 9999) /* sanity check */
@@ -433,7 +460,7 @@ static void parse_cmdline(int argc, char *argv[])
int key;
while (1) {
- key = getopt_long(argc, argv, "a:qDPr:t:h?", options, NULL);
+ key = getopt_long(argc, argv, "a:qDPr:s:t:h?", options, NULL);
if (key < 0)
break;