Browse Source

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

Samuel Thibault 9 years ago
parent
commit
423d41de04

+ 2 - 0
ChangeLog

@@ -156,6 +156,8 @@ Small features:
   * Add STARPU_NOWHERE to create synchronization tasks with 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_task_get_task_succs to get the list of children of a given
+    task.
 
 Changes:
   * 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
 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
 
 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
 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
 \ingroup API_Explicit_Dependencies
 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[]);
 
+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_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;
 }
 
+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 */
 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.
  *
- * Copyright (C) 2010, 2012-2013  Université de Bordeaux
+ * Copyright (C) 2010, 2012-2013, 2015  Université de Bordeaux
  * Copyright (C) 2010, 2011, 2013  CNRS
  *
  * 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_deinit(struct _starpu_cg_list *list);
 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_list(struct _starpu_cg_list *successors);
 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.
  *
- * Copyright (C) 2010-2014  Université de Bordeaux
+ * Copyright (C) 2010-2015  Université de Bordeaux
  * Copyright (C) 2010, 2011, 2012, 2013, 2015  CNRS
  * 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);
 }
+
+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/codelet_null_callback		\
 	main/pack				\
+	main/get_children_tasks			\
 	datawizard/allocate			\
 	datawizard/acquire_cb			\
 	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;
+}