Ver código fonte

Interface tests : API changes.

* Asking for a pointer to a handle rather than a pointer to a function that returns a handle
* Returning a "summary" that can easily be parsed in order to know what went wrong
* Code cleanup
* Better error messages
Cyril Roelandt 13 anos atrás
pai
commit
390585c990

+ 10 - 6
tests/Makefile.am

@@ -149,7 +149,7 @@ noinst_PROGRAMS =				\
 	datawizard/increment_redux_v2		\
 	datawizard/handle_to_pointer		\
 	datawizard/lazy_allocation		\
-	datawizard/interfaces/test_interfaces   \
+	datawizard/interfaces/test_vector_interface   \
 	errorcheck/starpu_init_noworker		\
 	errorcheck/invalid_blocking_calls	\
 	errorcheck/invalid_tasks		\
@@ -250,17 +250,21 @@ BUILT_SOURCES += 						\
 	microbenchs/null_kernel_gordon.spuelf
 endif
 
-datawizard_interfaces_test_interfaces_SOURCES =               \
-	datawizard/interfaces/test_interfaces.c     \
-	datawizard/interfaces/test_vector_interface.c
+
+##############
+# Interfaces #
+##############
+datawizard_interfaces_test_vector_interface_SOURCES =               \
+	datawizard/interfaces/test_vector_interface.c               \
+	datawizard/interfaces/test_interfaces.c
 
 if STARPU_USE_CUDA
-datawizard_interfaces_test_interfaces_SOURCES +=                \
+datawizard_interfaces_test_vector_interface_SOURCES +=               \
 	datawizard/interfaces/test_vector_cuda.cu
 endif
 
 if STARPU_USE_OPENCL
-datawizard_interfaces_test_interfaces_SOURCES +=                           \
+datawizard_interfaces_test_vector_interface_SOURCES +=               \
 	datawizard/interfaces/test_vector_opencl.c 
 nobase_STARPU_OPENCL_DATA_DATA += \
 	datawizard/interfaces/test_vector_opencl_kernel.cl

+ 174 - 110
tests/datawizard/interfaces/test_interfaces.c

@@ -18,25 +18,135 @@
 #include <starpu_opencl.h>
 #endif
 
+#include <assert.h>
+
 #include "test_interfaces.h"
 
+/*
+ * This is definitely note thrad-safe.
+ */
+static struct test_config *current_config;
+
 /* TODO :
 - OpenCL to OpenCL support
 - RAM to RAM ?
 - Asynchronous vs synchronous
 - Better error messages
-- call starpu_data_unregister
 */
 
-/* Interfaces to test */
-extern struct test_config vector_config;
+/*
+ * Users do not know about this enum. They only know that SUCCESS is 0, and
+ * FAILURE is 1. Therefore, the values of SUCCESS and FAILURE shall not be
+ * changed.
+ */
+enum exit_code {
+	SUCCESS                 = 0,
+	FAILURE                 = 1,
+	UNTESTED                = 2,
+	TASK_CREATION_FAILURE   = 3,
+	TASK_SUBMISSION_FAILURE = 4
+};
 
