Update API so that the worker_t parameter is given on creating the sync bloc.

(API breakage), more RAII like.
This commit is contained in:
Patrick Pelissier committed 2018-07-28 19:09:07 +02:00
1 parent 7678625071
commit 7b5ae3c15b
4 files changed
+57 -54

No files matched your search

+11 -11
View File
@@ -139,21 +139,21 @@ static void compute_hash(dict_oligonucleotide_t hash_Table, const polynucleotide
} }
worker_sync_t block; // Define a synchronization block worker_sync_t block; // Define a synchronization block
worker_start(block); worker_start(block, worker);
dict_oligonucleotide_t hash_Table3, *p_hash_Table3 = &hash_Table3; dict_oligonucleotide_t hash_Table3, *p_hash_Table3 = &hash_Table3;
dict_oligonucleotide_t hash_Table2, *p_hash_Table2 = &hash_Table2; dict_oligonucleotide_t hash_Table2, *p_hash_Table2 = &hash_Table2;
dict_oligonucleotide_t hash_Table1, *p_hash_Table1 = &hash_Table1; dict_oligonucleotide_t hash_Table1, *p_hash_Table1 = &hash_Table1;
WORKER_SPAWN(worker, block, (p_hash_Table1, size, tab, desiredLength), { WORKER_SPAWN(block, (p_hash_Table1, size, tab, desiredLength), {
init_hash(*p_hash_Table1, size, tab, desiredLength, 3, 4); init_hash(*p_hash_Table1, size, tab, desiredLength, 3, 4);
}, (/*no output*/)); }, (/*no output*/));
WORKER_SPAWN(worker, block, (p_hash_Table2, size, tab, desiredLength), { WORKER_SPAWN(block, (p_hash_Table2, size, tab, desiredLength), {
init_hash(*p_hash_Table2, size, tab, desiredLength, 2, 4); init_hash(*p_hash_Table2, size, tab, desiredLength, 2, 4);
}, (/*no output*/)); }, (/*no output*/));
WORKER_SPAWN(worker, block, (p_hash_Table3, size, tab, desiredLength), { WORKER_SPAWN(block, (p_hash_Table3, size, tab, desiredLength), {
init_hash(*p_hash_Table3, size, tab, desiredLength, 1, 4); init_hash(*p_hash_Table3, size, tab, desiredLength, 1, 4);
}, (/*no output*/)); }, (/*no output*/));
init_hash(hash_Table, size, tab, desiredLength, 0, 4); init_hash(hash_Table, size, tab, desiredLength, 0, 4);
worker_sync(worker, block); worker_sync(block);
// Merge all hashtables // Merge all hashtables
dict_oligonucleotide_splice(hash_Table, hash_Table1); dict_oligonucleotide_splice(hash_Table, hash_Table1);
@@ -237,24 +237,24 @@ int main()
// Do the following functions in parallel. // Do the following functions in parallel.
worker_sync_t block; // Define a synchronization block worker_sync_t block; // Define a synchronization block
worker_start(block); worker_start(block, worker);
WORKER_SPAWN(worker, block, (ptr, output), { WORKER_SPAWN(block, (ptr, output), {
compute_count(*ptr, "GGTATTTTAATTTATAGT", output[6]); compute_count(*ptr, "GGTATTTTAATTTATAGT", output[6]);
}, (/*no output*/)); }, (/*no output*/));
WORKER_SPAWN(worker, block, (ptr, output), { WORKER_SPAWN(block, (ptr, output), {
compute_count(*ptr, "GGTATTTTAATT", output[5]); compute_count(*ptr, "GGTATTTTAATT", output[5]);
}, (/*no output*/)); }, (/*no output*/));
WORKER_SPAWN(worker, block, (ptr, output), { WORKER_SPAWN(block, (ptr, output), {
compute_count(*ptr, "GGTATT", output[4]); compute_count(*ptr, "GGTATT", output[4]);
}, (/*no output*/)); }, (/*no output*/));
WORKER_SPAWN(worker, block, (ptr, output), { WORKER_SPAWN(block, (ptr, output), {
compute_count(*ptr, "GGTA", output[3]); compute_count(*ptr, "GGTA", output[3]);
}, (/*no output*/)); }, (/*no output*/));
compute_count(*ptr, "GGT", output[2]); compute_count(*ptr, "GGT", output[2]);
compute_freq(*ptr, 2, output[1]); compute_freq(*ptr, 2, output[1]);
compute_freq(p, 1, output[0]); compute_freq(p, 1, output[0]);
worker_sync(worker, block); worker_sync(block);
// Output the results to stdout. // Output the results to stdout.
for(int i=0; i<MAXMUM_NUMBER_OUTPUT; i++) for(int i=0; i<MAXMUM_NUMBER_OUTPUT; i++)
+9 -8
View File
@@ -1,10 +1,11 @@
Evolution of the API API incompatibility
-------------------- -------------------
V0.1.*: * First formal version of API V0.1.*: * First formal version of API
V0.2.*: * worker_sync takes a 'worker_t' as an additional parameter V0.2.*: * worker_start takes a 'worker_t' as an additional parameter
(This allows to perform a wait-on-event instead of a busy waiting). (This allows to perform a wait-on-event instead of a busy waiting).
* worker_spawn doesn't take into a 'worker_t' anymore.
* worker_init takes an int as numWorker instead of an unsingned int. * worker_init takes an int as numWorker instead of an unsingned int.
* RBTREE pop method has been renamed into _pop_at * RBTREE pop method has been renamed into _pop_at
* SNAPSHOT_DEF has been removed. use SNAPSHOT_SPSC_DEF * SNAPSHOT_DEF has been removed. use SNAPSHOT_SPSC_DEF
@@ -12,12 +13,12 @@ V0.2.*: * worker_sync takes a 'worker_t' as an additional parameter
The interface is similar to dict _get_at, making the API cleaner The interface is similar to dict _get_at, making the API cleaner
and more generic. and more generic.
_set_at2(a,i,x) ==> set(*_get_at(a,i),x) _set_at2(a,i,x) ==> set(*_get_at(a,i),x)
* DICT SET _set_at method has been renamed as _push * Rename DICT SET _set_at method as _push
Since there is no key, it is a push method, not a _set_at method. Since there is no key, it is a push method, not a _set_at method.
* DICT_SET_DEF2 ==> DICT_SET_DEF * Rename DICT_SET_DEF2 as DICT_SET_DEF
since it only requires one argument. since it only requires one argument.
* ALGO _contains ==> _contain_p * Rename ALGO _contains as _contain_p
since it is a predicate '_p' and it shall be in infinitive form. since it is a predicate '_p' and it shall be in infinitive form.
* Rename algo _map into _for_each (Standard name). * Rename algo _map as _for_each (Standard name).
+31 -29
View File
@@ -108,12 +108,6 @@ typedef struct worker_thread_s {
m_thread_t id; m_thread_t id;
} worker_thread_t; } worker_thread_t;
/* This type defines a synchronization point for workers */
typedef struct worker_sync_s {
atomic_int num_spawn;
atomic_int num_terminated_spawn;
} worker_sync_t[1];
/* Let's define the queue which will manage all work orders */ /* Let's define the queue which will manage all work orders */
BUFFER_DEF(worker_queue, worker_order_t, 0, BUFFER_QUEUE|BUFFER_UNBLOCKING_PUSH|BUFFER_BLOCKING_POP|BUFFER_THREAD_SAFE|BUFFER_DEFERRED_POP, M_POD_OPLIST) BUFFER_DEF(worker_queue, worker_order_t, 0, BUFFER_QUEUE|BUFFER_UNBLOCKING_PUSH|BUFFER_BLOCKING_POP|BUFFER_THREAD_SAFE|BUFFER_DEFERRED_POP, M_POD_OPLIST)
@@ -137,6 +131,13 @@ typedef struct worker_s {
} worker_t[1]; } worker_t[1];
/* This type defines a synchronization point for workers */
typedef struct worker_sync_s {
atomic_int num_spawn;
atomic_int num_terminated_spawn;
struct worker_s *worker;
} worker_sync_t[1];
/* Return the number of CPU of the system */ /* Return the number of CPU of the system */
static inline int static inline int
workeri_get_cpu_count(void) workeri_get_cpu_count(void)
@@ -266,20 +267,21 @@ worker_clear(worker_t g)
/* Start a new collaboration between workers /* Start a new collaboration between workers
and define the synchronization point 'block' */ and define the synchronization point 'block' */
static inline void static inline void
worker_start(worker_sync_t block) worker_start(worker_sync_t block, worker_t g)
{ {
atomic_init (&block->num_spawn, 0); atomic_init (&block->num_spawn, 0);
atomic_init (&block->num_terminated_spawn, 0); atomic_init (&block->num_terminated_spawn, 0);
block->worker = g;
} }
/* Spawn or not the given work order to workers, /* Spawn or not the given work order to workers,
or do it ourself if no worker is available */ or do it ourself if no worker is available */
static inline void static inline void
worker_spawn(worker_t g, worker_sync_t block, void (*func)(void *data), void *data) worker_spawn(worker_sync_t block, void (*func)(void *data), void *data)
{ {
const worker_order_t w = { block, data, func WORKER_EXTRA_ORDER }; const worker_order_t w = { block, data, func WORKER_EXTRA_ORDER };
if (M_UNLIKELY (!worker_queue_full_p(g->queue_g)) if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
&& worker_queue_push (g->queue_g, w) == true) { && worker_queue_push (block->worker->queue_g, w) == true) {
//printf ("Sending data to thread: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn); //printf ("Sending data to thread: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
atomic_fetch_add (&block->num_spawn, 1); atomic_fetch_add (&block->num_spawn, 1);
return; return;
@@ -293,11 +295,11 @@ worker_spawn(worker_t g, worker_sync_t block, void (*func)(void *data), void *da
/* Spawn or not the given work order to workers, /* Spawn or not the given work order to workers,
or do it ourself if no worker is available */ or do it ourself if no worker is available */
static inline void static inline void
worker_spawn_block(worker_t g, worker_sync_t block, void (^func)(void *data), void *data) worker_spawn_block(worker_sync_t block, void (^func)(void *data), void *data)
{ {
const worker_order_t w = { block, data, NULL, func }; const worker_order_t w = { block, data, NULL, func };
if (M_UNLIKELY (!worker_queue_full_p(g->queue_g)) if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
&& worker_queue_push (g->queue_g, w) == true) { && worker_queue_push (block->worker->queue_g, w) == true) {
//printf ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn); //printf ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
atomic_fetch_add (&block->num_spawn, 1); atomic_fetch_add (&block->num_spawn, 1);
return; return;
@@ -312,11 +314,11 @@ worker_spawn_block(worker_t g, worker_sync_t block, void (^func)(void *data), vo
/* Spawn or not the given work order to workers, /* Spawn or not the given work order to workers,
or do it ourself if no worker is available */ or do it ourself if no worker is available */
static inline void static inline void
worker_spawn_function(worker_t g, worker_sync_t block, std::function<void(void *data)> func, void *data) worker_spawn_function(worker_sync_t block, std::function<void(void *data)> func, void *data)
{ {
const worker_order_t w = { block, data, NULL, func }; const worker_order_t w = { block, data, NULL, func };
if (M_UNLIKELY (!worker_queue_full_p(g->queue_g)) if (M_UNLIKELY (!worker_queue_full_p(block->worker->queue_g))
&& worker_queue_push (g->queue_g, w) == true) { && worker_queue_push (block->worker->queue_g, w) == true) {
//printf ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn); //printf ("Sending data to thread as block: %p (block: %d / %d)\n", data, block->num_spawn, block->num_terminated_spawn);
atomic_fetch_add (&block->num_spawn, 1); atomic_fetch_add (&block->num_spawn, 1);
return; return;
@@ -339,15 +341,15 @@ worker_sync_p(worker_sync_t block)
/* Wait for all work orders to be finished */ /* Wait for all work orders to be finished */
static inline void static inline void
worker_sync(worker_t g, worker_sync_t block) worker_sync(worker_sync_t block)
{ {
//printf ("Waiting for thread terminasion.\n"); //printf ("Waiting for thread terminasion.\n");
if (worker_sync_p(block)) return; if (worker_sync_p(block)) return;
m_mutex_lock(g->lock); m_mutex_lock(block->worker->lock);
while (!worker_sync_p(block)) { while (!worker_sync_p(block)) {
m_cond_wait(g->a_thread_ends, g->lock); m_cond_wait(block->worker->a_thread_ends, block->worker->lock);
} }
m_mutex_unlock(g->lock); m_mutex_unlock(block->worker->lock);
} }
/* Flush any work order in the queue if some remains.*/ /* Flush any work order in the queue if some remains.*/
@@ -376,19 +378,19 @@ worker_count(worker_t g)
'output' is the list of output variables of the 'core' block within "( )" 'output' is the list of output variables of the 'core' block within "( )"
Output variables are only available after a synchronisation block. */ Output variables are only available after a synchronisation block. */
#if WORKER_USE_CLANG_BLOCK #if WORKER_USE_CLANG_BLOCK
#define WORKER_SPAWN(_worker, _block, _input, _core, _output) \ #define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \ WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBBLOCK(_input, _output, _core) \ WORKER_DEF_SUBBLOCK(_input, _output, _core) \
worker_spawn_block ((_worker), (_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME) worker_spawn_block ((_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME)
#elif WORKER_USE_CPP_FUNCTION #elif WORKER_USE_CPP_FUNCTION
// TODO: Explicit pass all arguments by reference. // TODO: Explicit pass all arguments by reference.
#define WORKER_SPAWN(_worker, _block, _input, _core, _output) \ #define WORKER_SPAWN(_block, _input, _core, _output) \
worker_spawn_function ((_worker), (_block), [&](void *param) {(void)param ; _core } , NULL) worker_spawn_function ((_block), [&](void *param) {(void)param ; _core } , NULL)
#else #else
#define WORKER_SPAWN(_worker, _block, _input, _core, _output) \ #define WORKER_SPAWN(_block, _input, _core, _output) \
WORKER_DEF_DATA(_input, _output) \ WORKER_DEF_DATA(_input, _output) \
WORKER_DEF_SUBFUNC(_input, _output, _core) \ WORKER_DEF_SUBFUNC(_input, _output, _core) \
worker_spawn ((_worker), (_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME) worker_spawn ((_block), WORKER_SPAWN_SUBFUNC_NAME, &WORKER_SPAWN_DATA_NAME)
#endif #endif
#define WORKER_SPAWN_STRUCT_NAME M_C(worker_data_s_, __LINE__) #define WORKER_SPAWN_STRUCT_NAME M_C(worker_data_s_, __LINE__)
@@ -467,11 +469,11 @@ typedef struct worker_s {
#define worker_init(g, numWorker, extraQueue, resetFunc) do { (void) g; } while (0) #define worker_init(g, numWorker, extraQueue, resetFunc) do { (void) g; } while (0)
#define worker_clear(g) do { (void) g; } while (0) #define worker_clear(g) do { (void) g; } while (0)
#define worker_start(b) do { (void) b; } while (0) #define worker_start(b, w) do { (void) b; } while (0)
#define worker_spawn(w, b, f, d) do { f(d); } while (0) #define worker_spawn(b, f, d) do { f(d); } while (0)
#define worker_sync(b) do { (void) b; } while (0) #define worker_sync(b) do { (void) b; } while (0)
#define worker_count(w) 1 #define worker_count(w) 1
#define WORKER_SPAWN(w, b, i, c, o) do { c } while (0) #define WORKER_SPAWN(b, i, c, o) do { c } while (0)
#endif /* WORKER_DISABLE */ #endif /* WORKER_DISABLE */
+6 -6
View File
@@ -48,11 +48,11 @@ static int fib(int n)
struct fib2_s f; struct fib2_s f;
worker_sync_t b; worker_sync_t b;
worker_start(b); worker_start(b, w_g);
f.n = n - 2; f.n = n - 2;
worker_spawn (w_g, b, subfunc_1, &f); worker_spawn (b, subfunc_1, &f);
int y = fib (n-1); int y = fib (n-1);
worker_sync(w_g, b); worker_sync(b);
return f.x + y; return f.x + y;
} }
@@ -90,10 +90,10 @@ static int fib2(int n)
worker_sync_t b; worker_sync_t b;
int y1, y2; int y1, y2;
worker_start(b); worker_start(b, w_g);
WORKER_SPAWN(w_g, b, (n), { y2 = fib2(n-2); }, (y2)); WORKER_SPAWN(b, (n), { y2 = fib2(n-2); }, (y2));
y1 = fib (n-1); y1 = fib (n-1);
worker_sync(w_g, b); worker_sync(b);
return y1 + y2; return y1 + y2;
} }