aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-12-14 11:59:22 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2024-12-14 11:59:22 +0100
commit4a88a686d5e08404080ed6954b70c0db252aa220 (patch)
treec1fb469d5a2a68c8e4651ad7837d3dd6fe2ff93e
parent9ac266c76f39620d8343e46ca41cb09d1534384c (diff)
downloadnissy-core-4a88a686d5e08404080ed6954b70c0db252aa220.tar.gz
nissy-core-4a88a686d5e08404080ed6954b70c0db252aa220.zip
Allow choosing number of threads when calling solve()
Diffstat (limited to '')
-rwxr-xr-xconfigure.sh4
-rw-r--r--python/example.py2
-rw-r--r--python/nissy_module.c12
-rw-r--r--shell/shell.c18
-rw-r--r--src/nissy.c16
-rw-r--r--src/nissy.h4
-rw-r--r--src/solvers/h48/solve.h17
-rw-r--r--tools/300_solve_small/solve_small.c2
-rw-r--r--tools/301_solve_file/solve_file.c2
-rw-r--r--tools/302_solve_multisol/solve_multisol.c2
10 files changed, 58 insertions, 21 deletions
diff --git a/configure.sh b/configure.sh
index aac6444..ec0343a 100755
--- a/configure.sh
+++ b/configure.sh
@@ -14,7 +14,9 @@
14# The string "architecture" must be one of "AVX2", "NEON" or "PORTABLE". 14# The string "architecture" must be one of "AVX2", "NEON" or "PORTABLE".
15# 15#
16# THREADS=n 16# THREADS=n
17# Choose how many threads to use for multi-threaded oerations. 17# The maximum number of threads to use for multi-threaded operations.
18# This is also used as default value in case an operation allows
19# specifying how many threads to use.
18# By default, 8 threads will be used (TODO: in the future this will be 20# By default, 8 threads will be used (TODO: in the future this will be
19# determined base on the system). 21# determined base on the system).
20# The number n must be between 1 and 128. 22# The number n must be between 1 and 128.
diff --git a/python/example.py b/python/example.py
index fdea2d4..b939183 100644
--- a/python/example.py
+++ b/python/example.py
@@ -23,7 +23,7 @@ data = bytearray(open("tables/" + solver, "rb").read())
23cube = nissy.applymoves(nissy.solved_cube, "U F R2"); 23cube = nissy.applymoves(nissy.solved_cube, "U F R2");
24 24
25# Solve! 25# Solve!
26solutions = nissy.solve(cube, solver, nissy.nissflag_normal, 0, 9, 3, -1, data) 26solutions = nissy.solve(cube, solver, nissy.nissflag_normal, 0, 9, 3, -1, 4, data)
27 27
28# Print the solutions, one per line 28# Print the solutions, one per line
29print("Found ", len(solutions), " solutions:") 29print("Found ", len(solutions), " solutions:")
diff --git a/python/nissy_module.c b/python/nissy_module.c
index 2357b90..947d06f 100644
--- a/python/nissy_module.c
+++ b/python/nissy_module.c
@@ -306,7 +306,8 @@ checkdata(PyObject *self, PyObject *args)
306} 306}
307 307
308PyDoc_STRVAR(solve_doc, 308PyDoc_STRVAR(solve_doc,
309"solve(cube, solver, nissflag, minmoves, maxmoves, maxsolutions, optimal, data)\n" 309"solve(cube, solver, nissflag, minmoves, maxmoves, maxsolutions,"
310" optimal, threads, data)\n"
310"--\n\n" 311"--\n\n"
311"Solves the given 'cube' with the given 'solver' and other parameters." 312"Solves the given 'cube' with the given 'solver' and other parameters."
312"See the documentation for libnissy (in nissy.h) for details.\n" 313"See the documentation for libnissy (in nissy.h) for details.\n"
@@ -319,6 +320,7 @@ PyDoc_STRVAR(solve_doc,
319" - maxsolution: the maximum number of solutions to return\n" 320" - maxsolution: the maximum number of solutions to return\n"
320" - optimal: the largest number of moves from the shortest solution" 321" - optimal: the largest number of moves from the shortest solution"
321"(set to -1 to ignore)\n" 322"(set to -1 to ignore)\n"
323" - threads: the number of threads to use (0 for default)\n"
322" - data: a bytearray containing the data for the solver\n" 324" - data: a bytearray containing the data for the solver\n"
323"\n" 325"\n"
324"Returns: a list with the solutions found\n" 326"Returns: a list with the solutions found\n"
@@ -328,20 +330,20 @@ solve(PyObject *self, PyObject *args)
328{ 330{
329 long long result; 331 long long result;
330 unsigned nissflag, minmoves, maxmoves, maxsolutions; 332 unsigned nissflag, minmoves, maxmoves, maxsolutions;
331 int optimal, i, j, k; 333 int optimal, i, j, k, threads;
332 const char *cube, *solver; 334 const char *cube, *solver;
333 char solutions[MAX_SOLUTIONS_SIZE]; 335 char solutions[MAX_SOLUTIONS_SIZE];
334 long long stats[NISSY_SIZE_SOLVE_STATS]; 336 long long stats[NISSY_SIZE_SOLVE_STATS];
335 PyByteArrayObject *data; 337 PyByteArrayObject *data;
336 PyObject *list, *item; 338 PyObject *list, *item;
337 339
338 if (!PyArg_ParseTuple(args, "ssIIIIiY", &cube, &solver, &nissflag, 340 if (!PyArg_ParseTuple(args, "ssIIIIiiY", &cube, &solver, &nissflag,
339 &minmoves, &maxmoves, &maxsolutions, &optimal, &data)) 341 &minmoves, &maxmoves, &maxsolutions, &optimal, &threads, &data))
340 return NULL; 342 return NULL;
341 343
342 Py_BEGIN_ALLOW_THREADS 344 Py_BEGIN_ALLOW_THREADS
343 result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, 345 result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves,
344 maxsolutions, optimal, data->ob_alloc, data->ob_bytes, 346 maxsolutions, optimal, threads, data->ob_alloc, data->ob_bytes,
345 MAX_SOLUTIONS_SIZE, solutions, stats); 347 MAX_SOLUTIONS_SIZE, solutions, stats);
346 Py_END_ALLOW_THREADS 348 Py_END_ALLOW_THREADS
347 349
diff --git a/shell/shell.c b/shell/shell.c
index e548fd6..5a2d283 100644
--- a/shell/shell.c
+++ b/shell/shell.c
@@ -28,6 +28,7 @@
28#define FLAG_MAXMOVES "-M" 28#define FLAG_MAXMOVES "-M"
29#define FLAG_OPTIMAL "-O" 29#define FLAG_OPTIMAL "-O"
30#define FLAG_MAXSOLUTIONS "-n" 30#define FLAG_MAXSOLUTIONS "-n"
31#define FLAG_THREADS "-t"
31 32
32#define INFO_CUBEFORMAT(cube) cube " must be given in B32 format." 33#define INFO_CUBEFORMAT(cube) cube " must be given in B32 format."
33#define INFO_MOVESFORMAT "The accepted moves are U, D, R, L, F and B, " \ 34#define INFO_MOVESFORMAT "The accepted moves are U, D, R, L, F and B, " \
@@ -54,6 +55,7 @@ typedef struct {
54 unsigned maxmoves; 55 unsigned maxmoves;
55 unsigned optimal; 56 unsigned optimal;
56 unsigned maxsolutions; 57 unsigned maxsolutions;
58 unsigned threads;
57} args_t; 59} args_t;
58 60
59static int64_t compose_exec(args_t *); 61static int64_t compose_exec(args_t *);
@@ -88,6 +90,7 @@ static bool set_minmoves(int, char **, args_t *);
88static bool set_maxmoves(int, char **, args_t *); 90static bool set_maxmoves(int, char **, args_t *);
89static bool set_optimal(int, char **, args_t *); 91static bool set_optimal(int, char **, args_t *);
90static bool set_maxsolutions(int, char **, args_t *); 92static bool set_maxsolutions(int, char **, args_t *);
93static bool set_threads(int, char **, args_t *);
91static bool set_id(int, char **, args_t *); 94static bool set_id(int, char **, args_t *);
92 95
93static uint64_t rand64(void); 96static uint64_t rand64(void);
@@ -113,6 +116,7 @@ struct {
113 OPTION(FLAG_MAXMOVES, 1, set_maxmoves), 116 OPTION(FLAG_MAXMOVES, 1, set_maxmoves),
114 OPTION(FLAG_OPTIMAL, 1, set_optimal), 117 OPTION(FLAG_OPTIMAL, 1, set_optimal),
115 OPTION(FLAG_MAXSOLUTIONS, 1, set_maxsolutions), 118 OPTION(FLAG_MAXSOLUTIONS, 1, set_maxsolutions),
119 OPTION(FLAG_THREADS, 1, set_threads),
116 OPTION(NULL, 0, NULL) 120 OPTION(NULL, 0, NULL)
117}; 121};
118 122
@@ -193,9 +197,10 @@ struct {
193 "solve", 197 "solve",
194 "solve " FLAG_SOLVER " SOLVER" 198 "solve " FLAG_SOLVER " SOLVER"
195 "[" FLAG_MINMOVES " n] [" FLAG_MAXMOVES " N] " 199 "[" FLAG_MINMOVES " n] [" FLAG_MAXMOVES " N] "
196 FLAG_CUBE " CUBE", 200 FLAG_CUBE " CUBE"
201 FLAG_THREADS " T",
197 "Solve the given CUBE using SOLVER, " 202 "Solve the given CUBE using SOLVER, "
198 "using at least n and at most N moves. " 203 "using at least n and at most N moves, and T threads. "
199 INFO_CUBEFORMAT("CUBE"), 204 INFO_CUBEFORMAT("CUBE"),
200 solve_exec 205 solve_exec
201 ), 206 ),
@@ -475,7 +480,7 @@ solve_exec(args_t *args)
475 480
476 ret = nissy_solve( 481 ret = nissy_solve(
477 args->cube, args->str_solver, nissflag, args->minmoves, 482 args->cube, args->str_solver, nissflag, args->minmoves,
478 args->maxmoves, args->maxsolutions, args->optimal, 483 args->maxmoves, args->maxsolutions, args->optimal, args->threads,
479 size, buf, SOLUTIONS_BUFFER_SIZE, solutions, stats); 484 size, buf, SOLUTIONS_BUFFER_SIZE, solutions, stats);
480 485
481 free(buf); 486 free(buf);
@@ -557,6 +562,7 @@ parse_args(int argc, char **argv, args_t *args)
557 .maxmoves = 20, 562 .maxmoves = 20,
558 .optimal = -1, 563 .optimal = -1,
559 .maxsolutions = 1, 564 .maxsolutions = 1,
565 .threads = 0,
560 }; 566 };
561 567
562 if (argc == 0) { 568 if (argc == 0) {
@@ -728,6 +734,12 @@ set_maxsolutions(int argc, char **argv, args_t *args)
728 return parse_uint(argv[0], &args->maxsolutions); 734 return parse_uint(argv[0], &args->maxsolutions);
729} 735}
730 736
737static bool
738set_threads(int argc, char **argv, args_t *args)
739{
740 return parse_uint(argv[0], &args->threads);
741}
742
731void 743void
732log_stderr(const char *str, ...) 744log_stderr(const char *str, ...)
733{ 745{
diff --git a/src/nissy.c b/src/nissy.c
index f933cab..5d009ba 100644
--- a/src/nissy.c
+++ b/src/nissy.c
@@ -489,6 +489,7 @@ nissy_solve(
489 unsigned maxmoves, 489 unsigned maxmoves,
490 unsigned maxsols, 490 unsigned maxsols,
491 int optimal, 491 int optimal,
492 int threads,
492 unsigned long long data_size, 493 unsigned long long data_size,
493 const char data[data_size], 494 const char data[data_size],
494 unsigned sols_size, 495 unsigned sols_size,
@@ -499,6 +500,7 @@ nissy_solve(
499 cube_t c; 500 cube_t c;
500 long long parse_ret; 501 long long parse_ret;
501 uint8_t h, k; 502 uint8_t h, k;
503 int t;
502 504
503 if (solver == NULL) { 505 if (solver == NULL) {
504 LOG("Error: 'solver' argument is NULL\n"); 506 LOG("Error: 'solver' argument is NULL\n");
@@ -522,10 +524,22 @@ nissy_solve(
522 return 0; 524 return 0;
523 } 525 }
524 526
527 t = threads == 0 ? THREADS : threads;
528 if (t < 0) {
529 LOG("solve: 'threads' is negative. Please provide a "
530 "number of threads between 1 and %d\n", THREADS);
531 return NISSY_ERROR_OPTIONS;
532 }
533 if (t > THREADS) {
534 LOG("solve: 'threads' is above the maximum value of %d\n",
535 THREADS);
536 return NISSY_ERROR_OPTIONS;
537 }
538
525 if (!strncmp(solver, "h48", 3)) { 539 if (!strncmp(solver, "h48", 3)) {
526 parse_ret = parse_h48_solver(solver, &h, &k); 540 parse_ret = parse_h48_solver(solver, &h, &k);
527 if (parse_ret == NISSY_OK) 541 if (parse_ret == NISSY_OK)
528 return solve_h48(c, minmoves, maxmoves, maxsols, 542 return solve_h48(c, minmoves, maxmoves, maxsols, t,
529 data_size, data, sols_size, sols, stats); 543 data_size, data, sols_size, sols, stats);
530 else 544 else
531 return parse_ret; 545 return parse_ret;
diff --git a/src/nissy.h b/src/nissy.h
index 8394fad..94c604c 100644
--- a/src/nissy.h
+++ b/src/nissy.h
@@ -259,6 +259,9 @@ Parameters:
259 maxsols - The maximum number of solutions. 259 maxsols - The maximum number of solutions.
260 optimal - If set to a non-negative value, the maximum number of moves 260 optimal - If set to a non-negative value, the maximum number of moves
261 above the optimal solution length. 261 above the optimal solution length.
262 threads - The number of threads to use. Must be less than or equalt to
263 the value of the compile-time constant THREADS. If set to 0,
264 the default value THREADS will be used.
262 data_size - The size of the data buffer. 265 data_size - The size of the data buffer.
263 data - The data for the solver. Can be computed with gendata. 266 data - The data for the solver. Can be computed with gendata.
264 sols_size - The size of the solutions buffer. 267 sols_size - The size of the solutions buffer.
@@ -286,6 +289,7 @@ nissy_solve(
286 unsigned maxmoves, 289 unsigned maxmoves,
287 unsigned maxsolutions, 290 unsigned maxsolutions,
288 int optimal, 291 int optimal,
292 int threads,
289 unsigned long long data_size, 293 unsigned long long data_size,
290 const char data[data_size], 294 const char data[data_size],
291 unsigned sols_size, 295 unsigned sols_size,
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index 8666007..0969c45 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -38,6 +38,7 @@ typedef struct {
38 int64_t nodes_visited; 38 int64_t nodes_visited;
39 int64_t table_fallbacks; 39 int64_t table_fallbacks;
40 int64_t table_lookups; 40 int64_t table_lookups;
41 int threads;
41 int ntasks; 42 int ntasks;
42 solve_h48_task_t *tasks; 43 solve_h48_task_t *tasks;
43 int thread_id; 44 int thread_id;
@@ -62,7 +63,7 @@ STATIC int64_t solve_h48_maketasks(
62 solve_h48_task_t [static STARTING_CUBES], int *); 63 solve_h48_task_t [static STARTING_CUBES], int *);
63STATIC void *solve_h48_runthread(void *); 64STATIC void *solve_h48_runthread(void *);
64STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t *); 65STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t *);
65STATIC int64_t solve_h48(cube_t, int8_t, int8_t, uint64_t, uint64_t, 66STATIC int64_t solve_h48(cube_t, int8_t, int8_t, uint64_t, int, uint64_t,
66 const void *, uint64_t, char *, long long [static NISSY_SIZE_SOLVE_STATS]); 67 const void *, uint64_t, char *, long long [static NISSY_SIZE_SOLVE_STATS]);
67 68
68STATIC int64_t 69STATIC int64_t
@@ -316,7 +317,7 @@ solve_h48_runthread(void *arg)
316 dfsarg = (dfsarg_solve_h48_t *)arg; 317 dfsarg = (dfsarg_solve_h48_t *)arg;
317 cube = dfsarg->start_cube; 318 cube = dfsarg->start_cube;
318 319
319 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += THREADS) { 320 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) {
320 task = dfsarg->tasks[i]; 321 task = dfsarg->tasks[i];
321 memcpy(dfsarg->moves, task.moves, STARTING_MOVES); 322 memcpy(dfsarg->moves, task.moves, STARTING_MOVES);
322 dfsarg->cube = cube; 323 dfsarg->cube = cube;
@@ -407,6 +408,7 @@ solve_h48(
407 int8_t minmoves, 408 int8_t minmoves,
408 int8_t maxmoves, 409 int8_t maxmoves,
409 uint64_t maxsolutions, 410 uint64_t maxsolutions,
411 int threads,
410 uint64_t data_size, 412 uint64_t data_size,
411 const void *data, 413 const void *data,
412 uint64_t solutions_size, 414 uint64_t solutions_size,
@@ -461,7 +463,7 @@ solve_h48(
461 fallback2 = h48data + offset; 463 fallback2 = h48data + offset;
462 464
463 symmask = symmetry_mask(cube); 465 symmask = symmetry_mask(cube);
464 for (i = 0; i < THREADS; i++) { 466 for (i = 0; i < threads; i++) {
465 arg[i] = (dfsarg_solve_h48_t) { 467 arg[i] = (dfsarg_solve_h48_t) {
466 .start_cube = cube, 468 .start_cube = cube,
467 .cube = cube, 469 .cube = cube,
@@ -481,6 +483,7 @@ solve_h48(
481 .nodes_visited = 0, 483 .nodes_visited = 0,
482 .table_fallbacks = 0, 484 .table_fallbacks = 0,
483 .table_lookups = 0, 485 .table_lookups = 0,
486 .threads = threads,
484 .thread_id = i, 487 .thread_id = i,
485 .solutions_mutex = &solutions_mutex, 488 .solutions_mutex = &solutions_mutex,
486 }; 489 };
@@ -505,7 +508,7 @@ solve_h48(
505 if (*arg[0].nsols >= (int64_t)maxsolutions) 508 if (*arg[0].nsols >= (int64_t)maxsolutions)
506 goto solve_h48_done; 509 goto solve_h48_done;
507 510
508 for (i = 0; i < THREADS; i++) { 511 for (i = 0; i < threads; i++) {
509 arg[i].ntasks = ntasks; 512 arg[i].ntasks = ntasks;
510 arg[i].tasks = tasks; 513 arg[i].tasks = tasks;
511 } 514 }
@@ -520,12 +523,12 @@ solve_h48(
520 if (d >= 10) 523 if (d >= 10)
521 LOG("Found %" PRId64 " solutions, searching at depth %" 524 LOG("Found %" PRId64 " solutions, searching at depth %"
522 PRId8 "\n", nsols, d); 525 PRId8 "\n", nsols, d);
523 for (i = 0; i < THREADS; i++) { 526 for (i = 0; i < threads; i++) {
524 arg[i].depth = d; 527 arg[i].depth = d;
525 pthread_create( 528 pthread_create(
526 &thread[i], NULL, solve_h48_runthread, &arg[i]); 529 &thread[i], NULL, solve_h48_runthread, &arg[i]);
527 } 530 }
528 for (i = 0; i < THREADS; i++) 531 for (i = 0; i < threads; i++)
529 pthread_join(thread[i], NULL); 532 pthread_join(thread[i], NULL);
530 } 533 }
531 534
@@ -534,7 +537,7 @@ solve_h48_done:
534 goto solve_h48_error_solutions_buffer; 537 goto solve_h48_error_solutions_buffer;
535 538
536 nodes_visited = table_lookups = table_fallbacks = 0; 539 nodes_visited = table_lookups = table_fallbacks = 0;
537 for (i = 0; i < THREADS; i++) { 540 for (i = 0; i < threads; i++) {
538 nodes_visited += arg[i].nodes_visited; 541 nodes_visited += arg[i].nodes_visited;
539 table_fallbacks += arg[i].table_fallbacks; 542 table_fallbacks += arg[i].table_fallbacks;
540 table_lookups += arg[i].table_lookups; 543 table_lookups += arg[i].table_lookups;
diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c
index 09ca85a..073de89 100644
--- a/tools/300_solve_small/solve_small.c
+++ b/tools/300_solve_small/solve_small.c
@@ -37,7 +37,7 @@ void run(void) {
37 continue; 37 continue;
38 } 38 }
39 n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, 39 n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
40 0, 20, 1, -1, size, buf, SOL_BUFFER_LEN, sol, stats); 40 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats);
41 if (n == 0) 41 if (n == 0)
42 printf("No solution found\n"); 42 printf("No solution found\n");
43 else 43 else
diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c
index aa45df0..fe41bb7 100644
--- a/tools/301_solve_file/solve_file.c
+++ b/tools/301_solve_file/solve_file.c
@@ -24,7 +24,7 @@ void run(void) {
24 continue; 24 continue;
25 } 25 }
26 nsols = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, 26 nsols = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
27 0, 20, 1, -1, size, buf, SOL_BUFFER_LEN, sol, stats); 27 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats);
28 if (nsols == 0) 28 if (nsols == 0)
29 printf("No solution found\n"); 29 printf("No solution found\n");
30 else 30 else
diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c
index 739ccbd..a03c2a0 100644
--- a/tools/302_solve_multisol/solve_multisol.c
+++ b/tools/302_solve_multisol/solve_multisol.c
@@ -30,7 +30,7 @@ void run(void) {
30 continue; 30 continue;
31 } 31 }
32 n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, 32 n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
33 0, 20, nsol, -1, size, buf, SOL_BUFFER_LEN, sol, stats); 33 0, 20, nsol, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats);
34 if (n == 0) 34 if (n == 0)
35 printf("No solution found\n"); 35 printf("No solution found\n");
36 else 36 else

Generated with cgit - Back to sebastiano.tronto.net