ソースを参照

more doc (that compile properly ;))
give exp_start, exp_len and exp_end the same semantic as in trunk in node_worker
+ various bug fixes

Simon Archipoff 12 年 前
コミット
b2f97b1271

+ 2 - 1
doc/doxygen/Makefile.am

@@ -177,7 +177,8 @@ dox_inputs = $(DOX_CONFIG) 				\
 	$(top_srcdir)/sc_hypervisor/include/sc_hypervisor_config.h 	\
 	$(top_srcdir)/sc_hypervisor/include/sc_hypervisor_lp.h		\
 	$(top_srcdir)/sc_hypervisor/include/sc_hypervisor_monitoring.h	\
-	$(top_srcdir)/sc_hypervisor/include/sc_hypervisor_policy.h
+	$(top_srcdir)/sc_hypervisor/include/sc_hypervisor_policy.h	\
+	$(top_srcdir)/src/sched_policies/node_sched.h
 
 $(DOX_TAG): $(dox_inputs)
 	rm -fr $(DOX_HTML_DIR) $(DOX_LATEX_DIR)

+ 15 - 4
doc/doxygen/chapters/api/modularized_scheduler.doxy

@@ -1,4 +1,4 @@
-/* !\defgroup API_Modularized_Scheduler
+/*! \defgroup API_Modularized_Scheduler Modularized scheduler interface
 
 \struct _starpu_sched_node
 \ingroup API_Modularized_Scheduler
@@ -28,6 +28,8 @@ This structure represent a scheduler module.
 	the array of scheduler module above indexed by scheduling context index
 \var _starpu_sched_node::init_data
 	is called after all the scheduler is created and should init data member
+	you can store things in node->data while calling _sched_node_create(arg)
+	and use it with init_data
 \var _starpu_sched_node::deinit_data
 	is called just before _starpu_sched_node_destroy
 \var _starpu_sched_node::obj
@@ -42,7 +44,7 @@ this structure containt predictions for a task and is filled by _starpu_sched_no
 \var _starpu_task_execute_preds::impl
 	those members are revelant is state is PERF_MODEL or CALIBRATING and is set to best or uncalibrated archtype and implementation, respectively, or suitable values if state is NO_PERF_MODEL
 \var _starpu_task_execute_preds::expected_finish_time
-	expected finish time of worker without task
+	expected finish time of task
 \var _starpu_task_execute_preds::expected_length
 	expected compute time of task
 \var _starpu_task_execute_preds::expected_transfer_length
@@ -60,7 +62,14 @@ this structure containt predictions for a task and is filled by _starpu_sched_no
 	this lock protect the worker member
 
 \fn struct _starpu_sched_node * _starpu_sched_node_create(void)
-    	   return an initialised scheduler module with default values
+
+        allocate and initalise node field with defaults values :
+	.pop_task make recursive call on father
+	.available make a recursive call on childrens
+	.estimated_load compute relative speedup and tasks in subtree
+	.estimated_execute_preds return the average of recursive call on childs
+
+
 \fn void _starpu_sched_node_destroy(struct _starpu_sched_node * node)
     	 free data allocated by _starpu_sched_node_create, but dont call node->deinit_data(node)
 \fn void _starpu_sched_node_set_father(struct _starpu_sched_node * node, struct _starpu_sched_node * father_node, unsigned sched_ctx_id)
@@ -70,4 +79,6 @@ this structure containt predictions for a task and is filled by _starpu_sched_no
 	 and dont modify child->fathers
 \fn void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child)
     	 remove child from node->childs and decrement nchilds
-*/
+
+
+*/

+ 1 - 0
doc/doxygen/doxygen-config.cfg.in

@@ -50,6 +50,7 @@ INPUT                  = @top_srcdir@/doc/doxygen/chapters \
 			 @top_srcdir@/include/starpu_top.h \
 			 @top_srcdir@/include/starpu_util.h \
 			 @top_srcdir@/include/starpu_worker.h \
+			 @top_srcdir@/src/sched_policies/node_sched.h \
 			 @top_srcdir@/mpi/include/ \
 			 @top_srcdir@/starpufft/starpufft.h \
 			 @top_srcdir@/sc_hypervisor/include

+ 2 - 1
src/sched_policies/node_fifo.c

