diff --git a/README b/README index 55fb74f1..fbbeb035 100644 --- a/README +++ b/README @@ -1045,6 +1045,10 @@ A: Your driver setup is failing to properly use the accessory GPUs. Your driver may be configured wrong or you have a driver version that needs a dummy plug on all the GPUs that aren't connected to a monitor. +Q: Should I use crossfire/SLI? +A: It does not benefit mining at all and depending on the GPU may actually +worsen performance. + Q: I have some random GPU performance related problem not addressed above. A: Seriously, it's the driver and/or SDK. Uninstall them and start again, noting there is no clean way to uninstall them so you have to use extra tools diff --git a/cgminer.c b/cgminer.c index 664ca99c..046f4a25 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2298,6 +2298,8 @@ static void reject_pool(struct pool *pool) pool->enabled = POOL_REJECTING; } +static void restart_threads(void); + /* Theoretically threads could race when modifying accepted and * rejected values but the chance of two submits completing at the * same time is zero so there is no point adding extra locking */ @@ -2351,6 +2353,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, enable_pool(pool); switch_pools(NULL); } + /* If we know we found the block we know better than anyone + * that new work is needed. */ + if (unlikely(work->block)) + restart_threads(); } else { mutex_lock(&stats_lock); cgpu->rejected++; @@ -5515,7 +5521,18 @@ void submit_work_async(struct work *work_in, struct timeval *tv_work_found) quit(1, "Failed to create submit_work_thread"); } -static bool hashtest(struct thr_info *thr, struct work *work) +void inc_hw_errors(struct thr_info *thr) +{ + mutex_lock(&stats_lock); + hw_errors++; + thr->cgpu->hw_errors++; + mutex_unlock(&stats_lock); + + thr->cgpu->drv->hw_error(thr); +} + +/* Returns 1 if meets difficulty target, 0 if not, -1 if hw error */ +static int hashtest(struct thr_info *thr, struct work *work) { uint32_t *data32 = (uint32_t *)(work->data); unsigned char swap[80]; @@ -5523,7 +5540,6 @@ static bool hashtest(struct thr_info *thr, struct work *work) unsigned char hash1[32]; unsigned char hash2[32]; uint32_t *hash2_32 = (uint32_t *)hash2; - bool ret = false; flip80(swap32, data32); sha2(swap, 80, hash1); @@ -5534,35 +5550,25 @@ static bool hashtest(struct thr_info *thr, struct work *work) applog(LOG_WARNING, "%s%d: invalid nonce - HW error", thr->cgpu->drv->name, thr->cgpu->device_id); - mutex_lock(&stats_lock); - hw_errors++; - thr->cgpu->hw_errors++; - mutex_unlock(&stats_lock); - - thr->cgpu->drv->hw_error(thr); - - goto out; + return -1; } - mutex_lock(&stats_lock); - thr->cgpu->last_device_valid_work = time(NULL); - mutex_unlock(&stats_lock); - - ret = fulltest(hash2, work->target); - if (!ret) { + if (!fulltest(hash2, work->target)) { applog(LOG_INFO, "Share below target"); /* Check the diff of the share, even if it didn't reach the * target, just to set the best share value if it's higher. */ share_diff(work); + return 0; } -out: - return ret; + + return 1; } void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) { uint32_t *work_nonce = (uint32_t *)(work->data + 64 + 12); struct timeval tv_work_found; + int valid; gettimeofday(&tv_work_found, NULL); *work_nonce = htole32(nonce); @@ -5574,10 +5580,22 @@ void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) mutex_unlock(&stats_lock); /* Do one last check before attempting to submit the work */ - if (!opt_scrypt && !hashtest(thr, work)) - return; + if (opt_scrypt) + valid = scrypt_test(work->data, work->target, nonce); + else + valid = hashtest(thr, work); - submit_work_async(work, &tv_work_found); + if (unlikely(valid == -1)) + return inc_hw_errors(thr); + + mutex_lock(&stats_lock); + thr->cgpu->last_device_valid_work = time(NULL); + mutex_unlock(&stats_lock); + + if (valid == 1) + submit_work_async(work, &tv_work_found); + else + applog(LOG_INFO, "Share below target"); } static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64_t hashes) @@ -6967,7 +6985,7 @@ struct _cgpu_devid_counter { UT_hash_handle hh; }; -bool add_cgpu(struct cgpu_info*cgpu) +bool add_cgpu(struct cgpu_info *cgpu) { static struct _cgpu_devid_counter *devids = NULL; struct _cgpu_devid_counter *d; @@ -6986,6 +7004,10 @@ bool add_cgpu(struct cgpu_info*cgpu) devices = realloc(devices, sizeof(struct cgpu_info *) * (total_devices + new_devices + 2)); wr_unlock(&devices_lock); + mutex_lock(&stats_lock); + cgpu->last_device_valid_work = time(NULL); + mutex_unlock(&stats_lock); + if (hotplug_mode) devices[total_devices + new_devices++] = cgpu; else diff --git a/driver-cpu.c b/driver-cpu.c index 6e563c5b..8f8b0d1f 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -75,7 +75,6 @@ static inline void affine_to_cpu(int __maybe_unused id, int __maybe_unused cpu) /* TODO: resolve externals */ -extern void submit_work_async(const struct work *work_in, struct timeval *tv); extern char *set_int_range(const char *arg, int *i, int min, int max); extern int dev_from_id(int thr_id); @@ -764,6 +763,8 @@ static void cpu_detect() cgpu->deven = DEV_ENABLED; cgpu->threads = 1; cgpu->kname = algo_names[opt_algo]; + if (opt_scrypt) + cgpu->drv->max_diff = 0xffffffff; add_cgpu(cgpu); } } @@ -833,7 +834,7 @@ CPUSearch: /* if nonce found, submit work */ if (unlikely(rc)) { applog(LOG_DEBUG, "CPU %d found something?", dev_from_id(thr_id)); - submit_work_async(work, NULL); + submit_nonce(thr, work, last_nonce); work->blk.nonce = last_nonce + 1; goto CPUSearch; } diff --git a/findnonce.c b/findnonce.c index e99b7e1b..2f9d27a7 100644 --- a/findnonce.c +++ b/findnonce.c @@ -179,19 +179,6 @@ struct pc_data { int found; }; -static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce) -{ - struct thr_info *thr = pcd->thr; - struct work *work = pcd->work; - - if (scrypt_test(work->data, work->target, nonce)) - submit_nonce(thr, work, nonce); - else { - applog(LOG_INFO, "Scrypt error, review settings"); - thr->cgpu->hw_errors++; - } -} - static void *postcalc_hash(void *userdata) { struct pc_data *pcd = (struct pc_data *)userdata; @@ -214,10 +201,7 @@ static void *postcalc_hash(void *userdata) uint32_t nonce = pcd->res[entry]; applog(LOG_DEBUG, "OCL NONCE %u found in slot %d", nonce, entry); - if (opt_scrypt) - send_scrypt_nonce(pcd, nonce); - else - submit_nonce(thr, pcd->work, nonce); + submit_nonce(thr, pcd->work, nonce); } discard_work(pcd->work); diff --git a/miner.h b/miner.h index 3d275daf..c992cce2 100644 --- a/miner.h +++ b/miner.h @@ -1201,6 +1201,7 @@ struct modminer_fpga_state { #endif extern void get_datestamp(char *, struct timeval *); +extern void inc_hw_errors(struct thr_info *thr); extern void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); extern struct work *get_queued(struct cgpu_info *cgpu); extern struct work *__find_work_bymidstate(struct work *que, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen); diff --git a/scrypt.c b/scrypt.c index e0af4f0f..da334df5 100644 --- a/scrypt.c +++ b/scrypt.c @@ -419,10 +419,12 @@ void scrypt_regenhash(struct work *work) flip32(ohash, ohash); } +static const uint32_t diff1targ = 0x0000ffff; + /* Used externally as confirmation of correct OCL code */ -bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce) +int scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce) { - uint32_t tmp_hash7, Htarg = ((const uint32_t *)ptarget)[7]; + uint32_t tmp_hash7, Htarg = le32toh(((const uint32_t *)ptarget)[7]); uint32_t data[20], ohash[8]; char *scratchbuf; @@ -432,7 +434,12 @@ bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t no scrypt_1024_1_1_256_sp(data, scratchbuf, ohash); tmp_hash7 = be32toh(ohash[7]); - return (tmp_hash7 <= Htarg); + applog(LOG_DEBUG, "harget %08lx diff1 %08lx hash %08lx", Htarg, diff1targ, tmp_hash7); + if (tmp_hash7 > diff1targ) + return -1; + if (tmp_hash7 > Htarg) + return 0; + return 1; } bool scanhash_scrypt(struct thr_info *thr, const unsigned char __maybe_unused *pmidstate, @@ -444,7 +451,7 @@ bool scanhash_scrypt(struct thr_info *thr, const unsigned char __maybe_unused *p char *scratchbuf; uint32_t data[20]; uint32_t tmp_hash7; - uint32_t Htarg = ((const uint32_t *)ptarget)[7]; + uint32_t Htarg = le32toh(((const uint32_t *)ptarget)[7]); bool ret = false; be32enc_vect(data, (const uint32_t *)pdata, 19); @@ -459,7 +466,7 @@ bool scanhash_scrypt(struct thr_info *thr, const unsigned char __maybe_unused *p uint32_t ostate[8]; *nonce = ++n; - data[19] = n; + data[19] = htobe32(n); scrypt_1024_1_1_256_sp(data, scratchbuf, ostate); tmp_hash7 = be32toh(ostate[7]); diff --git a/scrypt.h b/scrypt.h index c7b85387..8f3d2190 100644 --- a/scrypt.h +++ b/scrypt.h @@ -4,16 +4,16 @@ #include "miner.h" #ifdef USE_SCRYPT -extern bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget, +extern int scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce); extern void scrypt_regenhash(struct work *work); #else /* USE_SCRYPT */ -static inline bool scrypt_test(__maybe_unused unsigned char *pdata, +static inline int scrypt_test(__maybe_unused unsigned char *pdata, __maybe_unused const unsigned char *ptarget, __maybe_unused uint32_t nonce) { - return false; + return 0; } static inline void scrypt_regenhash(__maybe_unused struct work *work)