Drastically increase getwork efficiency
This commit is contained in:
parent
e0dc6649e1
commit
0426d3ace0
6 changed files with 73 additions and 32 deletions
6
NEWS
6
NEWS
|
@ -1,3 +1,9 @@
|
|||
Version 2.1 - Jan 19, 2012
|
||||
|
||||
- Share the same work among all threads
|
||||
- Do not ask for new work if the current one is not expired
|
||||
- Do not discard the work returned by long polling
|
||||
|
||||
Version 2.0 - Jan 16, 2012
|
||||
|
||||
- Change default port to 9332 for Litecoin and remove default credentials
|
||||
|
|
3
README
3
README
|
@ -23,3 +23,6 @@ Basic WIN32 build instructions (on Fedora 13; requires mingw32):
|
|||
|
||||
Usage instructions: Run "minerd --help" to see options.
|
||||
|
||||
Also many issues and FAQs are covered in the forum thread
|
||||
dedicated to this program,
|
||||
https://bitcointalk.org/index.php?topic=55038.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT([cpuminer], [2.0])
|
||||
AC_INIT([cpuminer], [2.1])
|
||||
|
||||
AC_PREREQ(2.52)
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
|
45
cpu-miner.c
45
cpu-miner.c
|
@ -101,7 +101,7 @@ int opt_scantime = 5;
|
|||
static json_t *opt_config;
|
||||
static const bool opt_time = true;
|
||||
static enum sha256_algos opt_algo = ALGO_SCRYPT;
|
||||
static int opt_n_threads;
|
||||
int opt_n_threads;
|
||||
static int num_processors;
|
||||
static char *rpc_url;
|
||||
static char *rpc_userpass;
|
||||
|
@ -213,6 +213,10 @@ struct work {
|
|||
unsigned char hash[32];
|
||||
};
|
||||
|
||||
static struct work g_work;
|
||||
static time_t g_work_time;
|
||||
static pthread_mutex_t g_work_lock;
|
||||
|
||||
static bool jobj_binary(const json_t *obj, const char *key,
|
||||
void *buf, size_t buflen)
|
||||
{
|
||||
|
@ -287,9 +291,6 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
|
|||
"{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
|
||||
hexstr);
|
||||
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "DBG: sending RPC call: %s", s);
|
||||
|
||||
/* issue JSON-RPC request */
|
||||
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false);
|
||||
if (unlikely(!val)) {
|
||||
|
@ -535,6 +536,7 @@ static void *miner_thread(void *userdata)
|
|||
struct thr_info *mythr = userdata;
|
||||
int thr_id = mythr->id;
|
||||
uint32_t max_nonce = 0xffffff;
|
||||
uint32_t next_nonce;
|
||||
unsigned char *scratchbuf = NULL;
|
||||
|
||||
/* Set worker threads to nice 19 and then preferentially to SCHED_IDLE
|
||||
|
@ -551,7 +553,7 @@ static void *miner_thread(void *userdata)
|
|||
if (opt_algo == ALGO_SCRYPT)
|
||||
{
|
||||
scratchbuf = scrypt_buffer_alloc();
|
||||
max_nonce = 0xffff;
|
||||
max_nonce = 0xffff * opt_n_threads;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
@ -563,12 +565,25 @@ static void *miner_thread(void *userdata)
|
|||
bool rc;
|
||||
|
||||
/* obtain new work from internal workio thread */
|
||||
if (unlikely(!get_work(mythr, &work))) {
|
||||
pthread_mutex_lock(&g_work_lock);
|
||||
if (!have_longpoll || time(NULL) >= g_work_time + opt_scantime) {
|
||||
if (unlikely(!get_work(mythr, &g_work))) {
|
||||
applog(LOG_ERR, "work retrieval failed, exiting "
|
||||
"mining thread %d", mythr->id);
|
||||
pthread_mutex_unlock(&g_work_lock);
|
||||
goto out;
|
||||
}
|
||||
time(&g_work_time);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "DEBUG: got new work");
|
||||
}
|
||||
if (memcmp(work.data, g_work.data, 76)) {
|
||||
memcpy(&work, &g_work, sizeof(struct work));
|
||||
next_nonce = thr_id;
|
||||
}
|
||||
pthread_mutex_unlock(&g_work_lock);
|
||||
|
||||
work_restart[thr_id].restart = 0;
|
||||
hashes_done = 0;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
|
||||
|
@ -576,7 +591,8 @@ static void *miner_thread(void *userdata)
|
|||
switch (opt_algo) {
|
||||
case ALGO_SCRYPT:
|
||||
rc = scanhash_scrypt(thr_id, work.data, scratchbuf,
|
||||
work.target, max_nonce, &hashes_done);
|
||||
work.target, next_nonce + max_nonce,
|
||||
&next_nonce, &hashes_done);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -595,8 +611,9 @@ static void *miner_thread(void *userdata)
|
|||
if (diffms > 0) {
|
||||
max64 =
|
||||
((uint64_t)hashes_done * opt_scantime * 1000) / diffms;
|
||||
if (max64 > 0xfffffffaULL)
|
||||
max64 = 0xfffffffaULL;
|
||||
max64 *= opt_n_threads;
|
||||
if (max64 > 0xffff0000ULL)
|
||||
max64 = 0xffff0000ULL;
|
||||
max_nonce = max64;
|
||||
}
|
||||
|
||||
|
@ -665,13 +682,19 @@ static void *longpoll_thread(void *userdata)
|
|||
false, true);
|
||||
if (likely(val)) {
|
||||
failures = 0;
|
||||
json_decref(val);
|
||||
|
||||
applog(LOG_INFO, "LONGPOLL detected new block");
|
||||
pthread_mutex_lock(&g_work_lock);
|
||||
if (work_decode(json_object_get(val, "result"), &g_work)) {
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "DEBUG: got new work");
|
||||
time(&g_work_time);
|
||||
restart_threads();
|
||||
}
|
||||
pthread_mutex_unlock(&g_work_lock);
|
||||
} else {
|
||||
/* longpoll failed, keep trying */
|
||||
}
|
||||
json_decref(val);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
3
miner.h
3
miner.h
|
@ -130,7 +130,7 @@ extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
|||
extern unsigned char *scrypt_buffer_alloc();
|
||||
extern int scanhash_scrypt(int, unsigned char *pdata, unsigned char *scratchbuf,
|
||||
const unsigned char *ptarget,
|
||||
uint32_t max_nonce, unsigned long *nHashesDone);
|
||||
uint32_t max_nonce, uint32_t *next_nonce, unsigned long *hashes_done);
|
||||
|
||||
extern int
|
||||
timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
|
||||
|
@ -141,6 +141,7 @@ extern int opt_scantime;
|
|||
extern int opt_timeout;
|
||||
extern bool want_longpoll;
|
||||
extern bool have_longpoll;
|
||||
extern int opt_n_threads;
|
||||
struct thread_q;
|
||||
|
||||
struct work_restart {
|
||||
|
|
38
scrypt.c
38
scrypt.c
|
@ -512,7 +512,7 @@ static int test_hash(const uint32_t *hash, const uint32_t *target)
|
|||
|
||||
int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||
const unsigned char *ptarget,
|
||||
uint32_t max_nonce, unsigned long *hashes_done)
|
||||
uint32_t max_nonce, uint32_t *next_nonce, unsigned long *hashes_done)
|
||||
{
|
||||
uint32_t data[20], hash[8];
|
||||
#ifdef SCRYPT_3WAY
|
||||
|
@ -520,12 +520,11 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
|||
uint32_t data3[20], hash3[8];
|
||||
int throughput;
|
||||
#endif
|
||||
uint32_t n = 0;
|
||||
unsigned long c = 0;
|
||||
uint32_t n = *next_nonce;
|
||||
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
|
||||
int i;
|
||||
|
||||
work_restart[thr_id].restart = 0;
|
||||
|
||||
for (i = 0; i < 19; i++)
|
||||
data[i] = be32dec(&((const uint32_t *)pdata)[i]);
|
||||
#ifdef SCRYPT_3WAY
|
||||
|
@ -535,16 +534,23 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
|||
#endif
|
||||
|
||||
while (1) {
|
||||
data[19] = n++;
|
||||
data[19] = n;
|
||||
n += opt_n_threads;
|
||||
++c;
|
||||
#ifdef SCRYPT_3WAY
|
||||
if (throughput >= 2 && n < max_nonce) {
|
||||
data2[19] = n++;
|
||||
if (throughput >= 3 && n < max_nonce) {
|
||||
data3[19] = n++;
|
||||
if (throughput >= 2 && n <= max_nonce) {
|
||||
data2[19] = n;
|
||||
n += opt_n_threads;
|
||||
++c;
|
||||
if (throughput >= 3 && n <= max_nonce) {
|
||||
data3[19] = n;
|
||||
n += opt_n_threads;
|
||||
++c;
|
||||
scrypt_1024_1_1_256_sp_3way(data, data2, data3, hash, hash2, hash3, scratchbuf);
|
||||
if (hash3[7] < Htarg || hash3[7] == Htarg && test_hash(hash3, (uint32_t *)ptarget)) {
|
||||
be32enc(&((uint32_t *)pdata)[19], data3[19]);
|
||||
*hashes_done = n;
|
||||
*next_nonce = n;
|
||||
*hashes_done = c;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -552,7 +558,8 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
|||
}
|
||||
if (hash2[7] < Htarg || hash2[7] == Htarg && test_hash(hash2, (uint32_t *)ptarget)) {
|
||||
be32enc(&((uint32_t *)pdata)[19], data2[19]);
|
||||
*hashes_done = n;
|
||||
*next_nonce = n;
|
||||
*hashes_done = c;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -564,15 +571,16 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
|||
|
||||
if (hash[7] < Htarg || hash[7] == Htarg && test_hash(hash, (uint32_t *)ptarget)) {
|
||||
be32enc(&((uint32_t *)pdata)[19], data[19]);
|
||||
*hashes_done = n;
|
||||
*next_nonce = n;
|
||||
*hashes_done = c;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((n >= max_nonce) || work_restart[thr_id].restart) {
|
||||
*hashes_done = n;
|
||||
if ((n > max_nonce) || work_restart[thr_id].restart)
|
||||
break;
|
||||
}
|
||||
}
|
||||
*next_nonce = n;
|
||||
*hashes_done = c;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue