diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-09-07 10:55:30 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-09-07 10:55:30 +0200 |
| commit | 0eba10bf55283acdb687a172404a89e5a72a00c2 (patch) | |
| tree | 877d4939c1ceb8850e41583a1f898760d4a0067b | |
| parent | 1fcba7fcea462d67379c8d289bd7e0ad52170e02 (diff) | |
| download | nissy-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).
| -rw-r--r-- | src/arch/arch.h | 4 | ||||
| -rw-r--r-- | src/solvers/h48/gendata_h48.h | 120 | ||||
| -rwxr-xr-x | tools/run_tool.sh | 3 |
3 files changed, 90 insertions, 37 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 | ||
| 61 | typedef struct { | 61 | typedef 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 *); | |||
| 84 | STATIC int64_t gendata_h48h0k4_bfs_fromdone(h48h0k4_bfs_arg_t *); | 81 | STATIC int64_t gendata_h48h0k4_bfs_fromdone(h48h0k4_bfs_arg_t *); |
| 85 | STATIC int64_t gendata_h48h0k4_bfs_fromnew(h48h0k4_bfs_arg_t *); | 82 | STATIC int64_t gendata_h48h0k4_bfs_fromnew(h48h0k4_bfs_arg_t *); |
| 86 | STATIC size_t gendata_h48k2(gendata_h48_arg_t *); | 83 | STATIC size_t gendata_h48k2(gendata_h48_arg_t *); |
| 84 | STATIC_INLINE void gendata_h48k2_mark(cube_t, int8_t, h48k2_dfs_arg_t *); | ||
| 85 | STATIC_INLINE bool gendata_h48k2_dfs_stop(cube_t, uint8_t, h48k2_dfs_arg_t *); | ||
| 87 | STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg); | 86 | STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg); |
| 88 | 87 | ||
| 89 | STATIC_INLINE int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint8_t, uint32_t *); | 88 | STATIC_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: | |||
| 365 | STATIC void | 362 | STATIC void |
| 366 | gendata_h48k2_dfs(h48k2_dfs_arg_t *arg) | 363 | gendata_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 | |||
| 421 | STATIC_INLINE void | ||
| 422 | gendata_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? */ | 437 | STATIC_INLINE bool |
| 387 | mval = h48map_value(arg->shortcubes, fullcoord); | 438 | gendata_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 | ||
diff --git a/tools/run_tool.sh b/tools/run_tool.sh index 495d68c..2462b2d 100755 --- a/tools/run_tool.sh +++ b/tools/run_tool.sh | |||
| @@ -20,4 +20,5 @@ for t in tools/*; do | |||
| 20 | break | 20 | break |
| 21 | done | 21 | done |
| 22 | 22 | ||
| 23 | rm -rf $BIN $CUBEOBJ | 23 | # $BIN is kept so it can be run manually for profiling |
| 24 | rm -rf $CUBEOBJ | ||
