Browse Source

Use multi-part batched SPI transfers for flushes (saves 2 secs on each flush)

Vitalii Demianets 11 years ago
parent
commit
318850075e
4 changed files with 97 additions and 8 deletions
  1. 25 7
      driver-titan.c
  2. 1 1
      knc-asic
  3. 70 0
      titan-asic.c
  4. 1 0
      titan-asic.h

+ 25 - 7
driver-titan.c

@@ -537,9 +537,11 @@ static void knc_titan_poll(struct thr_info * const thr)
 	int die;
 	int die;
 	int i, tmp_int;
 	int i, tmp_int;
 	struct knc_titan_die *die_p;
 	struct knc_titan_die *die_p;
-	struct timeval tv_now;
+	struct timeval tv_now, tv_prev;
+	bool any_was_flushed = false;
 
 
 	knc_titan_prune_local_queue(thr);
 	knc_titan_prune_local_queue(thr);
+	timer_set_now(&tv_prev);
 
 
 	for (asic = 0; asic < KNC_TITAN_MAX_ASICS; ++asic) {
 	for (asic = 0; asic < KNC_TITAN_MAX_ASICS; ++asic) {
 		for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
 		for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
@@ -558,20 +560,31 @@ static void knc_titan_poll(struct thr_info * const thr)
 					bool unused;
 					bool unused;
 					if (die_p->broadcast_flushes) {
 					if (die_p->broadcast_flushes) {
 						/* Use broadcast */
 						/* Use broadcast */
-						if (knc_titan_set_work(proc->proc_repr, knc->ctx, asic, die, ALL_CORES, die_p->next_slot, work, true, &unused, &report)) {
+						if (knc_titan_set_work(first_proc->device->dev_repr, knc->ctx, asic, die, ALL_CORES, die_p->next_slot, work, true, &unused, &report)) {
 							work_accepted = true;
 							work_accepted = true;
 						}
 						}
 					} else {
 					} else {
 						/* Use unicasts */
 						/* Use unicasts */
+						bool work_acc_arr[die_p->cores];
+						struct knc_report reports[die_p->cores];
 						for (proc = first_proc; proc; proc = proc->next_proc) {
 						for (proc = first_proc; proc; proc = proc->next_proc) {
 							mythr = proc->thr[0];
 							mythr = proc->thr[0];
 							core1 = mythr->cgpu_data;
 							core1 = mythr->cgpu_data;
 							if ((core1->dieno != die) || (core1->asicno != asic))
 							if ((core1->dieno != die) || (core1->asicno != asic))
 								break;
 								break;
-							if (knc_titan_set_work(proc->proc_repr, knc->ctx, asic, die, core1->coreno, die_p->next_slot, work, true, &unused, &report)) {
-								core1->last_nonce.slot = report.nonce[0].slot;
-								core1->last_nonce.nonce = report.nonce[0].nonce;
-								work_accepted = true;
+							work_acc_arr[core1->coreno] = false;
+						}
+						if (knc_titan_set_work_multi(first_proc->device->dev_repr, knc->ctx, asic, die, 0, die_p->next_slot, work, true, work_acc_arr, reports, die_p->cores)) {
+							for (proc = first_proc; proc; proc = proc->next_proc) {
+								mythr = proc->thr[0];
+								core1 = mythr->cgpu_data;
+								if ((core1->dieno != die) || (core1->asicno != asic))
+									break;
+								if (work_acc_arr[core1->coreno]) {
+									core1->last_nonce.slot = reports[core1->coreno].nonce[0].slot;
+									core1->last_nonce.nonce = reports[core1->coreno].nonce[0].nonce;
+									work_accepted = true;
+								}
 							}
 							}
 						}
 						}
 					}
 					}
@@ -598,6 +611,7 @@ static void knc_titan_poll(struct thr_info * const thr)
 					}
 					}
 					delay_usecs = 0;
 					delay_usecs = 0;
 					was_flushed = true;
 					was_flushed = true;
