Pārlūkot izejas kodu

big modifications of the nodes interface
bitmap for worker sets in subtrees
heft is not ported yet with new interface

Simon Archipoff 12 gadi atpakaļ
vecāks
revīzija
0e6004646d

+ 5 - 5
src/Makefile.am

@@ -226,13 +226,13 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 						\
 	sched_policies/node_worker.c				\
 	sched_policies/node_sched.c				\
 	sched_policies/node_eager.c				\
-	sched_policies/node_random.c				\
-	sched_policies/node_work_stealing.c			\
 	sched_policies/node_fifo.c 				\
-	sched_policies/node_heft.c				\
-	sched_policies/hierarchical_heft.c			\
+	sched_policies/node_work_stealing.c			\
 	sched_policies/prio_deque.c				\
-	sched_policies/bitmap.c
+	sched_policies/bitmap.c					\
+	sched_policies/node_random.c				
+#	sched_policies/node_heft.c				\
+	sched_policies/hierarchical_heft.c
 if STARPU_USE_CPU
 libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES += drivers/cpu/driver_cpu.c
 endif

+ 1 - 1
src/core/sched_policy.c

@@ -36,7 +36,7 @@ static struct starpu_sched_policy *predefined_policies[] =
 	&_starpu_sched_tree_eager_policy,
 	&_starpu_sched_tree_random_policy,
 	&_starpu_sched_tree_ws_policy,
-	&_starpu_sched_tree_heft_policy,
+//	&_starpu_sched_tree_heft_policy,
 	&_starpu_sched_eager_policy,
 	&_starpu_sched_prio_policy,
 	&_starpu_sched_random_policy,

+ 1 - 1
src/core/sched_policy.h

@@ -68,5 +68,5 @@ extern struct starpu_sched_policy _starpu_sched_peager_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_eager_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_random_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_ws_policy;
-extern struct starpu_sched_policy _starpu_sched_tree_heft_policy;
+//extern struct starpu_sched_policy _starpu_sched_tree_heft_policy;
 #endif // __SCHED_POLICY_H__

+ 123 - 25
src/sched_policies/bitmap.c

@@ -1,9 +1,12 @@
 #include <limits.h>
 #include <string.h>
 #include <stdlib.h>
+#include <starpu.h>
+#include "bitmap.h"
 struct _starpu_bitmap{
 	unsigned long * bits;
 	int size;
+	int cardinal;
 };
 
 struct _starpu_bitmap * _starpu_bitmap_create(void)
@@ -18,45 +21,53 @@ void _starpu_bitmap_destroy(struct _starpu_bitmap * b)
 	free(b);
 }
 
-
-struct tuple {
-	int nb_long;
-	int nb_bit;
-};
-
-static inline struct tuple get_tuple(int e)
-{
-	int i;
-	for(i = 0; e > LONG_BIT; e -= LONG_BIT, i++)
-		;
-	struct tuple t = {i, e};
-	return t;
-}
-
 void _starpu_bitmap_set(struct _starpu_bitmap * b, int e)
 {
-	struct tuple t = get_tuple(e);
-	if(t.nb_long + 1 > b->size)
+	if(!_starpu_bitmap_get(b, e))
+		b->cardinal++;
+	if((e/LONG_BIT) + 1 > b->size)
 	{
-		b->bits = realloc(b->bits, sizeof(unsigned long) * (t.nb_long + 1));
-		b->size = t.nb_long + 1;
+		b->bits = realloc(b->bits, sizeof(unsigned long) * ((e/LONG_BIT) + 1));
+		memset(b->bits + b->size, 0, sizeof(unsigned long) * ((e/LONG_BIT + 1) - b->size));
+		b->size = (e/LONG_BIT) + 1;
 	}
-	b->bits[t.nb_long] |= (1ul << t.nb_bit);
+	b->bits[e/LONG_BIT] |= (1ul << (e%LONG_BIT));
 }
 void _starpu_bitmap_unset(struct _starpu_bitmap *b, int e)
 {
-	struct tuple t = get_tuple(e);
+	if(!_starpu_bitmap_get(b, e))
+		b->cardinal--;
 	if(e / LONG_BIT > b->size)
 		return;
-	b->bits[t.nb_long] ^= ~(1ul << t.nb_bit);
+	b->bits[e/LONG_BIT] ^= ~(1ul << (e%LONG_BIT));
+}
+
+void _starpu_bitmap_unset_all(struct _starpu_bitmap * b)
+{
+	free(b->bits);
+	b->bits = NULL;
+	b->size = 0;
 }
 
 int _starpu_bitmap_get(struct _starpu_bitmap * b, int e)
 {
-	if(e / LONG_BIT > b->size)
+	if(e / LONG_BIT >= b->size)
 		return 0;
-	struct tuple t = get_tuple(e);
-	return b->bits[t.nb_long] & (1 << t.nb_bit);
+	return b->bits[e/LONG_BIT] & (1 << (e%LONG_BIT));
+}
+
+void _starpu_bitmap_or(struct _starpu_bitmap * a, struct _starpu_bitmap * b)
+{
+	if(a->size < b->size)
+	{
+		a->bits = realloc(a->bits, b->size * sizeof(unsigned long));
+		a->size = b->size;
+	}
+	int i;
+	for(i = 0; i < b->size; i++)
+	{
+		a->bits[i] |= b->bits[i];
+	}
 }
 
 
@@ -65,4 +76,91 @@ int _starpu_bitmap_and_get(struct _starpu_bitmap * b1, struct _starpu_bitmap * b
 	return _starpu_bitmap_get(b1,e) && _starpu_bitmap_get(b2,e);
 }
 
