aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--build.bat26
-rw-r--r--src/solvers/distribution.h10
-rw-r--r--src/solvers/h48/distribution_h48.h10
-rw-r--r--src/solvers/h48/gendata_h48.h14
-rw-r--r--src/solvers/h48/solve.h12
-rw-r--r--src/utils/prefetch.h16
-rw-r--r--src/utils/wrapthread.h86
8 files changed, 112 insertions, 68 deletions
diff --git a/README.md b/README.md
index 338a280..64871b5 100644
--- a/README.md
+++ b/README.md
@@ -64,9 +64,9 @@ can be used to build the basic shell, while
64Builds and runs the unit tests. See `build.bat help` for a list of 64Builds and runs the unit tests. See `build.bat help` for a list of
65all available options. 65all available options.
66 66
67Note: At the moment certain optimizations, such as multithreading and 67Note: The build script for Windows does not support all the options
68advanced CPU instructions, are not supported on Windows. 68available with build.sh. If you want to tune the build options, you'll
69Work is ongoing to improve Windows support. 69have to manually edit the build script.
70 70
71## Running tests 71## Running tests
72 72
diff --git a/build.bat b/build.bat
index 909ff01..9f9f5f1 100644
--- a/build.bat
+++ b/build.bat
@@ -9,15 +9,25 @@ if [%1]==[/d] (
9 9
10SET CC=clang 10SET CC=clang
11SET CXX=clang++ 11SET CXX=clang++
12SET ARCH=PORTABLE 12SET THREADS=16
13SET THREADS=1
14SET SANITIZE= 13SET SANITIZE=
15 14
16:: TODO depends on ARCH variable 15SET ARCH=PORTABLE
17SET ARCHOPTS= 16clang -march=native -dM -E - < NUL | findstr /C:"__AVX2__" >NUL 2>&1
18:: TODO depends on SANITIZE variable 17if %ERRORLEVEL% EQU 0 (
19SET DFLAGS=-g3 -DDEBUG 18 SET ARCH=AVX2
19 SET ARCHOPTS=-mavx2
20 goto :ArchDone
21)
22clang -march=native -dM -E - < NUL | findstr /C:"__ARM_NEON" >NUL 2>&1
23if %ERRORLEVEL% EQU 0 (
24 SET ARCH=NEON
25 goto :ArchDone
26)
27:ArchDone
28
20 29
30SET DFLAGS=-g3 -DDEBUG
21SET WARNINGS=-Wno-deprecated-declarations 31SET WARNINGS=-Wno-deprecated-declarations
22SET VARIABLES=-DTHREADS=%THREADS% -D%ARCH% 32SET VARIABLES=-DTHREADS=%THREADS% -D%ARCH%
23SET OFLAGS=-O3 33SET OFLAGS=-O3
@@ -28,7 +38,9 @@ SET STACKSIZE=-Wl,-stack:16777216
28SET LFLAGS=%STACKSIZE% 38SET LFLAGS=%STACKSIZE%
29 39
30:: Python libraries - change to match your local installation 40:: Python libraries - change to match your local installation
31SET PYPATH=%userprofile%\AppData\Local\Programs\Python\Python313 41for /f "delims=" %%i in ('python -c "import sys; print(sys.base_prefix)"') do set PYPATH=%%i
42::SET PYPATH=%userprofile%\AppData\Local\Programs\Python\Python313
43
32SET PYINCLUDE=%PYPATH%\include 44SET PYINCLUDE=%PYPATH%\include
33SET PYLIBS=%PYPATH%\libs 45SET PYLIBS=%PYPATH%\libs
34 46
diff --git a/src/solvers/distribution.h b/src/solvers/distribution.h
index e9302da..78b9b5e 100644
--- a/src/solvers/distribution.h
+++ b/src/solvers/distribution.h
@@ -10,13 +10,13 @@ typedef struct {
10 const unsigned char *table; 10 const unsigned char *table;
11} getdistribution_data_t; 11} getdistribution_data_t;
12 12
13STATIC void *getdistribution_runthread(void *); 13STATIC wrapthread_return_t getdistribution_runthread(void *);
14STATIC void getdistribution(const unsigned char *, 14STATIC void getdistribution(const unsigned char *,
15 uint64_t [static INFO_DISTRIBUTION_LEN], const tableinfo_t [static 1]); 15 uint64_t [static INFO_DISTRIBUTION_LEN], const tableinfo_t [static 1]);
16STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN], 16STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN],
17 const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t); 17 const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t);
18 18
19STATIC void * 19STATIC wrapthread_return_t
20getdistribution_runthread(void *arg) 20getdistribution_runthread(void *arg)
21{ 21{
22 getdistribution_data_t *data = (getdistribution_data_t *)arg; 22 getdistribution_data_t *data = (getdistribution_data_t *)arg;
@@ -33,7 +33,7 @@ getdistribution_runthread(void *arg)
33 for (j = 0; j < ENTRIES_PER_BYTE(k); j++) 33 for (j = 0; j < ENTRIES_PER_BYTE(k); j++)
34 data->distr[(table[i] & (m << (j*k))) >> (j*k)]++; 34 data->distr[(table[i] & (m << (j*k))) >> (j*k)]++;
35 35
36 return NULL; 36 return wrapthread_return_val;
37} 37}
38 38
39STATIC void 39STATIC void
@@ -60,12 +60,12 @@ getdistribution(
60 .distr = local_distr[i], 60 .distr = local_distr[i],
61 .table = table, 61 .table = table,
62 }; 62 };
63 wrapthread_create(&thread[i], NULL, 63 wrapthread_create(&thread[i],
64 getdistribution_runthread, &targ[i]); 64 getdistribution_runthread, &targ[i]);
65 } 65 }
66 66
67 for (i = 0; i < THREADS; i++) 67 for (i = 0; i < THREADS; i++)
68 wrapthread_join(thread[i], NULL); 68 wrapthread_join(thread[i]);
69 69
70 memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); 70 memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t));
71 for (i = 0; i < THREADS; i++) 71 for (i = 0; i < THREADS; i++)
diff --git a/src/solvers/h48/distribution_h48.h b/src/solvers/h48/distribution_h48.h
index 93a6933..80c946e 100644
--- a/src/solvers/h48/distribution_h48.h
+++ b/src/solvers/h48/distribution_h48.h
@@ -4,11 +4,11 @@ needed for H48 because of the intertwined fallback table, and it is easier
4to have some duplication than to make these functions needlessly generic. 4to have some duplication than to make these functions needlessly generic.
5*/ 5*/
6 6
7STATIC void *getdistribution_h48_runthread(void *); 7STATIC wrapthread_return_t getdistribution_h48_runthread(void *);
8STATIC void getdistribution_h48(const unsigned char *, 8STATIC void getdistribution_h48(const unsigned char *,
9 uint64_t [static INFO_DISTRIBUTION_LEN], const tableinfo_t [static 1]); 9 uint64_t [static INFO_DISTRIBUTION_LEN], const tableinfo_t [static 1]);
10 10
11STATIC void * 11STATIC wrapthread_return_t
12getdistribution_h48_runthread(void *arg) 12getdistribution_h48_runthread(void *arg)
13{ 13{
14 getdistribution_data_t *data = (getdistribution_data_t *)arg; 14 getdistribution_data_t *data = (getdistribution_data_t *)arg;
@@ -33,7 +33,7 @@ getdistribution_h48_runthread(void *arg)
33 data->distr[(t & (m << (3*k))) >> (3*k)]--; 33 data->distr[(t & (m << (3*k))) >> (3*k)]--;
34 } 34 }
35 35
36 return NULL; 36 return wrapthread_return_val;
37} 37}
38 38
39STATIC void 39STATIC void
@@ -58,12 +58,12 @@ getdistribution_h48(
58 .distr = local_distr[i], 58 .distr = local_distr[i],
59 .table = table, 59 .table = table,
60 }; 60 };
61 wrapthread_create(&thread[i], NULL, 61 wrapthread_create(&thread[i],
62 getdistribution_h48_runthread, &targ[i]); 62 getdistribution_h48_runthread, &targ[i]);
63 } 63 }
64 64
65 for (i = 0; i < THREADS; i++) 65 for (i = 0; i < THREADS; i++)
66 wrapthread_join(thread[i], NULL); 66 wrapthread_join(thread[i]);
67 67
68 memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); 68 memset(distr, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t));
69 for (i = 0; i < THREADS; i++) 69 for (i = 0; i < THREADS; i++)
diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h
index ef8a854..b37bcfb 100644
--- a/src/solvers/h48/gendata_h48.h
+++ b/src/solvers/h48/gendata_h48.h
@@ -3,7 +3,7 @@ STATIC long long gendata_h48_dispatch(
3STATIC uint64_t gendata_h48short(gendata_h48short_arg_t [static 1]); 3STATIC uint64_t gendata_h48short(gendata_h48short_arg_t [static 1]);
4STATIC int64_t gendata_h48(gendata_h48_arg_t [static 1]); 4STATIC int64_t gendata_h48(gendata_h48_arg_t [static 1]);
5STATIC void gendata_h48_maintable(gendata_h48_arg_t [static 1]); 5STATIC void gendata_h48_maintable(gendata_h48_arg_t [static 1]);
6STATIC void *gendata_h48_runthread(void *); 6STATIC wrapthread_return_t gendata_h48_runthread(void *);
7 7
8STATIC_INLINE void gendata_h48_mark(gendata_h48_mark_t [static 1]); 8STATIC_INLINE void gendata_h48_mark(gendata_h48_mark_t [static 1]);
9STATIC_INLINE bool gendata_h48_dfs_stop( 9STATIC_INLINE bool gendata_h48_dfs_stop(
@@ -230,9 +230,9 @@ gendata_h48_maintable(gendata_h48_arg_t arg[static 1])
230 230
231 inext = 0; 231 inext = 0;
232 count = 0; 232 count = 0;
233 wrapthread_mutex_init(&shortcubes_mutex, NULL); 233 wrapthread_mutex_init(&shortcubes_mutex);
234 for (i = 0; i < CHUNKS; i++) 234 for (i = 0; i < CHUNKS; i++)
235 wrapthread_mutex_init(&table_mutex[i], NULL); 235 wrapthread_mutex_init(&table_mutex[i]);
236 for (i = 0; i < THREADS; i++) { 236 for (i = 0; i < THREADS; i++) {
237 dfsarg[i] = (h48_dfs_arg_t){ 237 dfsarg[i] = (h48_dfs_arg_t){
238 .h = arg->h, 238 .h = arg->h,
@@ -251,7 +251,7 @@ gendata_h48_maintable(gendata_h48_arg_t arg[static 1])
251 dfsarg[i].table_mutex[ii] = &table_mutex[ii]; 251 dfsarg[i].table_mutex[ii] = &table_mutex[ii];
252 252
253 wrapthread_create( 253 wrapthread_create(
254 &thread[i], NULL, gendata_h48_runthread, &dfsarg[i]); 254 &thread[i], gendata_h48_runthread, &dfsarg[i]);
255 } 255 }
256 256
257 if (NISSY_CANSLEEP) { 257 if (NISSY_CANSLEEP) {
@@ -281,7 +281,7 @@ gendata_h48_maintable(gendata_h48_arg_t arg[static 1])
281 } 281 }
282 282
283 for (i = 0; i < THREADS; i++) 283 for (i = 0; i < THREADS; i++)
284 wrapthread_join(thread[i], NULL); 284 wrapthread_join(thread[i]);
285 285
286 h48map_destroy(&shortcubes); 286 h48map_destroy(&shortcubes);
287 287
@@ -291,7 +291,7 @@ gendata_h48_maintable(gendata_h48_arg_t arg[static 1])
291 writetableinfo(&arg->info, bufsize, (unsigned char *)arg->h48buf); 291 writetableinfo(&arg->info, bufsize, (unsigned char *)arg->h48buf);
292} 292}
293 293
294STATIC void * 294STATIC wrapthread_return_t
295gendata_h48_runthread(void *arg) 295gendata_h48_runthread(void *arg)
296{ 296{
297 uint64_t coord, coordext, coordmin; 297 uint64_t coord, coordext, coordmin;
@@ -328,7 +328,7 @@ gendata_h48_runthread(void *arg)
328 } 328 }
329 } 329 }
330 330
331 return NULL; 331 return wrapthread_return_val;
332} 332}
333 333
334STATIC void 334STATIC void
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index 15ac6ea..4fd0aea 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -78,7 +78,7 @@ STATIC_INLINE void h48_prune_restore_inverse(const h48_prune_t [static 1],
78STATIC int64_t solve_h48_maketasks( 78STATIC int64_t solve_h48_maketasks(
79 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], 79 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1],
80 solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]); 80 solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]);
81STATIC void *solve_h48_runthread(void *); 81STATIC wrapthread_return_t solve_h48_runthread(void *);
82STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); 82STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]);
83STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t); 83STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t);
84STATIC int solve_h48_compare_tasks(const void *, const void *); 84STATIC int solve_h48_compare_tasks(const void *, const void *);
@@ -383,7 +383,7 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1])
383 return ret; 383 return ret;
384} 384}
385 385
386STATIC void * 386STATIC wrapthread_return_t
387solve_h48_runthread(void *arg) 387solve_h48_runthread(void *arg)
388{ 388{
389 int i, j; 389 int i, j;
@@ -445,7 +445,7 @@ solve_h48_runthread(void *arg)
445 445
446solve_h48_runthread_end: 446solve_h48_runthread_end:
447 dfsarg->thread_done = true; 447 dfsarg->thread_done = true;
448 return NULL; 448 return wrapthread_return_val;
449} 449}
450 450
451STATIC int64_t 451STATIC int64_t
@@ -638,7 +638,7 @@ solve_h48(
638 638
639 } 639 }
640 640
641 wrapthread_mutex_init(&solutions_mutex, NULL); 641 wrapthread_mutex_init(&solutions_mutex);
642 642
643 mtarg = (dfsarg_solve_h48_maketasks_t) { 643 mtarg = (dfsarg_solve_h48_maketasks_t) {
644 .cube = oc.cube, 644 .cube = oc.cube,
@@ -689,7 +689,7 @@ solve_h48(
689 arg[i].target_depth = d; 689 arg[i].target_depth = d;
690 arg[i].thread_done = false; 690 arg[i].thread_done = false;
691 wrapthread_create( 691 wrapthread_create(
692 &thread[i], NULL, solve_h48_runthread, &arg[i]); 692 &thread[i], solve_h48_runthread, &arg[i]);
693 } 693 }
694 694
695 /* Log solutions and handle pause / stop / resume */ 695 /* Log solutions and handle pause / stop / resume */
@@ -718,7 +718,7 @@ solve_h48(
718 } 718 }
719 719
720 for (i = 0; i < threads; i++) 720 for (i = 0; i < threads; i++)
721 wrapthread_join(thread[i], NULL); 721 wrapthread_join(thread[i]);
722 722
723 solve_h48_log_solutions(&sollist, lastused); 723 solve_h48_log_solutions(&sollist, lastused);
724 lastused = sollist.used; 724 lastused = sollist.used;
diff --git a/src/utils/prefetch.h b/src/utils/prefetch.h
index 89b14e8..a2c41ef 100644
--- a/src/utils/prefetch.h
+++ b/src/utils/prefetch.h
@@ -1,15 +1,7 @@
1#if defined(AVX2)
2
3#define prefetch(a, i) _mm_prefetch(a+i, _MM_HINT_T0)
4
5#else
6#if defined(__GNUC__) || defined(__clang__) 1#if defined(__GNUC__) || defined(__clang__)
7 2 #define prefetch(a, i) __builtin_prefetch(a+i, 0, 0)
8#define prefetch(a, i) __builtin_prefetch(a+i, 0, 0) 3#elif defined(AVX2)
9 4 #define prefetch(a, i) _mm_prefetch((char *)(a+i), _MM_HINT_T0)
10#else 5#else
11 6 #define prefetch(a, i) (void)i
12#define prefetch(a, i) (void)i
13
14#endif
15#endif 7#endif
diff --git a/src/utils/wrapthread.h b/src/utils/wrapthread.h
index 28654fe..4ac72a6 100644
--- a/src/utils/wrapthread.h
+++ b/src/utils/wrapthread.h
@@ -1,37 +1,77 @@
1#if THREADS == 1 1#if THREADS == 1
2 #define WRAPTHREAD_NOTHREADS 1
3#elif defined(__unix__)
4 #define WRAPTHREAD_PTHREADS 1
5#elif defined(__has_include)
6 #if __has_include(<pthreads.h>)
7 #define WRAPTHREAD_PTHREADS 1
8 #elif __has_include(<threads.h>)
9 #define WRAPTHREAD_C11THREADS 1
10 #endif
11#else
12 #define WRAPTHREAD_NOTHREADS 1
13#endif
14
15#if WRAPTHREAD_PTHREADS
16 #include <pthread.h>
17
18 #define wrapthread_atomic _Atomic
19
20 #define wrapthread_return_t void *
21 #define wrapthread_return_val NULL
22
23 #define wrapthread_define_var_thread_t(x) pthread_t x
24 #define wrapthread_define_var_mutex_t(x) pthread_mutex_t x
25 #define wrapthread_define_struct_thread_t(x) pthread_t x
26 #define wrapthread_define_struct_mutex_t(x) pthread_mutex_t x
27
28 #define wrapthread_define_if_threads(T, x) T x
29
30 #define wrapthread_create(a, f, arg) pthread_create(a, NULL, f, arg)
31 #define wrapthread_join(a) pthread_join(a, NULL)
32 #define wrapthread_mutex_init(a) pthread_mutex_init(a, NULL)
33 #define wrapthread_mutex_lock(a) pthread_mutex_lock(a)
34 #define wrapthread_mutex_unlock(a) pthread_mutex_unlock(a)
35
36#elif WRAPTHREAD_C11THREADS
37 #include <threads.h>
38
39 #define wrapthread_atomic _Atomic
2 40
3#define wrapthread_atomic 41 #define wrapthread_return_t int
42 #define wrapthread_return_val 0
4 43
5#define wrapthread_define_var_thread_t(x) unused char x 44 #define wrapthread_define_var_thread_t(x) thrd_t x
6#define wrapthread_define_var_mutex_t(x) unused char x 45 #define wrapthread_define_var_mutex_t(x) mtx_t x
7#define wrapthread_define_struct_thread_t(x) char x 46 #define wrapthread_define_struct_thread_t(x) thrd_t x
8#define wrapthread_define_struct_mutex_t(x) char x 47 #define wrapthread_define_struct_mutex_t(x) mtx_t x
9 48
10#define wrapthread_define_if_threads(T, x) T x; (void)(x) 49 #define wrapthread_define_if_threads(T, x) T x
11 50
12#define wrapthread_create(a, b, c, d) c(d) 51 #define wrapthread_create(a, f, arg) thrd_create(a, f, arg)
13#define wrapthread_join(a, b) 52 #define wrapthread_join(a) thrd_join(a, NULL)
14#define wrapthread_mutex_init(a, b) 53 #define wrapthread_mutex_init(a) mtx_init(a, mtx_plain)
15#define wrapthread_mutex_lock(a) 54 #define wrapthread_mutex_lock(a) mtx_lock(a)
16#define wrapthread_mutex_unlock(a) 55 #define wrapthread_mutex_unlock(a) mtx_unlock(a)
17 56
18#else 57#else
19 58
20#include <pthread.h> 59 #define wrapthread_atomic
21 60
22#define wrapthread_atomic _Atomic 61 #define wrapthread_return_t int
62 #define wrapthread_return_val 0
23 63
24#define wrapthread_define_var_thread_t(x) pthread_t x 64 #define wrapthread_define_var_thread_t(x) unused char x
25#define wrapthread_define_var_mutex_t(x) pthread_mutex_t x 65 #define wrapthread_define_var_mutex_t(x) unused char x
26#define wrapthread_define_struct_thread_t(x) pthread_t x 66 #define wrapthread_define_struct_thread_t(x) char x
27#define wrapthread_define_struct_mutex_t(x) pthread_mutex_t x 67 #define wrapthread_define_struct_mutex_t(x) char x
28 68
29#define wrapthread_define_if_threads(T, x) T x 69 #define wrapthread_define_if_threads(T, x) T x; (void)(x)
30 70
31#define wrapthread_create(a, b, c, d) pthread_create(a, b, c, d) 71 #define wrapthread_create(t, f, arg) f(arg)
32#define wrapthread_join(a, b) pthread_join(a, b) 72 #define wrapthread_join(a)
33#define wrapthread_mutex_init(a, b) pthread_mutex_init(a, b) 73 #define wrapthread_mutex_init(a)
34#define wrapthread_mutex_lock(a) pthread_mutex_lock(a) 74 #define wrapthread_mutex_lock(a)
35#define wrapthread_mutex_unlock(a) pthread_mutex_unlock(a) 75 #define wrapthread_mutex_unlock(a)
36 76
37#endif 77#endif

Generated with cgit - Back to sebastiano.tronto.net