aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/solvers/h48/thread.h158
1 files changed, 66 insertions, 92 deletions
diff --git a/src/solvers/h48/thread.h b/src/solvers/h48/thread.h
index 1eade29..155bc6a 100644
--- a/src/solvers/h48/thread.h
+++ b/src/solvers/h48/thread.h
@@ -5,32 +5,31 @@
5#include <stdlib.h> 5#include <stdlib.h>
6 6
7#define MAX_QUEUE_SIZE 500 7#define MAX_QUEUE_SIZE 500
8
9typedef struct 8typedef struct
10{ 9{
11 dfsarg_solveh48_t *tasks[MAX_QUEUE_SIZE]; 10 dfsarg_solveh48_t *tasks[MAX_QUEUE_SIZE];
12 int front; 11 int front;
13 int rear; 12 int rear;
14 int tasks_count; 13 int tasks_count;
14 int active;
15 pthread_mutex_t mutex; 15 pthread_mutex_t mutex;
16 pthread_cond_t cond; 16 pthread_cond_t cond;
17 atomic_int active_tasks; 17 pthread_cond_t active_cond;
18 pthread_mutex_t active_tasks_mutex; 18 bool terminate;
19 pthread_cond_t active_tasks_cond;
20} task_queue_t; 19} task_queue_t;
21 20
22STATIC void solve_h48_appendsolution_thread(dfsarg_solveh48_t *, task_queue_t *); 21STATIC void solve_h48_appendsolution_thread(dfsarg_solveh48_t *, task_queue_t *);
23STATIC void init_queue(task_queue_t *); 22STATIC void init_queue(task_queue_t *);
24STATIC void submit_task(task_queue_t *, dfsarg_solveh48_t *); 23STATIC void submit_task(task_queue_t *, dfsarg_solveh48_t *);
25STATIC void copy_queue(task_queue_t *, task_queue_t *, int); 24STATIC void copy_queue(task_queue_t *, task_queue_t *, int, int64_t *);
26STATIC dfsarg_solveh48_t *get_task(task_queue_t *);
27STATIC void *start_thread(void *); 25STATIC void *start_thread(void *);
28STATIC int64_t solve_h48_bfs(dfsarg_solveh48_t *, task_queue_t *); 26STATIC int64_t solve_h48_bfs(dfsarg_solveh48_t *, task_queue_t *);
29STATIC int64_t solve_h48_single(dfsarg_solveh48_t *, task_queue_t *); 27STATIC int64_t solve_h48_single(dfsarg_solveh48_t *, task_queue_t *);
30STATIC int64_t solve_h48_parent(cube_t, int8_t, int8_t, int8_t, const void *, char *); 28STATIC int64_t solve_h48_parent(cube_t, int8_t, int8_t, int8_t, const void *, char *);
31 29
32STATIC void 30STATIC void
33solve_h48_appendsolution_thread(dfsarg_solveh48_t *arg, task_queue_t *tq){ 31solve_h48_appendsolution_thread(dfsarg_solveh48_t *arg, task_queue_t *tq)
32{
34 pthread_mutex_lock(&tq->mutex); 33 pthread_mutex_lock(&tq->mutex);
35 int strl; 34 int strl;
36 uint8_t invertedpremoves[MAXLEN]; 35 uint8_t invertedpremoves[MAXLEN];
@@ -62,8 +61,10 @@ init_queue(task_queue_t *queue)
62 queue->front = 0; 61 queue->front = 0;
63 queue->rear = 0; 62 queue->rear = 0;
64 queue->tasks_count = 0; 63 queue->tasks_count = 0;
64 queue->active = 0;
65 pthread_mutex_init(&queue->mutex, NULL); 65 pthread_mutex_init(&queue->mutex, NULL);
66 pthread_cond_init(&queue->cond, NULL); 66 pthread_cond_init(&queue->cond, NULL);
67 pthread_cond_init(&queue->active_cond, NULL);
67} 68}
68 69
69STATIC void 70STATIC void
@@ -73,14 +74,13 @@ submit_task(task_queue_t *queue, dfsarg_solveh48_t *task)
73 queue->tasks[queue->rear] = task; 74 queue->tasks[queue->rear] = task;
74 queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE; 75 queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
75 queue->tasks_count++; 76 queue->tasks_count++;
76 pthread_cond_signal(&queue->cond); 77 pthread_cond_broadcast(&queue->cond);
77 pthread_mutex_unlock(&queue->mutex); 78 pthread_mutex_unlock(&queue->mutex);
78} 79}
79 80
80STATIC void 81STATIC void
81copy_queue(task_queue_t *src, task_queue_t *dest, int depth) 82copy_queue(task_queue_t *src, task_queue_t *dest, int depth, int64_t *nsols)
82{ 83{
83 pthread_mutex_lock(&src->mutex);
84 pthread_mutex_lock(&dest->mutex); 84 pthread_mutex_lock(&dest->mutex);
85 for (int i = src->front; i != src->rear; i = (i + 1) % MAX_QUEUE_SIZE) 85 for (int i = src->front; i != src->rear; i = (i + 1) % MAX_QUEUE_SIZE)
86 { 86 {
@@ -93,46 +93,42 @@ copy_queue(task_queue_t *src, task_queue_t *dest, int depth)
93 dest->front = src->front; 93 dest->front = src->front;
94 dest->rear = src->rear; 94 dest->rear = src->rear;
95 dest->tasks_count = src->tasks_count; 95 dest->tasks_count = src->tasks_count;
96 pthread_mutex_unlock(&src->mutex); 96 dest->active = src->active;
97 pthread_cond_signal(&dest->cond); 97 pthread_cond_broadcast(&dest->cond);
98 pthread_mutex_unlock(&dest->mutex); 98 pthread_mutex_unlock(&dest->mutex);
99} 99}
100STATIC dfsarg_solveh48_t * 100
101get_task(task_queue_t *queue)
102{
103 pthread_mutex_lock(&queue->mutex);
104 while (queue->tasks_count == 0)
105 {
106 pthread_cond_wait(&queue->cond, &queue->mutex);
107 }
108 dfsarg_solveh48_t *task = queue->tasks[queue->front];
109 queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
110 queue->tasks_count--;
111 pthread_mutex_unlock(&queue->mutex);
112 return task;
113}
114 101
115STATIC void * 102STATIC void *
116start_thread(void *arg) 103start_thread(void *arg)
117{ 104{
118 task_queue_t *queue = (task_queue_t *)arg; 105 task_queue_t *queue = (task_queue_t *)arg;
119 while (true) 106 while (1) {
120 { 107 pthread_mutex_lock(&queue->mutex);
121 dfsarg_solveh48_t *task = get_task(queue); 108 while (queue->tasks_count == 0 && !queue->terminate) {
122 if (task == NULL) 109 pthread_cond_wait(&queue->cond, &queue->mutex);
123 { 110 }
111 if (queue->tasks_count == 0 && queue->terminate) {
112 pthread_mutex_unlock(&queue->mutex);
124 break; 113 break;
125 } 114 }
126 solve_h48_single(task, queue);
127 free(task);
128 115
129 pthread_mutex_lock(&queue->active_tasks_mutex); 116 if (queue->tasks_count > 0) {
130 atomic_fetch_sub(&queue->active_tasks, 1); 117 dfsarg_solveh48_t *task = queue->tasks[queue->front];
131 if (atomic_load(&queue->active_tasks) == 0) 118 queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
132 { 119 queue->tasks_count--;
133 pthread_cond_signal(&queue->active_tasks_cond); 120 queue->active++;
121 pthread_mutex_unlock(&queue->mutex);
122
123 solve_h48_single(task, queue);
124
125 pthread_mutex_lock(&queue->mutex);
126 queue->active--;
127
128 if(queue->tasks_count == 0 && queue->active == 0)
129 pthread_cond_signal(&queue->active_cond);
134 } 130 }
135 pthread_mutex_unlock(&queue->active_tasks_mutex); 131 pthread_mutex_unlock(&queue->mutex);
136 } 132 }
137 return NULL; 133 return NULL;
138} 134}
@@ -146,19 +142,16 @@ solve_h48_bfs(dfsarg_solveh48_t *arg_zero, task_queue_t *tq)
146 int depth = 0; 142 int depth = 0;
147 int nodes_at_current_depth = 1; 143 int nodes_at_current_depth = 1;
148 int nodes_at_next_depth = 0; 144 int nodes_at_next_depth = 0;
149
150 queue[rear++] = *arg_zero; 145 queue[rear++] = *arg_zero;
151 146
152 while (front < rear) 147 while (front < rear){
153 {
154 dfsarg_solveh48_t arg = queue[front++]; 148 dfsarg_solveh48_t arg = queue[front++];
155 nodes_at_current_depth--; 149 nodes_at_current_depth--;
156 150
157 if (*arg.nsols == arg.maxsolutions) 151 if (*arg.nsols == arg.maxsolutions)
158 return 1; 152 return 1;
159 153
160 if (issolved(arg.cube)) 154 if (issolved(arg.cube)){
161 {
162 if (arg.nmoves + arg.npremoves != arg.depth) 155 if (arg.nmoves + arg.npremoves != arg.depth)
163 continue; 156 continue;
164 solve_h48_appendsolution(&arg); 157 solve_h48_appendsolution(&arg);
@@ -168,42 +161,32 @@ solve_h48_bfs(dfsarg_solveh48_t *arg_zero, task_queue_t *tq)
168 arg.nissbranch = MM_NORMAL; 161 arg.nissbranch = MM_NORMAL;
169 uint32_t allowed = allowednextmove_h48(arg.moves, arg.nmoves, arg.nissbranch); 162 uint32_t allowed = allowednextmove_h48(arg.moves, arg.nmoves, arg.nissbranch);
170 163
171 for (uint8_t m = 0; m < 18; m++) 164 for (uint8_t m = 0; m < 18; m++){
172 { 165 if (allowed & (1 << m)){
173 if (allowed & (1 << m))
174 {
175 nextarg = arg; 166 nextarg = arg;
176 nextarg.nmoves = arg.nmoves + 1; 167 nextarg.nmoves = arg.nmoves + 1;
177 nextarg.moves[arg.nmoves] = m; 168 nextarg.moves[arg.nmoves] = m;
178 nextarg.cube = move(arg.cube, m); 169 nextarg.cube = move(arg.cube, m);
179 nextarg.inverse = premove(arg.inverse, m); 170 nextarg.inverse = premove(arg.inverse, m);
180 171
181 if (nextarg.nmoves == 2) 172 if (nextarg.nmoves == 2){
182 {
183 dfsarg_solveh48_t *task = malloc(sizeof(dfsarg_solveh48_t)); 173 dfsarg_solveh48_t *task = malloc(sizeof(dfsarg_solveh48_t));
184 *task = nextarg; 174 *task = nextarg;
185 submit_task(tq, task); 175 submit_task(tq, task);
186 } 176 } else {
187 else
188 {
189 queue[rear++] = nextarg; 177 queue[rear++] = nextarg;
190 nodes_at_next_depth++; 178 nodes_at_next_depth++;
191 } 179 }
192 } 180 }
193 } 181 }
194 182 if (nodes_at_current_depth == 0){
195 if (nodes_at_current_depth == 0)
196 {
197 depth++; 183 depth++;
198 nodes_at_current_depth = nodes_at_next_depth; 184 nodes_at_current_depth = nodes_at_next_depth;
199 nodes_at_next_depth = 0; 185 nodes_at_next_depth = 0;
200 } 186 }
201 if (depth == 2) 187 if (depth == 2) return 0;
202 {
203 return 0;
204 }
205 } 188 }
206 return 0; 189 return 1;
207} 190}
208 191
209STATIC int64_t 192STATIC int64_t
@@ -219,8 +202,7 @@ solve_h48_single(dfsarg_solveh48_t *arg, task_queue_t *tq)
219 if (solve_h48_stop(arg)) 202 if (solve_h48_stop(arg))
220 return 0; 203 return 0;
221 204
222 if (issolved(arg->cube)) 205 if (issolved(arg->cube)){
223 {
224 if (arg->nmoves + arg->npremoves != arg->depth) 206 if (arg->nmoves + arg->npremoves != arg->depth)
225 return 0; 207 return 0;
226 solve_h48_appendsolution_thread(arg, tq); 208 solve_h48_appendsolution_thread(arg, tq);
@@ -230,13 +212,10 @@ solve_h48_single(dfsarg_solveh48_t *arg, task_queue_t *tq)
230 nextarg = *arg; 212 nextarg = *arg;
231 ret = 0; 213 ret = 0;
232 uint32_t allowed; 214 uint32_t allowed;
233 if (arg->nissbranch & MM_INVERSE) 215 if (arg->nissbranch & MM_INVERSE){
234 {
235 allowed = allowednextmove_h48(arg->premoves, arg->npremoves, arg->nissbranch); 216 allowed = allowednextmove_h48(arg->premoves, arg->npremoves, arg->nissbranch);
236 for (m = 0; m < 18; m++) 217 for (m = 0; m < 18; m++){
237 { 218 if (allowed & (1 << m)){
238 if (allowed & (1 << m))
239 {
240 nextarg.npremoves = arg->npremoves + 1; 219 nextarg.npremoves = arg->npremoves + 1;
241 nextarg.premoves[arg->npremoves] = m; 220 nextarg.premoves[arg->npremoves] = m;
242 nextarg.inverse = move(arg->inverse, m); 221 nextarg.inverse = move(arg->inverse, m);
@@ -244,14 +223,10 @@ solve_h48_single(dfsarg_solveh48_t *arg, task_queue_t *tq)
244 ret += solve_h48_single(&nextarg, tq); 223 ret += solve_h48_single(&nextarg, tq);
245 } 224 }
246 } 225 }
247 } 226 } else {
248 else
249 {
250 allowed = allowednextmove_h48(arg->moves, arg->nmoves, arg->nissbranch); 227 allowed = allowednextmove_h48(arg->moves, arg->nmoves, arg->nissbranch);
251 for (m = 0; m < 18; m++) 228 for (m = 0; m < 18; m++){
252 { 229 if (allowed & (1 << m)){
253 if (allowed & (1 << m))
254 {
255 nextarg.nmoves = arg->nmoves + 1; 230 nextarg.nmoves = arg->nmoves + 1;
256 nextarg.moves[arg->nmoves] = m; 231 nextarg.moves[arg->nmoves] = m;
257 nextarg.cube = move(arg->cube, m); 232 nextarg.cube = move(arg->cube, m);
@@ -303,12 +278,7 @@ solve_h48_parent(
303 task_queue_t nq; 278 task_queue_t nq;
304 init_queue(&nq); 279 init_queue(&nq);
305 280
306 atomic_store(&nq.active_tasks, 0); 281 for (int i = 0; i < THREADS; i++){
307 pthread_mutex_init(&nq.active_tasks_mutex, NULL);
308 pthread_cond_init(&nq.active_tasks_cond, NULL);
309
310 for (int i = 0; i < THREADS; i++)
311 {
312 pthread_create(&threads[i], NULL, &start_thread, &nq); 282 pthread_create(&threads[i], NULL, &start_thread, &nq);
313 } 283 }
314 284
@@ -318,18 +288,22 @@ solve_h48_parent(
318 p_depth++) 288 p_depth++)
319 { 289 {
320 LOG("Found %" PRId64 " solutions, searching at depth %" PRId8 "\n", nsols, p_depth); 290 LOG("Found %" PRId64 " solutions, searching at depth %" PRId8 "\n", nsols, p_depth);
321 copy_queue(&q, &nq, p_depth); 291 copy_queue(&q, &nq, p_depth, &nsols);
322 pthread_mutex_lock(&nq.active_tasks_mutex); 292
323 while (nq.active_tasks > 0) 293 pthread_mutex_lock(&nq.mutex);
324 { 294 while (nq.active > 0 || nq.tasks_count > 0)
325 pthread_cond_wait(&nq.active_tasks_cond, &nq.active_tasks_mutex); 295 pthread_cond_wait(&nq.active_cond, &nq.mutex);
326 } 296 pthread_mutex_unlock(&nq.mutex);
327 pthread_mutex_unlock(&nq.active_tasks_mutex);
328 } 297 }
329 for (int i = 0; i < THREADS; i++) 298
330 { 299 pthread_mutex_lock(&nq.mutex);
300 nq.terminate = true;
301 pthread_cond_broadcast(&nq.cond);
302 pthread_mutex_unlock(&nq.mutex);
303
304 for (int i = 0; i < THREADS; i++){
331 pthread_join(threads[i], NULL); 305 pthread_join(threads[i], NULL);
332 } 306 }
333 307 // fix memory release for multiple scrambles.
334 return nsols; 308 return nsols;
335} 309}

Generated with cgit - Back to sebastiano.tronto.net