diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-09 00:42:39 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-09 00:42:39 +0100 |
| commit | 8acabe18cad69d7c7ed7a00ffef654abc3873a16 (patch) | |
| tree | 3fd05d3f6fb9ce51644d27688c073a49f7df0c73 /src | |
| parent | 849edbb69700a9f7520e159d94333ef5b798685b (diff) | |
| download | nissy-8acabe18cad69d7c7ed7a00ffef654abc3873a16.tar.gz nissy-8acabe18cad69d7c7ed7a00ffef654abc3873a16.zip | |
Multi-threaded pruning table generation - now it's actually fast :)
Diffstat (limited to '')
| -rw-r--r-- | src/cubetypes.h | 5 | ||||
| -rw-r--r-- | src/pruning.c | 136 | ||||
| -rw-r--r-- | src/pruning.h | 2 | ||||
| -rw-r--r-- | src/solve.c | 2 | ||||
| -rw-r--r-- | src/steps.c | 4 | ||||
| -rw-r--r-- | src/steps.h | 2 |
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 | |||
| 330 | threaddatagenpt | 330 | threaddatagenpt |
| 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 | ||
| 3 | static void genptable_bfs(PruneData *pd, int d, Move *ms); | 3 | /* Chunks for multithreading */ |
| 4 | static void genptable_branch(PruneData *pd,uint64_t ind,int d,Move *ms); | 4 | #define NCHUNKS 100000 |
| 5 | |||
| 6 | static int findchunk(PruneData *pd, int nchunks, uint64_t i); | ||
| 7 | static void genptable_bfs(PruneData *pd,int d,Move *ms,int nt,int nc); | ||
| 5 | static void genptable_fixnasty(PruneData *pd, int d); | 8 | static void genptable_fixnasty(PruneData *pd, int d); |
| 9 | static void * instance_bfs(void *arg); | ||
| 6 | static void ptable_update(PruneData *pd, Cube cube, int m); | 10 | static void ptable_update(PruneData *pd, Cube cube, int m); |
| 7 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); | 11 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); |
| 8 | static int ptableval_index(PruneData *pd, uint64_t ind); | 12 | static 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 | ||
| 86 | int | ||
| 87 | findchunk(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 | |||
| 82 | void | 98 | void |
| 83 | genptable(PruneData *pd) | 99 | genptable(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 | ||
| 133 | static void | 153 | static void |
| 134 | genptable_bfs(PruneData *pd, int d, Move *ms) | 154 | genptable_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 | |||
| 143 | static void | ||
| 144 | genptable_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 | ||
| 158 | static void | 188 | static 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 | |||
| 214 | static void * | ||
| 215 | instance_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 | ||
| 182 | void | 258 | void |
| @@ -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 | ||
| 226 | int | 302 | int |
| @@ -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; | |||
| 14 | extern PruneData pd_htrfin_htr; | 14 | extern PruneData pd_htrfin_htr; |
| 15 | extern PruneData pd_khuge_HTM; | 15 | extern PruneData pd_khuge_HTM; |
| 16 | 16 | ||
| 17 | void genptable(PruneData *pd); | 17 | void genptable(PruneData *pd, int nthreads); |
| 18 | void print_ptable(PruneData *pd); | 18 | void print_ptable(PruneData *pd); |
| 19 | uint64_t ptablesize(PruneData *pd); | 19 | uint64_t ptablesize(PruneData *pd); |
| 20 | int ptableval(PruneData *pd, Cube cube); | 20 | int 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 | ||
| 1145 | void | 1145 | void |
| 1146 | prepare_step(Step *step) | 1146 | prepare_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 | ||
| 10 | void free_localinfo(LocalInfo *li); | 10 | void free_localinfo(LocalInfo *li); |
| 11 | LocalInfo * new_localinfo(); | 11 | LocalInfo * new_localinfo(); |
| 12 | void prepare_step(Step *step); | 12 | void prepare_step(Step *step, int nthreads); |
| 13 | 13 | ||
| 14 | #endif | 14 | #endif |
