Browse Source

Allow running cgminer in benchmark mode with a work file --benchfile

port-ckolivas
Kano 11 years ago committed by Noel Maersk
parent
commit
d3d1493bcf
  1. 27
      README.md
  2. 204
      sgminer.c

27
README.md

@ -448,3 +448,30 @@ For example (this is wrapped, but it's all on one line for real):
000000004a4366808f81d44f26df3d69d7dc4b3473385930462d9ab707b50498 000000004a4366808f81d44f26df3d69d7dc4b3473385930462d9ab707b50498
f681634a4f1f63d01a0cd43fb338000000000080000000000000000000000000 f681634a4f1f63d01a0cd43fb338000000000080000000000000000000000000
0000000000000000000000000000000000000000000000000000000080020000 0000000000000000000000000000000000000000000000000000000080020000
## Benchmark
The --benchmark option hashes a single fixed work item over and over and does
not submit shares to any pools.
The --benchfile <arg> option hashes the work given in the file <arg> supplied.
The format of the work file is:
version,merkleroot,prevhash,diffbits,noncetime
Any empty line or any line starting with '#' or '/' is ignored.
When it reaches the end of the file it continues back at the top.
The format of the data items matches the byte ordering and format of the
the bitcoind getblock RPC output.
An example file containing bitcoin block #1 would be:
# Block 1
1,0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098,00000000001
9d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f,1d00ffff,1231469665
However, the work data should be one line without the linebreak in the middle
If you use --benchfile <arg>, then --benchfile-display will output a log line,
for each nonce found, showing the nonce value in decimal and hex and the work
used to find it in hex.

204
sgminer.c

@ -79,6 +79,29 @@ static char packagename[256];
bool opt_work_update; bool opt_work_update;
bool opt_protocol; bool opt_protocol;
static struct benchfile_layout {
int length;
char *name;
} benchfile_data[] = {
{ 1, "Version" },
{ 64, "MerkleRoot" },
{ 64, "PrevHash" },
{ 8, "DifficultyBits" },
{ 10, "NonceTime" } // 10 digits
};
enum benchwork {
BENCHWORK_VERSION = 0,
BENCHWORK_MERKLEROOT,
BENCHWORK_PREVHASH,
BENCHWORK_DIFFBITS,
BENCHWORK_NONCETIME,
BENCHWORK_COUNT
};
static char *opt_benchfile;
static bool opt_benchfile_display;
static FILE *benchfile_in;
static int benchfile_line;
static int benchfile_work;
static bool opt_benchmark; static bool opt_benchmark;
bool have_longpoll; bool have_longpoll;
bool want_per_device_stats; bool want_per_device_stats;
@ -1095,6 +1118,12 @@ static struct opt_table opt_config_table[] = {
OPT_WITHOUT_ARG("--balance", OPT_WITHOUT_ARG("--balance",
set_balance, &pool_strategy, set_balance, &pool_strategy,
"Change multipool strategy from failover to even share balance"), "Change multipool strategy from failover to even share balance"),
OPT_WITH_ARG("--benchfile",
opt_set_charp, opt_show_charp, &opt_benchfile,
"Run cgminer in benchmark mode using a work file - produces no shares"),
OPT_WITHOUT_ARG("--benchfile-display",
opt_set_bool, &opt_benchfile_display,
"Display each benchfile nonce found"),
OPT_WITHOUT_ARG("--benchmark", OPT_WITHOUT_ARG("--benchmark",
opt_set_bool, &opt_benchmark, opt_set_bool, &opt_benchmark,
"Run sgminer in benchmark mode - produces no shares"), "Run sgminer in benchmark mode - produces no shares"),
@ -2989,6 +3018,154 @@ static void get_benchmark_work(struct work *work)
calc_diff(work, 0); calc_diff(work, 0);
} }
static void benchfile_dspwork(struct work *work, uint32_t nonce)
{
char buf[1024];
uint32_t dn;
int i;
dn = 0;
for (i = 0; i < 4; i++) {
dn *= 0x100;
dn += nonce & 0xff;
nonce /= 0x100;
}
if ((sizeof(work->data) * 2 + 1) > sizeof(buf))
quithere(1, "BENCHFILE Invalid buf size");
__bin2hex(buf, work->data, sizeof(work->data));
applog(LOG_ERR, "BENCHFILE nonce %u=0x%08x for work=%s",
(unsigned int)dn, (unsigned int)dn, buf);
}
static bool benchfile_get_work(struct work *work)
{
char buf[1024];
char item[1024];
bool got = false;
if (!benchfile_in) {
if (opt_benchfile)
benchfile_in = fopen(opt_benchfile, "r");
else
quit(1, "BENCHFILE Invalid benchfile NULL");
if (!benchfile_in)
quit(1, "BENCHFILE Failed to open benchfile '%s'", opt_benchfile);
benchfile_line = 0;
if (!fgets(buf, 1024, benchfile_in))
quit(1, "BENCHFILE Failed to read benchfile '%s'", opt_benchfile);
got = true;
benchfile_work = 0;
}
if (!got) {
if (!fgets(buf, 1024, benchfile_in)) {
if (benchfile_work == 0)
quit(1, "BENCHFILE No work in benchfile '%s'", opt_benchfile);
fclose(benchfile_in);
benchfile_in = NULL;
return benchfile_get_work(work);
}
}
do
{
benchfile_line++;
// Empty lines and lines starting with '#' or '/' are ignored
if (*buf != '\0' && *buf != '#' && *buf != '/') {
char *commas[BENCHWORK_COUNT];
int i, j, len;
commas[0] = buf;
for (i = 1; i < BENCHWORK_COUNT; i++) {
commas[i] = strchr(commas[i-1], ',');
if (!commas[i]) {
quit(1, "BENCHFILE Invalid input file line %d"
" - field count is %d but should be %d",
benchfile_line, i, BENCHWORK_COUNT);
}
len = commas[i] - commas[i-1];
if (benchfile_data[i-1].length &&
(len != benchfile_data[i-1].length)) {
quit(1, "BENCHFILE Invalid input file line %d "
"field %d (%s) length is %d but should be %d",
benchfile_line, i,
benchfile_data[i-1].name,
len, benchfile_data[i-1].length);
}
*(commas[i]++) = '\0';
}
// NonceTime may have LF's etc
len = strlen(commas[BENCHWORK_NONCETIME]);
if (len < benchfile_data[BENCHWORK_NONCETIME].length) {
quit(1, "BENCHFILE Invalid input file line %d field %d"
" (%s) length is %d but should be least %d",
benchfile_line, BENCHWORK_NONCETIME+1,
benchfile_data[BENCHWORK_NONCETIME].name, len,
benchfile_data[BENCHWORK_NONCETIME].length);
}
sprintf(item, "0000000%c", commas[BENCHWORK_VERSION][0]);
j = strlen(item);
for (i = benchfile_data[BENCHWORK_PREVHASH].length-8; i >= 0; i -= 8) {
sprintf(&(item[j]), "%.8s", &commas[BENCHWORK_PREVHASH][i]);
j += 8;
}
for (i = benchfile_data[BENCHWORK_MERKLEROOT].length-8; i >= 0; i -= 8) {
sprintf(&(item[j]), "%.8s", &commas[BENCHWORK_MERKLEROOT][i]);
j += 8;
}
long time = atol(commas[BENCHWORK_NONCETIME]);
sprintf(&(item[j]), "%08lx", time);
j += 8;
strcpy(&(item[j]), commas[BENCHWORK_DIFFBITS]);
j += benchfile_data[BENCHWORK_DIFFBITS].length;
memset(work, 0, sizeof(*work));
hex2bin(work->data, item, j >> 1);
calc_midstate(work);
benchfile_work++;
return true;
}
} while (fgets(buf, 1024, benchfile_in));
if (benchfile_work == 0)
quit(1, "BENCHFILE No work in benchfile '%s'", opt_benchfile);
fclose(benchfile_in);
benchfile_in = NULL;
return benchfile_get_work(work);
}
static void get_benchfile_work(struct work *work)
{
benchfile_get_work(work);
work->mandatory = true;
work->pool = pools[0];
cgtime(&work->tv_getwork);
copy_time(&work->tv_getwork_reply, &work->tv_getwork);
work->getwork_mode = GETWORK_MODE_BENCHMARK;
calc_diff(work, 0);
}
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
static void disable_curses_windows(void) static void disable_curses_windows(void)
{ {
@ -3494,7 +3671,7 @@ static bool stale_work(struct work *work, bool share)
struct pool *pool; struct pool *pool;
int getwork_delay; int getwork_delay;
if (opt_benchmark) if (opt_benchmark || opt_benchfile)
return false; return false;
if (work->work_block != work_block) { if (work->work_block != work_block) {
@ -6091,6 +6268,9 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
return false; return false;
} }
if (opt_benchfile && opt_benchfile_display)
benchfile_dspwork(work, nonce);
return true; return true;
} }
@ -6111,6 +6291,10 @@ bool submit_noffset_nonce(struct thr_info *thr, struct work *work_in, uint32_t n
} }
ret = true; ret = true;
update_work_stats(thr, work); update_work_stats(thr, work);
if (opt_benchfile && opt_benchfile_display)
benchfile_dspwork(work, nonce);
if (!fulltest(work->hash, work->target)) { if (!fulltest(work->hash, work->target)) {
applog(LOG_INFO, "%s %d: Share above target", thr->cgpu->drv->name, applog(LOG_INFO, "%s %d: Share above target", thr->cgpu->drv->name,
thr->cgpu->device_id); thr->cgpu->device_id);
@ -6932,7 +7116,7 @@ static void *watchpool_thread(void __maybe_unused *userdata)
for (i = 0; i < total_pools; i++) { for (i = 0; i < total_pools; i++) {
struct pool *pool = pools[i]; struct pool *pool = pools[i];
if (!opt_benchmark) if (!opt_benchmark && !opt_benchfile)
reap_curl(pool); reap_curl(pool);
/* Get a rolling utility per pool over 10 mins */ /* Get a rolling utility per pool over 10 mins */
@ -7833,14 +8017,17 @@ int main(int argc, char *argv[])
if (!config_loaded) if (!config_loaded)
load_default_config(); load_default_config();
if (opt_benchmark) { if (opt_benchmark || opt_benchfile) {
struct pool *pool; struct pool *pool;
// FIXME: executes always (leftover from SHA256d days) // FIXME: executes always (leftover from SHA256d days)
quit(1, "Cannot use benchmark mode with scrypt"); quit(1, "Cannot use benchmark mode with scrypt");
pool = add_pool(); pool = add_pool();
pool->rpc_url = malloc(255); pool->rpc_url = malloc(255);
strcpy(pool->rpc_url, "Benchmark"); if (opt_benchfile)
strcpy(pool->rpc_url, "Benchfile");
else
strcpy(pool->rpc_url, "Benchmark");
pool->rpc_user = pool->rpc_url; pool->rpc_user = pool->rpc_url;
pool->rpc_pass = pool->rpc_url; pool->rpc_pass = pool->rpc_url;
enable_pool(pool); enable_pool(pool);
@ -8025,7 +8212,7 @@ int main(int argc, char *argv[])
} }
} }
if (opt_benchmark) if (opt_benchmark || opt_benchfile)
goto begin_bench; goto begin_bench;
/* Set pool state */ /* Set pool state */
@ -8218,7 +8405,12 @@ retry:
continue; continue;
} }
if (opt_benchmark) { if (opt_benchfile) {
get_benchfile_work(work);
applog(LOG_DEBUG, "Generated benchfile work");
stage_work(work);
continue;
} else if (opt_benchmark) {
get_benchmark_work(work); get_benchmark_work(work);
applog(LOG_DEBUG, "Generated benchmark work"); applog(LOG_DEBUG, "Generated benchmark work");
stage_work(work); stage_work(work);

Loading…
Cancel
Save