Przeglądaj źródła

- add testcase for omp api default return values
- plug ICVs stacksize, run_sched, def_sched

Olivier Aumage 11 lat temu
rodzic
commit
0fb6249b1c

+ 26 - 9
src/util/openmp_runtime_support.c

@@ -33,7 +33,7 @@
 #include <ctype.h>
 #include <strings.h>
 
-#define _STARPU_STACKSIZE 2097152
+#define _STARPU_INITIAL_THREAD_STACKSIZE 2097152
 
 static struct starpu_omp_global _global_state;
 static starpu_pthread_key_t omp_thread_key;
@@ -343,7 +343,7 @@ static void starpu_omp_implicit_task_exec(void *buffers[], void *cl_arg)
 		task->starpu_cl_arg = cl_arg;
 		STARPU_ASSERT (task->stack == NULL);
 		/* TODO: use ICV stack size info instead */
-		task->stack = malloc(_STARPU_STACKSIZE);
+		task->stack = malloc(task->stacksize);
 		if (task->stack == NULL)
 			_STARPU_ERROR("memory allocation failed");
 		getcontext(&task->ctx);
@@ -353,7 +353,7 @@ static void starpu_omp_implicit_task_exec(void *buffers[], void *cl_arg)
 		 */
 		task->ctx.uc_link                 = NULL;
 		task->ctx.uc_stack.ss_sp          = task->stack;
-		task->ctx.uc_stack.ss_size        = _STARPU_STACKSIZE;
+		task->ctx.uc_stack.ss_size        = task->stacksize;
 		makecontext(&task->ctx, (void (*) ()) starpu_omp_implicit_task_entry, 1, task);
 	}
 
@@ -403,7 +403,7 @@ static void starpu_omp_explicit_task_exec(void *buffers[], void *cl_arg)
 		task->starpu_cl_arg = cl_arg;
 		STARPU_ASSERT (task->stack == NULL);
 		/* TODO: use ICV stack size info instead */
-		task->stack = malloc(_STARPU_STACKSIZE);
+		task->stack = malloc(task->stacksize);
 		if (task->stack == NULL)
 			_STARPU_ERROR("memory allocation failed");
 		getcontext(&task->ctx);
@@ -413,7 +413,7 @@ static void starpu_omp_explicit_task_exec(void *buffers[], void *cl_arg)
 		 */
 		task->ctx.uc_link                 = NULL;
 		task->ctx.uc_stack.ss_sp          = task->stack;
-		task->ctx.uc_stack.ss_size        = _STARPU_STACKSIZE;
+		task->ctx.uc_stack.ss_size        = task->stacksize;
 		makecontext(&task->ctx, (void (*) ()) starpu_omp_explicit_task_entry, 1, task);
 	}
 	task->state = starpu_omp_task_state_clear;
@@ -516,6 +516,11 @@ static struct starpu_omp_task *create_omp_task_struct(struct starpu_omp_task *pa
 		memset(&task->implicit_task_icvs, 0, sizeof(task->implicit_task_icvs));
 	}
 
+	if (owner_region->level > 0)
+	{
+		task->stacksize = owner_region->owner_device->icvs.stacksize_var;
+	}
+
 	return task;
 }
 
@@ -541,7 +546,7 @@ static void omp_initial_thread_setup(void)
 	initial_thread->current_task = initial_task;
 	/* .owner_region already set in create_omp_thread_struct */
 	/* .initial_thread_stack */
-	initial_thread->initial_thread_stack = malloc(_STARPU_STACKSIZE);
+	initial_thread->initial_thread_stack = malloc(_STARPU_INITIAL_THREAD_STACKSIZE);
 	if (initial_thread->initial_thread_stack == NULL)
 		_STARPU_ERROR("memory allocation failed");
 	/* .ctx */
