Browse Source

Adding several features which needs each other to compute correctly :
- Multiple Fathers' support (by removing current multiple fathers'
support which concerned scheduling contexts : that support isn't
needed anymore) : modifying the pop and room functions for trees,
as the scheduling context is no longer needed to perform a pop or
a room.
- Adding a dedicated calibrator node based on the eager strategy.
- Correcting mct / heft issues when a performance model is purged
by the perfmodel_history during the calibration process, to take
care of tasks pushed to mct / heft for which the perfmodel had
been purged.

Marc Sergent 12 years ago
parent
commit
fe685563e7

+ 13 - 14
include/starpu_sched_node.h

@@ -49,16 +49,8 @@ struct starpu_sched_node
 	 *
 	 * a default implementation simply do a recursive call on father
 	 */
-	struct starpu_task * (*pop_task)(struct starpu_sched_node *,
-					 unsigned sched_ctx_id);
+	struct starpu_task * (*pop_task)(struct starpu_sched_node *);
 
-	/* node->push_back_task(node, task)
-	 * This function can be called by room-made functions to permit
-	 * the user to specify a particular push function which allows to
-	 * push back the task if the push submitted by the room function fail.
-	 */
-	int (*push_back_task)(struct starpu_sched_node *,
-			 struct starpu_task *);
 	/* this function is an heuristic that compute load of subtree, basicaly
 	 * it compute
 	 * estimated_load(node) = sum(estimated_load(node_childs)) +
@@ -76,7 +68,8 @@ struct starpu_sched_node
 	/* may be shared by several contexts
 	 * so we need several fathers
 	 */
-	struct starpu_sched_node * fathers[STARPU_NMAX_SCHED_CTXS];
+	struct starpu_sched_node ** fathers;
+	int nfathers;
 	/* the set of workers in the node's subtree
 	 */
 	struct starpu_bitmap * workers;
@@ -93,6 +86,8 @@ struct starpu_sched_node
 
 	void (*add_child)(struct starpu_sched_node * node, struct starpu_sched_node * child);
 	void (*remove_child)(struct starpu_sched_node * node, struct starpu_sched_node * child);
+	void (*add_father)(struct starpu_sched_node * node, struct starpu_sched_node * father);
+	void (*remove_father)(struct starpu_sched_node * node, struct starpu_sched_node * father);
 
 	/* this function is called for each node when workers are added or removed from a context
 	 */
@@ -112,7 +107,7 @@ struct starpu_sched_node
 	 * fathers, the user have to specify a personally-made function to catch those
 	 * calls.
 	 */ 
-	void (*room)(struct starpu_sched_node * node, unsigned sched_ctx_id);
+	int (*room)(struct starpu_sched_node * node);
 	/* This function allow a node to wake up a worker.
 	 * It is currently called by node which implements a queue, to signify to
 	 * its childs that a task have been pushed in its local queue, and is
@@ -154,7 +149,8 @@ struct starpu_sched_tree
 struct starpu_sched_node * starpu_sched_node_create(void);
 
 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_father(struct starpu_sched_node *node, struct starpu_sched_node *father_node);
+void starpu_sched_node_remove_father(struct starpu_sched_node *node, struct starpu_sched_node *father_node);
 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);
 
@@ -203,6 +199,9 @@ int starpu_sched_node_is_random(struct starpu_sched_node *);
 struct starpu_sched_node * starpu_sched_node_eager_create(void * arg STARPU_ATTRIBUTE_UNUSED);
 int starpu_sched_node_is_eager(struct starpu_sched_node *);
 
+struct starpu_sched_node * starpu_sched_node_eager_calibration_create(void * arg STARPU_ATTRIBUTE_UNUSED);
+int starpu_sched_node_is_eager_calibration(struct starpu_sched_node *);
+
 
 struct starpu_mct_data
 {
@@ -249,7 +248,7 @@ void starpu_sched_tree_destroy(struct starpu_sched_tree * tree);
 /* destroy node and all his child
  * except if they are shared between several contexts
  */
-void starpu_sched_node_destroy_rec(struct starpu_sched_node * node, unsigned sched_ctx_id);
+void starpu_sched_node_destroy_rec(struct starpu_sched_node * node);
 
 /* update all the node->workers member recursively
  */
@@ -265,7 +264,7 @@ void starpu_sched_node_wake_available_worker(struct starpu_sched_node * node, st
 void starpu_sched_node_available(struct starpu_sched_node * node);
 
 int starpu_sched_tree_push_task(struct starpu_task * task);
-struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx_id);
+struct starpu_task * starpu_sched_tree_pop_task();
 void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 void starpu_sched_node_worker_pre_exec_hook(struct starpu_task * task);

+ 1 - 0
src/Makefile.am

@@ -252,6 +252,7 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 		\
 	sched_policies/node_prio.c 				\
 	sched_policies/node_random.c				\
 	sched_policies/node_eager.c				\
+	sched_policies/node_eager_calibration.c				\
 	sched_policies/node_mct.c				\
 	sched_policies/node_heft.c				\
 	sched_policies/node_best_implementation.c		\

+ 5 - 0
src/sched_policies/helper_mct.c

