From ae9efca41b93c919ca8e5b49548ea87d8fb23e54 Mon Sep 17 00:00:00 2001 From: Avril Date: Sun, 22 Nov 2020 20:45:39 +0000 Subject: [PATCH] threaded mode with define _RUN_THREADED --- .gitignore | 2 + Makefile | 7 ++- include/fcmp.h | 25 +++++++++++ include/sched.h | 22 ++++++++++ include/vector.h | 8 +--- src/main.c | 109 ++++++++++++++++++++++++++++++++++++++++++++--- src/sched.c | 84 ++++++++++++++++++++++++++++++++++++ 7 files changed, 242 insertions(+), 15 deletions(-) create mode 100644 include/fcmp.h create mode 100644 include/sched.h create mode 100644 src/sched.c diff --git a/.gitignore b/.gitignore index 5dbb27e..fd9057f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ obj/ fcmp-* test/ +perf.* +flamegraph.svg diff --git a/Makefile b/Makefile index 5b09964..1d29dba 100644 --- a/Makefile +++ b/Makefile @@ -5,14 +5,17 @@ PROJECT=fcmp OPT_FLAGS+= -fgraphite +FEAT_CFLAGS?= -D_RUN_THREADED=0 +FEAT_LDFLAGS?= -lpthread + RELEASE_CFLAGS?= -O3 -march=native -flto $(OPT_FLAGS) RELEASE_LDFLAGS?= -O3 -flto DEBUG_CFLAGS?= -DDEBUG -O0 -g DEBUG_LDFLAGS?= -O0 -CFLAGS+= -Wall -pedantic --std=gnu11 $(addprefix -I,$(INCLUDE)) -LDFLAGS+= +CFLAGS+= $(FEAT_CFLAGS) -Wall -pedantic --std=gnu11 $(addprefix -I,$(INCLUDE)) +LDFLAGS+= $(FEAT_LDFLAGS) OBJ = $(addprefix obj/,$(SRC:.c=.o)) diff --git a/include/fcmp.h b/include/fcmp.h new file mode 100644 index 0000000..804f127 --- /dev/null +++ b/include/fcmp.h @@ -0,0 +1,25 @@ +#ifndef _FCMP_H +#define _FCMP_H + +#ifdef DEBUG +#define _FORCE_INLINE static inline __attribute__((gnu_inline)) +#else +#define _FORCE_INLINE extern inline __attribute__((gnu_inline)) +#endif + +#ifdef DEBUG +#define __name(d) #d +#define dprintf(fmt, ...) printf("[dbg @" __FILE__ "->%s:%d] " fmt "\n", __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif + +/// Enabled threaded scheduling +// Set to 1 to FORCE threaded scheduling, 0 to use when opportune. +// +//#define _RUN_THREADED 0 + + +extern const char* _prog_name; + +#endif /* _FCMP_H */ diff --git a/include/sched.h b/include/sched.h new file mode 100644 index 0000000..c526d06 --- /dev/null +++ b/include/sched.h @@ -0,0 +1,22 @@ +#ifndef _SCHED_H +#define _SCHED_H + +#include +#include + +typedef struct tasklist { + size_t argc; + struct taskarg* argv; + pthread_t* tasks; + +} tasklist_t; + +typedef void (*sched_cb)(vec_t* restrict tasklist); + +#ifdef _RUN_THREADED +bool sched_spawn(vec_t full, sched_cb callback, struct tasklist *restrict t_list); +void sched_wait(struct tasklist* restrict t_list); +bool sched_should(size_t ntasks); +#endif + +#endif /* _SHCED_H */ diff --git a/include/vector.h b/include/vector.h index ae7d7d1..5637a4e 100644 --- a/include/vector.h +++ b/include/vector.h @@ -4,6 +4,8 @@ #include #include +#include "fcmp.h" + typedef struct { size_t len, cap; @@ -12,12 +14,6 @@ typedef struct { void* ptr; } vec_t; -#ifdef DEBUG -#define _FORCE_INLINE static inline __attribute__((gnu_inline)) -#else -#define _FORCE_INLINE extern inline __attribute__((gnu_inline)) -#endif - #define VEC_DEFAULT_CAP 16 vec_t vec_new_with_cap(size_t elem, size_t cap); diff --git a/src/main.c b/src/main.c index 77b309a..4d3c5a4 100644 --- a/src/main.c +++ b/src/main.c @@ -2,18 +2,18 @@ #include #include + +#include + #include #include -static const char* _prog_name = "fcmp"; - -#ifdef DEBUG -#define __name(d) #d -#define dprintf(fmt, ...) printf("[dbg @" __FILE__ "->%s:%d] " fmt "\n", __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__) -#else -#define dprintf(fmt, ...) +#ifdef _RUN_THREADED +#include #endif +const char* _prog_name = "fcmp"; + __attribute__((noreturn, noinline)) void usage() { fprintf(stderr, "fcmp: compare files for identity\n"); @@ -56,6 +56,57 @@ static int compare_then_close(const mmap_t * restrict map1, mmap_t map2) return rval; } +#ifdef _RUN_THREADED +struct t_task { + _Atomic int* othis; + + int ithis; + const char* fthis; + mmap_t mthis; + const mmap_t* map1; +}; + +void proc_thread(vec_t* restrict v_tasks) +{ + struct t_task * tasks = v_tasks->ptr; + mmap_t mrest[v_tasks->len]; +#ifdef DEBUG + const char* frest[v_tasks->len]; +#endif + int nrest = v_tasks->len; + + const mmap_t* map1; + + { + for(register int i=0;ilen;i++) + { + mrest[i] = tasks[i].mthis; +#ifdef DEBUG + frest[i] = tasks[i].fthis; +#endif + } + map1 = tasks[0].map1; + } + + register int rval=0; + for(register int i=0;i +#include +#include + +#include +#include + +#ifdef _RUN_THREADED +inline static size_t num_cpus() { + return sysconf( _SC_NPROCESSORS_ONLN ); +} + +struct taskarg { + vec_t li; + sched_cb cb; +}; + +static void* _spawn(void* _arg) +{ + struct taskarg* restrict arg = _arg; + if(arg->li.len>0) + arg->cb(&arg->li); + vec_free(arg->li); + return NULL; +} + +bool sched_should(size_t ntasks) +{ + register size_t num = num_cpus(); + return (num > 1 && ntasks > 1); +} + +bool sched_spawn(vec_t full, sched_cb callback, struct tasklist *restrict t_list) +{ + register size_t spn = num_cpus() + 1; + + if (spn > full.len) spn = full.len; + + dprintf("Spawning %lu worker threads", spn); + // Split tasks + *t_list = (struct tasklist){ + .argc = spn, + .argv = calloc(sizeof(struct taskarg), spn), + .tasks = calloc(sizeof(pthread_t), spn), + }; + struct taskarg* tasklist = t_list->argv; + + for(register int i=0;itasks[i], NULL, &_spawn, &tasklist[i])) + { + perror("Failed to spawn thread"); + return false; + } + dprintf("Worker thead %d of %lu OK", i, spn); + } + + return true; +} + +void sched_wait(struct tasklist* restrict t_list) +{ + dprintf("Waiting on %lu worker threads", t_list->argc); + for (size_t i=0;iargc;i++) { + if(pthread_join(t_list->tasks[i], NULL)) { + perror("Failed to join thread"); + continue; + } + dprintf("Joined thread %lu of %lu okay", i, t_list->argc); + } + free(t_list->tasks); + free(t_list->argv); + dprintf("Freed args and thread handles okay"); +} +#endif