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
|
Version 2.0 - Jan 16, 2012
|
||||||
|
|
||||||
- Change default port to 9332 for Litecoin and remove default credentials
|
- 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.
|
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_PREREQ(2.52)
|
||||||
AC_CANONICAL_SYSTEM
|
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 json_t *opt_config;
|
||||||
static const bool opt_time = true;
|
static const bool opt_time = true;
|
||||||
static enum sha256_algos opt_algo = ALGO_SCRYPT;
|
static enum sha256_algos opt_algo = ALGO_SCRYPT;
|
||||||
static int opt_n_threads;
|
int opt_n_threads;
|
||||||
static int num_processors;
|
static int num_processors;
|
||||||
static char *rpc_url;
|
static char *rpc_url;
|
||||||
static char *rpc_userpass;
|
static char *rpc_userpass;
|
||||||
|
@ -213,6 +213,10 @@ struct work {
|
||||||
unsigned char hash[32];
|
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,
|
static bool jobj_binary(const json_t *obj, const char *key,
|
||||||
void *buf, size_t buflen)
|
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",
|
"{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
|
||||||
hexstr);
|
hexstr);
|
||||||
|
|
||||||
if (opt_debug)
|
|
||||||
applog(LOG_DEBUG, "DBG: sending RPC call: %s", s);
|
|
||||||
|
|
||||||
/* issue JSON-RPC request */
|
/* issue JSON-RPC request */
|
||||||
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false);
|
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false);
|
||||||
if (unlikely(!val)) {
|
if (unlikely(!val)) {
|
||||||
|
@ -535,6 +536,7 @@ static void *miner_thread(void *userdata)
|
||||||
struct thr_info *mythr = userdata;
|
struct thr_info *mythr = userdata;
|
||||||
int thr_id = mythr->id;
|
int thr_id = mythr->id;
|
||||||
uint32_t max_nonce = 0xffffff;
|
uint32_t max_nonce = 0xffffff;
|
||||||
|
uint32_t next_nonce;
|
||||||
unsigned char *scratchbuf = NULL;
|
unsigned char *scratchbuf = NULL;
|
||||||
|
|
||||||
/* Set worker threads to nice 19 and then preferentially to SCHED_IDLE
|
/* 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)
|
if (opt_algo == ALGO_SCRYPT)
|
||||||
{
|
{
|
||||||
scratchbuf = scrypt_buffer_alloc();
|
scratchbuf = scrypt_buffer_alloc();
|
||||||
max_nonce = 0xffff;
|
max_nonce = 0xffff * opt_n_threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -563,12 +565,25 @@ static void *miner_thread(void *userdata)
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
/* obtain new work from internal workio thread */
|
/* 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 "
|
applog(LOG_ERR, "work retrieval failed, exiting "
|
||||||
"mining thread %d", mythr->id);
|
"mining thread %d", mythr->id);
|
||||||
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
goto out;
|
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;
|
hashes_done = 0;
|
||||||
gettimeofday(&tv_start, NULL);
|
gettimeofday(&tv_start, NULL);
|
||||||
|
|
||||||
|
@ -576,7 +591,8 @@ static void *miner_thread(void *userdata)
|
||||||
switch (opt_algo) {
|
switch (opt_algo) {
|
||||||
case ALGO_SCRYPT:
|
case ALGO_SCRYPT:
|
||||||
rc = scanhash_scrypt(thr_id, work.data, scratchbuf,
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -595,8 +611,9 @@ static void *miner_thread(void *userdata)
|
||||||
if (diffms > 0) {
|
if (diffms > 0) {
|
||||||
max64 =
|
max64 =
|
||||||
((uint64_t)hashes_done * opt_scantime * 1000) / diffms;
|
((uint64_t)hashes_done * opt_scantime * 1000) / diffms;
|
||||||
if (max64 > 0xfffffffaULL)
|
max64 *= opt_n_threads;
|
||||||
max64 = 0xfffffffaULL;
|
if (max64 > 0xffff0000ULL)
|
||||||
|
max64 = 0xffff0000ULL;
|
||||||
max_nonce = max64;
|
max_nonce = max64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,13 +682,19 @@ static void *longpoll_thread(void *userdata)
|
||||||
false, true);
|
false, true);
|
||||||
if (likely(val)) {
|
if (likely(val)) {
|
||||||
failures = 0;
|
failures = 0;
|
||||||
json_decref(val);
|
|
||||||
|
|
||||||
applog(LOG_INFO, "LONGPOLL detected new block");
|
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();
|
restart_threads();
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
} else {
|
} else {
|
||||||
/* longpoll failed, keep trying */
|
/* longpoll failed, keep trying */
|
||||||
}
|
}
|
||||||
|
json_decref(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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 unsigned char *scrypt_buffer_alloc();
|
||||||
extern int scanhash_scrypt(int, unsigned char *pdata, unsigned char *scratchbuf,
|
extern int scanhash_scrypt(int, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
const unsigned char *ptarget,
|
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
|
extern int
|
||||||
timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
|
timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
|
||||||
|
@ -141,6 +141,7 @@ extern int opt_scantime;
|
||||||
extern int opt_timeout;
|
extern int opt_timeout;
|
||||||
extern bool want_longpoll;
|
extern bool want_longpoll;
|
||||||
extern bool have_longpoll;
|
extern bool have_longpoll;
|
||||||
|
extern int opt_n_threads;
|
||||||
struct thread_q;
|
struct thread_q;
|
||||||
|
|
||||||
struct work_restart {
|
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,
|
int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
const unsigned char *ptarget,
|
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];
|
uint32_t data[20], hash[8];
|
||||||
#ifdef SCRYPT_3WAY
|
#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];
|
uint32_t data3[20], hash3[8];
|
||||||
int throughput;
|
int throughput;
|
||||||
#endif
|
#endif
|
||||||
uint32_t n = 0;
|
unsigned long c = 0;
|
||||||
|
uint32_t n = *next_nonce;
|
||||||
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
|
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
work_restart[thr_id].restart = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < 19; i++)
|
for (i = 0; i < 19; i++)
|
||||||
data[i] = be32dec(&((const uint32_t *)pdata)[i]);
|
data[i] = be32dec(&((const uint32_t *)pdata)[i]);
|
||||||
#ifdef SCRYPT_3WAY
|
#ifdef SCRYPT_3WAY
|
||||||
|
@ -535,16 +534,23 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
data[19] = n++;
|
data[19] = n;
|
||||||
|
n += opt_n_threads;
|
||||||
|
++c;
|
||||||
#ifdef SCRYPT_3WAY
|
#ifdef SCRYPT_3WAY
|
||||||
if (throughput >= 2 && n < max_nonce) {
|
if (throughput >= 2 && n <= max_nonce) {
|
||||||
data2[19] = n++;
|
data2[19] = n;
|
||||||
if (throughput >= 3 && n < max_nonce) {
|
n += opt_n_threads;
|
||||||
data3[19] = n++;
|
++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);
|
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)) {
|
if (hash3[7] < Htarg || hash3[7] == Htarg && test_hash(hash3, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data3[19]);
|
be32enc(&((uint32_t *)pdata)[19], data3[19]);
|
||||||
*hashes_done = n;
|
*next_nonce = n;
|
||||||
|
*hashes_done = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} 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)) {
|
if (hash2[7] < Htarg || hash2[7] == Htarg && test_hash(hash2, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data2[19]);
|
be32enc(&((uint32_t *)pdata)[19], data2[19]);
|
||||||
*hashes_done = n;
|
*next_nonce = n;
|
||||||
|
*hashes_done = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} 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)) {
|
if (hash[7] < Htarg || hash[7] == Htarg && test_hash(hash, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data[19]);
|
be32enc(&((uint32_t *)pdata)[19], data[19]);
|
||||||
*hashes_done = n;
|
*next_nonce = n;
|
||||||
|
*hashes_done = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((n >= max_nonce) || work_restart[thr_id].restart) {
|
if ((n > max_nonce) || work_restart[thr_id].restart)
|
||||||
*hashes_done = n;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
*next_nonce = n;
|
||||||
|
*hashes_done = c;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue