From 5007805d1f1893e3a8bdefcdce8089739bf66200 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 3 Jul 2011 19:10:59 +1000 Subject: [PATCH] Update CPU reentrant scan code to work properly for extended periods up to scantime and adjust rate properly. Simplify locking in hashmeter since it's called relatively infrequently anyway. Set gpuminer hashmeter interval update to log interval / 5 as well. --- cpu-miner.c | 76 ++++++++++++++++++++++++--------------------- miner.h | 11 ++++--- sha256_4way.c | 4 +-- sha256_cryptopp.c | 4 +-- sha256_generic.c | 4 +-- sha256_sse2_amd64.c | 4 +-- sha256_via.c | 4 +-- 7 files changed, 56 insertions(+), 51 deletions(-) diff --git a/cpu-miner.c b/cpu-miner.c index 7fbb412d..b0593bdf 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -662,29 +662,20 @@ static void hashmeter(int thr_id, struct timeval *diff, if (opt_debug) applog(LOG_DEBUG, "[thread %d: %lu hashes, %.0f khash/sec]", thr_id, hashes_done, hashes_done / secs); + + /* Totals are updated by all threads so can race without locking */ + pthread_mutex_lock(&hash_lock); gettimeofday(&temp_tv_end, NULL); timeval_subtract(&total_diff, &temp_tv_end, &total_tv_end); local_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0); - if (opt_n_threads + gpu_threads > 1) { - /* Totals are updated by all threads so can race without locking */ - pthread_mutex_lock(&hash_lock); - total_mhashes_done += local_mhashes; - local_mhashes_done += local_mhashes; - if (total_diff.tv_sec < opt_log_interval) { - /* Only update the total every opt_log_interval seconds */ - pthread_mutex_unlock(&hash_lock); - return; - } - gettimeofday(&total_tv_end, NULL); - pthread_mutex_unlock(&hash_lock); - } else { - total_mhashes_done += local_mhashes; - local_mhashes_done += local_mhashes; - if (total_diff.tv_sec < opt_log_interval) - return; - gettimeofday(&total_tv_end, NULL); - } + total_mhashes_done += local_mhashes; + local_mhashes_done += local_mhashes; + if (total_diff.tv_sec < opt_log_interval) + /* Only update the total every opt_log_interval seconds */ + goto out_unlock; + gettimeofday(&total_tv_end, NULL); + /* Use a rolling average by faking an exponential decay over 5 * log */ rolling_local = ((rolling_local * 0.9) + local_mhashes_done) / 1.9; @@ -695,6 +686,8 @@ static void hashmeter(int thr_id, struct timeval *diff, rolling_local / local_secs, total_mhashes_done / total_secs, accepted, rejected, hw_errors); local_mhashes_done = 0; +out_unlock: + pthread_mutex_unlock(&hash_lock); } /* All work is queued flagged as being for thread 0 and then the mining thread @@ -824,10 +817,8 @@ static void *miner_thread(void *userdata) const int thr_id = mythr->id; uint32_t max_nonce = 0xffffff; bool needs_work = true; - unsigned long cycle; - /* Try to cycle approximately 5 times before each log update */ - cycle = opt_log_interval / 5 ? : 1; + const unsigned long cycle = opt_log_interval / 5 ? : 1; /* Set worker threads to nice 19 and then preferentially to SCHED_IDLE * and if that fails, then SCHED_BATCH. No need for this to be an @@ -857,6 +848,7 @@ static void *miner_thread(void *userdata) } work.thr_id = thr_id; needs_work = false; + work.blk.nonce = 0; } hashes_done = 0; gettimeofday(&tv_start, NULL); @@ -866,7 +858,8 @@ static void *miner_thread(void *userdata) case ALGO_C: rc = scanhash_c(thr_id, work.midstate, work.data + 64, work.hash1, work.hash, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); break; #ifdef WANT_X8664_SSE2 @@ -875,7 +868,8 @@ static void *miner_thread(void *userdata) scanhash_sse2_64(thr_id, work.midstate, work.data + 64, work.hash1, work.hash, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); rc = (rc5 == -1) ? false : true; } break; @@ -887,7 +881,8 @@ static void *miner_thread(void *userdata) ScanHash_4WaySSE2(thr_id, work.midstate, work.data + 64, work.hash1, work.hash, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); rc = (rc4 == -1) ? false : true; } break; @@ -896,20 +891,23 @@ static void *miner_thread(void *userdata) #ifdef WANT_VIA_PADLOCK case ALGO_VIA: rc = scanhash_via(thr_id, work.data, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); break; #endif case ALGO_CRYPTOPP: rc = scanhash_cryptopp(thr_id, work.midstate, work.data + 64, work.hash1, work.hash, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); break; #ifdef WANT_CRYPTOPP_ASM32 case ALGO_CRYPTOPP_ASM32: rc = scanhash_asm32(thr_id, work.midstate, work.data + 64, work.hash1, work.hash, work.target, - max_nonce, &hashes_done); + max_nonce, &hashes_done, + work.blk.nonce); break; #endif @@ -922,19 +920,21 @@ static void *miner_thread(void *userdata) gettimeofday(&tv_end, NULL); timeval_subtract(&diff, &tv_end, &tv_start); + hashes_done -= work.blk.nonce; hashmeter(thr_id, &diff, hashes_done); work.blk.nonce += hashes_done; /* adjust max_nonce to meet target cycle time */ if (diff.tv_usec > 500000) diff.tv_sec++; - if (diff.tv_sec > 0) { - max64 = - ((uint64_t)hashes_done * cycle) / diff.tv_sec; - if (max64 > 0xfffffffaULL) - max64 = 0xfffffffaULL; - max_nonce = max64; - } + if (diff.tv_sec != cycle) { + max64 = work.blk.nonce + + ((uint64_t)hashes_done * cycle) / diff.tv_sec; + } else + max64 = work.blk.nonce + hashes_done; + if (max64 > 0xfffffffaULL) + max64 = 0xfffffffaULL; + max_nonce = max64; /* if nonce found, submit work */ if (unlikely(rc)) { @@ -942,6 +942,7 @@ static void *miner_thread(void *userdata) applog(LOG_DEBUG, "CPU %d found something?", cpu_from_thr_id(thr_id)); if (unlikely(!submit_work_sync(mythr, &work))) break; + work.blk.nonce += 4; } timeval_subtract(&diff, &tv_end, &tv_workstart); @@ -1017,6 +1018,7 @@ static inline int gpu_from_thr_id(int thr_id) static void *gpuminer_thread(void *userdata) { + const unsigned long cycle = opt_log_interval / 5 ? : 1; struct thr_info *mythr = userdata; struct timeval tv_start, diff; const int thr_id = mythr->id; @@ -1113,7 +1115,9 @@ static void *gpuminer_thread(void *userdata) timeval_subtract(&diff, &tv_end, &tv_start); hashes_done += hashes; work->blk.nonce += hashes; - if (diff.tv_sec >= 1) { + if (diff.tv_usec > 500000) + diff.tv_sec++; + if (diff.tv_sec >= cycle) { hashmeter(thr_id, &diff, hashes_done); gettimeofday(&tv_start, NULL); hashes_done = 0; diff --git a/miner.h b/miner.h index b7c3c9e6..56c0d7b4 100644 --- a/miner.h +++ b/miner.h @@ -160,7 +160,7 @@ extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern unsigned int ScanHash_4WaySSE2(int, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, - uint32_t max_nonce, unsigned long *nHashesDone); + uint32_t max_nonce, unsigned long *nHashesDone, uint32_t nonce); extern unsigned int scanhash_sse2_amd64(int, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, @@ -169,16 +169,16 @@ extern unsigned int scanhash_sse2_amd64(int, const unsigned char *pmidstate, extern bool scanhash_via(int, unsigned char *data_inout, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done); + uint32_t max_nonce, unsigned long *hashes_done, uint32_t n); extern bool scanhash_c(int, const unsigned char *midstate, unsigned char *data, unsigned char *hash1, unsigned char *hash, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done); + uint32_t max_nonce, unsigned long *hashes_done, uint32_t n); extern bool scanhash_cryptopp(int, const unsigned char *midstate,unsigned char *data, unsigned char *hash1, unsigned char *hash, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done); + uint32_t max_nonce, unsigned long *hashes_done, uint32_t n); extern bool scanhash_asm32(int, const unsigned char *midstate,unsigned char *data, unsigned char *hash1, unsigned char *hash, const unsigned char *target, @@ -186,7 +186,8 @@ extern bool scanhash_asm32(int, const unsigned char *midstate,unsigned char *dat extern int scanhash_sse2_64(int, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, - uint32_t max_nonce, unsigned long *nHashesDone); + uint32_t max_nonce, unsigned long *nHashesDone, + uint32_t nonce); extern int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); diff --git a/sha256_4way.c b/sha256_4way.c index b13f86de..c81e05b9 100644 --- a/sha256_4way.c +++ b/sha256_4way.c @@ -105,10 +105,10 @@ unsigned int ScanHash_4WaySSE2(int thr_id, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, - uint32_t max_nonce, unsigned long *nHashesDone) + uint32_t max_nonce, unsigned long *nHashesDone, + uint32_t nonce) { unsigned int *nNonce_p = (unsigned int*)(pdata + 12); - unsigned int nonce = 0; work_restart[thr_id].restart = 0; diff --git a/sha256_cryptopp.c b/sha256_cryptopp.c index 4a8785e7..b2217b8d 100644 --- a/sha256_cryptopp.c +++ b/sha256_cryptopp.c @@ -97,11 +97,11 @@ bool scanhash_cryptopp(int thr_id, const unsigned char *midstate, unsigned char *data, unsigned char *hash1, unsigned char *hash, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done) + uint32_t max_nonce, unsigned long *hashes_done, + uint32_t n) { uint32_t *hash32 = (uint32_t *) hash; uint32_t *nonce = (uint32_t *)(data + 12); - uint32_t n = 0; unsigned long stat_ctr = 0; work_restart[thr_id].restart = 0; diff --git a/sha256_generic.c b/sha256_generic.c index 5d70b558..683e0697 100644 --- a/sha256_generic.c +++ b/sha256_generic.c @@ -242,11 +242,11 @@ const uint32_t sha256_init_state[8] = { bool scanhash_c(int thr_id, const unsigned char *midstate, unsigned char *data, unsigned char *hash1, unsigned char *hash, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done) + uint32_t max_nonce, unsigned long *hashes_done, + uint32_t n) { uint32_t *hash32 = (uint32_t *) hash; uint32_t *nonce = (uint32_t *)(data + 12); - uint32_t n = 0; unsigned long stat_ctr = 0; work_restart[thr_id].restart = 0; diff --git a/sha256_sse2_amd64.c b/sha256_sse2_amd64.c index eb6ae8f4..08ae12d1 100644 --- a/sha256_sse2_amd64.c +++ b/sha256_sse2_amd64.c @@ -53,10 +53,10 @@ int scanhash_sse2_64(int thr_id, const unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, const unsigned char *ptarget, - uint32_t max_nonce, unsigned long *nHashesDone) + uint32_t max_nonce, unsigned long *nHashesDone, + uint32_t nonce) { uint32_t *nNonce_p = (uint32_t *)(pdata + 12); - uint32_t nonce = 0; uint32_t m_midstate[8], m_w[16], m_w1[16]; __m128i m_4w[64], m_4hash[64], m_4hash1[64]; __m128i offset; diff --git a/sha256_via.c b/sha256_via.c index aa72055d..f12e4472 100644 --- a/sha256_via.c +++ b/sha256_via.c @@ -21,7 +21,8 @@ static void via_sha256(void *hash, void *buf, unsigned len) bool scanhash_via(int thr_id, unsigned char *data_inout, const unsigned char *target, - uint32_t max_nonce, unsigned long *hashes_done) + uint32_t max_nonce, unsigned long *hashes_done, + uint32_t n) { unsigned char data[128] __attribute__((aligned(128))); unsigned char tmp_hash[32] __attribute__((aligned(128))); @@ -29,7 +30,6 @@ bool scanhash_via(int thr_id, unsigned char *data_inout, uint32_t *data32 = (uint32_t *) data; uint32_t *hash32 = (uint32_t *) tmp_hash; uint32_t *nonce = (uint32_t *)(data + 64 + 12); - uint32_t n = 0; unsigned long stat_ctr = 0; int i;