Bladeren bron

- handle initial nested region completion

Olivier Aumage 11 jaren geleden
bovenliggende
commit
3a6e11b994
6 gewijzigde bestanden met toevoegingen van 68 en 7 verwijderingen
  1. 9 0
      src/core/jobs.c
  2. 5 0
      src/core/jobs.h
  3. 27 0
      src/core/task.c
  4. 6 0
      src/core/task.h
  5. 17 7
      src/util/openmp_runtime_support.c
  6. 4 0
      src/util/openmp_runtime_support.h

+ 9 - 0
src/core/jobs.c

@@ -139,6 +139,15 @@ void _starpu_wait_job(struct _starpu_job *j)
         _STARPU_LOG_OUT();
 }
 
+#ifdef STARPU_OPENMP
+int _starpu_test_job_termination(struct _starpu_job *j)
+{
+	STARPU_ASSERT(j->task);
+	STARPU_ASSERT(!j->task->detach);
+	return (j->terminated == 2);
+}
+#endif
+
 void _starpu_handle_job_termination(struct _starpu_job *j)
 {
 	struct starpu_task *task = j->task;

+ 5 - 0
src/core/jobs.h

@@ -154,6 +154,11 @@ void _starpu_job_destroy(struct _starpu_job *j);
 /* Wait for the termination of the job */
 void _starpu_wait_job(struct _starpu_job *j);
 
+#ifdef STARPU_OPENMP
+/* Test for the termination of the job */
+int _starpu_test_job_termination(struct _starpu_job *j);
+#endif
+
 /* Specify that the task should not appear in the DAG generated by debug tools. */
 void _starpu_exclude_task_from_dag(struct starpu_task *task);
 

+ 27 - 0
src/core/task.c

@@ -215,6 +215,33 @@ int starpu_task_wait(struct starpu_task *task)
 	return 0;
 }
 
+#ifdef STARPU_OPENMP
+int _starpu_task_test_termination(struct starpu_task *task)
+{
+	STARPU_ASSERT(task);
+	STARPU_ASSERT_MSG(!task->detach, "starpu_task_wait can only be called on tasks with detach = 0");
+
+	if (task->detach || task->synchronous)
+	{
+		_STARPU_DEBUG("Task is detached or synchronous\n");
+		_STARPU_LOG_OUT_TAG("einval");
+		return -EINVAL;
+	}
+
+	struct _starpu_job *j = (struct _starpu_job *)task->starpu_private;
+
+	int ret = _starpu_test_job_termination(j);
+
+	if (ret)
+	{
+		if (task->destroy)
+			_starpu_task_destroy(task);
+	}
+
+	return ret;
+}
+#endif
+
 struct _starpu_job *_starpu_get_job_associated_to_task(struct starpu_task *task)
 {
 	STARPU_ASSERT(task);

+ 6 - 0
src/core/task.h

@@ -26,6 +26,12 @@
 /* Internal version of starpu_task_destroy: don't check task->destroy flag */
 void _starpu_task_destroy(struct starpu_task *task);
 
+#ifdef STARPU_OPENMP
+/* Test for the termination of the task.
+ * Call starpu_task_destroy if required and the task is terminated. */
+int _starpu_task_test_termination(struct starpu_task *task);
+#endif
+
 /* A pthread key is used to store the task currently executed on the thread.
  * _starpu_initialize_current_task_key initializes this pthread key and
  * _starpu_set_current_task updates its current value. */

+ 17 - 7
src/util/openmp_runtime_support.c

@@ -57,6 +57,7 @@ static struct starpu_omp_region *create_omp_region_struct(struct starpu_omp_regi
 		_STARPU_ERROR("memory allocation failed");
 
 	region->parent_region = parent_region;
+	region->initial_nested_region = NULL;
 	region->owner_device = owner_device;
 	region->thread_list = starpu_omp_thread_list_new();
 	region->implicit_task_list = starpu_omp_task_list_new();
@@ -66,17 +67,24 @@ static struct starpu_omp_region *create_omp_region_struct(struct starpu_omp_regi
 	return region;
 }
 
-static void omp_initial_thread_func(struct starpu_omp_thread *init_thread, struct starpu_omp_task *init_task)
+static void omp_initial_thread_func(void)
 {
+	struct starpu_omp_region *init_region = _global_state.initial_region;
+	struct starpu_omp_thread *init_thread = _global_state.initial_thread;
+	struct starpu_omp_task *init_task = _global_state.initial_task;
+	struct starpu_task *continuation_task = init_region->initial_nested_region->continuation_starpu_task;
 	while (1)
 	{
 		starpu_driver_run_once(&init_thread->starpu_driver);
 
-		/* TODO: check if we are leaving the first nested region or not
-		 *
+		/*
 		 * if we are leaving the first nested region we give control back to initial task
-		 * otherwise, we should continue to execute work */
-		swapcontext(&init_thread->ctx, &init_task->ctx);
+		 * otherwise, we should continue to execute work
+		 */
+		if (_starpu_task_test_termination(continuation_task))
+		{
+			swapcontext(&init_thread->ctx, &init_task->ctx);
+		}
 	}
 }
 
@@ -102,7 +110,7 @@ static void omp_initial_thread_setup(void)
 	initial_thread->ctx.uc_link          = NULL;
 	initial_thread->ctx.uc_stack.ss_sp   = initial_thread->initial_thread_stack;
 	initial_thread->ctx.uc_stack.ss_size = _STARPU_STACKSIZE;
-	makecontext(&initial_thread->ctx, omp_initial_thread_func, 2, initial_thread, initial_task);
+	makecontext(&initial_thread->ctx, omp_initial_thread_func, 0);
 	/* .starpu_driver */
 	/*
 	 * we configure starpu to not launch CPU worker 0
@@ -301,7 +309,7 @@ static struct starpu_omp_task *create_omp_task_struct(struct starpu_omp_task *pa
 		task->ctx.uc_link                 = NULL;
 		task->ctx.uc_stack.ss_sp          = task->stack;
 		task->ctx.uc_stack.ss_size        = _STARPU_STACKSIZE;
-		makecontext(&task->ctx, starpu_omp_task_entry, 1, task);
+		makecontext(&task->ctx, (void (*) ()) starpu_omp_task_entry, 1, task);
 	}
 
 	return task;
@@ -381,6 +389,8 @@ void starpu_parallel_region(struct starpu_codelet *parallel_region_cl, void *par
 
 		/* in that case, the continuation starpu task is only used for synchronisation */
 		new_region->continuation_starpu_task->cl = NULL;
+		parent_region->initial_nested_region = new_region;
+
 	}
 	else
 	{

+ 4 - 0
src/util/openmp_runtime_support.h

@@ -27,7 +27,9 @@
  * 
  * TODO: add detection in configure.ac
  */
+#ifndef _XOPEN_SOURCE
 #define _XOPEN_SOURCE
+#endif
 #include <ucontext.h>
 
 /*
@@ -224,6 +226,8 @@ LIST_TYPE(starpu_omp_thread,
 struct starpu_omp_region
 {
 	struct starpu_omp_region *parent_region;
+	/* the first nested region of the initial region */
+	struct starpu_omp_region *initial_nested_region;
 	struct starpu_omp_device *owner_device;
 	/* note: the list of threads include the master_thread as first element */
 	struct starpu_omp_thread_list *thread_list;