Kaynağa Gözat

Add starpu_task_get_task_succs to get the list of children of a given task.

Samuel Thibault 9 yıl önce
ebeveyn
işleme
423d41de04

+ 2 - 0
ChangeLog

@@ -156,6 +156,8 @@ Small features:
   * Add STARPU_NOWHERE to create synchronization tasks with data.
   * Add STARPU_NOWHERE to create synchronization tasks with data.
   * Document how to switch between differents views of the same data.
   * Document how to switch between differents views of the same data.
   * Add STARPU_NAME to specify a task name from a starpu_task_insert call.
   * Add STARPU_NAME to specify a task name from a starpu_task_insert call.
+  * Add starpu_task_get_task_succs to get the list of children of a given
+    task.
 
 
 Changes:
 Changes:
   * Data interfaces (variable, vector, matrix and block) now define
   * Data interfaces (variable, vector, matrix and block) now define

+ 11 - 0
doc/doxygen/chapters/06tasks.doxy

@@ -341,6 +341,17 @@ be executed, and is allowed to read from <c>i</c> to use it e.g. as an
 index. Note that this macro is only avaible when compiling StarPU with
 index. Note that this macro is only avaible when compiling StarPU with
 the compiler <c>gcc</c>.
 the compiler <c>gcc</c>.
 
 
+\section GettingTaskChildren Getting Task Children
+
+It may be interesting to get the list of tasks which depend on a given task,
+notably when using implicit dependencies, since this list is computed by StarPU.
+starpu_task_get_task_succs() provides it. For instance:
+
+\code{.c}
+struct starpu_task *tasks[4];
+ret = starpu_task_get_task_succs(task, sizeof(tasks)/sizeof(*tasks), tasks);
+\endcode
+
 \section ParallelTasks Parallel Tasks
 \section ParallelTasks Parallel Tasks
 
 
 StarPU can leverage existing parallel computation libraries by the means of
 StarPU can leverage existing parallel computation libraries by the means of

+ 10 - 0
doc/doxygen/chapters/api/explicit_dependencies.doxy

@@ -22,6 +22,16 @@ call starpu_task_declare_deps_array() several times on the same task,
 in this case, the dependencies are added. It is possible to have
 in this case, the dependencies are added. It is possible to have
 redundancy in the task dependencies.
 redundancy in the task dependencies.
 
 
+\fn int starpu_task_get_task_succs(struct starpu_task *task, unsigned ndeps, struct starpu_task *task_array[])
+\ingroup API_Explicit_Dependencies
+Fills \p task_array with the list of tasks which are direct children of \p task.
+\p ndeps is the size of \p task_array.  This function returns the number of
+direct children. \p task_array can be set to NULL if \p ndeps is 0, which allows
+to compute the number of children before allocating an array to store them.
+This function can only be called if \p task has not completed yet, otherwise
+the results are undefined. The result may also be outdated if some additional
+dependency has been added in the meanwhile.
+
 \typedef starpu_tag_t
 \typedef starpu_tag_t
 \ingroup API_Explicit_Dependencies
 \ingroup API_Explicit_Dependencies
 This type defines a task logical identifer. It is possible to
 This type defines a task logical identifer. It is possible to

+ 2 - 0
include/starpu_task.h

@@ -264,6 +264,8 @@ void starpu_tag_declare_deps_array(starpu_tag_t id, unsigned ndeps, starpu_tag_t
 
 
 void starpu_task_declare_deps_array(struct starpu_task *task, unsigned ndeps, struct starpu_task *task_array[]);
 void starpu_task_declare_deps_array(struct starpu_task *task, unsigned ndeps, struct starpu_task *task_array[]);
 
 
+int starpu_task_get_task_succs(struct starpu_task *task, unsigned ndeps, struct starpu_task *task_array[]);
+
 int starpu_tag_wait(starpu_tag_t id);
 int starpu_tag_wait(starpu_tag_t id);
 int starpu_tag_wait_array(unsigned ntags, starpu_tag_t *id);
 int starpu_tag_wait_array(unsigned ntags, starpu_tag_t *id);
 
 

+ 40 - 0
src/core/dependencies/cg.c

@@ -94,6 +94,46 @@ int _starpu_add_successor_to_cg_list(struct _starpu_cg_list *successors, struct
 	return ret;
 	return ret;
 }
 }
 
 