-static struct test_config *tests[] = {
-	&vector_config,
-	NULL
+static char *
+enum_to_string(exit_code)
+{
+	switch (exit_code)
+	{
+		case SUCCESS:
+			return "Success";
+		case FAILURE:
+			return "Failure";
+		case UNTESTED:
+			return "Untested";
+		case TASK_CREATION_FAILURE:
+			return "Task creation failed";
+		case TASK_SUBMISSION_FAILURE:
+			return "Task submission failed";
+		default:
+			assert(0);
+	}
+}
+
+struct data_interface_test_summary {
+	int success;
+#ifdef STARPU_USE_CUDA
+	int cpu_to_cuda_async;
+	int cuda_to_cpu_async;
+	int cuda_to_cuda_async;
+#endif
+#ifdef STARPU_USE_OPENCL
+	int cpu_to_opencl_async;
+	int opencl_to_cpu_async;
+#endif
+};
+
+void data_interface_test_summary_print(FILE *f,
+				       struct data_interface_test_summary *s)
+{
+	if (!f)
+		f = stderr;
+
+	(void) fprintf(f, "%s : %s\n",
+			current_config->name, enum_to_string(s->success));
+
+	(void) fprintf(f, "Details :\n");
+	(void) fprintf(f, "\tCPU    -> CUDA   : %s\n",
+			enum_to_string(s->cpu_to_cuda_async));
+	(void) fprintf(f, "\tCUDA   -> CUDA   : %s\n",
+			enum_to_string(s->cuda_to_cuda_async));
+	(void) fprintf(f, "\tCUDA   -> CPU    : %s\n",
+			enum_to_string(s->cuda_to_cpu_async));
+	(void) fprintf(f, "\tCPU    -> OpenCl : %s\n",
+			enum_to_string(s->cpu_to_opencl_async));
+	(void) fprintf(f, "\tOpenCl -< CPU    : %s\n",
+			enum_to_string(s->opencl_to_cpu_async));
+}
+
+int
+data_interface_test_summary_success(data_interface_test_summary *s)
+{
+	return s->success;
+}
+
+static void
+set_field(struct data_interface_test_summary *s, int *test, int ret)
+{
+	switch (ret)
+	{
+		case SUCCESS:
+			*test = SUCCESS;
+			break;
+		case FAILURE:
+			*test = FAILURE;
+			s->success = FAILURE;
+			break;
+		case UNTESTED:
+			*test = UNTESTED;
+			break;
+		case TASK_CREATION_FAILURE:
+			*test = TASK_CREATION_FAILURE;
+			break;
+		case TASK_SUBMISSION_FAILURE:
+			*test = TASK_SUBMISSION_FAILURE;
+			break;
+		default:
+			assert(0);
+	}
+}
+
+static struct data_interface_test_summary summary = {
+#ifdef STARPU_USE_CUDA
+	.cpu_to_cuda_async     = UNTESTED,
+	.cuda_to_cpu_async     = UNTESTED,
+	.cuda_to_cuda_async    = UNTESTED,
+#endif
+#ifdef STARPU_USE_OPENCL
+	.cpu_to_opencl_async   = UNTESTED,
+	.opencl_to_cpu_async   = UNTESTED,
+#endif
+	.success               = SUCCESS
 };
 
-static struct test_config *current_config;
 
 /*
  * This variable has to be either -1 or 1.
@@ -134,6 +244,7 @@ create_task(struct starpu_task **taskp, enum starpu_archtype type, int id)
 			cl.opencl_func = current_config->opencl_func;
 			break;
 #endif /* ! STARPU_USE_OPENCL */
+		case STARPU_GORDON_WORKER: /* Not supported */
 		default:
 			return -ENODEV;
 	}
@@ -142,7 +253,7 @@ create_task(struct starpu_task **taskp, enum starpu_archtype type, int id)
 	struct starpu_task *task = starpu_task_create();
 	task->synchronous = 1;
 	task->cl = &cl;
