From 6b714dd431be7b3efdd8d77c585346b6a0c4dfb6 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 14:47:46 +1000 Subject: [PATCH 1/8] Increment hardware error count from the one site. --- cgminer.c | 18 +++++++++++------- findnonce.c | 6 ++---- miner.h | 1 + 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cgminer.c b/cgminer.c index 664ca99c..cbbb510d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5515,6 +5515,16 @@ void submit_work_async(struct work *work_in, struct timeval *tv_work_found) quit(1, "Failed to create submit_work_thread"); } +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); +} + static bool hashtest(struct thr_info *thr, struct work *work) { uint32_t *data32 = (uint32_t *)(work->data); @@ -5534,13 +5544,7 @@ 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); - + inc_hw_errors(thr); goto out; } diff --git a/findnonce.c b/findnonce.c index e99b7e1b..65055d9f 100644 --- a/findnonce.c +++ b/findnonce.c @@ -186,10 +186,8 @@ static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce) 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++; - } + else + inc_hw_errors(thr); } static void *postcalc_hash(void *userdata) 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); From c1ff90a7ab9c19e58df1ed6bd67a87e6e6a19421 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 15:07:32 +1000 Subject: [PATCH 2/8] Do testing for HW errors on submit nonce for both scrypt and sha. --- cgminer.c | 27 ++++++++++++++++----------- findnonce.c | 16 +--------------- scrypt.c | 8 ++++++-- scrypt.h | 6 +++--- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/cgminer.c b/cgminer.c index cbbb510d..cf1c03ab 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5525,7 +5525,8 @@ void inc_hw_errors(struct thr_info *thr) thr->cgpu->drv->hw_error(thr); } -static bool hashtest(struct thr_info *thr, struct work *work) +/* 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]; @@ -5533,7 +5534,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); @@ -5544,29 +5544,29 @@ 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); - inc_hw_errors(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); @@ -5578,10 +5578,15 @@ 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)) + inc_hw_errors(thr); + else if (valid == 1) + submit_work_async(work, &tv_work_found); } static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64_t hashes) diff --git a/findnonce.c b/findnonce.c index 65055d9f..2f9d27a7 100644 --- a/findnonce.c +++ b/findnonce.c @@ -179,17 +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 - inc_hw_errors(thr); -} - static void *postcalc_hash(void *userdata) { struct pc_data *pcd = (struct pc_data *)userdata; @@ -212,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/scrypt.c b/scrypt.c index e0af4f0f..3d92c15b 100644 --- a/scrypt.c +++ b/scrypt.c @@ -420,7 +420,7 @@ void scrypt_regenhash(struct work *work) } /* 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 data[20], ohash[8]; @@ -432,7 +432,11 @@ 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); + /* FIXME: Needs to be able to return 0 as well for not meeting target + * but target diff currently is sent to devices. */ + if (tmp_hash7 > Htarg) + return -1; + return 1; } bool scanhash_scrypt(struct thr_info *thr, const unsigned char __maybe_unused *pmidstate, 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) From bc0e71448e53c378a02de1a49594b3d3d65955fe Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 17:14:59 +1000 Subject: [PATCH 3/8] Make scrypt submission use the submit_nonce code, with nonces matching endianness. --- driver-cpu.c | 3 +-- scrypt.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/driver-cpu.c b/driver-cpu.c index 6e563c5b..2f72abce 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); @@ -833,7 +832,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/scrypt.c b/scrypt.c index 3d92c15b..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 */ 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,10 +434,11 @@ int scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t non scrypt_1024_1_1_256_sp(data, scratchbuf, ohash); tmp_hash7 = be32toh(ohash[7]); - /* FIXME: Needs to be able to return 0 as well for not meeting target - * but target diff currently is sent to devices. */ - if (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; } @@ -448,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); @@ -463,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]); From d49ecf198e5a0b4c2ea9f639543de8050a00b15a Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 17:22:38 +1000 Subject: [PATCH 4/8] Set opt_scrypt drv max diff for correctness. --- driver-cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver-cpu.c b/driver-cpu.c index 2f72abce..8f8b0d1f 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -763,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); } } From 3fa4a9f55f6f24e8ee3d104bc1130e0f43750e68 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 17:58:58 +1000 Subject: [PATCH 5/8] Increment last device valid work count in submit_nonce to cover scrypt. --- cgminer.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cgminer.c b/cgminer.c index cf1c03ab..a2ef4d81 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5547,10 +5547,6 @@ static int hashtest(struct thr_info *thr, struct work *work) return -1; } - mutex_lock(&stats_lock); - thr->cgpu->last_device_valid_work = time(NULL); - mutex_unlock(&stats_lock); - if (!fulltest(hash2, work->target)) { applog(LOG_INFO, "Share below target"); /* Check the diff of the share, even if it didn't reach the @@ -5584,9 +5580,16 @@ void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) valid = hashtest(thr, work); if (unlikely(valid == -1)) - inc_hw_errors(thr); - else if (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) From a3bbe0e1163945c9be2084d4355f60d48298ee29 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 18 Apr 2013 18:19:35 +1000 Subject: [PATCH 6/8] Set last device valid work on adding device. --- cgminer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index a2ef4d81..2833e8aa 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6979,7 +6979,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; @@ -6998,6 +6998,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 From 76ecffbf65962a5aee17dc26ae68542d6c3a9ebb Mon Sep 17 00:00:00 2001 From: ckolivas Date: Fri, 19 Apr 2013 09:12:31 +1000 Subject: [PATCH 7/8] Add more FAQs about crossfire. --- README | 4 ++++ 1 file changed, 4 insertions(+) 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 From 5315838d2d7ab103164ea12ca1c1210a422ff179 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Fri, 19 Apr 2013 09:19:05 +1000 Subject: [PATCH 8/8] Restart threads on the rare chance we found the block ourselves. --- cgminer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cgminer.c b/cgminer.c index 2833e8aa..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++;