Browse Source

Second step of hierarchical schedulers' restructuring.
All the schedulers are now working, and adding some more
to show how easy it is to create and experiment scheduling
strategies with this model of schedulers.
Still experimental. Documentation is yet to be done.

Marc Sergent 11 years ago
parent
commit
653110bc59

+ 4 - 0
ChangeLog

@@ -56,6 +56,10 @@ New features:
     the scheduling decision.
     the scheduling decision.
   * Add a watchdog which permits to easily trigger a crash when StarPU gets
   * Add a watchdog which permits to easily trigger a crash when StarPU gets
     stuck.
     stuck.
+  * New hierarchical schedulers which allow the user to easily build
+    its own scheduler, by coding itself each "box" it wants, or by
+    combining existing boxes in StarPU to build it. Hierarchical
+    schedulers have very interesting scalability properties.
 
 
 Small features:
 Small features:
   * New functions starpu_data_acquire_cb_sequential_consistency() and
   * New functions starpu_data_acquire_cb_sequential_consistency() and

+ 32 - 15
include/starpu_sched_node.h

@@ -53,8 +53,9 @@ struct starpu_sched_node
 					 unsigned sched_ctx_id);
 					 unsigned sched_ctx_id);
 
 
 	/* node->push_back_task(node, task)
 	/* node->push_back_task(node, task)
-	 * This function is called when a push fails after a pop has been done,
-	 * to push it back correctly to the popped node
+	 * 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 *,
 	int (*push_back_task)(struct starpu_sched_node *,
 			 struct starpu_task *);
 			 struct starpu_task *);
@@ -105,7 +106,20 @@ struct starpu_sched_node
 	 */
 	 */
 	int properties;
 	int properties;
 
 
+	/* This function is called by a node which implements a queue, allowing it to
+	 * signify to its fathers that an empty slot is available in its queue.
+	 * The basic implementation of this function is a recursive call to its
+	 * 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);
 	void (*room)(struct starpu_sched_node * node, unsigned sched_ctx_id);
+	/* 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
+	 * available to been popped by a worker, for example.
+	 * The basic implementation of this function is a recursive call to
+	 * its childs, until at least one worker have been woken up.
+	 */
 	int (*avail)(struct starpu_sched_node * node);
 	int (*avail)(struct starpu_sched_node * node);
 
 
 #ifdef STARPU_HAVE_HWLOC
 #ifdef STARPU_HAVE_HWLOC
@@ -186,8 +200,11 @@ int starpu_sched_tree_work_stealing_push_task(struct starpu_task *task);
 struct starpu_sched_node * starpu_sched_node_random_create(void * arg STARPU_ATTRIBUTE_UNUSED);
 struct starpu_sched_node * starpu_sched_node_random_create(void * arg STARPU_ATTRIBUTE_UNUSED);
 int starpu_sched_node_is_random(struct starpu_sched_node *);
 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_heft_data
+struct starpu_mct_data
 {
 {
 	double alpha;
 	double alpha;
 	double beta;
 	double beta;
@@ -195,13 +212,13 @@ struct starpu_heft_data
 	double idle_power;
 	double idle_power;
 };
 };
 
 
-/* create a node with heft_data paremeters
-   a copy the struct starpu_heft_data * given is performed during the init_data call
-   the heft node doesnt do anything but pushing tasks on no_perf_model_node and calibrating_node
+/* create a node with mct_data paremeters
+   a copy the struct starpu_mct_data * given is performed during the init_data call
+   the mct node doesnt do anything but pushing tasks on no_perf_model_node and calibrating_node
 */
 */
-struct starpu_sched_node * starpu_sched_node_heft_create(struct starpu_heft_data * heft_data);
+struct starpu_sched_node * starpu_sched_node_mct_create(struct starpu_mct_data * mct_data);
 
 
-int starpu_sched_node_is_heft(struct starpu_sched_node * node);
+int starpu_sched_node_is_mct(struct starpu_sched_node * node);
 
 
 /* this node select the best implementation for the first worker in context that can execute task.
 /* this node select the best implementation for the first worker in context that can execute task.
  * and fill task->predicted and task->predicted_transfer
  * and fill task->predicted and task->predicted_transfer
@@ -209,16 +226,16 @@ int starpu_sched_node_is_heft(struct starpu_sched_node * node);
  */
  */
 struct starpu_sched_node * starpu_sched_node_best_implementation_create(void * arg STARPU_ATTRIBUTE_UNUSED);
 struct starpu_sched_node * starpu_sched_node_best_implementation_create(void * arg STARPU_ATTRIBUTE_UNUSED);
 
 
-struct starpu_calibrator_data
+struct starpu_perfmodel_select_data
 {
 {
-	struct starpu_sched_node * (*no_perf_model_node_create)(void * arg_no_perf_model);
-	void * arg_no_perf_model;
-	struct starpu_sched_node * next_node;
+	struct starpu_sched_node * calibrator_node;
+	struct starpu_sched_node * no_perfmodel_node;
+	struct starpu_sched_node * perfmodel_node;
 };
 };
 
 
-struct starpu_sched_node * starpu_sched_node_calibrator_create(struct starpu_calibrator_data * calibrator_data);
-int starpu_sched_node_is_calibrator(struct starpu_sched_node * node);
-int starpu_sched_node_calibrator_room(struct starpu_sched_node * node, unsigned sched_ctx_id);
+struct starpu_sched_node * starpu_sched_node_perfmodel_select_create(struct starpu_perfmodel_select_data * perfmodel_select_data);
+int starpu_sched_node_is_perfmodel_select(struct starpu_sched_node * node);
+int starpu_sched_node_perfmodel_select_room(struct starpu_sched_node * node, unsigned sched_ctx_id);
 
 
 /*create an empty tree
 /*create an empty tree
  */
  */

+ 8 - 4
src/Makefile.am

@@ -240,7 +240,7 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 		\
 	top/starpu_top.c					\
 	top/starpu_top.c					\
 	top/starpu_top_task.c					\
 	top/starpu_top_task.c					\
 	top/starpu_top_message_queue.c				\
 	top/starpu_top_message_queue.c				\
-	top/starpu_top_connection.c                          	\
+	top/starpu_top_connection.c                        	\
 	worker_collection/worker_list.c				\
 	worker_collection/worker_list.c				\
 	sched_policies/node_worker.c				\
 	sched_policies/node_worker.c				\
 	sched_policies/node_sched.c				\
 	sched_policies/node_sched.c				\
@@ -249,15 +249,19 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 		\
 	sched_policies/prio_deque.c				\
 	sched_policies/prio_deque.c				\
 	sched_policies/node_prio.c 				\
 	sched_policies/node_prio.c 				\
 	sched_policies/node_random.c				\
 	sched_policies/node_random.c				\
-	sched_policies/node_heft.c				\
+	sched_policies/node_eager.c				\
+	sched_policies/node_mct.c				\
 	sched_policies/node_best_implementation.c		\
 	sched_policies/node_best_implementation.c		\
-	sched_policies/node_calibrator.c				\
+	sched_policies/node_perfmodel_select.c				\
 	sched_policies/node_composed.c				\
 	sched_policies/node_composed.c				\
 	sched_policies/tree_eager.c				\
 	sched_policies/tree_eager.c				\
+	sched_policies/tree_eager_prefetching.c				\
 	sched_policies/tree_prio.c				\
 	sched_policies/tree_prio.c				\
+	sched_policies/tree_prio_prefetching.c				\
 	sched_policies/tree_random.c				\
 	sched_policies/tree_random.c				\
+	sched_policies/tree_random_prefetching.c			\
 	sched_policies/tree_ws.c				\
 	sched_policies/tree_ws.c				\
-	sched_policies/tree_dmda.c				\
+	sched_policies/tree_heft.c				\
 	sched_policies/scheduler_maker.c			
 	sched_policies/scheduler_maker.c			
 
 
 
 