+int _starpu_list_task_successors_in_cg_list(struct _starpu_cg_list *successors, unsigned ndeps, struct starpu_task *task_array[])
+{
+	unsigned i;
+	unsigned n = 0;
+	_starpu_spin_lock(&successors->lock);
+	for (i = 0; i < successors->nsuccs; i++)
+	{
+		struct _starpu_cg *cg = successors->succ[i];
+		if (cg->cg_type != STARPU_CG_TASK)
+			continue;
+		if (n < ndeps)
+		{
+			task_array[n] = cg->succ.job->task;
+			n++;
+		}
+	}
+	_starpu_spin_unlock(&successors->lock);
+	return n;
+}
+
+int _starpu_list_tag_successors_in_cg_list(struct _starpu_cg_list *successors, unsigned ndeps, starpu_tag_t tag_array[])
+{
+	unsigned i;
+	unsigned n = 0;
+	_starpu_spin_lock(&successors->lock);
+	for (i = 0; i < successors->nsuccs; i++)
+	{
+		struct _starpu_cg *cg = successors->succ[i];
+		if (cg->cg_type != STARPU_CG_TAG)
+			continue;
+		if (n < ndeps)
+		{
+			tag_array[n] = cg->succ.tag->id;
+			n++;
+		}
+	}
+	_starpu_spin_unlock(&successors->lock);
+	return n;
+}
+
 /* Note: in case of a tag, it must be already locked */
 /* Note: in case of a tag, it must be already locked */
 void _starpu_notify_cg(struct _starpu_cg *cg)
 void _starpu_notify_cg(struct _starpu_cg *cg)
 {
 {

+ 3 - 1
src/core/dependencies/cg.h

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
  *
- * Copyright (C) 2010, 2012-2013  Université de Bordeaux
+ * Copyright (C) 2010, 2012-2013, 2015  Université de Bordeaux
  * Copyright (C) 2010, 2011, 2013  CNRS
  * Copyright (C) 2010, 2011, 2013  CNRS
  *
  *
  * StarPU is free software; you can redistribute it and/or modify
  * StarPU is free software; you can redistribute it and/or modify
@@ -99,6 +99,8 @@ struct _starpu_cg
 void _starpu_cg_list_init(struct _starpu_cg_list *list);
 void _starpu_cg_list_init(struct _starpu_cg_list *list);
 void _starpu_cg_list_deinit(struct _starpu_cg_list *list);
 void _starpu_cg_list_deinit(struct _starpu_cg_list *list);
 int _starpu_add_successor_to_cg_list(struct _starpu_cg_list *successors, struct _starpu_cg *cg);
 int _starpu_add_successor_to_cg_list(struct _starpu_cg_list *successors, struct _starpu_cg *cg);
+int _starpu_list_task_successors_in_cg_list(struct _starpu_cg_list *successors, unsigned ndeps, struct starpu_task *task_array[]);
+int _starpu_list_tag_successors_in_cg_list(struct _starpu_cg_list *successors, unsigned ndeps, starpu_tag_t tag_array[]);
 void _starpu_notify_cg(struct _starpu_cg *cg);
 void _starpu_notify_cg(struct _starpu_cg *cg);
 void _starpu_notify_cg_list(struct _starpu_cg_list *successors);
 void _starpu_notify_cg_list(struct _starpu_cg_list *successors);
 void _starpu_notify_task_dependencies(struct _starpu_job *j);
 void _starpu_notify_task_dependencies(struct _starpu_job *j);

+ 7 - 1
src/core/dependencies/task_deps.c

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
  *
- * Copyright (C) 2010-2014  Université de Bordeaux
+ * Copyright (C) 2010-2015  Université de Bordeaux
  * Copyright (C) 2010, 2011, 2012, 2013, 2015  CNRS
  * Copyright (C) 2010, 2011, 2012, 2013, 2015  CNRS
  * Copyright (C) 2014  INRIA
  * Copyright (C) 2014  INRIA
  *
  *
@@ -129,3 +129,9 @@ void starpu_task_declare_deps_array(struct starpu_task *task, unsigned ndeps, st
 {
 {
 	_starpu_task_declare_deps_array(task, ndeps, task_array, 1);
 	_starpu_task_declare_deps_array(task, ndeps, task_array, 1);
 }
 }
+
+int starpu_task_get_task_succs(struct starpu_task *task, unsigned ndeps, struct starpu_task *task_array[])
+{
+	struct _starpu_job *j = _starpu_get_job_associated_to_task(task);
+	return _starpu_list_task_successors_in_cg_list(&j->job_successors, ndeps, task_array);
+}

+ 1 - 0
tests/Makefile.am

@@ -149,6 +149,7 @@ noinst_PROGRAMS =				\
 	main/pause_resume			\
 	main/pause_resume			\
 	main/codelet_null_callback		\
 	main/codelet_null_callback		\
 	main/pack				\
 	main/pack				\
+	main/get_children_tasks			\
 	datawizard/allocate			\
 	datawizard/allocate			\
 	datawizard/acquire_cb			\
 	datawizard/acquire_cb			\
 	datawizard/acquire_cb_insert		\
 	datawizard/acquire_cb_insert		\

+ 79 - 0
tests/main/get_children_tasks.c

@@ -0,0 +1,79 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2015  Université Bordeaux
+ *
+ * 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 <config.h>
+#include <starpu.h>
+#include "../helper.h"
+
+void func_cpu(void *descr[], void *_args)
+{
+}
+
+struct starpu_codelet codelet_w =
+{
+	.modes = { STARPU_W },
+	.cpu_funcs = {func_cpu},
+	.cpu_funcs_name = {"func_cpu"},
+        .nbuffers = 1
+};
+
+struct starpu_codelet codelet_r =
+{
+	.modes = { STARPU_R },
+	.cpu_funcs = {func_cpu},
+	.cpu_funcs_name = {"func_cpu"},
+        .nbuffers = 1
+};
+
+int main(int argc, char **argv)
+{
+        int ret;
+	starpu_data_handle_t h;
+
+	ret = starpu_init(NULL);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	starpu_void_data_register(&h);
+
+	struct starpu_task *task1 = starpu_task_build(&codelet_w, STARPU_W, h, STARPU_TAG, (starpu_tag_t) 0, 0);
+	struct starpu_task *task2 = starpu_task_build(&codelet_r, STARPU_R, h, 0);
+	struct starpu_task *task3 = starpu_task_build(&codelet_r, STARPU_R, h, 0);
+	ret = starpu_task_submit(task1);
+	if (ret == -ENODEV) goto enodev;
+	ret = starpu_task_submit(task2);
+	if (ret == -ENODEV) goto enodev;
+	ret = starpu_task_submit(task3);
+	if (ret == -ENODEV) goto enodev;
+
+	struct starpu_task *tasks[4];
+
+	ret = starpu_task_get_task_succs(task1, sizeof(tasks)/sizeof(*tasks), tasks);
+	STARPU_ASSERT(ret == 2);
+	STARPU_ASSERT(tasks[0] == task2 || tasks[1] == task2);
+	STARPU_ASSERT(tasks[0] == task3 || tasks[1] == task3);
+
+	starpu_shutdown();
+
+	STARPU_RETURN(ret?0:1);
+
+enodev:
+	starpu_shutdown();
+	fprintf(stderr, "WARNING: No one can execute this task\n");
+	/* yes, we do not perform the computation but we did detect that no one
+ 	 * could perform the kernel, so this is not an error from StarPU */
+	return STARPU_TEST_SKIPPED;
+}