@@ -551,7 +556,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;
+	initial_thread->ctx.uc_stack.ss_size = _STARPU_INITIAL_THREAD_STACKSIZE;
 	makecontext(&initial_thread->ctx, omp_initial_thread_func, 0);
 	/* .starpu_driver */
 	/*
@@ -620,6 +625,8 @@ static void omp_initial_region_setup(void)
 	_starpu_omp_initial_icv_values->nest_var = 0;
 
 	_global_state.initial_device->icvs.max_active_levels_var = max_active_levels;
+	_global_state.initial_device->icvs.def_sched_var = _starpu_omp_initial_icv_values->def_sched_var;
+	_global_state.initial_device->icvs.def_sched_chunk_var = _starpu_omp_initial_icv_values->def_sched_chunk_var;
 	_global_state.initial_device->icvs.stacksize_var = _starpu_omp_initial_icv_values->stacksize_var;
 	_global_state.initial_device->icvs.wait_policy_var = _starpu_omp_initial_icv_values->wait_policy_var;
 
@@ -1514,7 +1521,12 @@ static inline void _starpu_omp_for_loop(struct starpu_omp_region *parallel_regio
 		unsigned long long nb_iterations, unsigned long long chunk, int schedule, int ordered, unsigned long long *_first_i, unsigned long long *_nb_i)
 {
 	*_nb_i = 0;
-	if (schedule == starpu_omp_sched_runtime)
+	if (schedule == starpu_omp_sched_undefined)
+	{
+		schedule = parallel_region->owner_device->icvs.def_sched_var;
+		chunk = parallel_region->owner_device->icvs.def_sched_chunk_var;
+	}
+	else if (schedule == starpu_omp_sched_runtime)
 	{
 		schedule = parallel_region->icvs.run_sched_var;
 		chunk = parallel_region->icvs.run_sched_chunk_var;
@@ -1523,7 +1535,12 @@ static inline void _starpu_omp_for_loop(struct starpu_omp_region *parallel_regio
 			|| schedule == starpu_omp_sched_dynamic
 			|| schedule == starpu_omp_sched_guided
 			|| schedule == starpu_omp_sched_auto);
-	if (schedule == starpu_omp_sched_static || schedule == starpu_omp_sched_auto)
+	if (schedule == starpu_omp_sched_auto)
+	{
+		schedule = starpu_omp_sched_static;
+		chunk = 0;
+	}
+	if (schedule == starpu_omp_sched_static)
 	{
 		if (chunk > 0)
 		{

+ 5 - 1
src/util/openmp_runtime_support.h

@@ -102,7 +102,8 @@ struct starpu_omp_device_icvs
 	int max_active_levels_var;
 
 	/* loop region icvs */
-	/* unused: int def_sched_var; */
+	int def_sched_var;
+	unsigned long long def_sched_chunk_var;
 
 	/* program execution icvs */
 	int stacksize_var;
@@ -129,6 +130,7 @@ struct starpu_omp_initial_icv_values
 	int run_sched_var;
 	unsigned long long run_sched_chunk_var;
 	int def_sched_var;
+	unsigned long long def_sched_chunk_var;
 	int *bind_var;
 	int stacksize_var;
 	int wait_policy_var;