-	task->buffers[0].handle = current_config->register_func();
+	task->buffers[0].handle = *current_config->handle;
 	task->buffers[0].mode = STARPU_RW;
 	if (id != -1)
 	{
@@ -165,7 +276,7 @@ create_task(struct starpu_task **taskp, enum starpu_archtype type, int id)
  * need to set the execute_on_a_specific_worker field...
  */
 #ifdef STARPU_USE_CUDA
-static int
+static enum exit_code
 ram_to_cuda(void)
 {
 	int err;
@@ -173,23 +284,18 @@ ram_to_cuda(void)
 
 	err = create_task(&task, STARPU_CUDA_WORKER, 0);
 	if (err != 0)
-	{
-		fprintf(stderr, "Could not create task\n");
-		return 1;
-	}
+		return TASK_CREATION_FAILURE;
 
 	err = starpu_task_submit(task);
 	if (err != 0)
-	{
-		fprintf(stderr, "Fail : %s\n", strerror(-err));
-		return 1;
-	}
+		return TASK_SUBMISSION_FAILURE;
 
 	fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
 	return current_config->copy_failed;
 }
 
-static int
+#if HAVE_CUDA_MEMCPY_PEER
+static enum exit_code
 cuda_to_cuda(void)
 {
 	int err;
@@ -197,21 +303,18 @@ cuda_to_cuda(void)
 
 	err = create_task(&task, STARPU_CUDA_WORKER, 1);
 	if (err != 0)
-	{
-		return 1;
-	}
+		return TASK_CREATION_FAILURE;
 
 	err = starpu_task_submit(task);
 	if (err != 0)
-	{
-		return 1;
-	}
+		return TASK_SUBMISSION_FAILURE;
 
 	fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
 	return current_config->copy_failed;
 }
+#endif
 
-static int
+static enum exit_code
 cuda_to_ram(void)
 {
 	int err;
@@ -219,17 +322,11 @@ cuda_to_ram(void)
 
 	err = create_task(&task, STARPU_CPU_WORKER, -1);
 	if (err != 0)
-	{
-		fprintf(stderr, "Could not create the task\n");
-		return 1;
-	}
+		return TASK_CREATION_FAILURE;
 
 	err = starpu_task_submit(task);
 	if (err != 0)
-	{
-		fprintf(stderr, "Fail : %s\n", strerror(-err));
-		return 1;
-	}
+		return TASK_SUBMISSION_FAILURE;
 
 	fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
 	return current_config->copy_failed;
@@ -237,7 +334,7 @@ cuda_to_ram(void)
 #endif /* !STARPU_USE_CUDA */
 
 #ifdef STARPU_USE_OPENCL
-static int
+static enum exit_code
 ram_to_opencl()
 {
 	int err;
@@ -245,23 +342,17 @@ ram_to_opencl()
 
 	err = create_task(&task, STARPU_OPENCL_WORKER, 0);
 	if (err != 0)
-	{
-		fprintf(stderr, "Could not create the task\n");
-		return 1;
-	}
+		return TASK_CREATION_FAILURE;
 
 	err = starpu_task_submit(task);
 	if (err != 0)
-	{
-		fprintf(stderr, "Fail : %s\n", strerror(-err));
-		return 1;
-	}
+		return TASK_SUBMISSION_FAILURE;
 
 	fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
 	return current_config->copy_failed;
 }
 
-static int
+static enum exit_code
 opencl_to_ram()
 {
 	int err;
@@ -269,17 +360,11 @@ opencl_to_ram()
 
 	err = create_task(&task, STARPU_CPU_WORKER, -1);
 	if (err != 0)
-	{
-		fprintf(stderr, "Could not create the task\n");
-		return 1;
-	}
+		return TASK_CREATION_FAILURE;
 
 	err = starpu_task_submit(task);
 	if (err != 0)
-	{
-		fprintf(stderr, "Fail : %s\n", strerror(-err));
-		return 1;
-	}
+		return TASK_SUBMISSION_FAILURE;
 
 	fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
 	return current_config->copy_failed;
@@ -287,54 +372,54 @@ opencl_to_ram()
 #endif /* !STARPU_USE_OPENCL */
 /* End of the <device1>_to_<device2> functions. */
 
-static int
-run(void)
+static void
+run_cuda_async(void)
 {
+	/* RAM -> CUDA (-> CUDA) -> RAM */
 	int err;
 #ifdef STARPU_USE_CUDA
-	/* RAM -> CUDA -> CUDA -> RAM */
 	err = ram_to_cuda();
-	if (err != 0)
-	{
-		fprintf(stderr, "RAM to CUDA failed\n");
-		return 1;
-	}
+	set_field(&summary, &summary.cpu_to_cuda_async, err);
+	/* If this failed, there is no point in continuing. */
+	if (err != SUCCESS)
+		return;
 
 #ifdef HAVE_CUDA_MEMCPY_PEER
 	err = cuda_to_cuda();
-	if (err != 0)
-	{
-		fprintf(stderr, "CUDA to RAM failed\n");
-		return 1;
-	}
+	set_field(&summary, &summary.cuda_to_cuda_async, err);
+	/* Even if cuda_to_cuda() failed, a valid copy is left on the first
+	 * cuda device, which means we can safely test cuda_to_ram() */
+#else
+	summary.cuda_to_cuda_async = UNTESTED;
 #endif /* !HAVE_CUDA_MEMCPY_PEER */
 
 	err = cuda_to_ram();
-	if (err != 0)
-	{
-		fprintf(stderr, "CUDA to RAM failed\n");
-		return 1;
-	}
+	set_field(&summary, &summary.cuda_to_cpu_async, err);
 #endif /* !STARPU_USE_CUDA */
+}
 
-#if STARPU_USE_OPENCL
+static void
+run_opencl_async(void)
+{
 	/* RAM -> OpenCL -> RAM */
+	int err;
+
+#if STARPU_USE_OPENCL
 	err = ram_to_opencl();
-	if (err != 0)
-	{
-		fprintf(stderr, "RAM to OpenCL failed\n");
-		return 1;
-	}
+	set_field(&summary, &summary.cpu_to_opencl_async, err);
+	if (err != SUCCESS)
+		return;
 
 	err = opencl_to_ram();
-	if (err != 0)
-	{
-		fprintf(stderr, "OpenCL to RAM failed\n");
-		return 1;
-	}
+	set_field(&summary, &summary.opencl_to_cpu_async, err);
 #endif /* !STARPU_USE_OPENCL */
+}
 
-	return 0;
+static void
+run_async(void)
+{
+	run_cuda_async();
+	run_opencl_async();
 }
 
 static int
@@ -348,7 +433,7 @@ load_conf(struct test_config *config)
 #ifdef STARPU_USE_OPENCL
 	    !config->opencl_func ||
 #endif
-	    !config->register_func)
+	    !config->handle)
 	{
 		return 1;
 	}
@@ -357,35 +442,14 @@ load_conf(struct test_config *config)
 	return 0;
 }
 