+ 6 - 1
src/core/sched_policy.c

@@ -34,10 +34,15 @@ int starpu_get_prefetch_flag(void)
 static struct starpu_sched_policy *predefined_policies[] =
 static struct starpu_sched_policy *predefined_policies[] =
 {
 {
 	&_starpu_sched_tree_eager_policy,
 	&_starpu_sched_tree_eager_policy,
+	&_starpu_sched_tree_eager_prefetching_policy,
 	&_starpu_sched_tree_prio_policy,
 	&_starpu_sched_tree_prio_policy,
+	&_starpu_sched_tree_prio_prefetching_policy,
 	&_starpu_sched_tree_random_policy,
 	&_starpu_sched_tree_random_policy,
+	&_starpu_sched_tree_random_prio_policy,
+	&_starpu_sched_tree_random_prefetching_policy,
+	&_starpu_sched_tree_random_prio_prefetching_policy,
 	&_starpu_sched_tree_ws_policy,
 	&_starpu_sched_tree_ws_policy,
-	&_starpu_sched_tree_dmda_policy,
+	&_starpu_sched_tree_heft_policy,
 	&_starpu_sched_eager_policy,
 	&_starpu_sched_eager_policy,
 	&_starpu_sched_prio_policy,
 	&_starpu_sched_prio_policy,
 	&_starpu_sched_random_policy,
 	&_starpu_sched_random_policy,

+ 6 - 1
src/core/sched_policy.h

@@ -68,8 +68,13 @@ extern struct starpu_sched_policy _starpu_sched_eager_policy;
 extern struct starpu_sched_policy _starpu_sched_parallel_heft_policy;
 extern struct starpu_sched_policy _starpu_sched_parallel_heft_policy;
 extern struct starpu_sched_policy _starpu_sched_peager_policy;
 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_eager_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_eager_prefetching_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_prio_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_prio_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_prio_prefetching_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_random_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_random_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_random_prio_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_random_prefetching_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_random_prio_prefetching_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_ws_policy;
 extern struct starpu_sched_policy _starpu_sched_tree_ws_policy;
-extern struct starpu_sched_policy _starpu_sched_tree_dmda_policy;
+extern struct starpu_sched_policy _starpu_sched_tree_heft_policy;
 #endif // __SCHED_POLICY_H__
 #endif // __SCHED_POLICY_H__

+ 4 - 0
src/datawizard/coherency.c

@@ -670,6 +670,10 @@ int starpu_prefetch_task_input_on_node(struct starpu_task *task, unsigned node)
 			continue;
 			continue;
 
 
 		struct _starpu_data_replicate *replicate = &handle->per_node[node];
 		struct _starpu_data_replicate *replicate = &handle->per_node[node];
+		
+		if (replicate->state != STARPU_INVALID)
+			continue;
+
 		prefetch_data_on_node(handle, replicate, mode);
 		prefetch_data_on_node(handle, replicate, mode);
 
 
 		_starpu_set_data_requested_flag_if_needed(replicate);
 		_starpu_set_data_requested_flag_if_needed(replicate);

+ 18 - 0
src/sched_policies/fifo_queues.c

@@ -148,6 +148,24 @@ int _starpu_fifo_push_task(struct _starpu_fifo_taskq *fifo_queue, struct starpu_
 	return 0;
 	return 0;
 }
 }
 
 
+int _starpu_fifo_push_back_task(struct _starpu_fifo_taskq *fifo_queue, struct starpu_task *task)
+{
+
+	if (task->priority > 0)
+	{
+		_starpu_fifo_push_sorted_task(fifo_queue, task);
+	}
+	else
+	{
+		starpu_task_list_push_front(&fifo_queue->taskq, task);
+
+		fifo_queue->ntasks++;
+		fifo_queue->nprocessed++;
+	}
+
+	return 0;
+}
+
 struct starpu_task *_starpu_fifo_pop_task(struct _starpu_fifo_taskq *fifo_queue, int workerid)
 struct starpu_task *_starpu_fifo_pop_task(struct _starpu_fifo_taskq *fifo_queue, int workerid)
 {
 {
 	struct starpu_task *task;
 	struct starpu_task *task;

+ 1 - 0
src/sched_policies/fifo_queues.h

@@ -48,6 +48,7 @@ int _starpu_fifo_empty(struct _starpu_fifo_taskq *fifo);
 int _starpu_fifo_push_sorted_task(struct _starpu_fifo_taskq *fifo_queue, struct starpu_task *task);
 int _starpu_fifo_push_sorted_task(struct _starpu_fifo_taskq *fifo_queue, struct starpu_task *task);
 
 
 int _starpu_fifo_push_task(struct _starpu_fifo_taskq *fifo, struct starpu_task *task);
 int _starpu_fifo_push_task(struct _starpu_fifo_taskq *fifo, struct starpu_task *task);
+int _starpu_fifo_push_back_task(struct _starpu_fifo_taskq *fifo_queue, struct starpu_task *task);
 
 
 struct starpu_task *_starpu_fifo_pop_task(struct _starpu_fifo_taskq *fifo, int workerid);
 struct starpu_task *_starpu_fifo_pop_task(struct _starpu_fifo_taskq *fifo, int workerid);
 struct starpu_task *_starpu_fifo_pop_local_task(struct _starpu_fifo_taskq *fifo);
 struct starpu_task *_starpu_fifo_pop_local_task(struct _starpu_fifo_taskq *fifo);

+ 0 - 148
src/sched_policies/node_calibrator.c

@@ -1,148 +0,0 @@
-/* StarPU --- Runtime system for heterogeneous multicore architectures.
- *
- * Copyright (C) 2013  Marc Sergent
- *
- * 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>
-
-struct _starpu_calibrator_data
-{
-	struct starpu_sched_node * no_perf_model_node;
-	struct starpu_sched_node * next_node;
-};
-
-static int calibrator_push_task(struct starpu_sched_node * node, struct starpu_task * task)
-{
-	STARPU_ASSERT(node && node->data && task && starpu_sched_node_is_calibrator(node));
-	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
-
-	struct _starpu_calibrator_data * data = node->data;
-	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)
-								return node->childs[i]->push_task(node->childs[i],task);
-						}
-					}
-				}
-				if(_STARPU_IS_ZERO(d))
-					return data->no_perf_model_node->push_task(data->no_perf_model_node,task);
-			}
-		}
-	}
-
-	return data->next_node->push_task(data->next_node,task);
-}
-
-int starpu_sched_node_is_calibrator(struct starpu_sched_node * node)
-{
-	return node->push_task == calibrator_push_task;
-}
-
-void calibrator_add_child(struct starpu_sched_node * node, struct starpu_sched_node * child)
-{
-	STARPU_ASSERT(starpu_sched_node_is_calibrator(node));
-	starpu_sched_node_add_child(node, child);
-	struct _starpu_calibrator_data * data = node->data;
-	starpu_sched_node_add_child(data->no_perf_model_node,child);
-	starpu_sched_node_add_child(data->next_node, child);
-}
-
-void calibrator_remove_child(struct starpu_sched_node * node, struct starpu_sched_node * child)
-{
-
-	STARPU_ASSERT(starpu_sched_node_is_calibrator(node));
-	starpu_sched_node_remove_child(node, child);
-	struct _starpu_calibrator_data * data = node->data;
-	starpu_sched_node_remove_child(data->no_perf_model_node,child);
-	starpu_sched_node_remove_child(data->next_node, child);
-}
-
-static void calibrator_notify_change_in_workers(struct starpu_sched_node * node)
-{
-	STARPU_ASSERT(starpu_sched_node_is_calibrator(node));
-	struct _starpu_calibrator_data * data = node->data;
-	starpu_bitmap_unset_all(data->no_perf_model_node->workers_in_ctx);
-	starpu_bitmap_unset_all(data->no_perf_model_node->workers);
-
-	starpu_bitmap_or(data->no_perf_model_node->workers_in_ctx, node->workers_in_ctx);
-	starpu_bitmap_or(data->no_perf_model_node->workers, node->workers);
-
-	data->no_perf_model_node->properties = node->properties;
-
-	starpu_bitmap_unset_all(data->next_node->workers_in_ctx);
-	starpu_bitmap_unset_all(data->next_node->workers);
-
-	starpu_bitmap_or(data->next_node->workers_in_ctx, node->workers_in_ctx);
-	starpu_bitmap_or(data->next_node->workers, node->workers);
-
-	data->next_node->properties = node->properties;
-}
-
-void calibrator_node_deinit_data(struct starpu_sched_node * node)
-
-{
-	STARPU_ASSERT(node && node->data);
-	struct _starpu_calibrator_data * d = node->data;
-	starpu_sched_node_destroy(d->no_perf_model_node);
-	starpu_sched_node_destroy(d->next_node);
-	free(d);
-}
-
-struct starpu_sched_node * starpu_sched_node_calibrator_create(struct starpu_calibrator_data * params)
-{
-	STARPU_ASSERT(params);
-	struct starpu_sched_node * node = starpu_sched_node_create();
-	struct _starpu_calibrator_data * data = malloc(sizeof(*data));
-	data->no_perf_model_node = params->no_perf_model_node_create(params->arg_no_perf_model);
-	data->next_node = params->next_node;
-	node->data = data;
-	node->push_task = calibrator_push_task;
-	node->add_child = calibrator_add_child;
-	node->remove_child = calibrator_remove_child;
-	node->deinit_data = calibrator_node_deinit_data;
-	node->notify_change_workers = calibrator_notify_change_in_workers;
-
-	return node;
-}

+ 77 - 0
src/sched_policies/node_eager.c

@@ -0,0 +1,77 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Marc Sergent
+ *
+ * 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_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+{
+	STARPU_ASSERT(node && task && starpu_sched_node_is_eager(node));
+	STARPU_ASSERT(starpu_sched_node_can_execute_task(node,task));
+	
+	int workerid;
+	for(workerid = starpu_bitmap_first(node->workers_in_ctx);
+	    workerid != -1;
+	    workerid = starpu_bitmap_next(node->workers_in_ctx, 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))
+			{
+				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
+							{
+								int ret = node->childs[i]->push_task(node->childs[i],task);
+								if(!ret)
+									return ret;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return 1;
+}
+
+int starpu_sched_node_is_eager(struct starpu_sched_node * node)
+{
+	return node->push_task == eager_push_task;
+}
+
+struct starpu_sched_node * starpu_sched_node_eager_create(void * ARG STARPU_ATTRIBUTE_UNUSED)
+{
+	struct starpu_sched_node * node = starpu_sched_node_create();
+	node->push_task = eager_push_task;
+
+	return node;
+}

+ 104 - 14
src/sched_policies/node_fifo.c

@@ -102,32 +102,96 @@ static int fifo_push_task(struct starpu_sched_node * node, struct starpu_task *
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret;
 	int ret;
 
 
-	STARPU_PTHREAD_MUTEX_LOCK(mutex);
-	double exp_len;
-	if(!isnan(task->predicted))
-		exp_len = fifo->exp_len + task->predicted;
+	STARPU_ASSERT(node->nchilds == 1);
+	struct starpu_sched_node * child = node->childs[0];
+	if(starpu_sched_node_is_worker(child))
+		ret = 1;
 	else
 	else
-		exp_len = fifo->exp_len;
+		ret = child->push_task(child,task);
 
 
-	if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
-			((fifo->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
+	if(ret)
 	{
 	{
-		ret = 1;
-		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
+		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)
+			{
+				_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
+		{
+			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;
 	else
 	else
+		ret = child->push_task(child,task);
+
+	if(ret)
 	{
 	{
-		ret = _starpu_fifo_push_task(fifo,task);
+		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;
+
+		_starpu_fifo_push_back_task(fifo,task);
 		if(!isnan(task->predicted))
 		if(!isnan(task->predicted))
 		{
 		{
-			fifo->exp_len += exp_len;
-			fifo->exp_end = fifo->exp_start + fifo->exp_len;
+			fifo->exp_len = exp_len;
+			fifo->exp_end = fifo->exp_start + exp_len;
 		}
 		}
 		STARPU_ASSERT(!isnan(fifo->exp_end));
 		STARPU_ASSERT(!isnan(fifo->exp_end));
 		STARPU_ASSERT(!isnan(fifo->exp_len));
 		STARPU_ASSERT(!isnan(fifo->exp_len));
 		STARPU_ASSERT(!isnan(fifo->exp_start));
 		STARPU_ASSERT(!isnan(fifo->exp_start));
 		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 		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);
 		node->avail(node);
 	}
 	}
 	return ret;
 	return ret;
@@ -162,7 +226,11 @@ static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node, unsig
 	STARPU_ASSERT(!isnan(fifo->exp_start));
 	STARPU_ASSERT(!isnan(fifo->exp_start));
 	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 
 
-	node->room(node, sched_ctx_id);
+	// 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);
 	
 	
 	if(task)
 	if(task)
 		return task;
 		return task;
@@ -170,6 +238,27 @@ static struct starpu_task * fifo_pop_task(struct starpu_sched_node * node, unsig
 	return NULL;
 	return NULL;
 }
 }
 
 
+/* When a room is caught by this function, we try to pop and push
+ * tasks from our local queue as much as possible, until a
+ * 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)
+{
+	STARPU_ASSERT(node && starpu_sched_node_is_fifo(node));
+	int ret = 0;
+
+	struct starpu_task * task = node->pop_task(node, sched_ctx_id);
+	if(task)
+		ret = node->push_back_task(node,task);	
+	while(task && !ret) 
+	{
+		task = node->pop_task(node, sched_ctx_id);
+		if(task)
+			ret = node->push_back_task(node,task);	
+	} 
+}
+
 struct starpu_sched_node * starpu_sched_node_fifo_create(struct starpu_fifo_data * params)
 struct starpu_sched_node * starpu_sched_node_fifo_create(struct starpu_fifo_data * params)
 {
 {
 	struct starpu_sched_node * node = starpu_sched_node_create();
 	struct starpu_sched_node * node = starpu_sched_node_create();
@@ -180,8 +269,9 @@ struct starpu_sched_node * starpu_sched_node_fifo_create(struct starpu_fifo_data
 	node->estimated_end = fifo_estimated_end;
 	node->estimated_end = fifo_estimated_end;
 	node->estimated_load = fifo_estimated_load;
 	node->estimated_load = fifo_estimated_load;
 	node->push_task = fifo_push_task;
 	node->push_task = fifo_push_task;
-	node->push_back_task = fifo_push_task;
+	node->push_back_task = fifo_push_back_task;
 	node->pop_task = fifo_pop_task;
 	node->pop_task = fifo_pop_task;
+	node->room = fifo_room;
 	node->deinit_data = fifo_node_deinit_data;
 	node->deinit_data = fifo_node_deinit_data;
 
 
 	if(params)
 	if(params)

+ 14 - 17
src/sched_policies/node_heft.c

@@ -19,7 +19,7 @@
 #include <starpu_perfmodel.h>
 #include <starpu_perfmodel.h>
 #include <float.h>
 #include <float.h>
 
 
-struct _starpu_heft_data
+struct _starpu_mct_data
 {
 {
 	double alpha;
 	double alpha;
 	double beta;
 	double beta;
@@ -58,7 +58,7 @@ double compute_expected_time(double now, double predicted_end, double predicted_
 }
 }
 
 
 
 
-static double compute_fitness(struct _starpu_heft_data * d, double exp_end, double best_exp_end, double max_exp_end, double transfer_len, double local_power)
+static double compute_fitness(struct _starpu_mct_data * d, double exp_end, double best_exp_end, double max_exp_end, double transfer_len, double local_power)
 {
 {
 	return d->alpha * (exp_end - best_exp_end)
 	return d->alpha * (exp_end - best_exp_end)
 		+ d->beta * transfer_len
 		+ d->beta * transfer_len
@@ -66,10 +66,10 @@ static double compute_fitness(struct _starpu_heft_data * d, double exp_end, doub
 		+ d->gamma * d->idle_power * (exp_end - max_exp_end);
 		+ d->gamma * d->idle_power * (exp_end - max_exp_end);
 }
 }
 
 
-static int heft_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+static int mct_push_task(struct starpu_sched_node * node, struct starpu_task * task)
 {
 {
-	STARPU_ASSERT(node && task && starpu_sched_node_is_heft(node));
-	struct _starpu_heft_data * d = node->data;	
+	STARPU_ASSERT(node && task && starpu_sched_node_is_mct(node));
+	struct _starpu_mct_data * d = node->data;	
 	struct starpu_sched_node * best_node = NULL;
 	struct starpu_sched_node * best_node = NULL;
 	double estimated_ends[node->nchilds];
 	double estimated_ends[node->nchilds];
 	double estimated_ends_with_task[node->nchilds];
 	double estimated_ends_with_task[node->nchilds];
@@ -128,29 +128,26 @@ static int heft_push_task(struct starpu_sched_node * node, struct starpu_task *
 
 
 	int ret = best_node->push_task(best_node, task);
 	int ret = best_node->push_task(best_node, task);
 
 
-	if(!ret)
-		starpu_sched_node_prefetch_on_node(best_node, task);
-
 	return ret;
 	return ret;
 }
 }
 
 
-void heft_node_deinit_data(struct starpu_sched_node * node)
+void mct_node_deinit_data(struct starpu_sched_node * node)
 {
 {
-	STARPU_ASSERT(starpu_sched_node_is_heft(node));
-	struct _starpu_heft_data * d = node->data;
+	STARPU_ASSERT(starpu_sched_node_is_mct(node));
+	struct _starpu_mct_data * d = node->data;
 	free(d);
 	free(d);
 }
 }
 
 
-int starpu_sched_node_is_heft(struct starpu_sched_node * node)
+int starpu_sched_node_is_mct(struct starpu_sched_node * node)
 {
 {
-	return node->push_task == heft_push_task;
+	return node->push_task == mct_push_task;
 }
 }
 
 
-struct starpu_sched_node * starpu_sched_node_heft_create(struct starpu_heft_data * params)
+struct starpu_sched_node * starpu_sched_node_mct_create(struct starpu_mct_data * params)
 {
 {
 	struct starpu_sched_node * node = starpu_sched_node_create();
 	struct starpu_sched_node * node = starpu_sched_node_create();
 
 
-	struct _starpu_heft_data * data = malloc(sizeof(*data));
+	struct _starpu_mct_data * data = malloc(sizeof(*data));
 	data->alpha = params->alpha;
 	data->alpha = params->alpha;
 	data->beta = params->beta;
 	data->beta = params->beta;
 	data->gamma = params->gamma;
 	data->gamma = params->gamma;
@@ -158,8 +155,8 @@ struct starpu_sched_node * starpu_sched_node_heft_create(struct starpu_heft_data
 
 
 	node->data = data;
 	node->data = data;
 
 
-	node->push_task = heft_push_task;
-	node->deinit_data = heft_node_deinit_data;
+	node->push_task = mct_push_task;
+	node->deinit_data = mct_node_deinit_data;
 
 
 	return node;
 	return node;
 }
 }

+ 149 - 0
src/sched_policies/node_perfmodel_select.c

@@ -0,0 +1,149 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Marc Sergent
+ *
+ * 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>
+
+struct _starpu_perfmodel_select_data
+{
+	struct starpu_sched_node * calibrator_node;
+	struct starpu_sched_node * no_perfmodel_node;
+	struct starpu_sched_node * perfmodel_node;
+};
+
+static int perfmodel_select_push_task(struct starpu_sched_node * node, struct starpu_task * task)
+{
+	STARPU_ASSERT(node && node->data && task && starpu_sched_node_is_perfmodel_select(node));
+	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;
+	
+
+	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 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);
+			}
+		}
+	}
+	return data->perfmodel_node->push_task(data->perfmodel_node,task);
+}
+
+int starpu_sched_node_is_perfmodel_select(struct starpu_sched_node * node)
+{
+	return node->push_task == perfmodel_select_push_task;
+}
+
+void perfmodel_select_add_child(struct starpu_sched_node * node, struct starpu_sched_node * child)
+{
+	STARPU_ASSERT(starpu_sched_node_is_perfmodel_select(node));
+	starpu_sched_node_add_child(node, child);
+	struct _starpu_perfmodel_select_data * data = node->data;
+	starpu_sched_node_add_child(data->calibrator_node,child);
+	starpu_sched_node_add_child(data->no_perfmodel_node,child);
+	starpu_sched_node_add_child(data->perfmodel_node, child);
+}
+
+void perfmodel_select_remove_child(struct starpu_sched_node * node, struct starpu_sched_node * child)
+{
+
+	STARPU_ASSERT(starpu_sched_node_is_perfmodel_select(node));
+	starpu_sched_node_remove_child(node, child);
+	struct _starpu_perfmodel_select_data * data = node->data;
+	starpu_sched_node_remove_child(data->calibrator_node,child);
+	starpu_sched_node_remove_child(data->no_perfmodel_node,child);
+	starpu_sched_node_remove_child(data->perfmodel_node, child);
+}
+
+static void perfmodel_select_notify_change_in_workers(struct starpu_sched_node * node)
+{
+	STARPU_ASSERT(starpu_sched_node_is_perfmodel_select(node));
+	struct _starpu_perfmodel_select_data * data = node->data;
+
+	starpu_bitmap_unset_all(data->no_perfmodel_node->workers_in_ctx);
+	starpu_bitmap_unset_all(data->no_perfmodel_node->workers);
+	starpu_bitmap_or(data->no_perfmodel_node->workers_in_ctx, node->workers_in_ctx);
+	starpu_bitmap_or(data->no_perfmodel_node->workers, node->workers);
+	data->no_perfmodel_node->properties = node->properties;
+
+	starpu_bitmap_unset_all(data->perfmodel_node->workers_in_ctx);
+	starpu_bitmap_unset_all(data->perfmodel_node->workers);
+	starpu_bitmap_or(data->perfmodel_node->workers_in_ctx, node->workers_in_ctx);
+	starpu_bitmap_or(data->perfmodel_node->workers, node->workers);
+	data->perfmodel_node->properties = node->properties;
+
+	starpu_bitmap_unset_all(data->calibrator_node->workers_in_ctx);
+	starpu_bitmap_unset_all(data->calibrator_node->workers);
+	starpu_bitmap_or(data->calibrator_node->workers_in_ctx, node->workers_in_ctx);
+	starpu_bitmap_or(data->calibrator_node->workers, node->workers);
+	data->calibrator_node->properties = node->properties;
+}
+
+void perfmodel_select_node_deinit_data(struct starpu_sched_node * node)
+
+{
+	STARPU_ASSERT(node && node->data);
+	struct _starpu_perfmodel_select_data * d = node->data;
+	starpu_sched_node_destroy(d->calibrator_node);
+	starpu_sched_node_destroy(d->no_perfmodel_node);
+	starpu_sched_node_destroy(d->perfmodel_node);
+	free(d);
+}
+
+struct starpu_sched_node * starpu_sched_node_perfmodel_select_create(struct starpu_perfmodel_select_data * params)
+{
+	STARPU_ASSERT(params);
+	STARPU_ASSERT(params->calibrator_node && params->no_perfmodel_node && params->perfmodel_node);
+	struct starpu_sched_node * node = starpu_sched_node_create();
+
+	struct _starpu_perfmodel_select_data * data = malloc(sizeof(*data));
+	data->calibrator_node = params->calibrator_node;
+	data->no_perfmodel_node = params->no_perfmodel_node;
+	data->perfmodel_node = params->perfmodel_node;
+	
+	node->data = data;
+	node->push_task = perfmodel_select_push_task;
+	node->add_child = perfmodel_select_add_child;
+	node->remove_child = perfmodel_select_remove_child;
+	node->deinit_data = perfmodel_select_node_deinit_data;
+	node->notify_change_workers = perfmodel_select_notify_change_in_workers;
+
+	return node;
+}

+ 19 - 6
src/sched_policies/node_prio.c

@@ -115,7 +115,7 @@ static int prio_push_task(struct starpu_sched_node * node, struct starpu_task *
 	struct _starpu_prio_deque * prio = &data->prio;
 	struct _starpu_prio_deque * prio = &data->prio;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	starpu_pthread_mutex_t * mutex = &data->mutex;
 	int ret;
 	int ret;
-
+	
 	STARPU_ASSERT(node->nchilds == 1);
 	STARPU_ASSERT(node->nchilds == 1);
 	struct starpu_sched_node * child = node->childs[0];
 	struct starpu_sched_node * child = node->childs[0];
 	if(starpu_sched_node_is_worker(child))
 	if(starpu_sched_node_is_worker(child))
@@ -135,18 +135,18 @@ static int prio_push_task(struct starpu_sched_node * node, struct starpu_task *
 		if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
 		if((data->ntasks_threshold != 0) && (data->exp_len_threshold != 0.0) && 
 				((prio->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
 				((prio->ntasks >= data->ntasks_threshold) || (exp_len >= data->exp_len_threshold)))
 		{
 		{
-			/*
-			if(task->predicted > data->exp_len_threshold)
+			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 thresold\n",task->predicted,data->exp_len_threshold);
-				data->exp_len_threshold *= 2;
+				_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;
 			ret = 1;
 			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 		}
 		}
 		else
 		else
 		{
 		{
+			starpu_sched_node_prefetch_on_node(node, task);
 			ret = _starpu_prio_deque_push_task(prio,task);
 			ret = _starpu_prio_deque_push_task(prio,task);
 			STARPU_TRACE_SCHED_NODE_PUSH_PRIO(node, prio->ntasks, exp_len);
 			STARPU_TRACE_SCHED_NODE_PUSH_PRIO(node, prio->ntasks, exp_len);
 			if(!isnan(task->predicted))
 			if(!isnan(task->predicted))
@@ -159,6 +159,9 @@ static int prio_push_task(struct starpu_sched_node * node, struct starpu_task *
 			STARPU_ASSERT(!isnan(prio->exp_start));
 			STARPU_ASSERT(!isnan(prio->exp_start));
 			STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 			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);
 			node->avail(node);
 		}
 		}
 	}
 	}
@@ -202,6 +205,9 @@ static int prio_push_back_task(struct starpu_sched_node * node, struct starpu_ta
 		STARPU_ASSERT(!isnan(prio->exp_start));
 		STARPU_ASSERT(!isnan(prio->exp_start));
 		STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 		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);
 		node->avail(node);
 	}
 	}
 	return ret;
 	return ret;
@@ -238,6 +244,8 @@ static struct starpu_task * prio_pop_task(struct starpu_sched_node * node, unsig
 	STARPU_ASSERT(!isnan(prio->exp_start));
 	STARPU_ASSERT(!isnan(prio->exp_start));
 	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 	STARPU_PTHREAD_MUTEX_UNLOCK(mutex);
 
 
+	// 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];
 	struct starpu_sched_node * father = node->fathers[sched_ctx_id];
 	if(father != NULL)
 	if(father != NULL)
 		father->room(father, sched_ctx_id);
 		father->room(father, sched_ctx_id);
@@ -248,6 +256,11 @@ static struct starpu_task * prio_pop_task(struct starpu_sched_node * node, unsig
 	return NULL;
 	return NULL;
 }
 }
 
 
+/* When a room is caught by this function, we try to pop and push
+ * tasks from our local queue as much as possible, until a
+ * 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 void prio_room(struct starpu_sched_node * node, unsigned sched_ctx_id)
 {
 {
 	STARPU_ASSERT(node && starpu_sched_node_is_prio(node));
 	STARPU_ASSERT(node && starpu_sched_node_is_prio(node));

+ 12 - 0
src/sched_policies/node_sched.c

@@ -464,6 +464,10 @@ double starpu_sched_node_transfer_length(struct starpu_sched_node * node, struct
 	return sum / nworkers;
 	return sum / nworkers;
 }
 }
 
 
+/* This function can be called by nodes when they think that a prefetching request can be submitted.
+ * For example, it is currently used by the MCT node to begin the prefetching on accelerators 
+ * on which it pushed tasks as soon as possible.
+ */
 void starpu_sched_node_prefetch_on_node(struct starpu_sched_node * node, struct starpu_task * task)
 void starpu_sched_node_prefetch_on_node(struct starpu_sched_node * node, struct starpu_task * task)
 {
 {
        if (starpu_get_prefetch_flag() && (node->properties >= STARPU_SCHED_NODE_SINGLE_MEMORY_NODE))
        if (starpu_get_prefetch_flag() && (node->properties >= STARPU_SCHED_NODE_SINGLE_MEMORY_NODE))
@@ -474,6 +478,10 @@ void starpu_sched_node_prefetch_on_node(struct starpu_sched_node * node, struct
        }
        }
 }
 }
 
 
+/* The default implementation of the room function is a recursive call to its fathers.
+ * 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)
 void starpu_sched_node_room(struct starpu_sched_node * node, unsigned sched_ctx_id)
 {
 {
 	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
 	STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
@@ -483,6 +491,10 @@ void starpu_sched_node_room(struct starpu_sched_node * node, unsigned sched_ctx_
 		father->room(father, sched_ctx_id);
 		father->room(father, sched_ctx_id);
 }
 }
 
 
+/* An avail call will try to wake up one worker associated to the childs of the
+ * node. It is currenly called by nodes which holds a queue (like fifo and prio
+ * nodes) to signify its childs that a task has been pushed on its local queue.
+ */
 int starpu_sched_node_avail(struct starpu_sched_node * node)
 int starpu_sched_node_avail(struct starpu_sched_node * node)
 {
 {
 	STARPU_ASSERT(node);
 	STARPU_ASSERT(node);

+ 9 - 6
src/sched_policies/tree_eager.c

@@ -17,20 +17,23 @@
 #include <starpu_sched_node.h>
 #include <starpu_sched_node.h>
 #include <starpu_scheduler.h>
 #include <starpu_scheduler.h>
 
 
-
 static void initialize_eager_center_policy(unsigned sched_ctx_id)
 static void initialize_eager_center_policy(unsigned sched_ctx_id)
 {
 {
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
  	t->root = starpu_sched_node_fifo_create(NULL);
  	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);
+
 	unsigned i;
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
 	{
-		struct starpu_sched_node * node = starpu_sched_node_worker_get(i);
-		if(!node)
-			continue;
-		node->fathers[sched_ctx_id] = t->root;
-		t->root->add_child(t->root, node);
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		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_tree_update_workers(t);
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 85 - 0
src/sched_policies/tree_eager_prefetching.c

@@ -0,0 +1,85 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Simon Archipoff
+ *
+ * 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>
+
+#define _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT 4
+#define _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT 1000000000.0
+static unsigned ntasks_threshold = _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT;
+static double exp_len_threshold = _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT;
+
+static void initialize_eager_prefetching_center_policy(unsigned sched_ctx_id)
+{
+	const char *strval_ntasks_threshold = getenv("STARPU_NTASKS_THRESHOLD");
+	if (strval_ntasks_threshold)
+		ntasks_threshold = atof(strval_ntasks_threshold);
+
+	const char *strval_exp_len_threshold = getenv("STARPU_EXP_LEN_THRESHOLD");
+	if (strval_exp_len_threshold)
+		exp_len_threshold = atof(strval_exp_len_threshold);
+
+	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+	struct starpu_sched_tree *t = starpu_sched_tree_create(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);
+
+	struct starpu_fifo_data fifo_data =
+		{
+			.ntasks_threshold = ntasks_threshold,
+			.exp_len_threshold = exp_len_threshold,
+		};
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
+	{
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		STARPU_ASSERT(worker_node);
+
+		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);
+
+		eager_node->add_child(eager_node, fifo_node);
+		starpu_sched_node_set_father(fifo_node, eager_node, sched_ctx_id);
+	}
+	starpu_sched_tree_update_workers(t);
+	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
+}
+
+static void deinitialize_eager_prefetching_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_sched_tree_destroy(tree);
+	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+}
+
+struct starpu_sched_policy _starpu_sched_tree_eager_prefetching_policy =
+{
+	.init_sched = initialize_eager_prefetching_center_policy,
+	.deinit_sched = deinitialize_eager_prefetching_center_policy,
+	.add_workers = starpu_sched_tree_add_workers,
+	.remove_workers = starpu_sched_tree_remove_workers,
+	.push_task = starpu_sched_tree_push_task,
+	.pop_task = starpu_sched_tree_pop_task,
+	.pre_exec_hook = starpu_sched_node_worker_pre_exec_hook,
+	.post_exec_hook = starpu_sched_node_worker_post_exec_hook,
+	.pop_every_task = NULL,
+	.policy_name = "tree-eager-prefetching",
+	.policy_description = "eager with prefetching tree policy"
+};

+ 69 - 23
src/sched_policies/tree_dmda.c

@@ -18,10 +18,22 @@
 #include <starpu_scheduler.h>
 #include <starpu_scheduler.h>
 #include <float.h>
 #include <float.h>
 
 
+/* Alpha, Beta and Gamma are heft-specific values, which allows the
+ * user to set more precisely the weight of each computing value.
+ * Beta, for example, controls the weight of communications between
+ * memories for the computation of the best node to choose. 
+ */
+/* The two thresolds concerns the prio nodes, which contains queues
+ * who can handle the priority of StarPU tasks. You can tune your
+ * scheduling by benching those values and choose which one is the
+ * best for your current application. 
+ * The current value of the ntasks_threshold is the best we found
+ * so far across several types of applications (cholesky, LU, stencil).
+ */
 #define _STARPU_SCHED_ALPHA_DEFAULT 1.0
 #define _STARPU_SCHED_ALPHA_DEFAULT 1.0
 #define _STARPU_SCHED_BETA_DEFAULT 1.0
 #define _STARPU_SCHED_BETA_DEFAULT 1.0
 #define _STARPU_SCHED_GAMMA_DEFAULT 1000.0
 #define _STARPU_SCHED_GAMMA_DEFAULT 1000.0
-#define _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT 150000
+#define _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT 15000000
 #define _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT 1000000000.0
 #define _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT 1000000000.0
 static double alpha = _STARPU_SCHED_ALPHA_DEFAULT;
 static double alpha = _STARPU_SCHED_ALPHA_DEFAULT;
 static double beta = _STARPU_SCHED_BETA_DEFAULT;
 static double beta = _STARPU_SCHED_BETA_DEFAULT;
@@ -56,7 +68,7 @@ static void param_modified(struct starpu_top_param* d)
 }
 }
 #endif /* !STARPU_USE_TOP */
 #endif /* !STARPU_USE_TOP */
 
 
-static void initialize_dmda_center_policy(unsigned sched_ctx_id)
+static void initialize_heft_center_policy(unsigned sched_ctx_id)
 {
 {
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	const char *strval_alpha = getenv("STARPU_SCHED_ALPHA");
 	const char *strval_alpha = getenv("STARPU_SCHED_ALPHA");
@@ -84,23 +96,55 @@ static void initialize_dmda_center_policy(unsigned sched_ctx_id)
 		exp_len_threshold = atof(strval_exp_len_threshold);
 		exp_len_threshold = atof(strval_exp_len_threshold);
 
 
 #ifdef STARPU_USE_TOP
 #ifdef STARPU_USE_TOP
-	starpu_top_register_parameter_float("DMDA_ALPHA", &alpha,
+	starpu_top_register_parameter_float("HEFT_ALPHA", &alpha,
 					    alpha_minimum, alpha_maximum, param_modified);
 					    alpha_minimum, alpha_maximum, param_modified);
-	starpu_top_register_parameter_float("DMDA_BETA", &beta,
+	starpu_top_register_parameter_float("HEFT_BETA", &beta,
 					    beta_minimum, beta_maximum, param_modified);
 					    beta_minimum, beta_maximum, param_modified);
-	starpu_top_register_parameter_float("DMDA_GAMMA", &_gamma,
+	starpu_top_register_parameter_float("HEFT_GAMMA", &_gamma,
 					    gamma_minimum, gamma_maximum, param_modified);
 					    gamma_minimum, gamma_maximum, param_modified);
-	starpu_top_register_parameter_float("DMDA_IDLE_POWER", &idle_power,
+	starpu_top_register_parameter_float("HEFT_IDLE_POWER", &idle_power,
 					    idle_power_minimum, idle_power_maximum, param_modified);
 					    idle_power_minimum, idle_power_maximum, param_modified);
 #endif /* !STARPU_USE_TOP */
 #endif /* !STARPU_USE_TOP */
 
 
 	
 	
+/* The scheduling strategy look like this :
+ *
+ *									  |
+ *								window_node
+ *									  |
+ * perfmodel_node <--push-- perfmodel_select_node --push--> eager_node
+ *			|						   						     |
+ *			|						   						     |
+ *			>----------------------------------------------------<
+ *					  |								|
+ *				best_impl_node					best_impl_node
+ *					  |								|
+ *				  prio_node						prio_node
+ *					  |								|
+ *				 worker_node				   worker_node
+ *
+ * A window contain the tasks that failed to be pushed, so as when the prio_nodes reclaim
+ * tasks by calling room to their father (classically, just after a successful pop have
+ * 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
+ * have been reached for it, or send a push_error signal to its father.
+ */
 	struct starpu_sched_tree * t = starpu_sched_tree_create(sched_ctx_id);
 	struct starpu_sched_tree * t = starpu_sched_tree_create(sched_ctx_id);
 
 
 	struct starpu_sched_node * window_node = starpu_sched_node_prio_create(NULL);
 	struct starpu_sched_node * window_node = starpu_sched_node_prio_create(NULL);
 	t->root = window_node;
 	t->root = window_node;
 
 
-	struct starpu_heft_data heft_data =
+	struct starpu_mct_data mct_data =
 		{
 		{
 			.alpha = alpha,
 			.alpha = alpha,
 			.beta = beta,
 			.beta = beta,
@@ -108,18 +152,20 @@ static void initialize_dmda_center_policy(unsigned sched_ctx_id)
 			.idle_power = idle_power,
 			.idle_power = idle_power,
 		};
 		};
 
 
-	struct starpu_sched_node * heft_node = starpu_sched_node_heft_create(&heft_data);
+	struct starpu_sched_node * perfmodel_node = starpu_sched_node_mct_create(&mct_data);
+	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_calibrator_data calibrator_data =
+	struct starpu_perfmodel_select_data perfmodel_select_data =
 		{
 		{
-			.no_perf_model_node_create = starpu_sched_node_prio_create,
-			.arg_no_perf_model = NULL,
-			.next_node = heft_node,
+			.calibrator_node = calibrator_node,
+			.no_perfmodel_node = no_perfmodel_node,
+			.perfmodel_node = perfmodel_node,
 		};
 		};
 
 
-	struct starpu_sched_node * calibrator_node = starpu_sched_node_calibrator_create(&calibrator_data);
-	window_node->add_child(window_node, calibrator_node);
-	starpu_sched_node_set_father(calibrator_node, window_node, 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);
 
 
 	struct starpu_prio_data prio_data =
 	struct starpu_prio_data prio_data =
 		{
 		{
@@ -141,25 +187,25 @@ static void initialize_dmda_center_policy(unsigned sched_ctx_id)
 		impl_node->add_child(impl_node, prio);
 		impl_node->add_child(impl_node, prio);
 		starpu_sched_node_set_father(prio, impl_node, sched_ctx_id);
 		starpu_sched_node_set_father(prio, impl_node, sched_ctx_id);
 
 
-		calibrator_node->add_child(calibrator_node, impl_node);
-		starpu_sched_node_set_father(impl_node, calibrator_node, sched_ctx_id);
+		perfmodel_select_node->add_child(perfmodel_select_node, impl_node);
+		starpu_sched_node_set_father(impl_node, perfmodel_select_node, sched_ctx_id);
 	}
 	}
 
 
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 }
 }
 
 
-static void deinitialize_dmda_center_policy(unsigned sched_ctx_id)
+static void deinitialize_heft_center_policy(unsigned sched_ctx_id)
 {
 {
 	struct starpu_sched_tree *t = (struct starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	struct starpu_sched_tree *t = (struct starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	starpu_sched_tree_destroy(t);
 	starpu_sched_tree_destroy(t);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 }
 }
 
 
-struct starpu_sched_policy _starpu_sched_tree_dmda_policy =
+struct starpu_sched_policy _starpu_sched_tree_heft_policy =
 {
 {
-	.init_sched = initialize_dmda_center_policy,
-	.deinit_sched = deinitialize_dmda_center_policy,
+	.init_sched = initialize_heft_center_policy,
+	.deinit_sched = deinitialize_heft_center_policy,
 	.add_workers = starpu_sched_tree_add_workers,
 	.add_workers = starpu_sched_tree_add_workers,
 	.remove_workers = starpu_sched_tree_remove_workers,
 	.remove_workers = starpu_sched_tree_remove_workers,
 	.push_task = starpu_sched_tree_push_task,
 	.push_task = starpu_sched_tree_push_task,
@@ -167,6 +213,6 @@ struct starpu_sched_policy _starpu_sched_tree_dmda_policy =
 	.pre_exec_hook = starpu_sched_node_worker_pre_exec_hook,
 	.pre_exec_hook = starpu_sched_node_worker_pre_exec_hook,
 	.post_exec_hook = starpu_sched_node_worker_post_exec_hook,
 	.post_exec_hook = starpu_sched_node_worker_post_exec_hook,
 	.pop_every_task = NULL,
 	.pop_every_task = NULL,
-	.policy_name = "tree-dmda",
-	.policy_description = "dmda tree policy"
+	.policy_name = "tree-heft",
+	.policy_description = "heft tree policy"
 };
 };

+ 9 - 6
src/sched_policies/tree_prio.c

@@ -17,20 +17,23 @@
 #include <starpu_sched_node.h>
 #include <starpu_sched_node.h>
 #include <starpu_scheduler.h>
 #include <starpu_scheduler.h>
 
 
-
 static void initialize_prio_center_policy(unsigned sched_ctx_id)
 static void initialize_prio_center_policy(unsigned sched_ctx_id)
 {
 {
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
  	t->root = starpu_sched_node_prio_create(NULL);
  	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);
+
 	unsigned i;
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
 	{
-		struct starpu_sched_node * node = starpu_sched_node_worker_get(i);
-		if(!node)
-			continue;
-		node->fathers[sched_ctx_id] = t->root;
-		t->root->add_child(t->root, node);
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		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_tree_update_workers(t);
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);

+ 85 - 0
src/sched_policies/tree_prio_prefetching.c

@@ -0,0 +1,85 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Marc Sergent
+ *
+ * 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>
+
+#define _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT 4
+#define _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT 1000000000.0
+static unsigned ntasks_threshold = _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT;
+static double exp_len_threshold = _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT;
+
+static void initialize_prio_prefetching_center_policy(unsigned sched_ctx_id)
+{
+	const char *strval_ntasks_threshold = getenv("STARPU_NTASKS_THRESHOLD");
+	if (strval_ntasks_threshold)
+		ntasks_threshold = atof(strval_ntasks_threshold);
+
+	const char *strval_exp_len_threshold = getenv("STARPU_EXP_LEN_THRESHOLD");
+	if (strval_exp_len_threshold)
+		exp_len_threshold = atof(strval_exp_len_threshold);
+
+	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+	struct starpu_sched_tree *t = starpu_sched_tree_create(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);
+
+	struct starpu_prio_data prio_data =
+		{
+			.ntasks_threshold = ntasks_threshold,
+			.exp_len_threshold = exp_len_threshold,
+		};
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
+	{
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		STARPU_ASSERT(worker_node);
+
+		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);
+
+		eager_node->add_child(eager_node, prio_node);
+		starpu_sched_node_set_father(prio_node, eager_node, sched_ctx_id);
+	}
+	starpu_sched_tree_update_workers(t);
+	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
+}
+
+static void deinitialize_prio_prefetching_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_sched_tree_destroy(tree);
+	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+}
+
+struct starpu_sched_policy _starpu_sched_tree_prio_prefetching_policy =
+{
+	.init_sched = initialize_prio_prefetching_center_policy,
+	.deinit_sched = deinitialize_prio_prefetching_center_policy,
+	.add_workers = starpu_sched_tree_add_workers,
+	.remove_workers = starpu_sched_tree_remove_workers,
+	.push_task = starpu_sched_tree_push_task,
+	.pop_task = starpu_sched_tree_pop_task,
+	.pre_exec_hook = starpu_sched_node_worker_pre_exec_hook,
+	.post_exec_hook = starpu_sched_node_worker_post_exec_hook,
+	.pop_every_task = NULL,
+	.policy_name = "tree-prio-prefetching",
+	.policy_description = "prio prefetching tree policy"
+};

+ 61 - 11
src/sched_policies/tree_random.c

@@ -17,37 +17,41 @@
 #include <starpu_sched_node.h>
 #include <starpu_sched_node.h>
 #include <starpu_scheduler.h>
 #include <starpu_scheduler.h>
 
 
+/* Random scheduler with a fifo queue for its scheduling window */
 
 
-static void initialize_random_center_policy(unsigned sched_ctx_id)
+static void initialize_random_fifo_center_policy(unsigned sched_ctx_id)
 {
 {
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
- 	t->root = starpu_sched_node_random_create(NULL);
+ 	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);
 
 
 	unsigned i;
 	unsigned i;
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
 	{
-		struct starpu_sched_node * node = starpu_sched_node_worker_get(i);
-		if(!node)
-			continue;
-		node->fathers[sched_ctx_id] = t->root;
-		t->root->add_child(t->root, node);
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		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_tree_update_workers(t);
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 }
 }
-static void deinitialize_random_center_policy(unsigned sched_ctx_id)
+
+static void deinitialize_random_fifo_center_policy(unsigned sched_ctx_id)
 {
 {
 	struct starpu_sched_tree *tree = (struct starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	struct starpu_sched_tree *tree = (struct starpu_sched_tree*)starpu_sched_ctx_get_policy_data(sched_ctx_id);
 	starpu_sched_tree_destroy(tree);
 	starpu_sched_tree_destroy(tree);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
 }
 }
 
 
-
 struct starpu_sched_policy _starpu_sched_tree_random_policy =
 struct starpu_sched_policy _starpu_sched_tree_random_policy =
 {
 {
-	.init_sched = initialize_random_center_policy,
-	.deinit_sched = deinitialize_random_center_policy,
+	.init_sched = initialize_random_fifo_center_policy,
+	.deinit_sched = deinitialize_random_fifo_center_policy,
 	.add_workers = starpu_sched_tree_add_workers,
 	.add_workers = starpu_sched_tree_add_workers,
 	.remove_workers = starpu_sched_tree_remove_workers,
 	.remove_workers = starpu_sched_tree_remove_workers,
 	.push_task = starpu_sched_tree_push_task,
 	.push_task = starpu_sched_tree_push_task,
@@ -58,3 +62,49 @@ struct starpu_sched_policy _starpu_sched_tree_random_policy =
 	.policy_name = "tree-random",
 	.policy_name = "tree-random",
 	.policy_description = "random tree policy"
 	.policy_description = "random tree policy"
 };
 };
+
+/* Random scheduler with a priority queue for its scheduling window */
+
+static void initialize_random_prio_center_policy(unsigned sched_ctx_id)
+{
+	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+	struct starpu_sched_tree *t = starpu_sched_tree_create(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);
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
+	{
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		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_tree_update_workers(t);
+	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
+}
+
+static void deinitialize_random_prio_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_sched_tree_destroy(tree);
+	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+}
+
+struct starpu_sched_policy _starpu_sched_tree_random_prio_policy =
+{
+	.init_sched = initialize_random_prio_center_policy,
+	.deinit_sched = deinitialize_random_prio_center_policy,
+	.add_workers = starpu_sched_tree_add_workers,
+	.remove_workers = starpu_sched_tree_remove_workers,
+	.push_task = starpu_sched_tree_push_task,
+	.pop_task = starpu_sched_tree_pop_task,
+	.pre_exec_hook = NULL,
+	.post_exec_hook = NULL,
+	.pop_every_task = NULL,
+	.policy_name = "tree-random-prio",
+	.policy_description = "random-prio tree policy"
+};

+ 151 - 0
src/sched_policies/tree_random_prefetching.c

@@ -0,0 +1,151 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Simon Archipoff
+ *
+ * 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>
+
+#define _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT 4
+#define _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT 1000000000.0
+static unsigned ntasks_threshold = _STARPU_SCHED_NTASKS_THRESHOLD_DEFAULT;
+static double exp_len_threshold = _STARPU_SCHED_EXP_LEN_THRESHOLD_DEFAULT;
+
+/* Random scheduler with fifo queues for its scheduling window and its workers. */
+
+static void initialize_random_fifo_prefetching_center_policy(unsigned sched_ctx_id)
+{
+	const char *strval_ntasks_threshold = getenv("STARPU_NTASKS_THRESHOLD");
+	if (strval_ntasks_threshold)
+		ntasks_threshold = atof(strval_ntasks_threshold);
+
+	const char *strval_exp_len_threshold = getenv("STARPU_EXP_LEN_THRESHOLD");
+	if (strval_exp_len_threshold)
+		exp_len_threshold = atof(strval_exp_len_threshold);
+
+	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+	struct starpu_sched_tree *t = starpu_sched_tree_create(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);
+
+	struct starpu_fifo_data fifo_data =
+		{
+			.ntasks_threshold = ntasks_threshold,
+			.exp_len_threshold = exp_len_threshold,
+		};
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
+	{
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		STARPU_ASSERT(worker_node);
+
+		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);
+
+		random_node->add_child(random_node, fifo_node);
+		starpu_sched_node_set_father(fifo_node, random_node, sched_ctx_id);
+	}
+	starpu_sched_tree_update_workers(t);
+	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
+}
+
+static void deinitialize_random_fifo_prefetching_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_sched_tree_destroy(tree);
+	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+}
+
+struct starpu_sched_policy _starpu_sched_tree_random_prefetching_policy =
+{
+	.init_sched = initialize_random_fifo_prefetching_center_policy,
+	.deinit_sched = deinitialize_random_fifo_prefetching_center_policy,
+	.add_workers = starpu_sched_tree_add_workers,
+	.remove_workers = starpu_sched_tree_remove_workers,
+	.push_task = starpu_sched_tree_push_task,
+	.pop_task = starpu_sched_tree_pop_task,
+	.pre_exec_hook = NULL,
+	.post_exec_hook = NULL,
+	.pop_every_task = NULL,
+	.policy_name = "tree-random-prefetching",
+	.policy_description = "random prefetching tree policy"
+};
+
+/* Random scheduler with priority queues for its scheduling window and its workers. */
+
+static void initialize_random_prio_prefetching_center_policy(unsigned sched_ctx_id)
+{
+	const char *strval_ntasks_threshold = getenv("STARPU_NTASKS_THRESHOLD");
+	if (strval_ntasks_threshold)
+		ntasks_threshold = atof(strval_ntasks_threshold);
+
+	const char *strval_exp_len_threshold = getenv("STARPU_EXP_LEN_THRESHOLD");
+	if (strval_exp_len_threshold)
+		exp_len_threshold = atof(strval_exp_len_threshold);
+
+	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
+	struct starpu_sched_tree *t = starpu_sched_tree_create(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);
+
+	struct starpu_prio_data prio_data =
+		{
+			.ntasks_threshold = ntasks_threshold,
+			.exp_len_threshold = exp_len_threshold,
+		};
+
+	unsigned i;
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
+	{
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		STARPU_ASSERT(worker_node);
+
+		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);
+
+		random_node->add_child(random_node, prio_node);
+		starpu_sched_node_set_father(prio_node, random_node, sched_ctx_id);
+	}
+	starpu_sched_tree_update_workers(t);
+	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
+}
+
+static void deinitialize_random_prio_prefetching_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_sched_tree_destroy(tree);
+	starpu_sched_ctx_delete_worker_collection(sched_ctx_id);
+}
+
+struct starpu_sched_policy _starpu_sched_tree_random_prio_prefetching_policy =
+{
+	.init_sched = initialize_random_prio_prefetching_center_policy,
+	.deinit_sched = deinitialize_random_prio_prefetching_center_policy,
+	.add_workers = starpu_sched_tree_add_workers,
+	.remove_workers = starpu_sched_tree_remove_workers,
+	.push_task = starpu_sched_tree_push_task,
+	.pop_task = starpu_sched_tree_pop_task,
+	.pre_exec_hook = NULL,
+	.post_exec_hook = NULL,
+	.pop_every_task = NULL,
+	.policy_name = "tree-random-prio-prefetching",
+	.policy_description = "random-prio prefetching tree policy"
+};