+int _starpu_bitmap_cardinal(struct _starpu_bitmap * b)
+{
+	return b->cardinal;
+}
+
+
+static inline int get_first_bit_rank(unsigned long ms)
+{
+	STARPU_ASSERT(ms != 0);
+	unsigned long m = 1ul;
+	int i = 0;
+	while(!(m&ms))
+		i++,m<<=1;
+	return i;
+}
+
+
+int _starpu_bitmap_first(struct _starpu_bitmap * b)
+{
+	int i = 0;
+	while(i < b->size && !b->bits[i])
+		i++;
+	if( i == b->size)
+		return -1;
+	int nb_long = i;
+	unsigned long ms = b->bits[i];
+	int m = 1;
+	i = 0;
+	while(!(m&ms))
+		i++,m<<=1;
+	return (nb_long * LONG_BIT) + i;
+}
+
+int _starpu_bitmap_has_next(struct _starpu_bitmap * b, int e)
+{
+	int nb_long = e / LONG_BIT;
+	int nb_bit = e % LONG_BIT;
+	unsigned long mask = (~0ul) << (nb_bit + 1);
+	if(b->bits[nb_long] & mask)
+		return 1;
+	for(nb_long++; nb_long < b->size; nb_long++)
+		if(b->bits[nb_long])
+			return 1;
+	return 0;
+}
+
+int _starpu_bitmap_last(struct _starpu_bitmap * b)
+{
+	if(b->cardinal == 0)
+		return -1;
+	int ilong;
+	for(ilong = b->size - 1; ilong >= 0; ilong--)
+	{
+		if(b->bits[ilong])
+			break;
+	}
+	STARPU_ASSERT(ilong >= 0);
+	unsigned long l = b->bits[ilong];
+	int ibit = LONG_BIT - 1;
+	while((!(1ul << ibit)) & l)
+		ibit--;
+	STARPU_ASSERT(ibit >= 0);
+	return ilong * LONG_BIT + ibit;
+}
+
+int _starpu_bitmap_next(struct _starpu_bitmap *b, int e)
+{
+	int nb_long = e / LONG_BIT;
+	int nb_bit = e % LONG_BIT;
+	if((~0ul << (nb_bit + 1)) & b->bits[nb_long])
+	{
+		unsigned long mask = 1ul<<nb_bit;
+		int i = nb_bit + 1;
+		while(1)
+		{
+			if(b->bits[nb_long] & (mask<<i))
+				return (nb_long * LONG_BIT) + nb_bit + i;
+			i++;
+		}
+	}
+
+	for(nb_long++;nb_long < b->size; nb_long++)
+		if(b->bits[nb_long])
+			return nb_long * LONG_BIT + get_first_bit_rank(b->bits[nb_long]);
+	return -1;
+}
+
 

+ 11 - 0
src/sched_policies/bitmap.h

@@ -8,14 +8,25 @@ void _starpu_bitmap_destroy(struct _starpu_bitmap *);
 
 void _starpu_bitmap_set(struct _starpu_bitmap *, int);
 void _starpu_bitmap_unset(struct _starpu_bitmap *, int);
+void _starpu_bitmap_unset_all(struct _starpu_bitmap *);
 
 int _starpu_bitmap_get(struct _starpu_bitmap *, int);
 
+//this is basically compute a |= b;
+void _starpu_bitmap_or(struct _starpu_bitmap * a,
+		       struct _starpu_bitmap * b);
+
 //return 1 iff e set in b1 AND e set in b2
 int _starpu_bitmap_and_get(struct _starpu_bitmap * b1,
 			   struct _starpu_bitmap * b2,
 			   int e);
 
+int _starpu_bitmap_cardinal(struct _starpu_bitmap *);
 
+//return the index of first bit, -1 if none
+int _starpu_bitmap_first(struct _starpu_bitmap *);
+int _starpu_bitmap_last(struct _starpu_bitmap *);
+//return the index of bit right after e, -1 if none
+int _starpu_bitmap_next(struct _starpu_bitmap *, int e);
 
 #endif

+ 1 - 2
src/sched_policies/hierarchical_heft.c

@@ -1,7 +1,7 @@
 #include "node_sched.h"
 #include <core/workers.h>
 
-#ifdef STARPU_HAVE_HWLOC
+#if 0//def STARPU_HAVE_HWLOC
 #include <hwloc.h>
 /*
  * this function attempt to create a scheduler with a heft node at top,
@@ -40,7 +40,6 @@ struct _starpu_sched_node * _starpu_heft_eager_scheduler_add_worker(unsigned sch
 	for(i = 0; i < root->nchilds; i++)
 	{
 		struct _starpu_sched_node * child = root->childs[i];
-		STARPU_ASSERT(child->nworkers > 0);
 		int wid = child->workerids[0];
 		hwloc_bitmap_t b = get_nodeset(child->workerids[0]);
 		if(hwloc_bitmap_intersects(b,node) && starpu_worker_get_type(wid) == starpu_worker_get_type(workerid))

+ 14 - 32
src/sched_policies/node_eager.c

@@ -11,54 +11,36 @@ static void initialize_eager_center_policy(unsigned sched_ctx_id)
 	struct _starpu_sched_tree *data = malloc(sizeof(struct _starpu_sched_tree));
 	STARPU_PTHREAD_RWLOCK_INIT(&data->lock,NULL);
  	data->root = _starpu_sched_node_fifo_create();
-	
+	data->workers = _starpu_bitmap_create();
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count(); i++)
+	{
+		struct _starpu_sched_node * node = _starpu_sched_node_worker_get(i);
+		if(!node)
+			continue;
+		node->fathers[sched_ctx_id] = data->root;
+		_starpu_sched_node_add_child(data->root, node);
+	}
+	_starpu_set_workers_bitmaps();
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)data);
 }
 
 static void deinitialize_eager_center_policy(unsigned sched_ctx_id)
 {
 	struct _starpu_sched_tree *tree = (struct _starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
+	_starpu_bitmap_destroy(tree->workers);
 	_starpu_tree_destroy(tree, sched_ctx_id);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 }
 
-static void add_worker_eager(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	unsigned i;
-	for(i = 0; i < nworkers; i++)
-	{
-		t->root->add_child(t->root, _starpu_sched_node_worker_get(workerids[i]), sched_ctx_id);
-		_starpu_sched_node_worker_get(workerids[i])->fathers[sched_ctx_id] = t->root;
-	}
-	_starpu_tree_update_after_modification(t);
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
-static void remove_worker_eager(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	unsigned i;	
-	for(i = 0; i < nworkers; i++)
-	{
-		t->root->remove_child(t->root, _starpu_sched_node_worker_get(workerids[i]), sched_ctx_id);
-		_starpu_sched_node_worker_get(workerids[i])->fathers[sched_ctx_id] = NULL;
-	}
-	_starpu_tree_update_after_modification(t);
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
 
 
 struct starpu_sched_policy _starpu_sched_tree_eager_policy =
 {
 	.init_sched = initialize_eager_center_policy,
 	.deinit_sched = deinitialize_eager_center_policy,
-	.add_workers = add_worker_eager,
-	.remove_workers = remove_worker_eager,
+	.add_workers = _starpu_tree_add_workers,
+	.remove_workers = _starpu_tree_remove_workers,
 	.push_task = _starpu_tree_push_task,
 	.pop_task = _starpu_tree_pop_task,
 	.pre_exec_hook = NULL,

+ 33 - 13
src/sched_policies/node_fifo.c

@@ -38,16 +38,34 @@ static struct _starpu_task_execute_preds estimated_execute_preds(struct _starpu_
 
 static double estimated_load(struct _starpu_sched_node * node)
 {
+	struct _starpu_fifo_data * data = node->data;
+	struct _starpu_prio_deque * fifo = &data->fifo;
+	starpu_pthread_mutex_t * mutex = &data->mutex;
 	double relative_speedup = 0.0;
+	double load;
+
+	if(node->is_homogeneous)
+	{
+		relative_speedup = starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(_starpu_bitmap_first(node->workers)));
+		STARPU_PTHREAD_MUTEX_LOCK(mutex);
+		load = fifo->ntasks / relative_speedup;
+		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		return load;
+	}
+	else
+	{
+		int i;
+		for(i = _starpu_bitmap_first(node->workers);
+		    i != -1;
+		    i = _starpu_bitmap_next(node->workers, i))
+			relative_speedup += starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(i));
+		relative_speedup /= _starpu_bitmap_cardinal(node->workers);
+			STARPU_ASSERT(!_STARPU_IS_ZERO(relative_speedup));
+			STARPU_PTHREAD_MUTEX_LOCK(mutex);
+			load = fifo->ntasks / relative_speedup;
+			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	}
 	int i;
-	STARPU_ASSERT(node->nworkers > 0);
-	int nworkers = node->is_homogeneous ? 1 : node->nworkers;
-	for(i = 0; i < nworkers; i++)
-		relative_speedup += starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(node->workerids[i]));
-	relative_speedup /= nworkers;
-	struct _starpu_prio_deque * fifo = node->data;
-	STARPU_ASSERT(!_STARPU_IS_ZERO(relative_speedup));
-	double load = fifo->ntasks / relative_speedup; 
 	for(i = 0; i < node->nchilds; i++)
 	{
 		struct _starpu_sched_node * c = node->childs[i];
@@ -56,9 +74,9 @@ static double estimated_load(struct _starpu_sched_node * node)
 	return load;
 }
 
-static int push_task(struct _starpu_sched_node * node, struct starpu_task * task)
+static int push_task(struct _starpu_sched_node * node, struct starpu_task * task, struct _starpu_bitmap * worker_mask)
 {
-	STARPU_ASSERT(node->nworkers > 0);
+	STARPU_ASSERT(_starpu_sched_node_can_execute_task(node,task, worker_mask));
 	struct _starpu_fifo_data * data = node->data;
 	struct _starpu_prio_deque * fifo = &data->fifo;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
@@ -69,7 +87,8 @@ static int push_task(struct _starpu_sched_node * node, struct starpu_task * task
 	int ret = _starpu_prio_deque_push_task(fifo, task);
 	if(!isnan(task->predicted))
 	{
-		fifo->exp_len += task->predicted/node->nworkers;
+		task->predicted /= _starpu_bitmap_cardinal(node->workers);
+		fifo->exp_len += task->predicted;
 		fifo->exp_end = fifo->exp_start + fifo->exp_len;
 	}
 	STARPU_ASSERT(!isnan(fifo->exp_end));
@@ -96,9 +115,8 @@ static struct starpu_task * pop_task(struct _starpu_sched_node * node, unsigned
 	if(task)
 	{
 		fifo->exp_start = starpu_timing_now();
-		STARPU_ASSERT(node->nworkers > 0);
 		if(!isnan(task->predicted))
-			fifo->exp_len -= task->predicted/node->nworkers;
+			fifo->exp_len -= task->predicted;
 		fifo->exp_end = fifo->exp_start + fifo->exp_len;
 	}
 	STARPU_ASSERT(!isnan(fifo->exp_end));
@@ -135,6 +153,8 @@ struct starpu_task_list  _starpu_sched_node_fifo_get_non_executable_tasks(struct
 	return list;
 }
 */
