parent
9db000e864
commit
ae9efca41b
@ -1,3 +1,5 @@
|
|||||||
obj/
|
obj/
|
||||||
fcmp-*
|
fcmp-*
|
||||||
test/
|
test/
|
||||||
|
perf.*
|
||||||
|
flamegraph.svg
|
||||||
|
@ -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 */
|
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _SCHED_H
|
||||||
|
#define _SCHED_H
|
||||||
|
|
||||||
|
#include <vector.h>
|
||||||
|
#include <fcmp.h>
|
||||||
|
|
||||||
|
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 */
|
@ -0,0 +1,84 @@
|
|||||||
|
// Scheduler
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <vector.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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;i<spn;i++) tasklist[i] = (struct taskarg){.li = vec_new_with_cap(full.element, full.len), .cb = callback };
|
||||||
|
|
||||||
|
for (register int i=0;i<full.len;i++)
|
||||||
|
{
|
||||||
|
vec_push(&tasklist[i%spn].li, vec_index(&full, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(register int i=0;i<spn;i++)
|
||||||
|
{
|
||||||
|
if(pthread_create(&t_list->tasks[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;i<t_list->argc;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
|
Loading…
Reference in new issue