-int
-main(void)
+data_interface_test_summary*
+run_tests(struct test_config *conf)
 {
-	int i;
-	int err;
-
-	err = starpu_init(NULL);
-	if (err != 0)
+	if (load_conf(conf) == 1)
 	{
-		fprintf(stderr, "starpu_init failed, not running the tests\n");
-		return EXIT_FAILURE;
+		fprintf(stderr, "Failed to load conf.\n");
+		return NULL;
 	}
-
-	for (i = 0; tests[i] != NULL; ++i)
-	{
-		err = load_conf(tests[i]);
-		if (err != 0)
-		{
-			fprintf(stderr, "Skipping test, invalid conf\n");
-			continue;
-		}
-
-		err = run();
-		if (err != 0)
-			fprintf(stderr, "%s : FAIL\n", current_config->name);
-		else
-			fprintf(stderr, "%s : OK\n", current_config->name);
-	}
-
-	starpu_shutdown();
-	return EXIT_SUCCESS;
+	run_async();
+	return &summary;
 }

+ 13 - 4
tests/datawizard/interfaces/test_interfaces.h

@@ -16,11 +16,12 @@
 #ifndef TEST_INTERFACES_H
 #define TEST_INTERFACES_H
 
-typedef starpu_data_handle (*register_func_t) (void);
-
 struct test_config {
-	/* Returns a valid handle to a piece of data registered by StarPU */
-	register_func_t register_func;
+	/* A pointer to a valid handle */
+	starpu_data_handle *handle;
+
+	/* Unregisters data, frees memory, tidies your room */
+	void (*cleanup)(void);
 
 	/* StarPU codelets. The following functions should :
 	 * 1) Check that the values are correct
@@ -42,4 +43,12 @@ struct test_config {
 	const char *name;
 };
 
+
+typedef struct data_interface_test_summary data_interface_test_summary;
+
+void data_interface_test_summary_print(FILE *, data_interface_test_summary *);
+int data_interface_test_summary_success(data_interface_test_summary *);
+
+data_interface_test_summary *run_tests(struct test_config*);
+
 #endif /* !TEST_INTERFACES_H */

+ 37 - 8
tests/datawizard/interfaces/test_vector_interface.c

@@ -17,7 +17,8 @@
 #include "test_interfaces.h"
 
 /* Prototypes */
-static starpu_data_handle register_data(void);
+static void register_data(void);
+static void unregister_data(void);
 static void test_vector_cpu_func(void *buffers[], void *args);
 #ifdef STARPU_USE_CUDA
 extern void test_vector_cuda_func(void *buffers[], void *_args);
@@ -37,7 +38,7 @@ struct test_config vector_config = {
 #ifdef STARPU_USE_OPENCL
 	.opencl_func   = test_vector_opencl_func,
 #endif
-	.register_func = register_data,
+	.handle        = &vector_handle,
 	.copy_failed   = 0,
 	.name          = "vector_interface"
 };
@@ -45,12 +46,9 @@ struct test_config vector_config = {
 #define VECTOR_SIZE 123
 static int vector[VECTOR_SIZE];
 
-static starpu_data_handle
+static void
 register_data(void)
 {
-	if (vector_handle)
-		return vector_handle;
-
 	/* Initializing data */
 	int i;
 	for (i = 0; i < VECTOR_SIZE; i++)
@@ -62,7 +60,12 @@ register_data(void)
                                     (uintptr_t)vector,
 				    VECTOR_SIZE,
 				    sizeof(int));
-	return vector_handle;
+}
+
+static void
+unregister_data(void)
+{
+	starpu_data_unregister(vector_handle);
 }
 
 static void test_vector_cpu_func(void *buffers[], void *args)
@@ -73,10 +76,36 @@ static void test_vector_cpu_func(void *buffers[], void *args)
 	unsigned int i;
 	for (i = 0; i < n; i++) {
 		if (val[i] != i*factor) {
-			fprintf(stderr, "HI %d => %d\n", i, val[i]);
 			vector_config.copy_failed = 1;
 			return;
 		}
 		val[i] = -val[i];
 	}
 }
+
+int
+main(void)
+{
+	data_interface_test_summary *summary;
+	struct starpu_conf conf = {
+		.ncpus   = -1,
+		.ncuda   = 2,
+		.nopencl = 1
+	};
+
+	starpu_init(&conf);
+
+	register_data();
+
+	summary = run_tests(&vector_config);
+	if (!summary)
+		exit(EXIT_FAILURE);
+
+	unregister_data();
+
+	starpu_shutdown();
+
+	data_interface_test_summary_print(stderr, summary);
+
+	return data_interface_test_summary_success(summary);
+}