+					any_was_flushed = true;
 				}
 				}
 				--knc->workqueue_size;
 				--knc->workqueue_size;
 				DL_DELETE(knc->workqueue, work);
 				DL_DELETE(knc->workqueue, work);
@@ -617,6 +631,10 @@ static void knc_titan_poll(struct thr_info * const thr)
 
 
 	applog(LOG_DEBUG, "%s: %d jobs accepted to queue (max=%d)", knc_titan_drv.dname, workaccept, knc->workqueue_max);
 	applog(LOG_DEBUG, "%s: %d jobs accepted to queue (max=%d)", knc_titan_drv.dname, workaccept, knc->workqueue_max);
 	timer_set_now(&tv_now);
 	timer_set_now(&tv_now);
+	if (any_was_flushed) {
+		double diff = ((tv_now.tv_sec - tv_prev.tv_sec) * 1000000.0 + (tv_now.tv_usec - tv_prev.tv_usec)) / 1000000.0;
+		applog(LOG_INFO, "%s: Flush took %f secs", knc_titan_drv.dname, diff);
+	}
 
 
 	for (asic = 0; asic < KNC_TITAN_MAX_ASICS; ++asic) {
 	for (asic = 0; asic < KNC_TITAN_MAX_ASICS; ++asic) {
 		for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
 		for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
@@ -644,7 +662,7 @@ static void knc_titan_poll(struct thr_info * const thr)
 					tmp_int = MAKE_WORKID(asic, die, report.nonce[i].slot);
 					tmp_int = MAKE_WORKID(asic, die, report.nonce[i].slot);
 					HASH_FIND_INT(knc->devicework, &tmp_int, work);
 					HASH_FIND_INT(knc->devicework, &tmp_int, work);
 					if (!work) {
 					if (!work) {
-						applog(LOG_WARNING, "%"PRIpreprv": Got nonce for unknown work in slot %u (asic %d)", proc->proc_repr, (unsigned)report.nonce[i].slot, asic);
+						applog(LOG_WARNING, "%"PRIpreprv"[%d:%d:%d]: Got nonce for unknown work in slot %u", proc->proc_repr, asic, die, knccore->coreno, (unsigned)report.nonce[i].slot);
 						continue;
 						continue;
 					}
 					}
 					if (submit_nonce(mythr, work, report.nonce[i].nonce)) {
 					if (submit_nonce(mythr, work, report.nonce[i].nonce)) {

+ 1 - 1
knc-asic

@@ -1 +1 @@
-Subproject commit 0d43f1d990d2b3a956d50948140ac604055247cb
+Subproject commit 6a5c83c4a576a17d5663464e01bb8609b20b0161

+ 70 - 0
titan-asic.c

@@ -52,6 +52,76 @@ bool knc_titan_set_work(const char *repr, void * const ctx, int channel, int die
 	return true;
 	return true;
 }
 }
 
 
+bool knc_titan_set_work_multi(const char *repr, void * const ctx, int channel, int die, int core_start, int slot, struct work *work, bool urgent, bool *work_accepted, struct knc_report *reports, int num)
+{
+	int REQUEST_BUFSIZE = 4 + 1 + BLOCK_HEADER_BYTES_WITHOUT_NONCE;
+	uint8_t *requests = malloc(REQUEST_BUFSIZE * num);
+	if (NULL == requests)
+		goto exit_err;
+	int RESPONSE_BUFSIZE = 1 + 1 + (1 + 4) * 5;
+	uint8_t *responses = malloc(RESPONSE_BUFSIZE * num);
+	if (NULL == responses)
+		goto exit_err;
+	int *request_lengths = malloc(num * sizeof(int));
+	if (NULL == request_lengths)
+		goto exit_err;
+	int *response_lengths = malloc(num * sizeof(int));
+	if (NULL == response_lengths)
+		goto exit_err;
+	int *statuses = malloc(num * sizeof(int));
+	if (NULL == statuses)
+		goto exit_err;
+	int i, core;
+
+	for (i = 0, core = core_start; i < num; ++i, ++core) {
+		request_lengths[i] = knc_prepare_titan_setwork(&requests[REQUEST_BUFSIZE * i], die, core, slot, work, urgent);
+		response_lengths[i] = RESPONSE_BUFSIZE;
+		statuses[i] = KNC_ERR_UNAVAIL;
+	}
+
+	knc_syncronous_transfer_multi(ctx, channel, request_lengths, REQUEST_BUFSIZE, requests, response_lengths, RESPONSE_BUFSIZE, responses, statuses, num);
+
+	for (i = 0, core = core_start; i < num; ++i, ++core) {
+		uint8_t *response = &responses[RESPONSE_BUFSIZE * i];
+		if (statuses[i] == KNC_ACCEPTED) {
+			work_accepted[i] = true;
+		} else {
+			work_accepted[i] = false;
+			if (response[0] == 0x7f) {
+				applog(LOG_DEBUG, "%s[%d:%d:%d]: Core disabled", repr, channel, die, core);
+				continue;
+			}
+			if (statuses[i] & KNC_ERR_MASK) {
+				applog(LOG_INFO, "%s[%d:%d:%d]: Failed to set work state (%x)", repr, channel, die, core, statuses[i]);
+				continue;
+			}
+			if (!(statuses[i] & KNC_ERR_MASK)) {
+				applog(LOG_DEBUG, "%s[%d:%d:%d]: Core busy (%x)", repr, channel, die, core, statuses[i]);
+			}
+		}
+		knc_decode_report(response, &reports[i], KNC_VERSION_TITAN);
+	}
+
+	free(response_lengths);
+	free(request_lengths);
+	free(statuses);
+	free(responses);
+	free(requests);
+	return true;
+exit_err:
+	if (NULL != response_lengths)
+		free(response_lengths);
+	if (NULL != request_lengths)
+		free(request_lengths);
+	if (NULL != statuses)
+		free(statuses);
+	if (NULL != responses)
+		free(responses);
+	if (NULL != requests)
+		free(requests);
+	return false;
+}
+
 bool knc_titan_get_report(const char *repr, void * const ctx, int channel, int die, int core, struct knc_report *report)
 bool knc_titan_get_report(const char *repr, void * const ctx, int channel, int die, int core, struct knc_report *report)
 {
 {
 	uint8_t request[4];
 	uint8_t request[4];

+ 1 - 0
titan-asic.h

@@ -23,6 +23,7 @@ struct nonce_report {
 
 
 bool knc_titan_get_info(const char *repr, void * const ctx, int channel, int die, struct knc_die_info *die_info);
 bool knc_titan_get_info(const char *repr, void * const ctx, int channel, int die, struct knc_die_info *die_info);
 bool knc_titan_set_work(const char *repr, void * const ctx, int channel, int die, int core, int slot, struct work *work, bool urgent, bool *work_accepted, struct knc_report *report);
 bool knc_titan_set_work(const char *repr, void * const ctx, int channel, int die, int core, int slot, struct work *work, bool urgent, bool *work_accepted, struct knc_report *report);
+bool knc_titan_set_work_multi(const char *repr, void * const ctx, int channel, int die, int core_start, int slot, struct work *work, bool urgent, bool *work_accepted, struct knc_report *reports, int num);
 bool knc_titan_get_report(const char *repr, void * const ctx, int channel, int die, int core, struct knc_report *report);
 bool knc_titan_get_report(const char *repr, void * const ctx, int channel, int die, int core, struct knc_report *report);
 bool knc_titan_setup_core_local(const char *repr, void * const ctx, int channel, int die, int core, struct titan_setup_core_params *params);
 bool knc_titan_setup_core_local(const char *repr, void * const ctx, int channel, int die, int core, struct titan_setup_core_params *params);