+
+
 int _starpu_sched_node_is_fifo(struct _starpu_sched_node * node)
 {
 	return node->estimated_execute_preds == estimated_execute_preds

+ 33 - 77
src/sched_policies/node_random.c

@@ -22,45 +22,34 @@ static double compute_relative_speedup(struct _starpu_sched_node * node)
 	return sum;
 }
 
-static void update_relative_childs_speedup(struct _starpu_sched_node * node)
+static void init_data_random(struct _starpu_sched_node * node)
 {
-	struct _starpu_random_data * rd = node->data;
-	rd->relative_speedup = realloc(rd->relative_speedup,sizeof(double) * node->nchilds);
+	struct _starpu_random_data * rd = malloc(sizeof(struct _starpu_random_data));
+	node->data = rd;
+	rd->relative_speedup = malloc(sizeof(double) * node->nchilds);
 	int i;
 	for(i = 0; i < node->nchilds; i++)
 		rd->relative_speedup[i] = compute_relative_speedup(node->childs[i]);
 }
 
-static void add_child(struct _starpu_sched_node *node,
-		      struct _starpu_sched_node *child,
-		      unsigned sched_ctx_id)
-{
-//	STARPU_PTHREAD_RWLOCK_WRLOCK(&node->mutex);
-	_starpu_sched_node_add_child(node, child, sched_ctx_id);
-	update_relative_childs_speedup(node);
-//	STARPU_PTHREAD_RWLOCK_UNLOCK(&node->mutex);
-}
-static void remove_child(struct _starpu_sched_node *node,
-			 struct _starpu_sched_node *child,
-			 unsigned sched_ctx_id)
+static void deinit_data_random(struct _starpu_sched_node * node)
 {
-//	STARPU_PTHREAD_RWLOCK_WRLOCK(&node->mutex);
-	_starpu_sched_node_remove_child(node, child, sched_ctx_id);
-	update_relative_childs_speedup(node);
-//	STARPU_PTHREAD_RWLOCK_UNLOCK(&node->mutex);
+	struct _starpu_random_data * rd = node->data;
+	free(rd->relative_speedup);
+	free(rd);
+	
 }
 
