aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-09 00:42:39 +0100
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2021-12-09 00:42:39 +0100
commit8acabe18cad69d7c7ed7a00ffef654abc3873a16 (patch)
tree3fd05d3f6fb9ce51644d27688c073a49f7df0c73 /src
parent849edbb69700a9f7520e159d94333ef5b798685b (diff)
downloadnissy-8acabe18cad69d7c7ed7a00ffef654abc3873a16.tar.gz
nissy-8acabe18cad69d7c7ed7a00ffef654abc3873a16.zip
Multi-threaded pruning table generation - now it's actually fast :)
Diffstat (limited to '')
-rw-r--r--src/cubetypes.h5
-rw-r--r--src/pruning.c136
-rw-r--r--src/pruning.h2
-rw-r--r--src/solve.c2
-rw-r--r--src/steps.c4
-rw-r--r--src/steps.h2
6 files changed, 114 insertions, 37 deletions
diff --git a/src/cubetypes.h b/src/cubetypes.h
index ccc2d34..9ec8620 100644
--- a/src/cubetypes.h
+++ b/src/cubetypes.h
@@ -330,12 +330,13 @@ struct
330threaddatagenpt 330threaddatagenpt
331{ 331{
332 int thid; 332 int thid;
333 int nthreads;
333 PruneData * pd; 334 PruneData * pd;
334 int d; 335 int d;
335 uint64_t rangemin; 336 Move * ms;
336 uint64_t rangemax;
337 int nchunks; 337 int nchunks;
338 pthread_mutex_t ** mutex; 338 pthread_mutex_t ** mutex;
339 pthread_mutex_t * upmutex;
339}; 340};
340 341
341#endif 342#endif
diff --git a/src/pruning.c b/src/pruning.c
index 8c6858d..f61912c 100644
--- a/src/pruning.c
+++ b/src/pruning.c
@@ -1,8 +1,12 @@
1#include "pruning.h" 1#include "pruning.h"
2 2
3static void genptable_bfs(PruneData *pd, int d, Move *ms); 3/* Chunks for multithreading */
4static void genptable_branch(PruneData *pd,uint64_t ind,int d,Move *ms); 4#define NCHUNKS 100000
5
6static int findchunk(PruneData *pd, int nchunks, uint64_t i);
7static void genptable_bfs(PruneData *pd,int d,Move *ms,int nt,int nc);
5static void genptable_fixnasty(PruneData *pd, int d); 8static void genptable_fixnasty(PruneData *pd, int d);
9static void * instance_bfs(void *arg);
6static void ptable_update(PruneData *pd, Cube cube, int m); 10static void ptable_update(PruneData *pd, Cube cube, int m);
7static void ptable_update_index(PruneData *pd, uint64_t ind, int m); 11static void ptable_update_index(PruneData *pd, uint64_t ind, int m);
8static int ptableval_index(PruneData *pd, uint64_t ind); 12static int ptableval_index(PruneData *pd, uint64_t ind);
@@ -79,11 +83,23 @@ pd_khuge_HTM = {
79 .moveset = moveset_HTM, 83 .moveset = moveset_HTM,
80}; 84};
81 85
86int
87findchunk(PruneData *pd, int nchunks, uint64_t i)
88{
89 uint64_t chunksize;
90
91 chunksize = pd->coord->max / (uint64_t)nchunks;
92 if (chunksize % 2 != 0)
93 chunksize++;
94
95 return MIN(nchunks-1, (int)(i / chunksize));
96}
97
82void 98void
83genptable(PruneData *pd) 99genptable(PruneData *pd, int nthreads)
84{ 100{
85 Move *ms; 101 Move *ms;
86 int d; 102 int d, nchunks;
87 uint64_t j, oldn; 103 uint64_t j, oldn;
88 104
89 if (pd->generated) 105 if (pd->generated)
@@ -98,7 +114,10 @@ genptable(PruneData *pd)
98 } 114 }
99 pd->generated = true; 115 pd->generated = true;
100 116
101 fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); 117 nchunks = MIN(pd->coord->max, NCHUNKS);
118 fprintf(stderr, "Cannot load %s, generating it "
119 "with %d threads and %d chunks\n",
120 pd->filename, nthreads, nchunks);
102 121
103 ms = malloc(NMOVES * sizeof(Move)); 122 ms = malloc(NMOVES * sizeof(Move));
104 moveset_to_list(pd->moveset, ms); 123 moveset_to_list(pd->moveset, ms);
@@ -110,13 +129,14 @@ genptable(PruneData *pd)
110 ptable_update(pd, (Cube){0}, 0); 129 ptable_update(pd, (Cube){0}, 0);
111 pd->n = 1; 130 pd->n = 1;
112 oldn = 0; 131 oldn = 0;
132 genptable_fixnasty(pd, 0);
113 fprintf(stderr, "Depth %d done, generated %" 133 fprintf(stderr, "Depth %d done, generated %"
114 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", 134 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n",
115 0, pd->n - oldn, pd->n, pd->coord->max); 135 0, pd->n - oldn, pd->n, pd->coord->max);
116 oldn = 1; 136 oldn = pd->n;
117 for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { 137 for (d = 0; d < 15 && pd->n < pd->coord->max; d++) {
118 genptable_fixnasty(pd, d); 138 genptable_bfs(pd, d, ms, nthreads, nchunks);
119 genptable_bfs(pd, d, ms); 139 genptable_fixnasty(pd, d+1);
120 fprintf(stderr, "Depth %d done, generated %" 140 fprintf(stderr, "Depth %d done, generated %"
121 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", 141 PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n",
122 d+1, pd->n - oldn, pd->n, pd->coord->max); 142 d+1, pd->n - oldn, pd->n, pd->coord->max);
@@ -131,28 +151,38 @@ genptable(PruneData *pd)
131} 151}
132 152
133static void 153static void
134genptable_bfs(PruneData *pd, int d, Move *ms) 154genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks)
135{
136 uint64_t i;
137
138 for (i = 0; i < pd->coord->max; i++)
139 if (ptableval_index(pd, i) == d)
140 genptable_branch(pd, i, d, ms);
141}
142
143static void
144genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms)
145{ 155{
146 int i; 156 int i;
147 Cube c, cc; 157 pthread_t t[nthreads];
158 ThreadDataGenpt td[nthreads];
159 pthread_mutex_t *mtx[nchunks], *upmtx;
148 160
149 c = pd->coord->cube(ind); 161 upmtx = malloc(sizeof(pthread_mutex_t));
162 pthread_mutex_init(upmtx, NULL);
163 for (i = 0; i < nchunks; i++) {
164 mtx[i] = malloc(sizeof(pthread_mutex_t));
165 pthread_mutex_init(mtx[i], NULL);
166 }
150 167
151 for (i = 0; ms[i] != NULLMOVE; i++) { 168 for (i = 0; i < nthreads; i++) {
152 cc = apply_move(ms[i], c); 169 td[i].thid = i;
153 if (ptableval(pd, cc) > d+1) 170 td[i].nthreads = nthreads;
154 ptable_update(pd, cc, d+1); 171 td[i].pd = pd;
172 td[i].d = d;
173 td[i].ms = ms;
174 td[i].nchunks = nchunks;
175 td[i].mutex = mtx;
176 td[i].upmutex = upmtx;
177 pthread_create(&t[i], NULL, instance_bfs, &td[i]);
155 } 178 }
179
180 for (i = 0; i < nthreads; i++)
181 pthread_join(t[i], NULL);
182
183 free(upmtx);
184 for (i = 0; i < nchunks; i++)
185 free(mtx[i]);
156} 186}
157 187
158static void 188static void
@@ -164,7 +194,7 @@ genptable_fixnasty(PruneData *pd, int d)
164 Trans t[NTRANS]; 194 Trans t[NTRANS];
165 195
166 for (i = 0; i < pd->coord->max; i++) { 196 for (i = 0; i < pd->coord->max; i++) {
167 if (ptableval_index(pd, i) == d) { 197 if (ptableval_index(pd, i) == d) {
168 n = pd->coord->trans(i, t); 198 n = pd->coord->trans(i, t);
169 if (n == 1) 199 if (n == 1)
170 continue; 200 continue;
@@ -172,11 +202,57 @@ genptable_fixnasty(PruneData *pd, int d)
172 c = pd->coord->cube(i); 202 c = pd->coord->cube(i);
173 for (j = 0; j < n; j++) { 203 for (j = 0; j < n; j++) {
174 cc = apply_trans(t[j], c); 204 cc = apply_trans(t[j], c);
175 if (ptableval(pd, cc) > d) 205 if (ptableval(pd, cc) > d) {
176 ptable_update(pd, cc, d); 206 ptable_update(pd, cc, d);
207 pd->n++;
208 }
209 }
210 }
211 }
212}
213
214static void *
215instance_bfs(void *arg)
216{
217 ThreadDataGenpt *td;
218 uint64_t i, ii, blocksize, rmin, rmax, updated;
219 int j, pval, ichunk;
220 Cube c, cc;
221
222 td = (ThreadDataGenpt *)arg;
223 blocksize = td->pd->coord->max / (uint64_t)td->nthreads;
224 rmin = ((uint64_t)td->thid) * blocksize;
225 rmax = td->thid == td->nthreads - 1 ?
226 td->pd->coord->max :
227 ((uint64_t)td->thid + 1) * blocksize;
228
229 updated = 0;
230 for (i = rmin; i < rmax; i++) {
231 ichunk = findchunk(td->pd, td->nchunks, i);
232 pthread_mutex_lock(td->mutex[ichunk]);
233 pval = ptableval_index(td->pd, i);
234 pthread_mutex_unlock(td->mutex[ichunk]);
235 if (pval == td->d) {
236 c = td->pd->coord->cube(i);
237 for (j = 0; td->ms[j] != NULLMOVE; j++) {
238 cc = apply_move(td->ms[j], c);
239 ii = td->pd->coord->index(cc);
240 ichunk = findchunk(td->pd, td->nchunks, ii);
241 pthread_mutex_lock(td->mutex[ichunk]);
242 pval = ptableval_index(td->pd, ii);
243 if (pval > td->d+1) {
244 ptable_update(td->pd, cc, td->d+1);
245 updated++;
246 }
247 pthread_mutex_unlock(td->mutex[ichunk]);
177 } 248 }
178 } 249 }
179 } 250 }
251 pthread_mutex_lock(td->upmutex);
252 td->pd->n += updated;
253 pthread_mutex_unlock(td->upmutex);
254
255 return NULL;
180} 256}
181 257
182void 258void
@@ -188,7 +264,7 @@ print_ptable(PruneData *pd)
188 a[i] = 0; 264 a[i] = 0;
189 265
190 if (!pd->generated) 266 if (!pd->generated)
191 genptable(pd); 267 genptable(pd, 1); /* TODO: set default nthreads somewhere */
192 268
193 for (i = 0; i < pd->coord->max; i++) 269 for (i = 0; i < pd->coord->max; i++)
194 a[ptableval_index(pd, i)]++; 270 a[ptableval_index(pd, i)]++;
@@ -220,7 +296,7 @@ ptable_update_index(PruneData *pd, uint64_t ind, int n)
220 other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; 296 other = (ind % 2) ? oldval2 % 16 : oldval2 / 16;
221 297
222 pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; 298 pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n;
223 pd->n++; 299 /*pd->n++;*/
224} 300}
225 301
226int 302int
@@ -237,7 +313,7 @@ ptableval_index(PruneData *pd, uint64_t ind)
237 " for uninitialized table %s.\n It's fine, but it" 313 " for uninitialized table %s.\n It's fine, but it"
238 " should not happen. Please report bug.\n", 314 " should not happen. Please report bug.\n",
239 pd->filename); 315 pd->filename);
240 genptable(pd); 316 genptable(pd, 1); /* TODO: set default or remove this case */
241 } 317 }
242 318
243 return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; 319 return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16;
diff --git a/src/pruning.h b/src/pruning.h
index 631ee3a..d337fd8 100644
--- a/src/pruning.h
+++ b/src/pruning.h
@@ -14,7 +14,7 @@ extern PruneData pd_htr_drud;
14extern PruneData pd_htrfin_htr; 14extern PruneData pd_htrfin_htr;
15extern PruneData pd_khuge_HTM; 15extern PruneData pd_khuge_HTM;
16 16
17void genptable(PruneData *pd); 17void genptable(PruneData *pd, int nthreads);
18void print_ptable(PruneData *pd); 18void print_ptable(PruneData *pd);
19uint64_t ptablesize(PruneData *pd); 19uint64_t ptablesize(PruneData *pd);
20int ptableval(PruneData *pd, Cube cube); 20int ptableval(PruneData *pd, Cube cube);
diff --git a/src/solve.c b/src/solve.c
index 42b4607..ec16935 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -282,7 +282,7 @@ solve(Cube cube, Step *step, SolveOptions *opts)
282 EstimateData *ed; 282 EstimateData *ed;
283 bool b; 283 bool b;
284 284
285 prepare_step(step); 285 prepare_step(step, opts->nthreads);
286 286
287 if (step->detect != NULL) 287 if (step->detect != NULL)
288 step->pre_trans = step->detect(cube); 288 step->pre_trans = step->detect(cube);
diff --git a/src/steps.c b/src/steps.c
index 4646abd..abb2918 100644
--- a/src/steps.c
+++ b/src/steps.c
@@ -1143,10 +1143,10 @@ new_localinfo()
1143} 1143}
1144 1144
1145void 1145void
1146prepare_step(Step *step) 1146prepare_step(Step *step, int nthreads)
1147{ 1147{
1148 int i; 1148 int i;
1149 1149
1150 for (i = 0; i < step->ntables; i++) 1150 for (i = 0; i < step->ntables; i++)
1151 genptable(step->tables[i]); 1151 genptable(step->tables[i], nthreads);
1152} 1152}
diff --git a/src/steps.h b/src/steps.h
index f23bc69..e145c64 100644
--- a/src/steps.h
+++ b/src/steps.h
@@ -9,6 +9,6 @@ extern Step * steps[NSTEPS];
9 9
10void free_localinfo(LocalInfo *li); 10void free_localinfo(LocalInfo *li);
11LocalInfo * new_localinfo(); 11LocalInfo * new_localinfo();
12void prepare_step(Step *step); 12void prepare_step(Step *step, int nthreads);
13 13
14#endif 14#endif

Generated with cgit - Back to sebastiano.tronto.net