diff --git a/cpu-miner.c b/cpu-miner.c index e487c583..cb707c06 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -32,7 +32,7 @@ #include "sha256_generic.c" enum { - STAT_SLEEP_INTERVAL = 10, + STAT_SLEEP_INTERVAL = 100, STAT_CTR_INTERVAL = 10000000, }; @@ -47,8 +47,6 @@ static bool program_running = true; static const bool opt_time = true; static enum sha256_algos opt_algo = ALGO_C; static int opt_n_threads = 1; -static pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER; -static uint64_t hash_ctr; static char *rpc_url = DEF_RPC_URL; static char *userpass = DEF_RPC_USERPASS; @@ -200,13 +198,22 @@ out: free(hexstr); } -static void inc_stats(uint64_t n_hashes) +static void hashmeter(int thr_id, struct timeval *tv_start, + unsigned long hashes_done) { - pthread_mutex_lock(&stats_mutex); + struct timeval tv_end, diff; + double khashes, secs; - hash_ctr += n_hashes; + gettimeofday(&tv_end, NULL); - pthread_mutex_unlock(&stats_mutex); + timeval_subtract(&diff, &tv_end, tv_start); + + khashes = hashes_done / 1000.0; + secs = (double)diff.tv_sec + ((double)diff.tv_usec / 1000000.0); + + printf("HashMeter(%d): %lu hashes, %.2f khash/sec\n", + thr_id, hashes_done, + khashes / secs); } static void runhash(void *state, void *input, const void *init) @@ -222,7 +229,8 @@ static const uint32_t init_state[8] = { /* suspiciously similar to ScanHash* from bitcoin */ static bool scanhash(unsigned char *midstate, unsigned char *data, - unsigned char *hash1, unsigned char *hash) + unsigned char *hash1, unsigned char *hash, + unsigned long *hashes_done) { uint32_t *hash32 = (uint32_t *) hash; uint32_t *nonce = (uint32_t *)(data + 12); @@ -236,6 +244,8 @@ static bool scanhash(unsigned char *midstate, unsigned char *data, runhash(hash1, data, midstate); runhash(hash, hash1, init_state); + stat_ctr++; + if (hash32[7] == 0) { char *hexstr; @@ -245,32 +255,29 @@ static bool scanhash(unsigned char *midstate, unsigned char *data, hexstr); free(hexstr); + *hashes_done = stat_ctr; return true; } - stat_ctr++; - if (stat_ctr >= STAT_CTR_INTERVAL) { - inc_stats(STAT_CTR_INTERVAL); - stat_ctr = 0; - } - if ((n & 0xffffff) == 0) { - inc_stats(stat_ctr); - if (opt_debug) fprintf(stderr, "DBG: end of nonce range\n"); + *hashes_done = stat_ctr; return false; } } } -static void *miner_thread(void *dummy) +static void *miner_thread(void *thr_id_int) { + int thr_id = (unsigned long) thr_id_int; static const char *rpc_req = "{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n"; while (1) { struct work work __attribute__((aligned(128))); + unsigned long hashes_done; + struct timeval tv_start; json_t *val; bool rc; @@ -290,21 +297,25 @@ static void *miner_thread(void *dummy) json_decref(val); + hashes_done = 0; + gettimeofday(&tv_start, NULL); + /* scan nonces for a proof-of-work hash */ if (opt_algo == ALGO_C) rc = scanhash(work.midstate, work.data + 64, - work.hash1, work.hash); + work.hash1, work.hash, &hashes_done); #ifdef __SSE__ else { - unsigned int hashesdone = 0; unsigned int rc4 = ScanHash_4WaySSE2(work.midstate, work.data + 64, work.hash1, work.hash, - &hashesdone); + &hashes_done); rc = (rc4 == -1) ? false : true; } #endif + hashmeter(thr_id, &tv_start, hashes_done); + /* if nonce found, submit work */ if (rc) submit_work(&work); @@ -387,27 +398,6 @@ static void parse_cmdline(int argc, char *argv[]) } } -static void calc_stats(void) -{ - uint64_t hashes; - double hd, sd; - - pthread_mutex_lock(&stats_mutex); - - hashes = hash_ctr; - hash_ctr = 0; - - pthread_mutex_unlock(&stats_mutex); - - hashes = hashes / 1000; - - hd = hashes; - sd = STAT_SLEEP_INTERVAL; - - fprintf(stderr, "wildly inaccurate HashMeter: %.2f khash/sec\n", - hd / sd); -} - int main (int argc, char *argv[]) { int i; @@ -423,7 +413,8 @@ int main (int argc, char *argv[]) for (i = 0; i < opt_n_threads; i++) { pthread_t t; - if (pthread_create(&t, NULL, miner_thread, NULL)) { + if (pthread_create(&t, NULL, miner_thread, + (void *)(unsigned long) i)) { fprintf(stderr, "thread %d create failed\n", i); return 1; } @@ -436,7 +427,7 @@ int main (int argc, char *argv[]) /* main loop */ while (program_running) { sleep(STAT_SLEEP_INTERVAL); - calc_stats(); + /* do nothing */ } return 0; diff --git a/miner.h b/miner.h index b4cc9397..69c56a7d 100644 --- a/miner.h +++ b/miner.h @@ -16,6 +16,9 @@ extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern unsigned int ScanHash_4WaySSE2(unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, - unsigned int *nHashesDone); + unsigned long *nHashesDone); + +extern int +timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); #endif /* __MINER_H__ */ diff --git a/sha256_4way.c b/sha256_4way.c index 56132ff1..ddb80f68 100644 --- a/sha256_4way.c +++ b/sha256_4way.c @@ -97,7 +97,7 @@ static const unsigned int pSHA256InitState[8] = unsigned int ScanHash_4WaySSE2(unsigned char *pmidstate, unsigned char *pdata, - unsigned char *phash1, unsigned char *phash, unsigned int *nHashesDone) + unsigned char *phash1, unsigned char *phash, unsigned long *nHashesDone) { unsigned int *nNonce_p = (unsigned int*)(pdata + 12); unsigned int nonce = 0; @@ -120,6 +120,7 @@ unsigned int ScanHash_4WaySSE2(unsigned char *pmidstate, unsigned char *pdata, for (i = 0; i < 32/4; i++) ((unsigned int*)phash)[i] = thash[i][j]; + *nHashesDone = nonce; return nonce + j; } } diff --git a/util.c b/util.c index 37bd9e81..5a55a05c 100644 --- a/util.c +++ b/util.c @@ -198,3 +198,32 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len) return (len == 0 && *hexstr == 0) ? true : false; } +/* Subtract the `struct timeval' values X and Y, + storing the result in RESULT. + Return 1 if the difference is negative, otherwise 0. */ + +int +timeval_subtract ( + struct timeval *result, struct timeval *x, struct timeval *y) +{ + /* Perform the carry for the later subtraction by updating Y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + `tv_usec' is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} +