@@ -68,6 +68,11 @@ int starpu_mct_compute_expected_times(struct starpu_sched_node *node, struct sta
 		struct starpu_sched_node * c = node->childs[i];
 		if(starpu_sched_node_execute_preds(c, task, estimated_lengths + i))
 		{
+			if(isnan(estimated_lengths[i]))
+				/* The perfmodel had been purged since the task was pushed
+				 * onto the mct node. */
+				continue;
+
 			/* Estimated availability of worker */
 			double estimated_end = c->estimated_end(c);
 			double now = starpu_timing_now();

+ 17 - 8
src/sched_policies/node_best_implementation.c

@@ -80,16 +80,25 @@ static int select_best_implementation_push_task(struct starpu_sched_node * node,
 	return node->childs[0]->push_task(node->childs[0],task);
 }
 
-static struct starpu_task * select_best_implementation_pop_task(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static struct starpu_task * select_best_implementation_pop_task(struct starpu_sched_node * node)
 {
-	struct starpu_task * t;
-	if(!node->fathers[sched_ctx_id])
-		return NULL;
-	t = node->fathers[sched_ctx_id]->pop_task(node->fathers[sched_ctx_id], sched_ctx_id);
-	if(t)
+	struct starpu_task * task = NULL;
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+		{
+			task = node->fathers[i]->pop_task(node->fathers[i]);
+			if(task)
+				break;
+		}
+	}
+	if(task)
 		/* this worker can execute this task as it was returned by a pop*/
-		(void)find_best_impl(t, starpu_worker_get_id());
-	return t;
+		(void)find_best_impl(task, starpu_worker_get_id());
+	return task;
 }
 
 struct starpu_sched_node * starpu_sched_node_best_implementation_create(void * ARG STARPU_ATTRIBUTE_UNUSED)

+ 23 - 9
src/sched_policies/node_composed.c

@@ -110,7 +110,7 @@ struct composed_node create_composed_node(struct starpu_sched_node_composed_reci
 		 */
 		unsigned j;
 		for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
-			starpu_sched_node_set_father(node, c.bottom, j);
+			starpu_sched_node_add_father(node, c.bottom);
 		c.bottom = node;
 	}
 	STARPU_ASSERT(!starpu_sched_node_is_worker(c.bottom));
@@ -123,16 +123,28 @@ static int composed_node_push_task(struct starpu_sched_node * node, struct starp
 	struct composed_node *c = node->data;
 	return c->top->push_task(c->top,task);
 }
-struct starpu_task * composed_node_pop_task(struct starpu_sched_node *node, unsigned sched_ctx_id)
+struct starpu_task * composed_node_pop_task(struct starpu_sched_node *node)
 {
 	struct composed_node *c = node->data;
-	struct starpu_task * t = c->bottom->pop_task(c->bottom, sched_ctx_id);
-	if(t)
-		return t;
-
-	if(node->fathers[sched_ctx_id])
-		return node->fathers[sched_ctx_id]->pop_task(node->fathers[sched_ctx_id], sched_ctx_id);
-	return NULL;
+	struct starpu_task * task = NULL;
+	
+	task = c->bottom->pop_task(c->bottom);
+	if(task)
+		return task;
+
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+		{
+			task = node->fathers[i]->pop_task(node->fathers[i]);
+			if(task)
+				break;
+		}
+	}
+	return task;
 }
 
 double composed_node_estimated_load(struct starpu_sched_node * node)
@@ -207,6 +219,8 @@ struct starpu_sched_node * starpu_sched_node_composed_node_create(struct starpu_
 );
 	c->bottom->nchilds = node->nchilds;
 	c->bottom->childs = node->childs;
+	c->bottom->nfathers = node->nfathers;
+	c->bottom->fathers = node->fathers;
 
 	node->data = c;
 	node->push_task = composed_node_push_task;

+ 86 - 0
src/sched_policies/node_eager_calibration.c

@@ -0,0 +1,86 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  INRIA
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <starpu_sched_node.h>
+#include <starpu_scheduler.h>
+
+static int eager_calibration_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+{
+	STARPU_ASSERT(node && task && starpu_sched_node_is_eager_calibration(node));
+	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
+	
+	starpu_task_bundle_t bundle = task->bundle;
+
+	int workerid;
+	for(workerid = starpu_bitmap_first(node->workers_in_ctx);
+	    workerid != -1;
+	    workerid = starpu_bitmap_next(node->workers_in_ctx, workerid))
+	{
+		struct starpu_perfmodel_arch* archtype = starpu_worker_get_perf_archtype(workerid);
+		int nimpl;
+		for(nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
+		{
+			if(starpu_worker_can_execute_task(workerid,task,nimpl)
+			   || starpu_combined_worker_can_execute_task(workerid, task, nimpl))
+			{
+				double d;
+
+				if(bundle)
+					d = starpu_task_bundle_expected_length(bundle, archtype, nimpl);
+				else
+					d = starpu_task_expected_length(task, archtype, nimpl);
+
+				if(isnan(d))
+				{
+					int i;
+					for (i = 0; i < node->nchilds; i++)
+					{
+						int idworker;
+						for(idworker = starpu_bitmap_first(node->childs[i]->workers);
+							idworker != -1;
+							idworker = starpu_bitmap_next(node->childs[i]->workers, idworker))
+						{
+							if (idworker == workerid)
+							{
+								if(starpu_sched_node_is_worker(node->childs[i]))
+								{
+									node->childs[i]->avail(node->childs[i]);
+									return 1;
+								}
+								else
+									return node->childs[i]->push_task(node->childs[i],task);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return 1;
+}
+
+int starpu_sched_node_is_eager_calibration(struct starpu_sched_node * node)
+{
+	return node->push_task == eager_calibration_push_task;
+}
+
+struct starpu_sched_node * starpu_sched_node_eager_calibration_create(void * ARG STARPU_ATTRIBUTE_UNUSED)
+{
+	struct starpu_sched_node * node = starpu_sched_node_create();
+	node->push_task = eager_calibration_push_task;
+
+	return node;
+}

+ 50 - 80
src/sched_policies/node_fifo.c

@@ -94,7 +94,7 @@ static double fifo_estimated_load(struct starpu_sched_node * node)
 	return load;
 }
 
-static int fifo_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+static int fifo_push_local_task(struct starpu_sched_node * node, struct starpu_task * task, unsigned is_pushback)
 {
 	STARPU_ASSERT(node && node->data && task);
 	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
@@ -103,87 +103,39 @@ static int fifo_push_task(struct starpu_sched_node * node, struct starpu_task *
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret;
 
-	STARPU_ASSERT(node->nchilds == 1);
-	struct starpu_sched_node * child = node->childs[0];
-	if(starpu_sched_node_is_worker(child))
-		ret = 1;
+	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	double exp_len;
+	if(!isnan(task->predicted))
+		exp_len = fifo->exp_len + task->predicted;
 	else
-		ret = child->push_task(child,task);
+		exp_len = fifo->exp_len;
 
-	if(ret)
+	if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
+			((fifo->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
-		double exp_len;
-		if(!isnan(task->predicted))
-			exp_len = fifo->exp_len + task->predicted;
-		else
-			exp_len = fifo->exp_len;
-
-		if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
-				((fifo->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
+		static int warned;
+		if(task->predicted > data->exp_len_threshold && !warned)
 		{
-			static int warned;
-			if(task->predicted > data->exp_len_threshold && !warned)
-			{
-				_STARPU_DISP("Warning : a predicted task length (%lf) exceeds the expected length threshold (%lf) of a prio node queue, you should reconsider the value of this threshold. This message will not be printed again for further thresholds exceeding.\n",task->predicted,data->exp_len_threshold);
-				warned = 1;
-			}
-			ret = 1;
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+			_STARPU_DISP("Warning : a predicted task length (%lf) exceeds the expected length threshold (%lf) of a prio node queue, you should reconsider the value of this threshold. This message will not be printed again for further thresholds exceeding.\n",task->predicted,data->exp_len_threshold);
+			warned = 1;
 		}
-		else
-		{
-			starpu_sched_node_prefetch_on_node(node, task);
-			ret = _starpu_fifo_push_task(fifo,task);
-			if(!isnan(task->predicted))
-			{
-				fifo->exp_len = exp_len;
-				fifo->exp_end = fifo->exp_start + fifo->exp_len;
-			}
-			STARPU_ASSERT(!isnan(fifo->exp_end));
-			STARPU_ASSERT(!isnan(fifo->exp_len));
-			STARPU_ASSERT(!isnan(fifo->exp_start));
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
-
-			// When a task is pushed onto the local queue, we signify to our children
-			// that a task has been pushed, and that if everyone is sleeping, someone
-			// needs to wake up to come and take it.
-			node->avail(node);
-		}
-	}
-	return ret;
-}
-
-static int fifo_push_back_task(struct starpu_sched_node * node, struct starpu_task * task)
-{
-	STARPU_ASSERT(node && node->data && task);
-	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
-	struct _starpu_fifo_data * data = node->data;
-	struct _starpu_fifo_taskq * fifo = data->fifo;
-	starpu_pthread_mutex_t * mutex = &data->mutex;
-	int ret;
-
-	STARPU_ASSERT(node->nchilds == 1);
-	struct starpu_sched_node * child = node->childs[0];
-	if(starpu_sched_node_is_worker(child))
 		ret = 1;
+		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	}
 	else
-		ret = child->push_task(child,task);
-
-	if(ret)
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
-		double exp_len;
-		if(!isnan(task->predicted))
-			exp_len = fifo->exp_len + task->predicted;
+		if(is_pushback)
+			ret = _starpu_fifo_push_back_task(fifo,task);
 		else
-			exp_len = fifo->exp_len;
+		{
+			ret = _starpu_fifo_push_task(fifo,task);
+			starpu_sched_node_prefetch_on_node(node, task);
+		}
 
-		_starpu_fifo_push_back_task(fifo,task);
 		if(!isnan(task->predicted))
 		{
 			fifo->exp_len = exp_len;
-			fifo->exp_end = fifo->exp_start + exp_len;
+			fifo->exp_end = fifo->exp_start + fifo->exp_len;
 		}
 		STARPU_ASSERT(!isnan(fifo->exp_end));
 		STARPU_ASSERT(!isnan(fifo->exp_len));
@@ -193,17 +145,24 @@ static int fifo_push_back_task(struct starpu_sched_node * node, struct starpu_ta
 		// When a task is pushed onto the local queue, we signify to our children
 		// that a task has been pushed, and that if everyone is sleeping, someone
 		// needs to wake up to come and take it.
-		node->avail(node);
+		if(!is_pushback)
+			node->avail(node);
 	}
+	
 	return ret;
 }
 
+static int fifo_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+{
+	return fifo_push_local_task(node, task, 0);
+}
+
 int starpu_sched_node_is_fifo(struct starpu_sched_node * node)
 {
 	return node->push_task == fifo_push_task;
 }
 
-static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node)
 {
 	STARPU_ASSERT(node && node->data);
 	struct _starpu_fifo_data * data = node->data;
@@ -229,9 +188,14 @@ static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node, unsig
 
 	// When a pop is called, a room is called for pushing tasks onto
 	// the empty place of the queue left by the popped task.
-	struct starpu_sched_node * father = node->fathers[sched_ctx_id];
-	if(father != NULL)
-		father->room(father, sched_ctx_id);
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+			node->fathers[i]->room(node->fathers[i]);
+	}
 	
 	if(task)
 		return task;
@@ -244,20 +208,27 @@ static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node, unsig
  * push fails, which means that the worker fifo_nodes are
  * currently "full".
  */
-static void fifo_room(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static int fifo_room(struct starpu_sched_node * node)
 {
 	STARPU_ASSERT(node && starpu_sched_node_is_fifo(node));
 	int ret = 0;
 
-	struct starpu_task * task = node->pop_task(node, sched_ctx_id);
+	STARPU_ASSERT(node->nchilds == 1);
+	struct starpu_sched_node * child = node->childs[0];
+
+	struct starpu_task * task = node->pop_task(node);
 	if(task)
-		ret = node->push_back_task(node,task);	
+		ret = child->push_task(child,task);	
 	while(task && !ret) 
 	{
-		task = node->pop_task(node, sched_ctx_id);
+		task = node->pop_task(node);
 		if(task)
-			ret = node->push_back_task(node,task);	
+			ret = child->push_task(child,task);	
 	} 
+	if(task && ret)
+		fifo_push_local_task(node,task,1); 
+
+	return 1;
 }
 
 struct starpu_sched_node * starpu_sched_node_fifo_create(struct starpu_fifo_data * params)
@@ -270,7 +241,6 @@ struct starpu_sched_node * starpu_sched_node_fifo_create(struct starpu_fifo_data
 	node->estimated_end = fifo_estimated_end;
 	node->estimated_load = fifo_estimated_load;
 	node->push_task = fifo_push_task;
-	node->push_back_task = fifo_push_back_task;
 	node->pop_task = fifo_pop_task;
 	node->room = fifo_room;
 	node->deinit_data = fifo_node_deinit_data;

+ 14 - 1
src/sched_policies/node_heft.c

@@ -189,9 +189,22 @@ static void heft_progress(struct starpu_sched_node *node)
 		;
 }
 
-static void heft_room(struct starpu_sched_node *node, unsigned sched_ctx_id)
+static int heft_room(struct starpu_sched_node *node)
 {
 	heft_progress(node);
+	int ret, j;
+	for(j=0; j < node->nfathers; j++)
+	{
+		if(node->fathers[j] == NULL)
+			continue;
+		else
+		{
+			ret = node->fathers[j]->room(node->fathers[j]);
+			if(ret)
+				break;
+		}
+	}
+	return ret;
 }
 
 void heft_node_deinit_data(struct starpu_sched_node * node)

+ 11 - 2
src/sched_policies/node_mct.c

@@ -35,6 +35,14 @@ static int mct_push_task(struct starpu_sched_node * node, struct starpu_task * t
 	/* Estimated transfer+task termination for each child */
 	double estimated_ends_with_task[node->nchilds];
 
+	int i;
+	for(i=0; i < node->nchilds; i++)
+	{
+		estimated_lengths[i] = 0.0;
+		estimated_transfer_length[i] = 0.0;
+		estimated_ends_with_task[i] = 0.0;
+
+	}
 	/* Minimum transfer+task termination on all children */
 	double min_exp_end_with_task = DBL_MAX;
 	/* Maximum transfer+task termination on all children */
@@ -43,12 +51,13 @@ static int mct_push_task(struct starpu_sched_node * node, struct starpu_task * t
 	int suitable_nodes[node->nchilds];
 	int nsuitable_nodes = 0;
 
-	int i;
-
 	nsuitable_nodes = starpu_mct_compute_expected_times(node, task,
 			estimated_lengths, estimated_transfer_length, estimated_ends_with_task,
 			&min_exp_end_with_task, &max_exp_end_with_task, suitable_nodes);
 
+	if(!nsuitable_nodes)
+		return 1;
+
 	double best_fitness = DBL_MAX;
 	int best_inode = -1;
 	for(i = 0; i < nsuitable_nodes; i++)

+ 19 - 31
src/sched_policies/node_perfmodel_select.c

@@ -17,6 +17,14 @@
 #include <starpu_sched_node.h>
 #include <starpu_scheduler.h>
 
+/* The decision node takes care of the scheduling of tasks which are not
+ * calibrated, or tasks which don't have a performance model, because the scheduling
+ * architecture of this scheduler for tasks with no performance model is exactly
+ * the same as the tree-prio scheduler.
+ * Tasks with a perfmodel are pushed to the perfmodel_node, which takes care of the
+ * scheduling of those tasks on the correct worker_node.
+ */
+
 struct _starpu_perfmodel_select_data
 {
 	struct starpu_sched_node * calibrator_node;
@@ -30,40 +38,20 @@ static int perfmodel_select_push_task(struct starpu_sched_node * node, struct st
 	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
 
 	struct _starpu_perfmodel_select_data * data = node->data;
-	starpu_task_bundle_t bundle = task->bundle;
+	double length;
+	int can_execute = starpu_sched_node_execute_preds(node,task,&length);
 	
-
-	int workerid;
-	for(workerid = starpu_bitmap_first(node->workers_in_ctx);
-	    workerid != -1;
-	    workerid = starpu_bitmap_next(node->workers_in_ctx, workerid))
+	if(can_execute)
 	{
-		struct starpu_perfmodel_arch* archtype = starpu_worker_get_perf_archtype(workerid);
-		int nimpl;
-		for(nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
-		{
-			if(starpu_worker_can_execute_task(workerid,task,nimpl)
-			   || starpu_combined_worker_can_execute_task(workerid, task, nimpl))
-			{
-				double d;
-
-				if(bundle)
-					d = starpu_task_bundle_expected_length(bundle, archtype, nimpl);
-				else
-					d = starpu_task_expected_length(task, archtype, nimpl);
-
-				// If the task has not been calibrated, or has no performance model, or if the
-				// perfmodel_select has no associated node, i.e the perfmodel_select is the core of the
-				// current scheduler.
-				if(isnan(d))
-					return data->calibrator_node->push_task(data->calibrator_node,task);
-
-				if(_STARPU_IS_ZERO(d))
-					return data->no_perfmodel_node->push_task(data->no_perfmodel_node,task);
-			}
-		}
+		if(isnan(length))
+			return data->calibrator_node->push_task(data->calibrator_node,task);
+		if(_STARPU_IS_ZERO(length))
+			return data->no_perfmodel_node->push_task(data->no_perfmodel_node,task);
+		return data->perfmodel_node->push_task(data->perfmodel_node,task);
 	}
-	return data->perfmodel_node->push_task(data->perfmodel_node,task);
+	else
+		return 1;
+
 }
 
 int starpu_sched_node_is_perfmodel_select(struct starpu_sched_node * node)

+ 50 - 85
src/sched_policies/node_prio.c

@@ -107,7 +107,7 @@ static double prio_estimated_load(struct starpu_sched_node * node)
 	return load;
 }
 
-static int prio_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+static int prio_push_local_task(struct starpu_sched_node * node, struct starpu_task * task, unsigned is_pushback)
 {
 	STARPU_ASSERT(node && node->data && task);
 	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
@@ -116,93 +116,40 @@ static int prio_push_task(struct starpu_sched_node * node, struct starpu_task *
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret;
 	
-	STARPU_ASSERT(node->nchilds == 1);
-	struct starpu_sched_node * child = node->childs[0];
-
-	if(starpu_sched_node_is_worker(child))
-		ret = 1;
+	STARPU_PTHREAD_MUTEX_LOCK(mutex);
+	double exp_len;
+	if(!isnan(task->predicted))
+		exp_len = prio->exp_len + task->predicted;
 	else
-		/* TODO: no, don't try to push it immediately to the child.
-		 * Just push it to the queue, pop one task from the queue and
-		 * try to push that task to the child. */
-		ret = child->push_task(child,task);
+		exp_len = prio->exp_len;
 
-	if(ret)
+	if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
+			((prio->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
 	{
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
-		double exp_len;
-		if(!isnan(task->predicted))
-			exp_len = prio->exp_len + task->predicted;
-		else
-			exp_len = prio->exp_len;
-
-		if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
-				((prio->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
+		static int warned;
+		if(task->predicted > data->exp_len_threshold && !warned)
 		{
-			static int warned;
-			if(task->predicted > data->exp_len_threshold && !warned)
-			{
-				_STARPU_DISP("Warning : a predicted task length (%lf) exceeds the expected length threshold (%lf) of a prio node queue, you should reconsider the value of this threshold. This message will not be printed again for further thresholds exceeding.\n",task->predicted,data->exp_len_threshold);
-				warned = 1;
-			}
-			ret = 1;
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+			_STARPU_DISP("Warning : a predicted task length (%lf) exceeds the expected length threshold (%lf) of a prio node queue, you should reconsider the value of this threshold. This message will not be printed again for further thresholds exceeding.\n",task->predicted,data->exp_len_threshold);
+			warned = 1;
 		}
+		ret = 1;
+		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+	}
+	else
+	{
+		if(is_pushback)
+			ret = _starpu_prio_deque_push_back_task(prio,task);
 		else
 		{
-			starpu_sched_node_prefetch_on_node(node, task);
 			ret = _starpu_prio_deque_push_task(prio,task);
+			starpu_sched_node_prefetch_on_node(node, task);
 			STARPU_TRACE_SCHED_NODE_PUSH_PRIO(node, prio->ntasks, exp_len);
-			if(!isnan(task->predicted))
-			{
-				prio->exp_len = exp_len;
-				prio->exp_end = prio->exp_start + prio->exp_len;
-			}
-			STARPU_ASSERT(!isnan(prio->exp_end));
-			STARPU_ASSERT(!isnan(prio->exp_len));
-			STARPU_ASSERT(!isnan(prio->exp_start));
-			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
-
-			// When a task is pushed onto the local queue, we signify to our children
-			// that a task has been pushed, and that if everyone is sleeping, someone
-			// needs to wake up to come and take it.
-			node->avail(node);
 		}
-	}
-	return ret;
-}
-
-static int prio_push_back_task(struct starpu_sched_node * node, struct starpu_task * task)
-{
-	STARPU_ASSERT(node && node->data && task);
-	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
-	struct _starpu_prio_data * data = node->data;
-	struct _starpu_prio_deque * prio = &data->prio;
-	starpu_pthread_mutex_t * mutex = &data->mutex;
-	int ret;
-
-	STARPU_ASSERT(node->nchilds == 1);
-	struct starpu_sched_node * child = node->childs[0];
-	if(starpu_sched_node_is_worker(child))
-		ret = 1;
-	else
-		ret = child->push_task(child,task);
 
-	if(ret)
-	{
-		STARPU_PTHREAD_MUTEX_LOCK(mutex);
-		double exp_len;
-		if(!isnan(task->predicted))
-			exp_len = prio->exp_len + task->predicted;
-		else
-			exp_len = prio->exp_len;
-
-		_starpu_prio_deque_push_back_task(prio,task);
-		STARPU_TRACE_SCHED_NODE_PUSH_PRIO(node, prio->ntasks, exp_len);
 		if(!isnan(task->predicted))
 		{
 			prio->exp_len = exp_len;
-			prio->exp_end = prio->exp_start + exp_len;
+			prio->exp_end = prio->exp_start + prio->exp_len;
 		}
 		STARPU_ASSERT(!isnan(prio->exp_end));
 		STARPU_ASSERT(!isnan(prio->exp_len));
@@ -212,17 +159,24 @@ static int prio_push_back_task(struct starpu_sched_node * node, struct starpu_ta
 		// When a task is pushed onto the local queue, we signify to our children
 		// that a task has been pushed, and that if everyone is sleeping, someone
 		// needs to wake up to come and take it.
-		node->avail(node);
+		if(!is_pushback)
+			node->avail(node);
 	}
+
 	return ret;
 }
 
+static int prio_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+{
+	return prio_push_local_task(node, task, 0);
+}
+
 int starpu_sched_node_is_prio(struct starpu_sched_node * node)
 {
 	return node->push_task == prio_push_task;
 }
 
-static struct starpu_task * prio_pop_task(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static struct starpu_task * prio_pop_task(struct starpu_sched_node * node)
 {
 	STARPU_ASSERT(node && node->data);
 	struct _starpu_prio_data * data = node->data;
@@ -250,9 +204,14 @@ static struct starpu_task * prio_pop_task(struct starpu_sched_node * node, unsig
 
 	// When a pop is called, a room is called for pushing tasks onto
 	// the empty place of the queue left by the popped task.
-	struct starpu_sched_node * father = node->fathers[sched_ctx_id];
-	if(father != NULL)
-		father->room(father, sched_ctx_id);
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+			node->fathers[i]->room(node->fathers[i]);
+	}
 	
 	if(task)
 		return task;
@@ -265,20 +224,27 @@ static struct starpu_task * prio_pop_task(struct starpu_sched_node * node, unsig
  * push fails, which means that the worker prio_nodes are
  * currently "full".
  */
-static void prio_room(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static int prio_room(struct starpu_sched_node * node)
 {
 	STARPU_ASSERT(node && starpu_sched_node_is_prio(node));
 	int ret = 0;
 
-	struct starpu_task * task = node->pop_task(node, sched_ctx_id);
+	STARPU_ASSERT(node->nchilds == 1);
+	struct starpu_sched_node * child = node->childs[0];
+
+	struct starpu_task * task = node->pop_task(node);
 	if(task)
-		ret = node->push_back_task(node,task);	
+		ret = child->push_task(child,task);	
 	while(task && !ret) 
 	{
-		task = node->pop_task(node, sched_ctx_id);
+		task = node->pop_task(node);
 		if(task)
-			ret = node->push_back_task(node,task);	
+			ret = child->push_task(child,task);	
 	} 
+	if(task && ret)
+		prio_push_local_task(node,task,1); 
+
+	return 1;
 }
 
 struct starpu_sched_node * starpu_sched_node_prio_create(struct starpu_prio_data * params)
@@ -291,7 +257,6 @@ struct starpu_sched_node * starpu_sched_node_prio_create(struct starpu_prio_data
 	node->estimated_end = prio_estimated_end;
 	node->estimated_load = prio_estimated_load;
 	node->push_task = prio_push_task;
-	node->push_back_task = prio_push_back_task;
 	node->pop_task = prio_pop_task;
 	node->room = prio_room;
 	node->deinit_data = prio_node_deinit_data;

+ 80 - 70
src/sched_policies/node_sched.c

@@ -121,26 +121,49 @@ void starpu_sched_node_available(struct starpu_sched_node * node)
 /* default implementation for node->pop_task()
  * just perform a recursive call on father
  */
-static struct starpu_task * pop_task_node(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static struct starpu_task * pop_task_node(struct starpu_sched_node * node)
 {
-	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
 	STARPU_ASSERT(node);
-	if(node->fathers[sched_ctx_id] == NULL)
-		return NULL;
-	else
-		return node->fathers[sched_ctx_id]->pop_task(node->fathers[sched_ctx_id], sched_ctx_id);
+	struct starpu_task * task = NULL;
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+		{
+			task = node->fathers[i]->pop_task(node->fathers[i]);
+			if(task)
+				break;
+		}
+	}
+	return task;
 }
 
-
-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_father(struct starpu_sched_node* node, struct starpu_sched_node * father)
 {
-	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
-	STARPU_ASSERT(node);
-	node->fathers[sched_ctx_id] = father_node;
+	STARPU_ASSERT(node && father);
+	int i;
+	for(i = 0; i < node->nfathers; i++){
+		STARPU_ASSERT(node->fathers[i] != node);
+		STARPU_ASSERT(node->fathers[i] != NULL);
+	}
+
+	node->fathers = realloc(node->fathers, sizeof(struct starpu_sched_node *) * (node->nfathers + 1));
+	node->fathers[node->nfathers] = father;
+	node->nfathers++;
 }
 
+void starpu_sched_node_remove_father(struct starpu_sched_node * node, struct starpu_sched_node * father)
+{
+	STARPU_ASSERT(node && father);
+	int pos;
+	for(pos = 0; pos < node->nfathers; pos++)
+		if(node->fathers[pos] == father)
+			break;
+	STARPU_ASSERT(pos != node->nfathers);
+	node->fathers[pos] = node->fathers[--node->nfathers];
+}
 
 
 /******************************************************************************
@@ -168,15 +191,14 @@ int starpu_sched_tree_push_task(struct starpu_task * task)
 	return ret_val;
 }
 
-struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx_id)
+struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx STARPU_ATTRIBUTE_UNUSED)
 {
-	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
 	int workerid = starpu_worker_get_id();
 	struct starpu_sched_node * node = starpu_sched_node_worker_get(workerid);
 
 	/* _starpu_sched_node_lock_worker(workerid) is called by node->pop_task()
 	 */
-	struct starpu_task * task = node->pop_task(node, sched_ctx_id);
+	struct starpu_task * task = node->pop_task(node);
 	return task;
 }
 
@@ -221,55 +243,19 @@ void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, uns
 
 
 
-void starpu_sched_node_destroy_rec(struct starpu_sched_node * node, unsigned sched_ctx_id)
+void starpu_sched_node_destroy_rec(struct starpu_sched_node * node)
 {
 	if(node == NULL)
 		return;
-	struct starpu_sched_node ** stack = NULL;
-	int top = -1;
-#define PUSH(n)								\
-	do{								\
-		stack = realloc(stack, sizeof(*stack) * (top + 2));	\
-		stack[++top] = n;					\
-	}while(0)
-#define POP() stack[top--]
-#define EMPTY() (top == -1)
-
-	/* we want to delete all subtrees exept if a pointer in fathers point in an other tree
-	 * ie an other context
-	 */
-	node->fathers[sched_ctx_id] = NULL;
-	int shared = 0;
-	{
-		int i;
-		for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
-			if(node->fathers[i] != NULL)
-				shared = 1;
-	}
-	if(!shared)
-		PUSH(node);
-	while(!EMPTY())
+
+	int i;
+	if(node->nchilds > 0)
 	{
-		struct starpu_sched_node * n = POP();
-		int i;
-		for(i = 0; i < n->nchilds; i++)
-		{
-			struct starpu_sched_node * child = n->childs[i];
-			int j;
-			shared = 0;
-			STARPU_ASSERT(child->fathers[sched_ctx_id] == n);
-			child->fathers[sched_ctx_id] = NULL;
-			for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
-			{
-				if(child->fathers[j] != NULL)/* child is shared */
-					shared = 1;
-			}
-			if(!shared)/* if not shared we want to destroy it and his childs */
-				PUSH(child);
-		}
-		starpu_sched_node_destroy(n);
+		for(i=0; i < node->nchilds; i++)
+			starpu_sched_node_destroy_rec(node->childs[i]);
 	}
-	free(stack);
+
+	starpu_sched_node_destroy(node);
 }
 
 struct starpu_sched_tree * starpu_sched_tree_create(unsigned sched_ctx_id)
@@ -287,11 +273,12 @@ void starpu_sched_tree_destroy(struct starpu_sched_tree * tree)
 {
 	STARPU_ASSERT(tree);
 	if(tree->root)
-		starpu_sched_node_destroy_rec(tree->root, tree->sched_ctx_id);
+		starpu_sched_node_destroy_rec(tree->root);
 	starpu_bitmap_destroy(tree->workers);
 	STARPU_PTHREAD_MUTEX_DESTROY(&tree->lock);
 	free(tree);
 }
+
 void starpu_sched_node_add_child(struct starpu_sched_node* node, struct starpu_sched_node * child)
 {
 	STARPU_ASSERT(node && child);
@@ -356,7 +343,7 @@ static double _starpu_sched_node_estimated_end_min(struct starpu_sched_node * no
  * and set prediction in *length. nan if a implementation need to be calibrated, 0.0 if no perf model are available
  * return false if no worker on the node can execute that task
  */
-int STARPU_WARN_UNUSED_RESULT starpu_sched_node_execute_preds(struct starpu_sched_node * node, struct starpu_task * task, double * length)
+int starpu_sched_node_execute_preds(struct starpu_sched_node * node, struct starpu_task * task, double * length)
 {
 	STARPU_ASSERT(node && task);
 	int can_execute = 0;
@@ -491,13 +478,23 @@ void starpu_sched_node_prefetch_on_node(struct starpu_sched_node * node, struct
  * A personally-made room in a node (like in prio nodes) is necessary to catch
  * this recursive call somewhere, if the user wants to exploit it.
  */
-void starpu_sched_node_room(struct starpu_sched_node * node, unsigned sched_ctx_id)
+int starpu_sched_node_room(struct starpu_sched_node * node)
 {
-	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
 	STARPU_ASSERT(node);
-	struct starpu_sched_node * father = node->fathers[sched_ctx_id];
-	if(father != NULL)
-		father->room(father, sched_ctx_id);
+	int ret = 0;
+	if(node->nfathers > 0)
+	{
+		int i;
+		for(i=0; i < node->nfathers; i++)
+		{
+			struct starpu_sched_node * father = node->fathers[i];
+			if(father != NULL)
+				ret = father->room(father);
+			if(ret)
+				break;
+		}
+	}
+	return ret;
 }
 
 /* An avail call will try to wake up one worker associated to the childs of the
@@ -534,6 +531,8 @@ struct starpu_sched_node * starpu_sched_node_create(void)
 	node->workers_in_ctx = starpu_bitmap_create();
 	node->add_child = starpu_sched_node_add_child;
 	node->remove_child = starpu_sched_node_remove_child;
+	node->add_father = starpu_sched_node_add_father;
+	node->remove_father = starpu_sched_node_remove_father;
 	node->pop_task = pop_task_node;
 	node->room = starpu_sched_node_room;
 	node->avail = starpu_sched_node_avail;
@@ -557,15 +556,26 @@ void starpu_sched_node_destroy(struct starpu_sched_node *node)
 	for(i = 0; i < node->nchilds; i++)
 	{
 		struct starpu_sched_node * child = node->childs[i];
-		for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
-			if(child->fathers[i] == node)
-				child->fathers[i] = NULL;
+		for(j = 0; j < child->nfathers; j++)
+			if(child->fathers[j] == node)
+				child->remove_father(child,node);
 
 	}
 	while(node->nchilds != 0)
 		node->remove_child(node, node->childs[0]);
+	for(i = 0; i < node->nfathers; i++)
+	{
+		struct starpu_sched_node * father = node->fathers[i];
+		for(j = 0; j < father->nchilds; j++)
+			if(father->childs[j] == node)
+				father->remove_child(father,node);
+
+	}
+	while(node->nfathers != 0)
+		node->remove_father(node, node->fathers[0]);
 	node->deinit_data(node);
 	free(node->childs);
+	free(node->fathers);
 	starpu_bitmap_destroy(node->workers);
 	starpu_bitmap_destroy(node->workers_in_ctx);
 	free(node);

+ 14 - 3
src/sched_policies/node_work_stealing.c

@@ -116,7 +116,7 @@ static int is_worker_of_node(struct starpu_sched_node * node, int workerid)
 
 
 
-static struct starpu_task * pop_task(struct starpu_sched_node * node, unsigned sched_ctx_id)
+static struct starpu_task * pop_task(struct starpu_sched_node * node)
 {
 	int workerid = starpu_worker_get_id();
 	int i;
@@ -155,8 +155,19 @@ static struct starpu_task * pop_task(struct starpu_sched_node * node, unsigned s
 
 		return task;
 	}
-	if(node->fathers[sched_ctx_id])
-		return node->fathers[sched_ctx_id]->pop_task(node->fathers[sched_ctx_id],sched_ctx_id);
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+		{
+			task = node->fathers[i]->pop_task(node->fathers[i]);
+			if(task)
+				break;
+		}
+	}
+	if(task)
+		return task;
 	else
 		return NULL;
 }

+ 14 - 6
src/sched_policies/node_worker.c

@@ -374,7 +374,7 @@ static int simple_worker_push_task(struct starpu_sched_node * node, struct starp
 	return 0;
 }
 
-struct starpu_task * simple_worker_pop_task(struct starpu_sched_node *node,unsigned sched_ctx_id)
+struct starpu_task * simple_worker_pop_task(struct starpu_sched_node *node)
 {
 	struct _starpu_worker_node_data * data = node->data;
 	struct _starpu_worker_task_list * list = data->list;
@@ -387,10 +387,18 @@ struct starpu_task * simple_worker_pop_task(struct starpu_sched_node *node,unsig
 		return task;
 	}
 	STARPU_PTHREAD_MUTEX_LOCK(&data->lock);
-	struct starpu_sched_node *father = node->fathers[sched_ctx_id];
-	if(father == NULL)
-		return NULL;
-	task = father->pop_task(father,sched_ctx_id);
+	int i;
+	for(i=0; i < node->nfathers; i++)
+	{
+		if(node->fathers[i] == NULL)
+			continue;
+		else
+		{
+			task = node->fathers[i]->pop_task(node->fathers[i]);
+			if(task)
+				break;
+		}
+	}
 	STARPU_PTHREAD_MUTEX_UNLOCK(&data->lock);
 	if(!task)
 		return NULL;
@@ -405,7 +413,7 @@ struct starpu_task * simple_worker_pop_task(struct starpu_sched_node *node,unsig
 		struct starpu_sched_node * combined_worker_node = starpu_sched_node_worker_get(workerid);
 		(void)combined_worker_node->push_task(combined_worker_node, task);
 		/* we have pushed a task in queue, so can make a recursive call */
-		return simple_worker_pop_task(node, sched_ctx_id);
+		return simple_worker_pop_task(node);
 
 	}
 	if(task)

+ 4 - 4
src/sched_policies/scheduler_maker.c

@@ -92,7 +92,7 @@ static struct sched_node_list helper_make_scheduler(hwloc_obj_t obj, struct star
 	for(i = 0; i < l.size; i++)
 	{
 		node->add_child(node, l.arr[i]);
-		starpu_sched_node_set_father(l.arr[i],node,sched_ctx_id);
+		starpu_sched_node_add_father(l.arr[i],node);
 	}
 	destroy_list(&l);
 	init_list(&l);
@@ -174,7 +174,7 @@ static struct starpu_sched_node * where_should_we_plug_this(struct starpu_sched_
 		struct starpu_sched_node * node = starpu_sched_node_composed_node_create(specs.hwloc_node_composed_sched_node);
 		node->obj = obj;
 		father->add_child(father, node);
-		starpu_sched_node_set_father(node, father, sched_ctx_id);
+		starpu_sched_node_add_father(node, father);
 		return node;
 	}
 	return father;
@@ -195,13 +195,13 @@ static void set_worker_leaf(struct starpu_sched_node * root, struct starpu_sched
 #warning FIXME node->obj is set to worker_node->obj even for accelerators workers
 #endif
 		tmp->obj = worker_node->obj;
-		starpu_sched_node_set_father(tmp, node, sched_ctx_id);
+		starpu_sched_node_add_father(tmp, node);
 		node->add_child(node, tmp);
 		node = tmp;
 		
 	}
 	starpu_destroy_composed_sched_node_recipe(recipe);
-	starpu_sched_node_set_father(worker_node, node, sched_ctx_id);
+	starpu_sched_node_add_father(worker_node, node);
 	node->add_child(node, worker_node);
 }
 

+ 2 - 2
src/sched_policies/tree_eager.c

@@ -27,7 +27,7 @@ static void initialize_eager_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_fifo_create(NULL);
 	struct starpu_sched_node * eager_node = starpu_sched_node_eager_create(NULL);
 	t->root->add_child(t->root, eager_node);
-	starpu_sched_node_set_father(eager_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(eager_node, t->root);
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
@@ -36,7 +36,7 @@ static void initialize_eager_center_policy(unsigned sched_ctx_id)
 		STARPU_ASSERT(worker_node);
 
 		eager_node->add_child(eager_node, worker_node);
-		starpu_sched_node_set_father(worker_node, eager_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, eager_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 3 - 3
src/sched_policies/tree_eager_prefetching.c

@@ -42,7 +42,7 @@ static void initialize_eager_prefetching_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_fifo_create(NULL);
 	struct starpu_sched_node * eager_node = starpu_sched_node_eager_create(NULL);
 	t->root->add_child(t->root, eager_node);
-	starpu_sched_node_set_father(eager_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(eager_node, t->root);
 
 	struct starpu_fifo_data fifo_data =
 		{
@@ -58,10 +58,10 @@ static void initialize_eager_prefetching_center_policy(unsigned sched_ctx_id)
 
 		struct starpu_sched_node * fifo_node = starpu_sched_node_fifo_create(&fifo_data);
 		fifo_node->add_child(fifo_node, worker_node);
-		starpu_sched_node_set_father(worker_node, fifo_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, fifo_node);
 
 		eager_node->add_child(eager_node, fifo_node);
-		starpu_sched_node_set_father(fifo_node, eager_node, sched_ctx_id);
+		starpu_sched_node_add_father(fifo_node, eager_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 12 - 14
src/sched_policies/tree_heft.c

@@ -67,12 +67,6 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
  * been made by its associated worker_node), this call goes up to the window_node which
  * pops a task from its local queue and try to schedule it by pushing it to the
  * decision_node. 
- * The decision node takes care of the scheduling of tasks which are not
- * calibrated, or tasks which don't have a performance model, because the scheduling
- * architecture of this scheduler for tasks with no performance model is exactly
- * the same as the tree-prio scheduler.
- * Tasks with a perfmodel are pushed to the perfmodel_node, which takes care of the
- * scheduling of those tasks on the correct worker_node.
  * Finally, the task will be pushed to the prio_node which is the direct
  * father in the tree of the worker_node the task has been scheduled on. This
  * node will push the task on its local queue if no one of the two thresholds
@@ -85,7 +79,7 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
 
 	struct starpu_sched_node * perfmodel_node = starpu_sched_node_mct_create(NULL);
 	struct starpu_sched_node * no_perfmodel_node = starpu_sched_node_eager_create(NULL);
-	struct starpu_sched_node * calibrator_node = starpu_sched_node_eager_create(NULL);
+	struct starpu_sched_node * calibrator_node = starpu_sched_node_eager_calibration_create(NULL);
 	
 	struct starpu_perfmodel_select_data perfmodel_select_data =
 		{
@@ -96,14 +90,14 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
 
 	struct starpu_sched_node * perfmodel_select_node = starpu_sched_node_perfmodel_select_create(&perfmodel_select_data);
 	window_node->add_child(window_node, perfmodel_select_node);
-	starpu_sched_node_set_father(perfmodel_select_node, window_node, sched_ctx_id);
+	starpu_sched_node_add_father(perfmodel_select_node, window_node);
 
 	perfmodel_select_node->add_child(perfmodel_select_node, calibrator_node);
-	starpu_sched_node_set_father(calibrator_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(calibrator_node, perfmodel_select_node);
 	perfmodel_select_node->add_child(perfmodel_select_node, perfmodel_node);
-	starpu_sched_node_set_father(perfmodel_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(perfmodel_node, perfmodel_select_node);
 	perfmodel_select_node->add_child(perfmodel_select_node, no_perfmodel_node);
-	starpu_sched_node_set_father(no_perfmodel_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(no_perfmodel_node, perfmodel_select_node);
 
 	struct starpu_prio_data prio_data =
 		{
@@ -119,14 +113,18 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
 
 		struct starpu_sched_node * prio = starpu_sched_node_prio_create(&prio_data);
 		prio->add_child(prio, worker_node);
-		starpu_sched_node_set_father(worker_node, prio, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, prio);
 
 		struct starpu_sched_node * impl_node = starpu_sched_node_best_implementation_create(NULL);
 		impl_node->add_child(impl_node, prio);
-		starpu_sched_node_set_father(prio, impl_node, sched_ctx_id);
+		starpu_sched_node_add_father(prio, impl_node);
 
 		perfmodel_node->add_child(perfmodel_node, impl_node);
-		starpu_sched_node_set_father(impl_node, perfmodel_node, sched_ctx_id);
+		starpu_sched_node_add_father(impl_node, perfmodel_node);
+		no_perfmodel_node->add_child(no_perfmodel_node, impl_node);
+		starpu_sched_node_add_father(impl_node, no_perfmodel_node);
+		calibrator_node->add_child(calibrator_node, impl_node);
+		starpu_sched_node_add_father(impl_node, calibrator_node);
 	}
 
 	starpu_sched_tree_update_workers(t);

+ 15 - 7
src/sched_policies/tree_heft2.c

@@ -59,15 +59,19 @@ static void initialize_heft2_center_policy(unsigned sched_ctx_id)
 			.perfmodel_node = perfmodel_node,
 		};
 
+	struct starpu_sched_node * window_node = starpu_sched_node_prio_create(NULL);
+	t->root = window_node;
+
 	struct starpu_sched_node * perfmodel_select_node = starpu_sched_node_perfmodel_select_create(&perfmodel_select_data);
-	t->root = perfmodel_select_node;
+	window_node->add_child(window_node, perfmodel_select_node);
+	starpu_sched_node_add_father(perfmodel_select_node, window_node);
 
 	perfmodel_select_node->add_child(perfmodel_select_node, calibrator_node);
-	starpu_sched_node_set_father(calibrator_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(calibrator_node, perfmodel_select_node);
 	perfmodel_select_node->add_child(perfmodel_select_node, perfmodel_node);
-	starpu_sched_node_set_father(perfmodel_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(perfmodel_node, perfmodel_select_node);
 	perfmodel_select_node->add_child(perfmodel_select_node, no_perfmodel_node);
-	starpu_sched_node_set_father(no_perfmodel_node, perfmodel_select_node, sched_ctx_id);
+	starpu_sched_node_add_father(no_perfmodel_node, perfmodel_select_node);
 
 	struct starpu_prio_data prio_data =
 		{
@@ -83,14 +87,18 @@ static void initialize_heft2_center_policy(unsigned sched_ctx_id)
 
 		struct starpu_sched_node * prio = starpu_sched_node_prio_create(&prio_data);
 		prio->add_child(prio, worker_node);
-		starpu_sched_node_set_father(worker_node, prio, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, prio);
 
 		struct starpu_sched_node * impl_node = starpu_sched_node_best_implementation_create(NULL);
 		impl_node->add_child(impl_node, prio);
-		starpu_sched_node_set_father(prio, impl_node, sched_ctx_id);
+		starpu_sched_node_add_father(prio, impl_node);
 
 		perfmodel_node->add_child(perfmodel_node, impl_node);
-		starpu_sched_node_set_father(impl_node, perfmodel_node, sched_ctx_id);
+		starpu_sched_node_add_father(impl_node, perfmodel_node);
+		no_perfmodel_node->add_child(no_perfmodel_node, impl_node);
+		starpu_sched_node_add_father(impl_node, no_perfmodel_node);
+		calibrator_node->add_child(calibrator_node, impl_node);
+		starpu_sched_node_add_father(impl_node, calibrator_node);
 	}
 
 	starpu_sched_tree_update_workers(t);

+ 2 - 2
src/sched_policies/tree_prio.c

@@ -24,7 +24,7 @@ static void initialize_prio_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_prio_create(NULL);
 	struct starpu_sched_node * eager_node = starpu_sched_node_eager_create(NULL);
 	t->root->add_child(t->root, eager_node);
-	starpu_sched_node_set_father(eager_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(eager_node, t->root);
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
@@ -33,7 +33,7 @@ static void initialize_prio_center_policy(unsigned sched_ctx_id)
 		STARPU_ASSERT(worker_node);
 
 		eager_node->add_child(eager_node, worker_node);
-		starpu_sched_node_set_father(worker_node, eager_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, eager_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 3 - 3
src/sched_policies/tree_prio_prefetching.c

@@ -38,7 +38,7 @@ static void initialize_prio_prefetching_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_prio_create(NULL);
 	struct starpu_sched_node * eager_node = starpu_sched_node_eager_create(NULL);
 	t->root->add_child(t->root, eager_node);
-	starpu_sched_node_set_father(eager_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(eager_node, t->root);
 
 	struct starpu_prio_data prio_data =
 		{
@@ -54,10 +54,10 @@ static void initialize_prio_prefetching_center_policy(unsigned sched_ctx_id)
 
 		struct starpu_sched_node * prio_node = starpu_sched_node_prio_create(&prio_data);
 		prio_node->add_child(prio_node, worker_node);
-		starpu_sched_node_set_father(worker_node, prio_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, prio_node);
 
 		eager_node->add_child(eager_node, prio_node);
-		starpu_sched_node_set_father(prio_node, eager_node, sched_ctx_id);
+		starpu_sched_node_add_father(prio_node, eager_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 4 - 4
src/sched_policies/tree_random.c

@@ -27,7 +27,7 @@ static void initialize_random_fifo_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_fifo_create(NULL);
 	struct starpu_sched_node * random_node = starpu_sched_node_random_create(NULL);
 	t->root->add_child(t->root, random_node);
-	starpu_sched_node_set_father(random_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(random_node, t->root);
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
@@ -36,7 +36,7 @@ static void initialize_random_fifo_center_policy(unsigned sched_ctx_id)
 		STARPU_ASSERT(worker_node);
 
 		random_node->add_child(random_node, worker_node);
-		starpu_sched_node_set_father(worker_node, random_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, random_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
@@ -73,7 +73,7 @@ static void initialize_random_prio_center_policy(unsigned sched_ctx_id)
  	t->root = starpu_sched_node_prio_create(NULL);
 	struct starpu_sched_node * random_node = starpu_sched_node_random_create(NULL);
 	t->root->add_child(t->root, random_node);
-	starpu_sched_node_set_father(random_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(random_node, t->root);
 
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
@@ -82,7 +82,7 @@ static void initialize_random_prio_center_policy(unsigned sched_ctx_id)
 		STARPU_ASSERT(worker_node);
 
 		random_node->add_child(random_node, worker_node);
-		starpu_sched_node_set_father(worker_node, random_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, random_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 6 - 6
src/sched_policies/tree_random_prefetching.c

@@ -41,7 +41,7 @@ static void initialize_random_fifo_prefetching_center_policy(unsigned sched_ctx_
  	t->root = starpu_sched_node_fifo_create(NULL);
 	struct starpu_sched_node * random_node = starpu_sched_node_random_create(NULL);
 	t->root->add_child(t->root, random_node);
-	starpu_sched_node_set_father(random_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(random_node, t->root);
 
 	struct starpu_fifo_data fifo_data =
 		{
@@ -57,10 +57,10 @@ static void initialize_random_fifo_prefetching_center_policy(unsigned sched_ctx_
 
 		struct starpu_sched_node * fifo_node = starpu_sched_node_fifo_create(&fifo_data);
 		fifo_node->add_child(fifo_node, worker_node);
-		starpu_sched_node_set_father(worker_node, fifo_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, fifo_node);
 
 		random_node->add_child(random_node, fifo_node);
-		starpu_sched_node_set_father(fifo_node, random_node, sched_ctx_id);
+		starpu_sched_node_add_father(fifo_node, random_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
@@ -108,7 +108,7 @@ static void initialize_random_prio_prefetching_center_policy(unsigned sched_ctx_
  	t->root = starpu_sched_node_prio_create(NULL);
 	struct starpu_sched_node * random_node = starpu_sched_node_random_create(NULL);
 	t->root->add_child(t->root, random_node);
-	starpu_sched_node_set_father(random_node, t->root, sched_ctx_id);
+	starpu_sched_node_add_father(random_node, t->root);
 
 	struct starpu_prio_data prio_data =
 		{
@@ -124,10 +124,10 @@ static void initialize_random_prio_prefetching_center_policy(unsigned sched_ctx_
 
 		struct starpu_sched_node * prio_node = starpu_sched_node_prio_create(&prio_data);
 		prio_node->add_child(prio_node, worker_node);
-		starpu_sched_node_set_father(worker_node, prio_node, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, prio_node);
 
 		random_node->add_child(random_node, prio_node);
-		starpu_sched_node_set_father(prio_node, random_node, sched_ctx_id);
+		starpu_sched_node_add_father(prio_node, random_node);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 1 - 1
src/sched_policies/tree_ws.c

@@ -31,7 +31,7 @@ static void initialize_ws_center_policy(unsigned sched_ctx_id)
 		STARPU_ASSERT(worker_node);
 
 		t->root->add_child(t->root, worker_node);
-		starpu_sched_node_set_father(worker_node, t->root, sched_ctx_id);
+		starpu_sched_node_add_father(worker_node, t->root);
 	}
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);