diff --git a/Makefile b/Makefile index ccee39a..b9d1d9d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ PROJECT=shuffle3 # DEBUG: Pretend we're building a debug release even though we're not. Will enable additional output messages and may interfere with some optimisations FEATURE_FLAGS?= -COMMON_FLAGS = $(addprefix -D,$(FEATURE_FLAGS)) -Wall -pedantic $(addprefix -I,$(INCLUDE)) -fno-strict-aliasing +COMMON_FLAGS+= $(addprefix -D,$(FEATURE_FLAGS)) -Wall -Wstrict-aliasing $(addprefix -I,$(INCLUDE)) -fno-strict-aliasing OPT_FLAGS?= -march=native -fgraphite -fopenmp -floop-parallelize-all -ftree-parallelize-loops=4 \ -floop-interchange -ftree-loop-distribution -floop-strip-mine -floop-block \ @@ -21,14 +21,17 @@ OPT_FLAGS?= -march=native -fgraphite -fopenmp -floop-parallelize-all -ftree-para CXX_OPT_FLAGS?= $(OPT_FLAGS) -felide-constructors CFLAGS += $(COMMON_FLAGS) --std=gnu11 -CXXFLAGS += $(COMMON_FLAGS) --std=gnu++20 -fno-exceptions +CXXFLAGS += $(COMMON_FLAGS) --std=gnu++23 -fno-exceptions LDFLAGS += STRIP=strip -RELEASE_CFLAGS?= -O3 -flto $(OPT_FLAGS) -RELEASE_CXXFLAGS?= -O3 -flto $(CXX_OPT_FLAGS) -RELEASE_LDFLAGS?= -O3 -flto +RELEASE_COMMON_FLAGS?= -DNOTRACE +RELEASE_COMMON_FLAGS+= -DRELEASE + +RELEASE_CFLAGS?= -O3 -flto $(OPT_FLAGS) $(RELEASE_COMMON_FLAGS) +RELEASE_CXXFLAGS?= -O3 -flto $(CXX_OPT_FLAGS) $(RELEASE_COMMON_FLAGS) +RELEASE_LDFLAGS?= -Wl,-O3 -Wl,-flto DEBUG_CFLAGS?= -O0 -g -DDEBUG DEBUG_CXXFLAGS?= $(DEBUG_CFLAGS) @@ -111,14 +114,19 @@ pgo-profile: | pgo-reset pgo-generate for i in {1..$(PGO_ITERATIONS)}; do \ dd if=/dev/urandom of=$(PGO_SET_LOC)/small bs=1024 count=1 >> /dev/null 2>&1; \ printf "Iteration $$i / $(PGO_ITERATIONS)\r"; \ - ./pgo-generate -s $(PGO_SET_LOC)/small >>/dev/null; \ - ./pgo-generate -u $(PGO_SET_LOC)/small >>/dev/null; \ - ./pgo-generate -h >> /dev/null; \ - FCNT=1 ./test.sh ./pgo-generate >>/dev/null; \ - FCNT=2 ./test.sh ./pgo-generate >>/dev/null; \ - FCNT=3 ./test.sh ./pgo-generate >>/dev/null; \ - FCNT=4 ./test.sh ./pgo-generate >>/dev/null; \ + ( echo ">> $$i" >&2; \ + echo ">> $$i"; \ + ./pgo-generate -s $(PGO_SET_LOC)/small; \ + ./pgo-generate -u $(PGO_SET_LOC)/small; \ + ./pgo-generate -h; \ + FCNT=1 ./test.sh ./pgo-generate; \ + FCNT=2 ./test.sh ./pgo-generate; \ + FCNT=3 ./test.sh ./pgo-generate; \ + FCNT=4 ./test.sh ./pgo-generate; \ + ) >>$(PGO_SET_LOC)/stdout.log 2>>$(PGO_SET_LOC)/stderr.log; \ done + $(shell command -v bat >/dev/null && echo "bat --pager=none" || echo cat) $(PGO_SET_LOC)/stdout.log; \ + $(shell command -v bat >/dev/null && echo "bat --pager=none" || echo cat) $(PGO_SET_LOC)/stderr.log >&2 rm -rf $(PGO_SET_LOC) rm pgo-generate diff --git a/include/debug.h b/include/debug.h index 334e6d1..29fe4d9 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,6 +1,14 @@ #ifndef _DEBUG_H #define _DEBUG_H +// If `TRACE` is defined, or if `NOTRACE` is defined, use simplified debug info +#if defined(TRACE) || !defined(NOTRACE) +#define D_TRACE +#define _D__FUNC __PRETTY_FUNCTION__ +#else +#define _D__FUNC __func__ +#endif + #ifdef __cplusplus extern "C" { #endif @@ -8,12 +16,14 @@ extern "C" { struct debuginfo { const char* file; const char* function; + //const char* pfunction; //TODO: for `#if defined(TRACE)`, __PRETTY_FUNCTION__ goes here, __func__ goes above. int line; }; void _do_dprintf(struct debuginfo di, const char* fmt, ...); #ifdef __cplusplus +#define _D_COMPTIME constexpr extern "C++" { #include template @@ -24,14 +34,15 @@ extern "C++" { _do_dprintf(i, fmt, std::forward(args)...); #endif } -#define D_dprintf(fmt, ...) _real_dprintf(__FILE__, __func__, __LINE__, fmt __VA_OPT__(,) __VA_ARGS__) +#define D_dprintf(fmt, ...) do { if consteval { (void)0; } else { _real_dprintf(__FILE__, _D__FUNC, __LINE__, fmt __VA_OPT__(,) __VA_ARGS__); } } while(0) } #else +#define _D_COMPTIME #ifdef DEBUG -#define D_dprintf(fmt, ...) _do_dprintf( (struct debuginfo){.file = __FILE__, .function = __func__, .line = __LINE__}, fmt __VA_OPT__(,) __VA_ARGS__) +#define D_dprintf(fmt, ...) _do_dprintf( (struct debuginfo){.file = __FILE__, .function = _D__FUNC, .line = __LINE__}, fmt __VA_OPT__(,) __VA_ARGS__) #else -static inline void _do__nothing(const char* fmt, ...) {} +static _D_COMPTIME inline void _do__nothing(const char* fmt, ...) {} #define D_dprintf(fmt, ...) _do__nothing(fmt __VA_OPT__(,) __VA_ARGS__) //(fmt __VA_OPT__(,) __VA_ARGS__, (void)0) #endif #endif @@ -39,5 +50,6 @@ static inline void _do__nothing(const char* fmt, ...) {} #ifdef __cplusplus } #endif +#undef _D_COMPTIME #endif /* _DEBUG_H */ diff --git a/include/uuid.hpp b/include/uuid.hpp index 5331ccc..56dc06c 100644 --- a/include/uuid.hpp +++ b/include/uuid.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/src/debug.c b/src/debug.c index c830c4b..d2bcc2f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,17 +1,85 @@ #include #include #include +#include +#include +#include #include #include +enum jt_comp { + JT_COMP_UNIX, + JT_COMP_DATE, + JT_COMP_TIME, + JT_COMP_DATETIME, +}; + +#define CLONE(p) ({ __auto_type $__p = (p); \ + __auto_type $__r = __builtin_choose_expr(__builtin_classify_type($__p) == 5, *$__p, $__p); \ + /* ((__typeof__($__r) []) { $__r }); }) */ \ + __typeof__($__r) $__rp[1]; \ + $__rp[0] = $__r; \ + &$__rp[0]; }) + +__attribute__((returns_nonnull, nonnull(1))) +static inline +const char* jtime(const struct tm* restrict lt, enum jt_comp kind) +{ + _Thread_local static char datebuf[1 + + 4 + 2 + 4 + 1 // `dd/mm/yyyy` + + 6 + 3 // ` hh:MM:ss` + ]; + _Static_assert(sizeof(datebuf) != sizeof(char*), "Unexpected decay"); + + //memset(datebuf, '0', sizeof(datebuf)-1); + if(!kind) + snprintf(datebuf, sizeof(datebuf), "%lu", mktime(CLONE(lt))); + else { + size_t w = 0, sz = sizeof(datebuf); + if(kind & JT_COMP_DATE) + w += snprintf(datebuf, sz, "%02u/%02u/%4.4u" + , (unsigned)lt->tm_mday + , (unsigned)lt->tm_mon + , (unsigned)(1900 + lt->tm_year)); + + if(kind & JT_COMP_TIME) + w += snprintf(datebuf+w, sz - w, " %02u:%02u:%02u" + , (unsigned)lt->tm_hour + , (unsigned)lt->tm_min + , (unsigned)lt->tm_sec); + } + return datebuf; +} + void _do_dprintf(struct debuginfo info, const char* fmt, ...) { #ifdef DEBUG va_list li; + + time_t utime; + struct tm ltime; + time(&utime); + localtime_r(&utime, <ime); + va_start(li, fmt); - fprintf(stderr, "["FGRN("dbg")" " FYEL("@") BOLD("%s") "->" FWHT("%s") ":" FYEL("%d") "]: ", info.file, info.function,info.line); + +#ifdef D_TRACE +#define FMT_FUNC "%s" +#else +#define FMT_FUNC "%s()" +#endif + +#define TTY_OUT "["FGRN("dbg")" (%s %s) " FYEL("@") BOLD("%s") "->" FWHT(FMT_FUNC) ":" FYEL("%d") "]: " +#define NCOL(x) x +#define FIL_OUT "["NCOL("dbg")" (%s %s) " NCOL("@") NCOL("%s") "->" NCOL(FMT_FUNC) ":" NCOL("%d") "]: " + + fprintf(stderr, isatty(fileno(stderr)) ? (TTY_OUT) : (FIL_OUT) + , jtime(<ime, JT_COMP_DATETIME), ltime.tm_zone + , info.file + , info.function + , info.line); vfprintf(stderr, fmt, li); fprintf(stderr, "\n"); va_end(li); diff --git a/src/work.cpp b/src/work.cpp index 1df52b9..06efa40 100644 --- a/src/work.cpp +++ b/src/work.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -62,12 +63,12 @@ namespace work auto [long_l, long_h] = minmax_t(map.as_span().reinterpret()); D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h); - rng::xoroshiro128plus xorng(*(const std::uint64_t*)&long_l, *(const std::uint64_t*)&long_h); + rng::xoroshiro128plus xorng(std::bit_cast(long_l), std::bit_cast(long_h)); rng::unshuffle(xorng, map.as_span().reinterpret()); } else { auto [long_l, long_h] = minmax_t(map.as_span().reinterpret()); D_dprintf("MMX res (u64): %ld -- %ld", long_l, long_h); - rng::xoroshiro128plus xorng(*(const std::uint64_t*)&long_l, *(const std::uint64_t*)&long_h); + rng::xoroshiro128plus xorng(std::bit_cast(long_l), std::bit_cast(long_h)); rng::shuffle(xorng, map.as_span().reinterpret()); auto [float_l, float_h] = minmax_t(map.as_span().reinterpret(), [](float f) -> bool { return !( (f!=f) || f < -FLT_MAX || f > FLT_MAX); });