diff options
author | John Hawthorn <john.hawthorn@gmail.com> | 2017-01-14 21:19:45 -0800 |
---|---|---|
committer | John Hawthorn <john.hawthorn@gmail.com> | 2017-01-26 22:09:16 -0800 |
commit | 267e6a40e1cbc53d60917e5423d69f2686308f82 (patch) | |
tree | cc82061b0913b66096109536f7a36addc49c7f18 /src/choices.c | |
parent | 77a2eb52bf0022ab15f8c2ab2f645d22a227e5dd (diff) |
Perform sort in parallel
Diffstat (limited to 'src/choices.c')
-rw-r--r-- | src/choices.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/src/choices.c b/src/choices.c index 1431551..150ce94 100644 --- a/src/choices.c +++ b/src/choices.c @@ -193,9 +193,48 @@ static void *choices_search_worker(void *data) { } } + /* Sort the partial result */ + qsort(w->results, w->available, sizeof(struct scored_result), cmpchoice); + return w; } +static void merge_step(struct search_job *job, struct worker *all_workers) { + /* Merge our sorted partial-results */ + choices_t *c = job->choices; + size_t worker_count = 0; + struct worker *workers[c->worker_count]; + size_t indexes[c->worker_count]; + + for (unsigned int w = 0; w < c->worker_count; w++) { + indexes[w] = 0; + if (all_workers[w].available) { + workers[worker_count++] = &all_workers[w]; + } + } + + while (worker_count) { + /* Loop over each sorted block to find the lowest scoring result */ + unsigned int min_w = 0; + for (unsigned int w = 0; w < worker_count; w++) { + if (cmpchoice(&workers[w]->results[indexes[w]], &workers[min_w]->results[indexes[min_w]]) < 0) { + min_w = w; + } + } + + /* Move that result onto our global list */ + c->results[c->available++] = workers[min_w]->results[indexes[min_w]++]; + + /* If we have merged all the results for this worker, shuffle it + * out of our list */ + if (indexes[min_w] == workers[min_w]->available) { + indexes[min_w] = indexes[worker_count - 1]; + workers[min_w] = workers[worker_count - 1]; + worker_count--; + } + } +} + void choices_search(choices_t *c, const char *search) { choices_reset_search(c); @@ -226,26 +265,21 @@ void choices_search(choices_t *c, const char *search) { } for (unsigned int i = 0; i < c->worker_count; i++) { - struct worker *w = &workers[i]; - - if (pthread_join(w->thread_id, NULL)) { + if (pthread_join(workers[i].thread_id, NULL)) { perror("pthread_join"); exit(EXIT_FAILURE); } - memcpy(&c->results[c->available], w->results, w->available * sizeof(struct scored_result)); - c->available += w->available; - - free(w->results); } - pthread_mutex_destroy(&job->lock); - free(workers); - free(job); + merge_step(job, workers); - if(*search) { - qsort(c->results, c->available, sizeof(struct scored_result), cmpchoice); + for (unsigned int i = 0; i < c->worker_count; i++) { + free(workers[i].results); } + free(workers); + pthread_mutex_destroy(&job->lock); + free(job); } const char *choices_get(choices_t *c, size_t n) { |