-
-static int push_task(struct _starpu_sched_node * node, struct starpu_task * task)
+static int push_task(struct _starpu_sched_node * node, struct starpu_task * task, struct _starpu_bitmap * worker_mask)
 {
 	struct _starpu_random_data * rd = node->data;
-//	STARPU_PTHREAD_RWLOCK_RDLOCK(&node->mutex);
+
 	int indexes_nodes[node->nchilds];
 	int size=0,i;
 	double alpha_sum = 0.0;
 	for(i = 0; i < node->nchilds ; i++)
 	{
-		if(_starpu_sched_node_can_execute_task(node->childs[i],task))
+		if(_starpu_sched_node_can_execute_task(node->childs[i],task, worker_mask))
 		{
 			indexes_nodes[size++] = i;
 			alpha_sum += rd->relative_speedup[i];
@@ -82,32 +71,20 @@ static int push_task(struct _starpu_sched_node * node, struct starpu_task * task
 		alpha += rd->relative_speedup[index];
 	}
 	STARPU_ASSERT(select != NULL);
-	int ret_val = select->push_task(select,task);
+	int ret_val = select->push_task(select,task, worker_mask);
 	node->available(node);
-//	STARPU_PTHREAD_RWLOCK_UNLOCK(&node->mutex);
-	return ret_val;
-}
 
-static void destroy_random_node(struct _starpu_sched_node * node)
-{
-	struct _starpu_random_data * rd = node->data;
-	free(rd->relative_speedup);
-	free(rd);
-	_starpu_sched_node_destroy(node);
+	return ret_val;
 }
 
 
 struct _starpu_sched_node * _starpu_sched_node_random_create(void)
 {
 	struct _starpu_sched_node * node = _starpu_sched_node_create();
-	struct _starpu_random_data * rd = malloc(sizeof(struct _starpu_random_data));
-
-	rd->relative_speedup = NULL;
-	node->data = rd;
-	node->destroy_node = destroy_random_node;
+	node->data = NULL;
+	node->init_data = init_data_random;
+	node->deinit_data = deinit_data_random;
 	node->push_task = push_task;
-	node->add_child = add_child;
-	node->remove_child = remove_child;
 	starpu_srand48(time(NULL));
 	return node;
 }
@@ -118,57 +95,36 @@ static void initialize_random_center_policy(unsigned sched_ctx_id)
 	struct _starpu_sched_tree *data = malloc(sizeof(struct _starpu_sched_tree));
 	STARPU_PTHREAD_RWLOCK_INIT(&data->lock,NULL);
  	data->root = _starpu_sched_node_random_create();
+	data->workers = _starpu_bitmap_create();
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count(); i++)
+	{
+		struct _starpu_sched_node * node = _starpu_sched_node_worker_get(i);
+		if(!node)
+			continue;
+		node->fathers[sched_ctx_id] = data->root;
+		_starpu_sched_node_add_child(data->root, node);
+	}
+	_starpu_set_workers_bitmaps();
+	_starpu_call_init_data(data);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)data);
 }
 static void deinitialize_random_center_policy(unsigned sched_ctx_id)
 {
 	struct _starpu_sched_tree *tree = (struct _starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
+	_starpu_bitmap_destroy(tree->workers);
 	_starpu_tree_destroy(tree, sched_ctx_id);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 }
 
 
- static void add_worker_random(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-		struct _starpu_sched_node * random_node = t->root;
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	unsigned i;
-	for(i = 0; i < nworkers; i++)
-	{
-		struct _starpu_sched_node * worker = _starpu_sched_node_worker_get(workerids[i]);
-		t->root->add_child(random_node, _starpu_sched_node_worker_get(workerids[i]), sched_ctx_id);
-		_starpu_sched_node_set_father(worker, random_node, sched_ctx_id);
-	}
-	_starpu_tree_update_after_modification(t);
-	update_relative_childs_speedup(random_node);
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
-static void remove_worker_random(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	struct _starpu_sched_node * random_node = t->root;
-	unsigned i;
-	for(i = 0; i < nworkers; i++)
-	{
-		struct _starpu_sched_node * worker = _starpu_sched_node_worker_get(workerids[i]);
-		random_node->remove_child(random_node, worker, sched_ctx_id);
-		_starpu_sched_node_set_father(worker, NULL, sched_ctx_id);
-	}
-	_starpu_tree_update_after_modification(t);
-	update_relative_childs_speedup(t->root);
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
 struct starpu_sched_policy _starpu_sched_tree_random_policy =
 {
 	.init_sched = initialize_random_center_policy,
 	.deinit_sched = deinitialize_random_center_policy,
-	.add_workers = add_worker_random,
-	.remove_workers = remove_worker_random,
+	.add_workers = _starpu_tree_add_workers,
+	.remove_workers = _starpu_tree_remove_workers,
 	.push_task = _starpu_tree_push_task,
 	.pop_task = _starpu_tree_pop_task,
 	.pre_exec_hook = NULL,

+ 97 - 89
src/sched_policies/node_sched.c

@@ -71,11 +71,32 @@ int push_task(struct starpu_task * task)
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	STARPU_PTHREAD_RWLOCK_RDLOCK(&t->lock);
-	int ret = t->root->push_task(t->root, task);
+	int ret = t->root->push_task(t->root, task, t->workers);
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
 	return ret;
 }
 
+void _starpu_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
+{
+	struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
+	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
+	unsigned i;
+	for(i = 0; i < nworkers; i++)
+		_starpu_bitmap_set(t->workers, workerids[i]);
+	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
+}
+
+void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
+{
+	struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
+	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
+	unsigned i;
+	for(i = 0; i < nworkers; i++)
+		_starpu_bitmap_unset(t->workers, workerids[i]);
+	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
+}
+
+
 void _starpu_node_destroy_rec(struct _starpu_sched_node * node, unsigned sched_ctx_id)
 {
 	if(node == NULL)
@@ -119,7 +140,8 @@ void _starpu_node_destroy_rec(struct _starpu_sched_node * node, unsigned sched_c
 			if(!shared)//if not shared we want to destroy it and his childs
 				PUSH(child);
 		}
-		n->destroy_node(n);
+		n->deinit_data(n);
+		_starpu_sched_node_destroy(n);
 	}
 	free(stack);
 }
@@ -129,7 +151,7 @@ void _starpu_tree_destroy(struct _starpu_sched_tree * tree, unsigned sched_ctx_i
 	STARPU_PTHREAD_RWLOCK_DESTROY(&tree->lock);
 	free(tree);
 }
-void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starpu_sched_node * child,unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
+void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starpu_sched_node * child)
 {
 	STARPU_ASSERT(!_starpu_sched_node_is_worker(node));
 	int i;
@@ -142,7 +164,7 @@ void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starp
 	node->childs[node->nchilds] = child;
 	node->nchilds++;
 }
-void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child,unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
+void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child)
 {
 	int pos;
 	for(pos = 0; pos < node->nchilds; pos++)
@@ -158,7 +180,7 @@ int _starpu_tree_push_task(struct starpu_task * task)
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct _starpu_sched_tree *tree = starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	STARPU_PTHREAD_RWLOCK_RDLOCK(&tree->lock);
-	int ret_val = tree->root->push_task(tree->root,task); 
+	int ret_val = tree->root->push_task(tree->root,task,tree->workers);
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&tree->lock);
 	return ret_val;
 }
@@ -263,48 +285,62 @@ static double estimated_transfer_length(struct _starpu_sched_node * node, struct
 	return sum;
 }
 */
