| ... | ... |
@@ -140,6 +140,11 @@ size_t choices_available(choices_t *c) {
|
| 140 | 140 |
|
| 141 | 141 |
#define BATCH_SIZE 512 |
| 142 | 142 |
|
| 143 |
+struct result_list {
|
|
| 144 |
+ struct scored_result *list; |
|
| 145 |
+ size_t size; |
|
| 146 |
+}; |
|
| 147 |
+ |
|
| 143 | 148 |
struct search_job {
|
| 144 | 149 |
pthread_mutex_t lock; |
| 145 | 150 |
choices_t *choices; |
| ... | ... |
@@ -199,40 +204,57 @@ static void *choices_search_worker(void *data) {
|
| 199 | 204 |
return w; |
| 200 | 205 |
} |
| 201 | 206 |
|
| 202 |
-static void merge_step(struct search_job *job, struct worker *all_workers) {
|
|
| 203 |
- /* Merge our sorted partial-results */ |
|
| 204 |
- choices_t *c = job->choices; |
|
| 205 |
- size_t worker_count = 0; |
|
| 206 |
- struct worker *workers[c->worker_count]; |
|
| 207 |
- size_t indexes[c->worker_count]; |
|
| 207 |
+static struct result_list merge2(struct result_list list1, struct result_list list2) {
|
|
| 208 |
+ size_t result_index = 0, index1 = 0, index2 = 0; |
|
| 208 | 209 |
|
| 209 |
- for (unsigned int w = 0; w < c->worker_count; w++) {
|
|
| 210 |
- indexes[w] = 0; |
|
| 211 |
- if (all_workers[w].available) {
|
|
| 212 |
- workers[worker_count++] = &all_workers[w]; |
|
| 213 |
- } |
|
| 210 |
+ struct result_list result; |
|
| 211 |
+ result.size = list1.size + list2.size; |
|
| 212 |
+ result.list = malloc(result.size * sizeof(struct scored_result)); |
|
| 213 |
+ if (!result.list) {
|
|
| 214 |
+ fprintf(stderr, "Error: Can't allocate memory\n"); |
|
| 215 |
+ abort(); |
|
| 214 | 216 |
} |
| 215 | 217 |
|
| 216 |
- while (worker_count) {
|
|
| 217 |
- /* Loop over each sorted block to find the lowest scoring result */ |
|
| 218 |
- unsigned int min_w = 0; |
|
| 219 |
- for (unsigned int w = 0; w < worker_count; w++) {
|
|
| 220 |
- if (cmpchoice(&workers[w]->results[indexes[w]], &workers[min_w]->results[indexes[min_w]]) < 0) {
|
|
| 221 |
- min_w = w; |
|
| 222 |
- } |
|
| 218 |
+ while(index1 < list1.size && index2 < list2.size) {
|
|
| 219 |
+ if (cmpchoice(&list1.list[index1], &list2.list[index2]) < 0) {
|
|
| 220 |
+ result.list[result_index++] = list1.list[index1++]; |
|
| 221 |
+ } else {
|
|
| 222 |
+ result.list[result_index++] = list2.list[index2++]; |
|
| 223 | 223 |
} |
| 224 |
+ } |
|
| 224 | 225 |
|
| 225 |
- /* Move that result onto our global list */ |
|
| 226 |
- c->results[c->available++] = workers[min_w]->results[indexes[min_w]++]; |
|
| 226 |
+ while(index1 < list1.size) {
|
|
| 227 |
+ result.list[result_index++] = list1.list[index1++]; |
|
| 228 |
+ } |
|
| 229 |
+ while(index2 < list2.size) {
|
|
| 230 |
+ result.list[result_index++] = list2.list[index2++]; |
|
| 231 |
+ } |
|
| 227 | 232 |
|
| 228 |
- /* If we have merged all the results for this worker, shuffle it |
|
| 229 |
- * out of our list */ |
|
| 230 |
- if (indexes[min_w] == workers[min_w]->available) {
|
|
| 231 |
- indexes[min_w] = indexes[worker_count - 1]; |
|
| 232 |
- workers[min_w] = workers[worker_count - 1]; |
|
| 233 |
- worker_count--; |
|
| 234 |
- } |
|
| 233 |
+ free(list1.list); |
|
| 234 |
+ free(list2.list); |
|
| 235 |
+ |
|
| 236 |
+ return result; |
|
| 237 |
+} |
|
| 238 |
+ |
|
| 239 |
+static void merge_step(struct search_job *job, struct worker *workers) {
|
|
| 240 |
+ /* Merge our sorted partial-results */ |
|
| 241 |
+ choices_t *c = job->choices; |
|
| 242 |
+ |
|
| 243 |
+ struct result_list result = {NULL, 0};
|
|
| 244 |
+ |
|
| 245 |
+ for (unsigned int w = 0; w < c->worker_count; w++) {
|
|
| 246 |
+ struct result_list new_result; |
|
| 247 |
+ struct worker *worker = &workers[w]; |
|
| 248 |
+ |
|
| 249 |
+ struct result_list worker_result = {worker->results, worker->available};
|
|
| 250 |
+ new_result = merge2(result, worker_result); |
|
| 251 |
+ |
|
| 252 |
+ free(result.list); |
|
| 253 |
+ result = new_result; |
|
| 235 | 254 |
} |
| 255 |
+ |
|
| 256 |
+ c->results = result.list; |
|
| 257 |
+ c->available = result.size; |
|
| 236 | 258 |
} |
| 237 | 259 |
|
| 238 | 260 |
void choices_search(choices_t *c, const char *search) {
|
| ... | ... |
@@ -246,13 +268,6 @@ void choices_search(choices_t *c, const char *search) {
|
| 246 | 268 |
abort(); |
| 247 | 269 |
} |
| 248 | 270 |
|
| 249 |
- /* allocate storage for our results */ |
|
| 250 |
- c->results = malloc(c->size * sizeof(struct scored_result)); |
|
| 251 |
- if (!c->results) {
|
|
| 252 |
- fprintf(stderr, "Error: Can't allocate memory\n"); |
|
| 253 |
- abort(); |
|
| 254 |
- } |
|
| 255 |
- |
|
| 256 | 271 |
struct worker *workers = calloc(c->worker_count, sizeof(struct worker)); |
| 257 | 272 |
for (unsigned int i = 0; i < c->worker_count; i++) {
|
| 258 | 273 |
workers[i].job = job; |