+ 7 - 9
src/sched_policies/tree_ws.c

@@ -22,17 +22,15 @@ static void initialize_ws_center_policy(unsigned sched_ctx_id)
 {
 {
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	starpu_sched_ctx_create_worker_collection(sched_ctx_id, STARPU_WORKER_LIST);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
 	struct starpu_sched_tree *t = starpu_sched_tree_create(sched_ctx_id);
-	struct starpu_sched_node * ws;
- 	t->root = ws = starpu_sched_node_work_stealing_create(NULL);
-	t->workers = starpu_bitmap_create();
+ 	t->root = starpu_sched_node_work_stealing_create(NULL);
 	unsigned i;
 	unsigned i;
-	for(i = 0; i < starpu_worker_get_count(); i++)
+	for(i = 0; i < starpu_worker_get_count() + starpu_combined_worker_get_count(); i++)
 	{
 	{
-		struct starpu_sched_node * node = starpu_sched_node_worker_get(i);
-		if(!node)
-			continue;
-		node->fathers[sched_ctx_id] = ws;
-		ws->add_child(ws, node);
+		struct starpu_sched_node * worker_node = starpu_sched_node_worker_get(i);
+		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_tree_update_workers(t);
 	starpu_sched_tree_update_workers(t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);
 	starpu_sched_ctx_set_policy_data(sched_ctx_id, (void*)t);