-int _starpu_sched_node_can_execute_task(struct _starpu_sched_node * node, struct starpu_task * task)
+int _starpu_sched_node_can_execute_task(struct _starpu_sched_node * node, struct starpu_task * task, struct _starpu_bitmap * worker_mask)
 {
 	unsigned nimpl;
 	int worker;
 	STARPU_ASSERT(task);
 	STARPU_ASSERT(node);
 	for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
-		for(worker = 0; worker < node->nworkers; worker++)
-			if (starpu_worker_can_execute_task(node->workerids[worker], task, nimpl))
+		for(worker = _starpu_bitmap_first(node->workers);
+		    -1 != worker;
+		    worker = _starpu_bitmap_next(node->workers, worker))
+			if (_starpu_bitmap_get(worker_mask, worker)
+			    && starpu_worker_can_execute_task(worker, task, nimpl))
 				return 1;
+
 	return 0;
 }
 
-int _starpu_sched_node_can_execute_task_with_impl(struct _starpu_sched_node * node, struct starpu_task * task, unsigned nimpl)
+int _starpu_sched_node_can_execute_task_with_impl(struct _starpu_sched_node * node, struct starpu_task * task, unsigned nimpl, struct _starpu_bitmap * worker_mask)
 {
 
 	int worker;
 	STARPU_ASSERT(task);
 	STARPU_ASSERT(nimpl < STARPU_MAXIMPLEMENTATIONS);
-	for(worker = 0; worker < node->nworkers; worker++)
-		if (starpu_worker_can_execute_task(worker, task, nimpl))
+	for(worker = _starpu_bitmap_first(node->workers);
+	    worker != -1;
+	    worker = _starpu_bitmap_next(node->workers, worker))
+		if (_starpu_bitmap_get(worker_mask, worker)
+		    && starpu_worker_can_execute_task(worker, task, nimpl))
 			return 1;
 	return 0;
 
 }
 
+void take_node_and_does_nothing(struct _starpu_sched_node * node STARPU_ATTRIBUTE_UNUSED)
+{
+}
+
 struct _starpu_sched_node * _starpu_sched_node_create(void)
 {
 	struct _starpu_sched_node * node = malloc(sizeof(*node));
 	memset(node,0,sizeof(*node));
+	node->workers = _starpu_bitmap_create();
 	node->available = available;
+	node->init_data = take_node_and_does_nothing;
+	node->deinit_data = take_node_and_does_nothing;
 	node->pop_task = pop_task_node;
 	node->estimated_load = estimated_load;
 	node->estimated_execute_preds = estimated_execute_preds;
-	node->destroy_node = _starpu_sched_node_destroy;
-	node->add_child = _starpu_sched_node_add_child;
-	node->remove_child = _starpu_sched_node_remove_child;
 
 	return node;
 }
 void _starpu_sched_node_destroy(struct _starpu_sched_node *node)
 {
+	if(_starpu_sched_node_is_worker(node))
+		return;
+
 	int i,j;
 	for(i = 0; i < node->nchilds; i++)
 	{
@@ -315,103 +351,70 @@ void _starpu_sched_node_destroy(struct _starpu_sched_node *node)
 
 	}
 	free(node->childs);
+	_starpu_bitmap_destroy(node->workers);
+
 	free(node);
 }
 
 
-static int is_homogeneous(int * workerids, int nworkers)
+static void set_is_homogeneous(struct _starpu_sched_node * node)
 {
-	if(nworkers < 2)
-		return 1;
-	int i = 0;
-	uint32_t last_worker = _starpu_get_worker_struct(workerids[i])->worker_mask;
-	for(i = 1; i < nworkers; i++)
+	STARPU_ASSERT(_starpu_bitmap_cardinal(node->workers) > 0);
+	if(_starpu_bitmap_cardinal(node->workers) == 1)
+		node->is_homogeneous = 1;
+	int worker = _starpu_bitmap_first(node->workers);
+	uint32_t last_worker = _starpu_get_worker_struct(worker)->worker_mask;
+	for(;
+	    worker != -1;
+	    worker = _starpu_bitmap_next(node->workers, worker))
+		
 	{
-		if(last_worker != _starpu_get_worker_struct(workerids[i])->worker_mask)
-		   return 0;
-		last_worker = _starpu_get_worker_struct(workerids[i])->worker_mask;
+		if(last_worker != _starpu_get_worker_struct(worker)->worker_mask)
+		{
+			node->is_homogeneous = 0;
+			return;
+		}
+		last_worker = _starpu_get_worker_struct(worker)->worker_mask;
 	}
-	return 1;
+	node->is_homogeneous = 1;
 }
 
 
-static int in_tab(int elem, int * tab, int size)
+static void add_worker_bit(struct _starpu_sched_node * node, int worker)
 {
-	for(size--;size >= 0; size--)
-		if(tab[size] == elem)
-			return 1;
-	return 0;
-}
-static void _update_workerids_after_tree_modification(struct _starpu_sched_node * node)
-{
-	if(_starpu_sched_node_is_worker(node))
-	{
-		node->nworkers = 1;
-		node->workerids[0] =  _starpu_sched_node_worker_get_workerid(node);
-	}
-	else
-	{
-		int i;
-		node->nworkers = 0;
-		for(i = 0; i < node->nchilds; i++)
+	STARPU_ASSERT(node);
+	_starpu_bitmap_set(node->workers, worker);
+	int i;
+	for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
+		if(node->fathers[i])
 		{
-			struct _starpu_sched_node * child = node->childs[i];
-			_update_workerids_after_tree_modification(child);
-			int j;
-			for(j = 0; j < child->nworkers; j++)
-			{
-				int id = child->workerids[j];
-				if(!in_tab(id, node->workerids, node->nworkers))
-					node->workerids[node->nworkers++] = id;
-			}
+			add_worker_bit(node->fathers[i], worker);
+			set_is_homogeneous(node->fathers[i]);
 		}
-	}
-	node->is_homogeneous = is_homogeneous(node->workerids, node->nworkers);
 }
 
-
-void _starpu_tree_update_after_modification(struct _starpu_sched_tree * tree)
+void _starpu_set_workers_bitmaps(void)
 {
-	_update_workerids_after_tree_modification(tree->root);
+	unsigned worker;	
+	for(worker = 0; worker < starpu_worker_get_count(); worker++)
+	{
+		struct _starpu_sched_node * worker_node = _starpu_sched_node_worker_get(worker);
+		add_worker_bit(worker_node, worker);
+	}
 }
 