@@ -234,6 +236,8 @@ LIST_TYPE(starpu_omp_task,
 	 * in case blocking/recursive task operation
 	 */
 	void *stack;
+
+	size_t stacksize;
 )
 
 LIST_TYPE(starpu_omp_thread,

+ 6 - 3
src/util/openmp_runtime_support_environment.c

@@ -23,16 +23,19 @@
 
 #define _STARPU_INITIAL_PLACES_LIST_SIZE      4
 #define _STARPU_INITIAL_PLACE_ITEMS_LIST_SIZE 4
+#define _STARPU_DEFAULT_STACKSIZE 2097152
 
 static struct starpu_omp_initial_icv_values _initial_icv_values =
 {
 	.dyn_var = 0,
 	.nest_var = 0,
 	.nthreads_var = NULL,
-	.run_sched_var = 0,
-	.def_sched_var = 0,
+	.run_sched_var = starpu_omp_sched_static,
+	.run_sched_chunk_var = 0,
+	.def_sched_var = starpu_omp_sched_static,
+	.def_sched_chunk_var = 0,
 	.bind_var = NULL,
-	.stacksize_var = 0,
+	.stacksize_var = _STARPU_DEFAULT_STACKSIZE,
 	.wait_policy_var = 0,
 	.max_active_levels_var = STARPU_OMP_MAX_ACTIVE_LEVELS,
 	.active_levels_var = 0,

+ 2 - 3
src/util/openmp_runtime_support_omp_api.c

@@ -257,9 +257,8 @@ int starpu_omp_get_team_num(void)
 
 int starpu_omp_is_initial_device(void)
 {
-	/* TODO: is_initial_device not supported for now
-	 * assume host device */
-	return 1;
+	const struct starpu_omp_device * const device = _starpu_omp_get_task()->owner_region->owner_device;
+	return device == _starpu_omp_global_state->initial_device;
 }
 
 

+ 4 - 0
tests/Makefile.am

@@ -223,6 +223,7 @@ noinst_PROGRAMS =				\
 	openmp/init_exit_01			\
 	openmp/init_exit_02			\
 	openmp/environment			\
+	openmp/api_01				\
 	openmp/parallel_01			\
 	openmp/parallel_02			\
 	openmp/parallel_03			\
@@ -464,6 +465,9 @@ openmp_init_exit_02_SOURCES = 	\
 openmp_environment_SOURCES = 	\
 	openmp/environment.c
 
+openmp_api_01_SOURCES = 	\
+	openmp/api_01.c
+
 openmp_parallel_01_SOURCES = 	\
 	openmp/parallel_01.c
 

+ 135 - 0
tests/openmp/api_01.c

@@ -0,0 +1,135 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2014  Inria
+ *
+ * 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.h>
+#include "../helper.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(STARPU_OPENMP)
+int main(int argc, char **argv)
+{
+	return STARPU_TEST_SKIPPED;
+}
+#else
+__attribute__((constructor))
+static void omp_constructor(void)
+{
+	int ret;
+	/* we clear the whole OMP environment for this test, to check the
+	 * default behaviour of API functions */
+	unsetenv("OMP_DYNAMIC");
+	unsetenv("OMP_NESTED");
+	unsetenv("OMP_SCHEDULE");
+	unsetenv("OMP_STACKSIZE");
+	unsetenv("OMP_WAIT_POLICY");
+	unsetenv("OMP_THREAD_LIMIT");
+	unsetenv("OMP_MAX_ACTIVE_LEVELS");
+	unsetenv("OMP_CANCELLATION");
+	unsetenv("OMP_DEFAULT_DEVICE");
+	unsetenv("OMP_PROC_BIND");
+	unsetenv("OMP_NUM_THREADS");
+	unsetenv("OMP_PLACES");
+	unsetenv("OMP_DISPLAY_ENV");
+	ret = starpu_omp_init();
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_omp_init");
+}
+
+__attribute__((destructor))
+static void omp_destructor(void)
+{
+	starpu_omp_shutdown();
+}
+
+#define check_omp_func(f,_tv)					\
+{								\
+	const int v = (f());					\
+	const int tv = (_tv);					\
+	printf(#f ": %d (should be %d)\n", v, tv);		\
+	STARPU_ASSERT(v == tv);					\
+}
+
+const char * get_sched_name(int sched_value)
+{
+	const char *sched_name = NULL;
+
+	switch (sched_value)
+	{
+		case starpu_omp_sched_undefined: sched_name = "<undefined>"; break;
+		case starpu_omp_sched_static:    sched_name = "static"; break;
+		case starpu_omp_sched_dynamic:   sched_name = "dynamic"; break;
+		case starpu_omp_sched_guided:    sched_name = "guided"; break;
+		case starpu_omp_sched_auto:      sched_name = "auto"; break;
+		case starpu_omp_sched_runtime:   sched_name = "runtime"; break;
+		default: _STARPU_ERROR("invalid omp schedule value");
+	}
+	return sched_name;
+}
+
+int
+main (int argc, char *argv[])
+{
+	const int nb_cpus = starpu_cpu_worker_get_count();
+
+	check_omp_func(starpu_omp_get_num_threads, 1);
+	check_omp_func(starpu_omp_get_thread_num, 0);
+	/* since OMP_NUM_THREADS is cleared, starpu_omp_get_max_threads() should return nb_cpus */
+	check_omp_func(starpu_omp_get_max_threads, nb_cpus);
+	check_omp_func(starpu_omp_get_num_procs, nb_cpus);
+	check_omp_func(starpu_omp_in_parallel, 0);
+	check_omp_func(starpu_omp_get_dynamic, 0);
+	check_omp_func(starpu_omp_get_nested, 0);
+	check_omp_func(starpu_omp_get_cancellation, 0);
+	{
+		const enum starpu_omp_sched_value target_kind = starpu_omp_sched_static;
+		const int target_modifier = 0;
+		enum starpu_omp_sched_value kind;
+		int modifier;
+		const char *sched_name;
+		const char *target_sched_name;
+		starpu_omp_get_schedule(&kind, &modifier);
+		sched_name = get_sched_name(kind);
+		target_sched_name = get_sched_name(target_kind);
+		printf("starpu_omp_get_schedule: %s,%d (should be %s,%d)\n", sched_name, modifier, target_sched_name, target_modifier);
+		STARPU_ASSERT(kind == target_kind && modifier == target_modifier);
+	}
+	check_omp_func(starpu_omp_get_thread_limit, nb_cpus);
+	check_omp_func(starpu_omp_get_max_active_levels, 1);
+	check_omp_func(starpu_omp_get_level, 0);
+	{
+		const int tv = 0;
+		const int v = starpu_omp_get_ancestor_thread_num(0);
+		printf("starpu_omp_get_ancestor_thread_num(0): %d (should be %d)\n", v, tv);
+		STARPU_ASSERT(v == tv);
+	}
+	{
+		const int tv = 1;
+		const int v = starpu_omp_get_team_size(0);
+		printf("starpu_omp_get_team_size(0): %d (should be %d)\n", v, tv);
+		STARPU_ASSERT(v == tv);
+	}
+	check_omp_func(starpu_omp_get_active_level, 0);
+	check_omp_func(starpu_omp_in_final, 0);
+	check_omp_func(starpu_omp_get_proc_bind, starpu_omp_proc_bind_true);
+	check_omp_func(starpu_omp_get_default_device, 0);
+	/* TODO: support more than one device */
+	check_omp_func(starpu_omp_get_num_devices, 1);
+	check_omp_func(starpu_omp_get_num_teams, 1);
+	check_omp_func(starpu_omp_get_team_num, 0);
+	check_omp_func(starpu_omp_is_initial_device, 1);
+	return 0;
+}
+#endif