diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-16 19:25:58 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-16 19:25:58 +0100 |
| commit | 2f924f942bd6e7126e8f1d8692e475c95bd9fe82 (patch) | |
| tree | dd5877c2fd836f43523263e48632946423401093 /src/pruning.c | |
| parent | 4e2b4e603c7e84c7556f489d7d8dab06915b3a9b (diff) | |
| download | nissy-2f924f942bd6e7126e8f1d8692e475c95bd9fe82.tar.gz nissy-2f924f942bd6e7126e8f1d8692e475c95bd9fe82.zip | |
Added a new pruning table (equivalent to nxopt31). I have not tested it yet, it takes a while to generate.
Plus I have done a whole lot of refactoring in random places because I cannot focus on
one thing at the time.
Diffstat (limited to '')
| -rw-r--r-- | src/pruning.c | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/src/pruning.c b/src/pruning.c index b305a89..0a6e305 100644 --- a/src/pruning.c +++ b/src/pruning.c | |||
| @@ -1,11 +1,10 @@ | |||
| 1 | #include "pruning.h" | 1 | #include "pruning.h" |
| 2 | 2 | ||
| 3 | /* Chunks for multithreading */ | 3 | #define NCHUNKS 100000 |
| 4 | /* TODO: try smaller */ | 4 | #define ENTRIES_PER_GROUP (2*sizeof(entry_group_t)) |
| 5 | #define NCHUNKS 100000 | ||
| 6 | 5 | ||
| 7 | static int findchunk(PruneData *pd, int nchunks, uint64_t i); | 6 | static int findchunk(PruneData *pd, int nchunks, uint64_t i); |
| 8 | static void genptable_bfs(PruneData *pd,int d,Move *ms,int nt,int nc); | 7 | static void genptable_bfs(PruneData *pd, int d, int nt, int nc); |
| 9 | static void genptable_fixnasty(PruneData *pd, int d); | 8 | static void genptable_fixnasty(PruneData *pd, int d); |
| 10 | static void * instance_bfs(void *arg); | 9 | static void * instance_bfs(void *arg); |
| 11 | static void ptable_update(PruneData *pd, Cube cube, int m); | 10 | static void ptable_update(PruneData *pd, Cube cube, int m); |
| @@ -18,70 +17,77 @@ PruneData | |||
| 18 | pd_eofb_HTM = { | 17 | pd_eofb_HTM = { |
| 19 | .filename = "pt_eofb_HTM", | 18 | .filename = "pt_eofb_HTM", |
| 20 | .coord = &coord_eofb, | 19 | .coord = &coord_eofb, |
| 21 | .moveset = moveset_HTM, | 20 | .moveset = &moveset_HTM, |
| 22 | }; | 21 | }; |
| 23 | 22 | ||
| 24 | PruneData | 23 | PruneData |
| 25 | pd_coud_HTM = { | 24 | pd_coud_HTM = { |
| 26 | .filename = "pt_coud_HTM", | 25 | .filename = "pt_coud_HTM", |
| 27 | .coord = &coord_coud, | 26 | .coord = &coord_coud, |
| 28 | .moveset = moveset_HTM, | 27 | .moveset = &moveset_HTM, |
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 31 | PruneData | 30 | PruneData |
| 32 | pd_cornershtr_HTM = { | 31 | pd_cornershtr_HTM = { |
| 33 | .filename = "pt_cornershtr_HTM", | 32 | .filename = "pt_cornershtr_HTM", |
| 34 | .coord = &coord_cornershtr, | 33 | .coord = &coord_cornershtr, |
| 35 | .moveset = moveset_HTM, | 34 | .moveset = &moveset_HTM, |
| 36 | }; | 35 | }; |
| 37 | 36 | ||
| 38 | PruneData | 37 | PruneData |
| 39 | pd_corners_HTM = { | 38 | pd_corners_HTM = { |
| 40 | .filename = "pt_corners_HTM", | 39 | .filename = "pt_corners_HTM", |
| 41 | .coord = &coord_corners, | 40 | .coord = &coord_corners, |
| 42 | .moveset = moveset_HTM, | 41 | .moveset = &moveset_HTM, |
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | PruneData | 44 | PruneData |
| 46 | pd_drud_sym16_HTM = { | 45 | pd_drud_sym16_HTM = { |
| 47 | .filename = "pt_drud_sym16_HTM", | 46 | .filename = "pt_drud_sym16_HTM", |
| 48 | .coord = &coord_drud_sym16, | 47 | .coord = &coord_drud_sym16, |
| 49 | .moveset = moveset_HTM, | 48 | .moveset = &moveset_HTM, |
| 50 | }; | 49 | }; |
| 51 | 50 | ||
| 52 | PruneData | 51 | PruneData |
| 53 | pd_drud_eofb = { | 52 | pd_drud_eofb = { |
| 54 | .filename = "pt_drud_eofb", | 53 | .filename = "pt_drud_eofb", |
| 55 | .coord = &coord_drud_eofb, | 54 | .coord = &coord_drud_eofb, |
| 56 | .moveset = moveset_eofb, | 55 | .moveset = &moveset_eofb, |
| 57 | }; | 56 | }; |
| 58 | 57 | ||
| 59 | PruneData | 58 | PruneData |
| 60 | pd_drudfin_noE_sym16_drud = { | 59 | pd_drudfin_noE_sym16_drud = { |
| 61 | .filename = "pt_drudfin_noE_sym16_drud", | 60 | .filename = "pt_drudfin_noE_sym16_drud", |
| 62 | .coord = &coord_drudfin_noE_sym16, | 61 | .coord = &coord_drudfin_noE_sym16, |
| 63 | .moveset = moveset_drud, | 62 | .moveset = &moveset_drud, |
| 64 | }; | 63 | }; |
| 65 | 64 | ||
| 66 | PruneData | 65 | PruneData |
| 67 | pd_htr_drud = { | 66 | pd_htr_drud = { |
| 68 | .filename = "pt_htr_drud", | 67 | .filename = "pt_htr_drud", |
| 69 | .coord = &coord_htr_drud, | 68 | .coord = &coord_htr_drud, |
| 70 | .moveset = moveset_drud, | 69 | .moveset = &moveset_drud, |
| 71 | }; | 70 | }; |
| 72 | 71 | ||
| 73 | PruneData | 72 | PruneData |
| 74 | pd_htrfin_htr = { | 73 | pd_htrfin_htr = { |
| 75 | .filename = "pt_htrfin_htr", | 74 | .filename = "pt_htrfin_htr", |
| 76 | .coord = &coord_htrfin, | 75 | .coord = &coord_htrfin, |
| 77 | .moveset = moveset_htr, | 76 | .moveset = &moveset_htr, |
| 78 | }; | 77 | }; |
| 79 | 78 | ||
| 80 | PruneData | 79 | PruneData |
| 81 | pd_khuge_HTM = { | 80 | pd_khuge_HTM = { |
| 82 | .filename = "pt_khuge_HTM", | 81 | .filename = "pt_khuge_HTM", |
| 83 | .coord = &coord_khuge, | 82 | .coord = &coord_khuge, |
| 84 | .moveset = moveset_HTM, | 83 | .moveset = &moveset_HTM, |
| 84 | }; | ||
| 85 | |||
| 86 | PruneData | ||
| 87 | pd_nxopt31_HTM = { | ||
| 88 | .filename = "pt_nxopt31_HTM", | ||
| 89 | .coord = &coord_nxopt31, | ||
| 90 | .moveset = &moveset_HTM, | ||
| 85 | }; | 91 | }; |
| 86 | 92 | ||
| 87 | PruneData * allpd[NPTABLES] = { | 93 | PruneData * allpd[NPTABLES] = { |
| @@ -95,6 +101,7 @@ PruneData * allpd[NPTABLES] = { | |||
| 95 | &pd_htr_drud, | 101 | &pd_htr_drud, |
| 96 | &pd_htrfin_htr, | 102 | &pd_htrfin_htr, |
| 97 | &pd_khuge_HTM, | 103 | &pd_khuge_HTM, |
| 104 | &pd_nxopt31_HTM, | ||
| 98 | }; | 105 | }; |
| 99 | 106 | ||
| 100 | /* Functions *****************************************************************/ | 107 | /* Functions *****************************************************************/ |
| @@ -105,8 +112,7 @@ findchunk(PruneData *pd, int nchunks, uint64_t i) | |||
| 105 | uint64_t chunksize; | 112 | uint64_t chunksize; |
| 106 | 113 | ||
| 107 | chunksize = pd->coord->max / (uint64_t)nchunks; | 114 | chunksize = pd->coord->max / (uint64_t)nchunks; |
| 108 | if (chunksize % 2 != 0) | 115 | chunksize += ENTRIES_PER_GROUP - (chunksize % ENTRIES_PER_GROUP); |
| 109 | chunksize++; | ||
| 110 | 116 | ||
| 111 | return MIN(nchunks-1, (int)(i / chunksize)); | 117 | return MIN(nchunks-1, (int)(i / chunksize)); |
| 112 | } | 118 | } |
| @@ -114,15 +120,14 @@ findchunk(PruneData *pd, int nchunks, uint64_t i) | |||
| 114 | void | 120 | void |
| 115 | genptable(PruneData *pd, int nthreads) | 121 | genptable(PruneData *pd, int nthreads) |
| 116 | { | 122 | { |
| 117 | Move *ms; | ||
| 118 | int d, nchunks; | 123 | int d, nchunks; |
| 119 | uint64_t j, oldn; | 124 | uint64_t oldn; |
| 120 | 125 | ||
| 121 | if (pd->generated) | 126 | if (pd->generated) |
| 122 | return; | 127 | return; |
| 123 | 128 | ||
| 124 | /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ | 129 | /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ |
| 125 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | 130 | pd->ptable = malloc(ptablesize(pd) * sizeof(entry_group_t)); |
| 126 | 131 | ||
| 127 | if (read_ptable_file(pd)) { | 132 | if (read_ptable_file(pd)) { |
| 128 | pd->generated = true; | 133 | pd->generated = true; |
| @@ -130,17 +135,12 @@ genptable(PruneData *pd, int nthreads) | |||
| 130 | } | 135 | } |
| 131 | pd->generated = true; | 136 | pd->generated = true; |
| 132 | 137 | ||
| 133 | nchunks = MIN(pd->coord->max/2, NCHUNKS); | 138 | nchunks = MIN(pd->coord->max/ENTRIES_PER_GROUP, NCHUNKS); |
| 134 | fprintf(stderr, "Cannot load %s, generating it " | 139 | fprintf(stderr, "Cannot load %s, generating it " |
| 135 | "with %d threads and %d chunks\n", | 140 | "with %d threads and %d chunks\n", |
| 136 | pd->filename, nthreads, nchunks); | 141 | pd->filename, nthreads, nchunks); |
| 137 | 142 | ||
| 138 | ms = malloc(NMOVES * sizeof(Move)); | 143 | memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t)); |
| 139 | moveset_to_list(pd->moveset, ms); | ||
| 140 | |||
| 141 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 142 | for (j = 0; j < pd->coord->max; j++) | ||
| 143 | ptable_update_index(pd, j, 15); | ||
| 144 | 144 | ||
| 145 | ptable_update(pd, (Cube){0}, 0); | 145 | ptable_update(pd, (Cube){0}, 0); |
| 146 | pd->n = 1; | 146 | pd->n = 1; |
| @@ -151,7 +151,7 @@ genptable(PruneData *pd, int nthreads) | |||
| 151 | 0, pd->n - oldn, pd->n, pd->coord->max); | 151 | 0, pd->n - oldn, pd->n, pd->coord->max); |
| 152 | oldn = pd->n; | 152 | oldn = pd->n; |
| 153 | for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { | 153 | for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { |
| 154 | genptable_bfs(pd, d, ms, nthreads, nchunks); | 154 | genptable_bfs(pd, d, nthreads, nchunks); |
| 155 | genptable_fixnasty(pd, d+1); | 155 | genptable_fixnasty(pd, d+1); |
| 156 | fprintf(stderr, "Depth %d done, generated %" | 156 | fprintf(stderr, "Depth %d done, generated %" |
| 157 | PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", | 157 | PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", |
| @@ -162,12 +162,10 @@ genptable(PruneData *pd, int nthreads) | |||
| 162 | 162 | ||
| 163 | if (!write_ptable_file(pd)) | 163 | if (!write_ptable_file(pd)) |
| 164 | fprintf(stderr, "Error writing ptable file\n"); | 164 | fprintf(stderr, "Error writing ptable file\n"); |
| 165 | |||
| 166 | free(ms); | ||
| 167 | } | 165 | } |
| 168 | 166 | ||
| 169 | static void | 167 | static void |
| 170 | genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks) | 168 | genptable_bfs(PruneData *pd, int d, int nthreads, int nchunks) |
| 171 | { | 169 | { |
| 172 | int i; | 170 | int i; |
| 173 | pthread_t t[nthreads]; | 171 | pthread_t t[nthreads]; |
| @@ -186,7 +184,6 @@ genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks) | |||
| 186 | td[i].nthreads = nthreads; | 184 | td[i].nthreads = nthreads; |
| 187 | td[i].pd = pd; | 185 | td[i].pd = pd; |
| 188 | td[i].d = d; | 186 | td[i].d = d; |
| 189 | td[i].ms = ms; | ||
| 190 | td[i].nchunks = nchunks; | 187 | td[i].nchunks = nchunks; |
| 191 | td[i].mutex = mtx; | 188 | td[i].mutex = mtx; |
| 192 | td[i].upmutex = upmtx; | 189 | td[i].upmutex = upmtx; |
| @@ -237,8 +234,10 @@ instance_bfs(void *arg) | |||
| 237 | uint64_t i, ii, blocksize, rmin, rmax, updated; | 234 | uint64_t i, ii, blocksize, rmin, rmax, updated; |
| 238 | int j, pval, ichunk; | 235 | int j, pval, ichunk; |
| 239 | Cube c, cc; | 236 | Cube c, cc; |
| 237 | Move *ms; | ||
| 240 | 238 | ||
| 241 | td = (ThreadDataGenpt *)arg; | 239 | td = (ThreadDataGenpt *)arg; |
| 240 | ms = td->pd->moveset->sorted_moves; | ||
| 242 | blocksize = td->pd->coord->max / (uint64_t)td->nthreads; | 241 | blocksize = td->pd->coord->max / (uint64_t)td->nthreads; |
| 243 | rmin = ((uint64_t)td->thid) * blocksize; | 242 | rmin = ((uint64_t)td->thid) * blocksize; |
| 244 | rmax = td->thid == td->nthreads - 1 ? | 243 | rmax = td->thid == td->nthreads - 1 ? |
| @@ -253,8 +252,8 @@ instance_bfs(void *arg) | |||
| 253 | pthread_mutex_unlock(td->mutex[ichunk]); | 252 | pthread_mutex_unlock(td->mutex[ichunk]); |
| 254 | if (pval == td->d) { | 253 | if (pval == td->d) { |
| 255 | c = td->pd->coord->cube(i); | 254 | c = td->pd->coord->cube(i); |
| 256 | for (j = 0; td->ms[j] != NULLMOVE; j++) { | 255 | for (j = 0; ms[j] != NULLMOVE; j++) { |
| 257 | cc = apply_move(td->ms[j], c); | 256 | cc = apply_move(ms[j], c); |
| 258 | ii = td->pd->coord->index(cc); | 257 | ii = td->pd->coord->index(cc); |
| 259 | ichunk = findchunk(td->pd, td->nchunks, ii); | 258 | ichunk = findchunk(td->pd, td->nchunks, ii); |
| 260 | pthread_mutex_lock(td->mutex[ichunk]); | 259 | pthread_mutex_lock(td->mutex[ichunk]); |
| @@ -296,7 +295,7 @@ print_ptable(PruneData *pd) | |||
| 296 | uint64_t | 295 | uint64_t |
| 297 | ptablesize(PruneData *pd) | 296 | ptablesize(PruneData *pd) |
| 298 | { | 297 | { |
| 299 | return (pd->coord->max + 1) / 2; | 298 | return (pd->coord->max + ENTRIES_PER_GROUP - 1) / ENTRIES_PER_GROUP; |
| 300 | } | 299 | } |
| 301 | 300 | ||
| 302 | static void | 301 | static void |
| @@ -308,14 +307,16 @@ ptable_update(PruneData *pd, Cube cube, int n) | |||
| 308 | static void | 307 | static void |
| 309 | ptable_update_index(PruneData *pd, uint64_t ind, int n) | 308 | ptable_update_index(PruneData *pd, uint64_t ind, int n) |
| 310 | { | 309 | { |
| 311 | uint8_t oldval2; | 310 | int sh; |
| 312 | int other; | 311 | entry_group_t mask; |
| 312 | uint64_t i; | ||
| 313 | 313 | ||
| 314 | oldval2 = pd->ptable[ind/2]; | 314 | sh = 4 * (ind % ENTRIES_PER_GROUP); |
| 315 | other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | 315 | mask = ((entry_group_t)15) << sh; |
| 316 | i = ind/ENTRIES_PER_GROUP; | ||
| 316 | 317 | ||
| 317 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | 318 | pd->ptable[i] &= ~mask; |
| 318 | /*pd->n++;*/ | 319 | pd->ptable[i] |= (((entry_group_t)n)&15) << sh; |
| 319 | } | 320 | } |
| 320 | 321 | ||
| 321 | int | 322 | int |
| @@ -327,6 +328,10 @@ ptableval(PruneData *pd, Cube cube) | |||
| 327 | static int | 328 | static int |
| 328 | ptableval_index(PruneData *pd, uint64_t ind) | 329 | ptableval_index(PruneData *pd, uint64_t ind) |
| 329 | { | 330 | { |
| 331 | int sh; | ||
| 332 | entry_group_t mask; | ||
| 333 | uint64_t i; | ||
| 334 | |||
| 330 | if (!pd->generated) { | 335 | if (!pd->generated) { |
| 331 | fprintf(stderr, "Warning: request pruning table value" | 336 | fprintf(stderr, "Warning: request pruning table value" |
| 332 | " for uninitialized table %s.\n It's fine, but it" | 337 | " for uninitialized table %s.\n It's fine, but it" |
| @@ -335,7 +340,11 @@ ptableval_index(PruneData *pd, uint64_t ind) | |||
| 335 | genptable(pd, 1); /* TODO: set default or remove this case */ | 340 | genptable(pd, 1); /* TODO: set default or remove this case */ |
| 336 | } | 341 | } |
| 337 | 342 | ||
| 338 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | 343 | sh = 4 * (ind % ENTRIES_PER_GROUP); |
| 344 | mask = ((entry_group_t)15) << sh; | ||
| 345 | i = ind/ENTRIES_PER_GROUP; | ||
| 346 | |||
| 347 | return (pd->ptable[i] & mask) >> sh; | ||
| 339 | } | 348 | } |
| 340 | 349 | ||
| 341 | static bool | 350 | static bool |
| @@ -354,7 +363,7 @@ read_ptable_file(PruneData *pd) | |||
| 354 | if ((f = fopen(fname, "rb")) == NULL) | 363 | if ((f = fopen(fname, "rb")) == NULL) |
| 355 | return false; | 364 | return false; |
| 356 | 365 | ||
| 357 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | 366 | r = fread(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f); |
| 358 | fclose(f); | 367 | fclose(f); |
| 359 | 368 | ||
| 360 | return r == ptablesize(pd); | 369 | return r == ptablesize(pd); |
| @@ -376,7 +385,7 @@ write_ptable_file(PruneData *pd) | |||
| 376 | if ((f = fopen(fname, "wb")) == NULL) | 385 | if ((f = fopen(fname, "wb")) == NULL) |
| 377 | return false; | 386 | return false; |
| 378 | 387 | ||
| 379 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | 388 | written = fwrite(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f); |
| 380 | fclose(f); | 389 | fclose(f); |
| 381 | 390 | ||
| 382 | return written == ptablesize(pd); | 391 | return written == ptablesize(pd); |
