Commit 5007805d1f1893e3a8bdefcdce8089739bf66200

Con Kolivas 2011-07-03T19:10:59

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.

diff --git a/cpu-miner.c b/cpu-miner.c
index 7fbb412..b0593bd 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 b7c3c9e..56c0d7b 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 b13f86d..c81e05b 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 4a8785e..b2217b8 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 5d70b55..683e069 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 eb6ae8f..08ae12d 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 aa72055..f12e447 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;