aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-09-07 10:55:30 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2024-09-07 10:55:30 +0200
commit0eba10bf55283acdb687a172404a89e5a72a00c2 (patch)
tree877d4939c1ceb8850e41583a1f898760d4a0067b /src
parent1fcba7fcea462d67379c8d289bd7e0ad52170e02 (diff)
downloadnissy-core-0eba10bf55283acdb687a172404a89e5a72a00c2.tar.gz
nissy-core-0eba10bf55283acdb687a172404a89e5a72a00c2.zip
Improved gendata_h48k2 performance
Performance for the "real coordinate" case (h0) is ok, but still around 3x slower than the gendata_h48k4 method. Performance for the intermediate tables is not good, but for now I'll keep it like this. This also shows that for h11 we should use the gendata_h48k4 method for h11. For intermediate table, h8, h9 and h10 might be too slow to compute in an acceptable time. We could restrict to h7 (largest with base = 9).
Diffstat (limited to '')
-rw-r--r--src/arch/arch.h4
-rw-r--r--src/solvers/h48/gendata_h48.h120
2 files changed, 88 insertions, 36 deletions
diff --git a/src/arch/arch.h b/src/arch/arch.h
index d5e0218..e5de0cf 100644
--- a/src/arch/arch.h
+++ b/src/arch/arch.h
@@ -1,4 +1,4 @@
1#if defined(CUBE_AVX2) 1#if defined(AVX2)
2 2
3#include <immintrin.h> 3#include <immintrin.h>
4 4
@@ -9,7 +9,7 @@ typedef __m256i cube_t;
9#include "avx2.h" 9#include "avx2.h"
10#endif 10#endif
11 11
12#elif defined(CUBE_NEON) 12#elif defined(NEON)
13 13
14#include <stdlib.h> 14#include <stdlib.h>
15#include <arm_neon.h> 15#include <arm_neon.h>
diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h
index 299491e..4b20c13 100644
--- a/src/solvers/h48/gendata_h48.h
+++ b/src/solvers/h48/gendata_h48.h
@@ -60,13 +60,10 @@ typedef struct {
60 60
61typedef struct { 61typedef struct {
62 cube_t cube; 62 cube_t cube;
63 uint8_t moves[MAXLEN];
64 uint8_t h; 63 uint8_t h;
65 uint8_t k; 64 uint8_t k;
66 uint8_t base; 65 uint8_t base;
67 uint8_t depth;
68 uint8_t shortdepth; 66 uint8_t shortdepth;
69 uint8_t maxdepth;
70 uint32_t *cocsepdata; 67 uint32_t *cocsepdata;
71 uint32_t *h48data; 68 uint32_t *h48data;
72 uint64_t *selfsim; 69 uint64_t *selfsim;
@@ -84,6 +81,8 @@ STATIC int64_t gendata_h48h0k4_bfs(h48h0k4_bfs_arg_t *);
84STATIC int64_t gendata_h48h0k4_bfs_fromdone(h48h0k4_bfs_arg_t *); 81STATIC int64_t gendata_h48h0k4_bfs_fromdone(h48h0k4_bfs_arg_t *);
85STATIC int64_t gendata_h48h0k4_bfs_fromnew(h48h0k4_bfs_arg_t *); 82STATIC int64_t gendata_h48h0k4_bfs_fromnew(h48h0k4_bfs_arg_t *);
86STATIC size_t gendata_h48k2(gendata_h48_arg_t *); 83STATIC size_t gendata_h48k2(gendata_h48_arg_t *);
84STATIC_INLINE void gendata_h48k2_mark(cube_t, int8_t, h48k2_dfs_arg_t *);
85STATIC_INLINE bool gendata_h48k2_dfs_stop(cube_t, uint8_t, h48k2_dfs_arg_t *);
87STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg); 86STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg);
88 87
89STATIC_INLINE int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint8_t, uint32_t *); 88STATIC_INLINE int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint8_t, uint32_t *);
@@ -328,9 +327,7 @@ gendata_h48k2(gendata_h48_arg_t *arg)
328 .h = arg->h, 327 .h = arg->h,
329 .k = arg->k, 328 .k = arg->k,
330 .base = base[arg->h], 329 .base = base[arg->h],
331 .depth = shortdepth,
332 .shortdepth = shortdepth, 330 .shortdepth = shortdepth,
333 .maxdepth = MIN(arg->maxdepth, base[arg->h]+2),
334 .cocsepdata = arg->cocsepdata, 331 .cocsepdata = arg->cocsepdata,
335 .h48data = arg->h48data, 332 .h48data = arg->h48data,
336 .selfsim = arg->selfsim, 333 .selfsim = arg->selfsim,
@@ -345,7 +342,7 @@ gendata_h48k2(gendata_h48_arg_t *arg)
345 ) { 342 ) {
346 dfsarg.cube = invcoord_h48(kv.key, arg->crep, 11); 343 dfsarg.cube = invcoord_h48(kv.key, arg->crep, 11);
347 gendata_h48k2_dfs(&dfsarg); 344 gendata_h48k2_dfs(&dfsarg);
348 if (++i % UINT64_C(1000000) == 0) 345 if (++ii % UINT64_C(1000000) == 0)
349 LOG("Processed %" PRIu64 " short cubes\n", ii); 346 LOG("Processed %" PRIu64 " short cubes\n", ii);
350 } 347 }
351 348
@@ -365,43 +362,98 @@ gendata_h48k2_return_size:
365STATIC void 362STATIC void
366gendata_h48k2_dfs(h48k2_dfs_arg_t *arg) 363gendata_h48k2_dfs(h48k2_dfs_arg_t *arg)
367{ 364{
368 cube_t ccc; 365 int8_t d;
369 bool toodeep, backtracked; 366 uint8_t m[4];
370 uint8_t nmoves, oldval, newval; 367 cube_t cube[4];
371 uint64_t mval; 368
369 d = (int8_t)arg->shortdepth - (int8_t)arg->base;
370
371 /* Depth d+0 (shortcubes) */
372 gendata_h48k2_mark(arg->cube, d, arg);
373
374 /* Depth d+1 */
375 for (m[0] = 0; m[0] < 18; m[0]++) {
376 cube[0] = move(arg->cube, m[0]);
377 if (gendata_h48k2_dfs_stop(cube[0], d+1, arg))
378 continue;
379 gendata_h48k2_mark(cube[0], d+1, arg);
380
381 /* Depth d+2 */
382 for (m[1] = 0; m[1] < 18; m[1]++) {
383 if (m[0] / 3 == m[1] / 3) {
384 m[1] += 2;
385 continue;
386 }
387 cube[1] = move(cube[0], m[1]);
388 if (gendata_h48k2_dfs_stop(cube[1], d+2, arg))
389 continue;
390 gendata_h48k2_mark(cube[1], d+2, arg);
391 if (d >= 0)
392 continue;
393
394 /* Depth d+3 */
395 for (m[2] = 0; m[2] < 18; m[2]++) {
396 if (!allowednextmove(m, 3)) {
397 m[2] += 2;
398 continue;
399 }
400 cube[2] = move(cube[1], m[2]);
401 if (gendata_h48k2_dfs_stop(cube[2], d+3, arg))
402 continue;
403 gendata_h48k2_mark(cube[2], d+3, arg);
404 if (d >= -1)
405 continue;
406
407 /* Depth d+4 */
408 for (m[3] = 0; m[3] < 18; m[3]++) {
409 if (!allowednextmove(m, 4)) {
410 m[3] += 2;
411 continue;
412 }
413 cube[3] = move(cube[2], m[3]);
414 gendata_h48k2_mark(cube[3], d+4, arg);
415 }
416 }
417 }
418 }
419}
420
421STATIC_INLINE void
422gendata_h48k2_mark(cube_t cube, int8_t depth, h48k2_dfs_arg_t *arg)
423{
424 uint8_t oldval, newval;
372 int64_t coord, fullcoord; 425 int64_t coord, fullcoord;
373 h48k2_dfs_arg_t nextarg;
374 uint8_t m;
375 426
376 ccc = arg->cube; 427 FOREACH_H48SIM(cube, arg->cocsepdata, arg->selfsim,
377 FOREACH_H48SIM(ccc, arg->cocsepdata, arg->selfsim, 428 fullcoord = coord_h48(cube, arg->cocsepdata, 11);
378 fullcoord = coord_h48(ccc, arg->cocsepdata, 11);
379 coord = fullcoord >> (int64_t)(11 - arg->h); 429 coord = fullcoord >> (int64_t)(11 - arg->h);
380 oldval = get_esep_pval(arg->h48data, coord, arg->k); 430 oldval = get_esep_pval(arg->h48data, coord, arg->k);
381 newval = arg->depth >= arg->base ? arg->depth - arg->base : 0; 431 newval = (uint8_t)MAX(depth, 0);
382 set_esep_pval( 432 set_esep_pval(
383 arg->h48data, coord, arg->k, MIN(oldval, newval)); 433 arg->h48data, coord, arg->k, MIN(oldval, newval));
384 ) 434 )
435}
385 436
386 fullcoord = coord_h48(arg->cube, arg->cocsepdata, 11); /* Necessary? */ 437STATIC_INLINE bool
387 mval = h48map_value(arg->shortcubes, fullcoord); 438gendata_h48k2_dfs_stop(cube_t cube, uint8_t depth, h48k2_dfs_arg_t *arg)
388 backtracked = mval <= arg->shortdepth && arg->depth != arg->shortdepth; 439{
389 toodeep = arg->depth >= arg->maxdepth; 440 uint64_t val;
390 if (backtracked || toodeep) 441 int64_t coord;
391 return; 442 uint8_t oldval;
392 443
393 /* TODO: avoid copy, change arg and undo changes after recursion */ 444 if (arg->h == 0 || arg->h == 11) {
394 nextarg = *arg; 445 /* We are in the "real coordinate" case, we can stop
395 nextarg.depth++; 446 if this coordinate has already been visited */
396 nmoves = nextarg.depth - arg->shortdepth; 447 coord = coord_h48(cube, arg->cocsepdata, arg->h);
397 for (m = 0; m < 18; m++) { 448 oldval = get_esep_pval(arg->h48data, coord, arg->k);
398 nextarg.moves[nmoves - 1] = m; 449 return oldval <= depth;
399 if (!allowednextmove(nextarg.moves, nmoves)) { 450 } else {
400 m += 2; 451 /* With 0 < k < 11 we do not have a "real coordinate".
401 continue; 452 The best we can do is checking if we backtracked to
402 } 453 one of the "short cubes". */
403 nextarg.cube = move(arg->cube, m); 454 coord = coord_h48(cube, arg->cocsepdata, 11);
404 gendata_h48k2_dfs(&nextarg); 455 val = h48map_value(arg->shortcubes, coord);
456 return val <= arg->shortdepth;
405 } 457 }
406} 458}
407 459

Generated with cgit - Back to sebastiano.tronto.net