h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit ca68b59475f6b1773fa62e6dbc4b68349602b441
parent 762d285f3b914c877887469de06a70cee9028159
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Thu, 12 Sep 2024 16:55:28 +0200

Update build files to enable multithreading

Diffstat:
MMakefile | 16++++++++--------
Mconfigure.sh | 73++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mtools/010_stats_tables_h48/stats_tables_h48.c | 13++++++-------
3 files changed, 66 insertions(+), 36 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,34 +3,34 @@ include config.mk all: cube.o debugcube.o cube.s: clean - ${CC} -D${ARCH} ${CFLAGS} -c -S -o cube.s src/nissy.c + ${CC} ${MACROS} ${CFLAGS} -c -S -o cube.s src/nissy.c cube.o: clean - ${CC} -D${ARCH} ${CFLAGS} -c -o cube.o src/nissy.c + ${CC} ${MACROS} ${CFLAGS} -c -o cube.o src/nissy.c debugcube.o: clean - ${CC} -D${ARCH} ${DBGFLAGS} -c -o debugcube.o src/nissy.c + ${CC} ${MACROS} ${DBGFLAGS} -c -o debugcube.o src/nissy.c clean: rm -rf *.o run test: debugcube.o - CC="${CC} -D${ARCH} ${DBGFLAGS}" ./test/test.sh + CC="${CC} ${MACROS} ${DBGFLAGS}" ./test/test.sh tool: cube.o mkdir -p tools/results - CC="${CC} ${CFLAGS}" CUBEOBJ=cube.o ./tools/run_tool.sh + CC="${CC} ${MACROS} ${CFLAGS}" CUBEOBJ=cube.o ./tools/run_tool.sh debugtool: debugcube.o mkdir -p tools/results - CC="${CC} ${DBGFLAGS}" CUBEOBJ=debugcube.o ./tools/run_tool.sh + CC="${CC} ${MACROS} ${DBGFLAGS}" CUBEOBJ=debugcube.o ./tools/run_tool.sh shell: cube.o mkdir -p tables - ${CC} ${CFLAGS} -o run cube.o shell.c + ${CC} ${MACROS} ${CFLAGS} -o run cube.o shell.c debugshell: debugcube.o mkdir -p tables - ${CC} ${DBGFLAGS} -o run debugcube.o shell.c + ${CC} ${MACROS} ${DBGFLAGS} -o run debugcube.o shell.c .PHONY: all clean test tool debugtool shell debugshell diff --git a/configure.sh b/configure.sh @@ -1,51 +1,82 @@ #!/bin/sh -cc=${CC:-cc} +greparch() { + $CC -march=native -dM -E - </dev/null 2>/dev/null | grep "$1" +} + +grepsan() { + $CC -fsanitize=$1 -dM -E -x c - </dev/null 2>/dev/null | grep "SANITIZE" +} + +detectthreads() { + echo 16 # TODO: choose based on system +} detectarch() { - ${cc} -march=native -dM -E - </dev/null 2>/dev/null | grep "$1" + [ -n "$(greparch __AVX2__)" ] && detected="AVX2" + [ -n "$(greparch __ARM_NEON)" ] && detected="NEON" + [ -z "$detected" ] && detected="PORTABLE" + + echo "$detected" } -detectsan() { - ${cc} -fsanitize=$1 -dM -E -x c - </dev/null 2>/dev/null \ - | grep "SANITIZE" + +validatecc() { + if ! (which "$CC" >/dev/null 2>&1) ; then + echo "Error: compiler '$CC' not found" + exit 1 + fi } -[ -n "$(detectarch __AVX2__)" ] && detected="AVX2" -[ -n "$(detectarch __ARM_NEON)" ] && detected="NEON" -[ -z "$detected" ] && detected="PORTABLE" +validatethreads() { + if [ "$THREADS" -le 0 ] || [ "$THREADS" -gt 128 ]; then + echo "Error: number of threads must be between 1 and 128" + exit 1 + fi +} + +validatearch() { + case "$ARCH" in + AVX2|NEON|PORTABLE) + ;; + *) + echo "Error: architecture '$ARCH' not supported" + exit 1 + ;; + esac +} -ARCH=${ARCH-"$detected"} +CC=${CC:-cc} +THREADS=${THREADS-"$(detectthreads)"} +ARCH=${ARCH-"$(detectarch)"} -case "$ARCH" in -AVX2|NEON|PORTABLE) - ;; -*) - echo "Error: architecture $ARCH not supported" - exit 1 - ;; -esac +validatecc +validatethreads +validatearch STD="-std=c99" WFLAGS="-pedantic -Wall -Wextra" WNOFLAGS="-Wno-unused-parameter -Wno-unused-function -Wno-unknown-pragmas" [ "$ARCH" = "AVX2" ] && AVX="-mavx2" -[ -n "$(detectsan address)" ] && ADDR="-fsanitize=address" -[ -n "$(detectsan undefined)" ] && UNDEF="-fsanitize=undefined" +[ -n "$(grepsan address)" ] && ADDR="-fsanitize=address" +[ -n "$(grepsan undefined)" ] && UNDEF="-fsanitize=undefined" SAN="$ADDR $UNDEF" LIBS="-lpthread" CFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS $AVX -O3" DBGFLAGS="$STD $LIBS $WFLAGS $WNOFLAGS $SAN $AVX -g3 -DDEBUG" +MACROS="-DTHREADS=$THREADS -D$ARCH" echo "Selected architecture: $ARCH" -echo "Compiler: ${CC:-cc}" +echo "Number of threads: $THREADS" +echo "Compiler: $CC" { echo "ARCH = $ARCH"; echo ""; echo "CFLAGS = $CFLAGS"; echo "DBGFLAGS = $DBGFLAGS"; +echo "MACROS = $MACROS" echo ""; -echo "CC = ${cc}" +echo "CC = $CC" } > config.mk diff --git a/tools/010_stats_tables_h48/stats_tables_h48.c b/tools/010_stats_tables_h48/stats_tables_h48.c @@ -3,7 +3,6 @@ #include "../tool.h" #define MAXMOVES 20 -#define NTHREADS 32 #define NCUBES_PER_THREAD 10000 #define LOG_EVERY (NCUBES_PER_THREAD / 10) @@ -57,10 +56,10 @@ run_thread(void *arg) void run(void) { int64_t i, j, k, tot; double avg; - pthread_t thread[NTHREADS]; - thread_arg_t arg[NTHREADS]; + pthread_t thread[THREADS]; + thread_arg_t arg[THREADS]; - for (i = 0; i < NTHREADS; i++) { + for (i = 0; i < THREADS; i++) { arg[i] = (thread_arg_t) { .thread_id = i, .n = NCUBES_PER_THREAD, @@ -69,18 +68,18 @@ void run(void) { pthread_create(&thread[i], NULL, run_thread, &arg[i]); } - for (i = 0; i < NTHREADS; i++) + for (i = 0; i < THREADS; i++) pthread_join(thread[i], NULL); for (j = 0; j < 12; j++) { printf("Data for h=%" PRId64 "\n", j); for (k = 0, avg = 0.0; k <= 16; k++) { - for (i = 0, tot = 0; i < NTHREADS; i++) + for (i = 0, tot = 0; i < THREADS; i++) tot += arg[i].v[j][k]; printf("%" PRId64 "\t%" PRId64 "\n", k, tot); avg += tot * k; } - avg /= (double)(NCUBES_PER_THREAD * NTHREADS); + avg /= (double)(NCUBES_PER_THREAD * THREADS); printf("Average: %.4lf\n", avg); printf("\n"); }