@@ -101,7 +101,6 @@ static int push_task(struct _starpu_sched_node * node, struct starpu_task * task
 	int ret = _starpu_prio_deque_push_task(fifo, task);
 	if(!isnan(task->predicted))
 	{
-//		task->predicted /= _starpu_bitmap_cardinal(node->workers);
 		fifo->exp_len += task->predicted;
 		fifo->exp_end = fifo->exp_start + fifo->exp_len;
 	}
@@ -132,6 +131,8 @@ static struct starpu_task * pop_task(struct _starpu_sched_node * node, unsigned
 		if(!isnan(task->predicted))
 			fifo->exp_len -= task->predicted;
 		fifo->exp_end = fifo->exp_start + fifo->exp_len;
+		if(fifo->ntasks == 0)
+			fifo->exp_len = 0.0;
 	}
 	STARPU_ASSERT(!isnan(fifo->exp_end));
 	STARPU_ASSERT(!isnan(fifo->exp_len));

+ 1 - 1
src/sched_policies/node_sched.c

@@ -18,7 +18,7 @@ double _starpu_compute_expected_time(double now, double predicted_end, double pr
 		predicted_transfer += now;
 		predicted_transfer -= predicted_end;
 	}
-	if(!isnan(predicted_transfer)) 
+	if(!isnan(predicted_transfer))
 	{
 		predicted_end += predicted_transfer;
 		predicted_length += predicted_transfer;

+ 4 - 15
src/sched_policies/node_sched.h

@@ -136,14 +136,7 @@ struct _starpu_sched_tree
 };
 
 
-/* allocate and initalise node field with defaults values :
- *  .pop_task make recursive call on father
- *  .estimated_finish_time  max of the recursives calls on childrens
- *  .estimated_load compute relative speedup and tasks in subtree
- *  .estimated_transfer_length  average transfer cost for all workers in the subtree
- *  .estimated_execution_length average execution cost for all workers in the subtree
- *  .available make a recursive call on childrens
- */
+
 struct _starpu_sched_node * _starpu_sched_node_create(void);
 
 void _starpu_sched_node_destroy(struct _starpu_sched_node * node);
@@ -172,7 +165,7 @@ struct _starpu_sched_node * _starpu_sched_node_fifo_create(void * arg STARPU_ATT
 int _starpu_sched_node_is_fifo(struct _starpu_sched_node * node);
 //struct starpu_task_list  _starpu_sched_node_fifo_get_non_executable_tasks(struct _starpu_sched_node * fifo_node);
 
-/* struct _starpu_sched_node * _starpu_sched_node_work_stealing_create(void); */
+struct _starpu_sched_node * _starpu_sched_node_work_stealing_create(void);
 int _starpu_sched_node_is_work_stealing(struct _starpu_sched_node * node);
 
 struct _starpu_sched_node * _starpu_sched_node_random_create(void * arg STARPU_ATTRIBUTE_UNUSED);
@@ -204,15 +197,13 @@ void _starpu_node_destroy_rec(struct _starpu_sched_node * node, unsigned sched_c
 
 int _starpu_tree_push_task(struct starpu_task * task);
 struct starpu_task * _starpu_tree_pop_task(unsigned sched_ctx_id);
-void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
-void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
-
 void _starpu_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 void _starpu_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
+void _starpu_sched_node_worker_pre_exec_hook(struct starpu_task * task);
+void _starpu_sched_node_worker_post_exec_hook(struct starpu_task * task);
 
 /* return the bitmap of worker that are allowed to use in this scheduling context
  */
-
 struct _starpu_bitmap * _starpu_get_worker_mask(struct starpu_task * task);
 
 /* this function fill all the node->workers member
@@ -229,8 +220,6 @@ int _starpu_sched_node_push_tasks_to_firsts_suitable_parent(struct _starpu_sched
 
 
 
-void _starpu_sched_node_worker_pre_exec_hook(struct starpu_task * task);
-void _starpu_sched_node_worker_post_exec_hook(struct starpu_task * task);
 
 
 

+ 142 - 15
src/sched_policies/node_worker.c

@@ -30,11 +30,13 @@ static struct _starpu_sched_node * _worker_nodes[STARPU_NMAXWORKERS];
  *   P--N--N
  *   |  |  |
  *   W  W  W
-
-
+ *
+ *
  * this API is a little asymmetric : struct _starpu_task_grid are allocated by the caller and freed by the data structure
+ *
  */
 
+
 struct _starpu_task_grid
 {
 	/* this member may be NULL if a worker have poped it but its a
@@ -57,6 +59,11 @@ struct _starpu_task_grid
 	};
 };
 
+
+/* list->exp_start, list->exp_len, list-exp_end and list->ntasks
+ * are updated by _starpu_sched_node_worker_push_task(node, task) and pre_exec_hook
+ */
+
 struct _starpu_worker_task_list
 {
 	double exp_start, exp_len, exp_end;
@@ -112,15 +119,44 @@ static inline void _starpu_worker_task_list_push(struct _starpu_worker_task_list
 	t->up = NULL;
 	l->last = t;
 	l->ntasks++;
-	l->exp_start = starpu_timing_now();
-	if(!isnan(t->task->predicted))
+
+	double predicted = t->task->predicted;
+	double predicted_transfer = t->task->predicted_transfer;
+
+	/* Sometimes workers didn't take the tasks as early as we expected */
+	l->exp_start = STARPU_MAX(l->exp_start, starpu_timing_now());
+	l->exp_end = l->exp_start + l->exp_len;
+
+	if ((starpu_timing_now() + predicted_transfer) < l->exp_end)
+	{
+		/* We may hope that the transfer will be finished by
+		 * the start of the task. */
+		predicted_transfer = 0.0;
+	}
+	else
 	{
-		l->exp_len += t->task->predicted;
-		l->exp_end = l->exp_start + l->exp_end;
+		/* The transfer will not be finished by then, take the
+		 * remainder into account */
+		predicted_transfer = (starpu_timing_now() + predicted_transfer) - l->exp_end;
 	}
+
+	if(!isnan(predicted_transfer))
+	{
+		l->exp_end += predicted_transfer;
+		l->exp_len += predicted_transfer;
+	}
+
+	if(!isnan(predicted))
+	{
+		l->exp_end += predicted;
+		l->exp_len += predicted;
+	}
+
+	t->task->predicted = predicted;
+	t->task->predicted_transfer = predicted_transfer;
 }
 
-//recursively set left and right pointers to NULL
+/* recursively set left and right pointers to NULL */
 static inline void _starpu_task_grid_unset_left_right_member(struct _starpu_task_grid * t)
 {
 	STARPU_ASSERT(t->task == NULL);
@@ -182,6 +218,7 @@ static inline struct starpu_task * _starpu_worker_task_list_pop(struct _starpu_w
 				l->exp_len -= task->predicted;
 				l->exp_end = l->exp_start + l->exp_len;
 			}
+
 			return task;
 		}
 		t = t->up;
@@ -203,10 +240,15 @@ struct _starpu_sched_node * _starpu_sched_node_worker_get(int workerid)
 	if(_worker_nodes[workerid])
 		return _worker_nodes[workerid];
 	else
-		return _worker_nodes[workerid] =
-			(workerid < (int) starpu_worker_get_count() ?
-			 _starpu_sched_node_worker_create:
-			 _starpu_sched_node_combined_worker_create)(workerid);
+	{
+		struct _starpu_sched_node * node;
+		if(workerid < (int) starpu_worker_get_count())
+			node = _starpu_sched_node_worker_create(workerid);
+		else
+			node = _starpu_sched_node_combined_worker_create(workerid);
+		_worker_nodes[workerid] = node;
+		return node;
+	}
 }
 
 struct _starpu_worker * _starpu_sched_node_worker_get_worker(struct _starpu_sched_node * worker_node)
@@ -239,6 +281,13 @@ int _starpu_sched_node_worker_push_task(struct _starpu_sched_node * node, struct
 	struct _starpu_task_grid * t = _starpu_task_grid_create();
 	t->task = task;
 	t->ntasks = 1;
+
+	task->workerid = _starpu_bitmap_first(node->workers);
+	if (starpu_get_prefetch_flag())
+	{
+		unsigned memory_node = starpu_worker_get_memory_node(task->workerid);
+		starpu_prefetch_task_input_on_node(task, memory_node);
+	}
 	STARPU_PTHREAD_MUTEX_LOCK(&data->list->mutex);
 	_starpu_worker_task_list_push(data->list, t);
 	STARPU_PTHREAD_MUTEX_UNLOCK(&data->list->mutex);
@@ -453,7 +502,7 @@ static struct _starpu_task_execute_preds estimated_execute_preds(struct _starpu_
 		if(bundle)
 			preds.expected_power = starpu_task_bundle_expected_power(bundle, preds.archtype, preds.impl);
 		else
-			preds.expected_power = starpu_task_expected_power(task, preds.archtype,preds.impl);
+			preds.expected_power = starpu_task_expected_power(task, preds.archtype, preds.impl);
 	}
 
 	return preds;
@@ -530,6 +579,7 @@ static int _starpu_sched_node_combined_worker_push_task(struct _starpu_sched_nod
 	starpu_parallel_task_barrier_init(task, _starpu_bitmap_first(node->workers));
 	task_alias[0] = _starpu_task_grid_create();
 	task_alias[0]->task = starpu_task_dup(task);
+	task_alias[0]->task->workerid = combined_worker->combined_workerid[0];
 	task_alias[0]->left = NULL;
 	task_alias[0]->ntasks = combined_worker->worker_size;
 	int i;
@@ -537,6 +587,7 @@ static int _starpu_sched_node_combined_worker_push_task(struct _starpu_sched_nod
 	{
 		task_alias[i] = _starpu_task_grid_create();
 		task_alias[i]->task = starpu_task_dup(task);
+		task_alias[i]->task->workerid = combined_worker->combined_workerid[i];
 		task_alias[i]->left = task_alias[i-1];
 		task_alias[i - 1]->right = task_alias[i];
 		task_alias[i]->pntasks = &task_alias[0]->ntasks;
@@ -558,6 +609,7 @@ static int _starpu_sched_node_combined_worker_push_task(struct _starpu_sched_nod
 		i++;
 	}
 	while(i < combined_worker->worker_size);
+	
 	STARPU_PTHREAD_MUTEX_UNLOCK(mutex_to_unlock);
 
 	int workerid = starpu_worker_get_id();
@@ -719,16 +771,91 @@ static struct _starpu_worker_task_list * _worker_get_list(void)
 
 void _starpu_sched_node_worker_pre_exec_hook(struct starpu_task * task)
 {
-/*	if(!isnan(task->predicted))
+	if(!isnan(task->predicted))
 	{
 		struct _starpu_worker_task_list * list = _worker_get_list();
 		STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+		STARPU_ASSERT(list->ntasks != 0);
+		list->ntasks--;
+		if(!task->execute_on_a_specific_worker)
+			list->exp_len = STARPU_MIN(list->exp_len - task->predicted, 0.0);
+
+		list->exp_start = starpu_timing_now() + task->predicted;
+		if(list->ntasks == 0)
+		{
+			list->exp_end = list->exp_start;
+			list->exp_end = 0.0;
+		}
+		else
+			list->exp_end = list->exp_start + list->exp_len;
 		STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
-		
 	}
-*/
 }
 void _starpu_sched_node_worker_post_exec_hook(struct starpu_task * task)
 {
+	if(task->execute_on_a_specific_worker)
+		return;
+	struct _starpu_worker_task_list * list = _worker_get_list();
+	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+	list->exp_start = starpu_timing_now();
+	list->exp_end = list->exp_start + list->exp_len;
+	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
+}
 
+static void _starpu_sched_node_worker_push_task_notify(struct starpu_task *task, int workerid, unsigned sched_ctx_id)
+{
+
+	struct _starpu_sched_node * worker_node = _starpu_sched_node_worker_get(workerid);
+	/* dont work with parallel tasks */
+	if(_starpu_sched_node_is_combined_worker(worker_node))
+	   return;
+
+	struct _starpu_worker_node_data * d = worker_node->data;
+	struct _starpu_worker_task_list * list = d->list;
+	/* Compute the expected penality */
+	enum starpu_perfmodel_archtype perf_arch = starpu_worker_get_perf_archtype(workerid);
+	unsigned memory_node = starpu_worker_get_memory_node(workerid);
+
+	double predicted = starpu_task_expected_length(task, perf_arch,
+						       starpu_task_get_implementation(task));
+
+	double predicted_transfer = starpu_task_expected_data_transfer_time(memory_node, task);
+
+	/* Update the predictions */
+	STARPU_PTHREAD_MUTEX_LOCK(&list->mutex);
+	/* Sometimes workers didn't take the tasks as early as we expected */
+	list->exp_start = STARPU_MAX(list->exp_start, starpu_timing_now());
+	list->exp_end = list->exp_start + list->exp_len;
+
+	/* If there is no prediction available, we consider the task has a null length */
+	if (!isnan(predicted_transfer))
+	{
+		if (starpu_timing_now() + predicted_transfer < list->exp_end)
+		{
+			/* We may hope that the transfer will be finished by
+			 * the start of the task. */
+			predicted_transfer = 0;
+		}
+		else
+		{
+			/* The transfer will not be finished by then, take the
+			 * remainder into account */
+			predicted_transfer = (starpu_timing_now() + predicted_transfer) - list->exp_end;
+		}
+		task->predicted_transfer = predicted_transfer;
+		list->exp_end += predicted_transfer;
+		list->exp_len += predicted_transfer;
+	}
+
+	/* If there is no prediction available, we consider the task has a null length */
+	if (!isnan(predicted))
+	{
+		task->predicted = predicted;
+		list->exp_end += predicted;
+		list->exp_len += predicted;
+	}
+
+	list->ntasks++;
+
+	STARPU_PTHREAD_MUTEX_UNLOCK(&list->mutex);
 }