-
-static struct _starpu_sched_node * _starpu_sched_node_remove_worker(struct _starpu_sched_node * node, int workerid, int sched_ctx_id)
+static void helper_starpu_call_init_data(struct _starpu_sched_node *node)
 {
-	if(node == NULL)
-		return NULL;
-	if(node->nworkers == 1 && node->workerids[0] == workerid)//special case if there is only one worker left
-		return node;
 	int i;
 	for(i = 0; i < node->nchilds; i++)
-	{
-
-		struct _starpu_sched_node * child = node->childs[i];
-		if(in_tab(workerid, child->workerids, child->nworkers))
-		{
-			if(child->nworkers == 1)//we wants to remove this subtree
-			{
-				node->remove_child(node, child, sched_ctx_id);
-//				if(childs->fathers[sched_ctx_id] == node)
-//					_starpu_sched_node_set_father(child, NULL, sched_ctx_id);
-				return child;
-			}
-			else//we have several worker in this subtree
-			{
-				return _starpu_sched_node_remove_worker(child, workerid, sched_ctx_id);
-			}
-		}
-	}
-	return NULL;
+		helper_starpu_call_init_data(node->childs[i]);
+	if(!node->data)
+		node->init_data(node);
 }
 
-struct _starpu_sched_node * _starpu_sched_tree_remove_worker(struct _starpu_sched_tree * t, int workerid, int sched_ctx_id)
+void _starpu_call_init_data(struct _starpu_sched_tree * t)
 {
-	struct _starpu_sched_node * node = _starpu_sched_node_remove_worker(t->root, workerid, sched_ctx_id);
-	_starpu_tree_update_after_modification(t);
-	if(node == t->root)
-		t->root = NULL;
-	return node;
+	helper_starpu_call_init_data(t->root);
 }
 
 
@@ -419,14 +422,18 @@ static int push_task_to_first_suitable_parent(struct _starpu_sched_node * node,
 {
 	if(node == NULL || node->fathers[sched_ctx_id] == NULL)
 		return 1;
+
+	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
+
 	
 	struct _starpu_sched_node * father = node->fathers[sched_ctx_id];
-	if(_starpu_sched_node_can_execute_task(father,task))
-		return father->push_task(father, task);
+	if(_starpu_sched_node_can_execute_task(father,task,t->workers))
+		return father->push_task(father, task, t->workers);
 	else
 		return push_task_to_first_suitable_parent(father, task, sched_ctx_id);
 }
 
+
 int _starpu_sched_node_push_tasks_to_firsts_suitable_parent(struct _starpu_sched_node * node, struct starpu_task_list *list, int sched_ctx_id)
 {
 	while(!starpu_task_list_empty(list))
@@ -441,3 +448,4 @@ int _starpu_sched_node_push_tasks_to_firsts_suitable_parent(struct _starpu_sched
 	}
 	return 0;
 }
+

+ 28 - 26
src/sched_policies/node_sched.h

@@ -2,9 +2,12 @@
 #define __SCHED_NODE_H__
 #include <starpu.h>
 #include <common/starpu_spinlock.h>
+#include "bitmap.h"
 struct _starpu_sched_node
 {
-	int (*push_task)(struct _starpu_sched_node *, struct starpu_task *);
+	int (*push_task)(struct _starpu_sched_node *,
+			 struct starpu_task *,
+			 struct _starpu_bitmap * sched_ctx_workers_mask);
 	struct starpu_task * (*pop_task)(struct _starpu_sched_node *,
 					 unsigned sched_ctx_id);
 	void (*available)(struct _starpu_sched_node *);
@@ -19,9 +22,8 @@ struct _starpu_sched_node
 	struct _starpu_sched_node ** childs;
 
 
-	//the list of workers in the node's subtree
-	int workerids[STARPU_NMAXWORKERS];
-	int nworkers;
+	//the set of workers in the node's subtree
+	struct _starpu_bitmap * workers;
 
 	//is_homogeneous is 0 iff workers in the node's subtree are heterogeneous,
 	//this field is set and updated automaticaly, you shouldn't write on it
@@ -33,17 +35,14 @@ struct _starpu_sched_node
 	 */
 	struct _starpu_sched_node * fathers[STARPU_NMAX_SCHED_CTXS];
 
+	
+	/* this function is called after all childs has been set
+	 */
+	void (*init_data)(struct _starpu_sched_node *);
+	/* this function is called to free init_data malloc
+	 */
+	void (*deinit_data)(struct _starpu_sched_node *);
 
-	void (*add_child)(struct _starpu_sched_node *node,
-			  struct _starpu_sched_node *child,
-			  unsigned sched_ctx_id);
-
-	void (*remove_child)(struct _starpu_sched_node *node,
-			     struct _starpu_sched_node *child,
-			     unsigned sched_ctx_id);
-	/* this function is called to free node (it must call _starpu_sched_node_destroy(node));
-	*/
-	void (*destroy_node)(struct _starpu_sched_node *);
 };
 
 struct _starpu_task_execute_preds
@@ -69,6 +68,7 @@ struct _starpu_task_execute_preds
 struct _starpu_sched_tree
 {
 	struct _starpu_sched_node * root;
+	struct _starpu_bitmap * workers;
 	//this lock is used to protect the scheduler during modifications of his structure
 	starpu_pthread_rwlock_t lock;
 };
@@ -91,12 +91,12 @@ void _starpu_sched_node_destroy(struct _starpu_sched_node * node);
 
 void _starpu_sched_node_set_father(struct _starpu_sched_node *node, struct _starpu_sched_node *father_node, unsigned sched_ctx_id);
 
-void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starpu_sched_node * child, unsigned sched_ctx_id);
-void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child, unsigned sched_ctx_id);
+void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starpu_sched_node * child);
+void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child);
 
 
-int _starpu_sched_node_can_execute_task(struct _starpu_sched_node * node, struct starpu_task * task);
-int _starpu_sched_node_can_execute_task_with_impl(struct _starpu_sched_node * node, struct starpu_task * task, unsigned nimpl);
+int _starpu_sched_node_can_execute_task(struct _starpu_sched_node * node, struct starpu_task * task, struct _starpu_bitmap * worker_mask);
+int _starpu_sched_node_can_execute_task_with_impl(struct _starpu_sched_node * node, struct starpu_task * task, unsigned nimpl, struct _starpu_bitmap * worker_mask);
 
 /* no public create function for workers because we dont want to have several node_worker for a single workerid */
 struct _starpu_sched_node * _starpu_sched_node_worker_get(int workerid);
@@ -134,17 +134,19 @@ void _starpu_node_destroy_rec(struct _starpu_sched_node * node, unsigned sched_c
 
 int _starpu_tree_push_task(struct starpu_task * task);
 struct starpu_task * _starpu_tree_pop_task(unsigned sched_ctx_id);
+void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
+void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
+
+void _starpu_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
+void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 
-/* this function must be called after all modification of tree
- * this function make a top bottom traversal , ence dont use .fathers field
- * if the tree is partialy shared between contexts, this function have to be called in thoses contexts
+/* this function fill all the node->workers member
  */
-void _starpu_tree_update_after_modification(struct _starpu_sched_tree * tree);
-/* remove and return a subtree that contain only this worker and call starpu_tree_update_after_modification
- * this function may be called several time
- * this function dont update father fields in subtree
+void _starpu_set_workers_bitmaps(void);
+/* this function call init data on all nodes in postfix order
  */
-struct _starpu_sched_node * _starpu_sched_tree_remove_worker(struct _starpu_sched_tree * tree, int workerid, int sched_ctx_id);
+void _starpu_call_init_data(struct _starpu_sched_tree * t);
+
 
 /* push task of list lower as possible in the tree, a non null value is returned if some task couldn't be pushed
  */

+ 42 - 104
src/sched_policies/node_work_stealing.c

@@ -1,7 +1,7 @@
 #include "node_sched.h"
 #include "fifo_queues.h"
 #include <starpu_scheduler.h>
-
+#include <starpu.h>
 
 struct _starpu_work_stealing_data
 {
@@ -89,13 +89,7 @@ static inline unsigned select_worker(struct _starpu_sched_node * node)
 
 static int is_worker_of_node(struct _starpu_sched_node * node, int workerid)
 {
-	int j;
-	for(j = 0; j < node->nworkers; j++)
-	{
-		if(node->workerids[j] == workerid)
-			return 1;
-	}
-	return 0;
+	return _starpu_bitmap_get(node->workers, workerid);
 }
 
 
@@ -132,7 +126,7 @@ static struct starpu_task * pop_task(struct _starpu_sched_node * node, unsigned
 
 
 
-static int push_task(struct _starpu_sched_node * node, struct starpu_task * task)
+static int push_task(struct _starpu_sched_node * node, struct starpu_task * task, struct _starpu_bitmap * worker_mask)
 {
 	struct _starpu_work_stealing_data * wsd = node->data;
 	int ret = -1;
@@ -141,7 +135,7 @@ static int push_task(struct _starpu_sched_node * node, struct starpu_task * task
 	for(i = (start+1)%node->nchilds; i != start; i = (i+1)%node->nchilds)
 	{
 		struct _starpu_sched_node * child = node->childs[i];
-		if(_starpu_sched_node_can_execute_task(child,task))
+		if(_starpu_sched_node_can_execute_task(child,task, worker_mask))
 		{
 			ret = _starpu_fifo_push_sorted_task(wsd->fifos[i], task);
 			break;
@@ -153,12 +147,6 @@ static int push_task(struct _starpu_sched_node * node, struct starpu_task * task
 }
 
 
-static void add_child(struct _starpu_sched_node *node,
-		      struct _starpu_sched_node *child,
-		      unsigned sched_ctx_id);
-
-
-
 //this function is special, when a worker call it, we want to push the task in his fifo
 int _starpu_ws_push_task(struct starpu_task *task)
 {
@@ -202,83 +190,54 @@ int _starpu_ws_push_task(struct starpu_task *task)
 }
 
 
-static void add_child(struct _starpu_sched_node *node,
-		      struct _starpu_sched_node *child,
-		      unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
+static void init_ws_data(struct _starpu_sched_node *node)
 {
+	struct _starpu_work_stealing_data * wsd = malloc(sizeof(*wsd));
+	memset(wsd, 0, sizeof(*wsd));
+	node->data = wsd;
 	int i;
 	for(i = 0; i < node->nchilds; i++){
 		STARPU_ASSERT(node->childs[i] != node);
 		STARPU_ASSERT(node->childs[i] != NULL);
 	}
-	struct _starpu_work_stealing_data * wsd = node->data;
-	int new_size = node->nchilds + 1;
-	node->childs = realloc(node->childs,
-			       sizeof(struct _starpu_sched_node*)
-			       * new_size);
-	wsd->fifos = realloc(wsd->fifos,
-			     sizeof(struct _starpu_fifo_taskq*)
-			     * new_size);
-	wsd->mutexes = realloc(wsd->mutexes,
-			     sizeof(starpu_pthread_rwlock_t)
-			     * new_size);
-	node->childs[new_size - 1] = child;
-	wsd->fifos[new_size - 1] = _starpu_create_fifo();
-	STARPU_PTHREAD_MUTEX_INIT(wsd->mutexes + (new_size - 1), NULL);
-	node->nchilds = new_size;
-}
+	int size = node->nchilds;
+	wsd->fifos = malloc(sizeof(struct _starpu_fifo_taskq*) * size);
+	wsd->mutexes = malloc(sizeof(starpu_pthread_rwlock_t) * size);
 
+	for(i = 0; i < size; i++)
+	{
+		wsd->fifos[i] = _starpu_create_fifo();
+		STARPU_PTHREAD_MUTEX_INIT(wsd->mutexes + i, NULL);
+	}
+}
 
-static void remove_child(struct _starpu_sched_node *node,
-			 struct _starpu_sched_node *child,
-			 unsigned sched_ctx_id STARPU_ATTRIBUTE_UNUSED)
+static void deinit_ws_data(struct _starpu_sched_node *node)
 {
-	int pos;
-	for(pos = 0; pos < node->nchilds; pos++)
-		if(node->childs[pos] == child)
-			break;
-	STARPU_ASSERT(pos != node->nchilds);
 	struct _starpu_work_stealing_data * wsd = node->data;
-	struct _starpu_fifo_taskq * fifo = wsd->fifos[pos];
-	wsd->fifos[pos] = wsd->fifos[node->nchilds - 1];
-	node->childs[pos] = node->childs[node->nchilds - 1];
-	STARPU_PTHREAD_MUTEX_DESTROY(wsd->mutexes + pos);
-	wsd->mutexes[pos] = wsd->mutexes[node->nchilds - 1];
-	node->nchilds--;
 	int i;
-	struct starpu_task * task = fifo->taskq.head;
-	_starpu_destroy_fifo(fifo);
-	for(i = 0; task; i = (i + 1)%node->nchilds)
+	for(i = 0; i < node->nchilds; i++)
 	{
-		struct starpu_task * next = task->next;
-		STARPU_PTHREAD_MUTEX_LOCK(wsd->mutexes + i);
-		_starpu_fifo_push_sorted_task(wsd->fifos[i],task);
-		STARPU_PTHREAD_MUTEX_UNLOCK(wsd->mutexes + i);
-		task = next;
+		STARPU_PTHREAD_MUTEX_DESTROY(wsd->mutexes + i);
+		_starpu_destroy_fifo(wsd->fifos[i]);
 	}
+	free(wsd);
+	node->data = NULL;
 }
 
 
-
 struct _starpu_sched_node * _starpu_sched_node_work_stealing_create(void)
 {
 	struct _starpu_sched_node * node = _starpu_sched_node_create();
-	struct _starpu_work_stealing_data * wsd = malloc(sizeof(*wsd));
-	memset(wsd, 0, sizeof(*wsd));
-	node->data = wsd;
 	node->pop_task = pop_task;
+	node->init_data = init_ws_data;
+	node->deinit_data = deinit_ws_data;
 	node->push_task = push_task;
-	node->add_child = add_child;
-	node->remove_child = remove_child;
 	return node;
 }
 
 int _starpu_sched_node_is_work_stealing(struct _starpu_sched_node * node)
 {
-	return node->add_child == add_child
-		|| node->remove_child == remove_child
-		|| node->pop_task == pop_task
-		|| node->push_task == push_task;//...
+	return node->init_data == init_ws_data;
 }
 
 
@@ -288,7 +247,20 @@ static void initialize_ws_center_policy(unsigned sched_ctx_id)
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	struct _starpu_sched_tree *data = malloc(sizeof(struct _starpu_sched_tree));
 	STARPU_PTHREAD_RWLOCK_INIT(&data->lock,NULL);
- 	data->root = _starpu_sched_node_work_stealing_create();
+	struct _starpu_sched_node * ws;
+ 	data->root = ws = _starpu_sched_node_work_stealing_create();
+	data->workers = _starpu_bitmap_create();
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count(); i++)
+	{
+		struct _starpu_sched_node * node = _starpu_sched_node_worker_get(i);
+		if(!node)
+			continue;
+		node->fathers[sched_ctx_id] = ws;
+		_starpu_sched_node_add_child(ws, node);
+	}
+	_starpu_set_workers_bitmaps();
+	_starpu_call_init_data(data);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)data);
 }
 
@@ -300,46 +272,12 @@ static void deinitialize_ws_center_policy(unsigned sched_ctx_id)
 }
 
 
-static void add_worker_ws(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	unsigned i;
-	struct _starpu_sched_node * ws_node = t->root;
-	for(i = 0; i < nworkers; i++)
-	{
-		struct _starpu_sched_node * worker =_starpu_sched_node_worker_get(workerids[i]);
-		ws_node->add_child(ws_node,
-				   worker,
-				   sched_ctx_id);
-		_starpu_sched_node_set_father(worker, ws_node, sched_ctx_id);
-	}
-	_starpu_tree_update_after_modification(t);
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
-static void remove_worker_ws(unsigned sched_ctx_id, int * workerids, unsigned nworkers)
-{
-	struct _starpu_sched_tree *t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
-	STARPU_PTHREAD_RWLOCK_WRLOCK(&t->lock);
-	struct _starpu_sched_node * ws_node = t->root;
-	unsigned i;
-	for(i = 0; i < nworkers; i++)
-	{
-		struct _starpu_sched_node * worker =_starpu_sched_node_worker_get(workerids[i]);
-		ws_node->remove_child(ws_node, worker, sched_ctx_id);
-		_starpu_sched_node_set_father(worker,NULL,sched_ctx_id);
-	}
-	STARPU_PTHREAD_RWLOCK_UNLOCK(&t->lock);
-}
-
-
 struct starpu_sched_policy _starpu_sched_tree_ws_policy =
 {
 	.init_sched = initialize_ws_center_policy,
 	.deinit_sched = deinitialize_ws_center_policy,
-	.add_workers = add_worker_ws,
-	.remove_workers = remove_worker_ws,
+	.add_workers = _starpu_tree_add_workers,
+	.remove_workers = _starpu_tree_remove_workers,
 	.push_task = _starpu_ws_push_task,
 	.pop_task = _starpu_tree_pop_task,
 	.pre_exec_hook = NULL,

+ 7 - 6
src/sched_policies/node_worker.c

@@ -18,7 +18,7 @@ struct _starpu_sched_node * _starpu_sched_node_worker_get(int workerid)
 
 
 
-int _starpu_sched_node_worker_push_task(struct _starpu_sched_node * node, struct starpu_task *task)
+int _starpu_sched_node_worker_push_task(struct _starpu_sched_node * node, struct starpu_task *task, struct _starpu_bitmap * worker_mask STARPU_ATTRIBUTE_UNUSED)
 {
 	/*this function take the worker's mutex */
 	
@@ -67,7 +67,7 @@ static double estimated_transfer_length(struct _starpu_sched_node * node,
 					struct starpu_task * task)
 {
 	STARPU_ASSERT(_starpu_sched_node_is_worker(node));
-	unsigned memory_node = starpu_worker_get_memory_node(node->workerids[0]);
+	unsigned memory_node = starpu_worker_get_memory_node(_starpu_bitmap_first(node->workers));
 	double d = starpu_task_expected_data_transfer_time(memory_node, task);
 	return d;
 }
@@ -159,7 +159,7 @@ static double estimated_load(struct _starpu_sched_node * node)
 		nb_task++;
 	STARPU_PTHREAD_MUTEX_UNLOCK(&worker->mutex);
 	return (double) nb_task
-		/ starpu_worker_get_relative_speedup(starpu_worker_get_perf_archtype(node->workerids[0]));
+		/ starpu_worker_get_relative_speedup(_starpu_bitmap_first(node->workers));
 }
 
 
@@ -172,16 +172,17 @@ static struct _starpu_sched_node  * _starpu_sched_node_worker_create(int workeri
 		return _worker_nodes[workerid];
 
 	struct _starpu_worker * worker = _starpu_get_worker_struct(workerid);
+	if(worker == NULL)
+		return NULL;
 	struct _starpu_sched_node * node = _starpu_sched_node_create();
 	node->data = worker;
 	node->push_task = _starpu_sched_node_worker_push_task;
 	node->pop_task = _starpu_sched_node_worker_pop_task;
 	node->estimated_execute_preds = estimated_execute_preds;
 	node->estimated_load = estimated_load;
-	node->destroy_node = _starpu_sched_node_worker_destroy;
 	node->available = available;
-	node->workerids[0] = workerid;
-	node->nworkers = 1;
+	node->workers = _starpu_bitmap_create();
+	_starpu_bitmap_set(node->workers, workerid);
 	_worker_nodes[workerid] = node;
 	return node;
 }

+ 2 - 2
src/sched_policies/prio_deque.c

@@ -127,8 +127,8 @@ static inline int pred_can_execute(struct starpu_task * t, void * pworkerid)
 
 struct starpu_task * _starpu_prio_deque_pop_task(struct _starpu_prio_deque * pdeque)
 {
-	struct starpu_task * t = REMOVE_TASK(pdeque, head, prev, pred_true, STARPU_POISON_PTR);
-	return t;
+	struct starpu_task * task = REMOVE_TASK(pdeque, head, prev, pred_true, STARPU_POISON_PTR);
+	return task;
 }
 struct starpu_task * _starpu_prio_deque_pop_task_for_worker(struct _starpu_prio_deque * pdeque, int workerid)
 {