Andra Hugo 13 years ago
parent
commit
cad1d5971d

+ 186 - 0
tests/datawizard/interfaces/multiformat/advanced/generic.c

@@ -0,0 +1,186 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011  Institut National de Recherche en Informatique et Automatique
+ *
+ * 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_data_interfaces.h>
+#include "generic.h"
+#include "../../../../helper.h"
+
+struct stats global_stats;
+
+#ifdef STARPU_USE_CPU
+void cpu_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.cpu++;
+}
+#endif /* !STARPU_USE_CPU */
+
+#ifdef STARPU_USE_CUDA
+void cuda_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.cuda++;
+}
+
+void cpu_to_cuda_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.cpu_to_cuda++;
+}
+
+void cuda_to_cpu_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.cuda_to_cpu++;
+}
+
+struct starpu_codelet cpu_to_cuda_cl =
+{
+	.where = STARPU_CUDA,
+	.cuda_funcs = {cpu_to_cuda_func, NULL},
+	.nbuffers = 1
+};
+
+struct starpu_codelet cuda_to_cpu_cl =
+{
+	.where = STARPU_CPU,
+	.cpu_funcs = {cuda_to_cpu_func, NULL},
+	.nbuffers = 1
+};
+#endif /* !STARPU_USE_CUDA */
+
+#ifdef STARPU_USE_OPENCL
+void opencl_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.opencl++;
+}
+
+void cpu_to_opencl_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.cpu_to_opencl++;
+}
+
+void opencl_to_cpu_func(void *buffers[], void *args)
+{
+	STARPU_SKIP_IF_VALGRIND;
+
+	global_stats.opencl_to_cpu++;
+}
+
+struct starpu_codelet cpu_to_opencl_cl =
+{
+	.where = STARPU_OPENCL,
+	.opencl_funcs = {cpu_to_opencl_func, NULL},
+	.nbuffers = 1
+};
+
+struct starpu_codelet opencl_to_cpu_cl =
+{
+	.where = STARPU_CPU,
+	.cpu_funcs = {opencl_to_cpu_func, NULL},
+	.nbuffers = 1
+};
+#endif /* !STARPU_USE_OPENCL */
+
+
+struct starpu_multiformat_data_interface_ops ops =
+{
+#ifdef STARPU_USE_CUDA
+	.cuda_elemsize = sizeof(int),
+	.cpu_to_cuda_cl = &cpu_to_cuda_cl,
+	.cuda_to_cpu_cl = &cuda_to_cpu_cl,
+#endif
+#ifdef STARPU_USE_OPENCL
+	.opencl_elemsize = sizeof(int),
+	.cpu_to_opencl_cl = &cpu_to_opencl_cl,
+	.opencl_to_cpu_cl = &opencl_to_cpu_cl,
+#endif
+	.cpu_elemsize = sizeof(int)
+};
+
+void
+print_stats(struct stats *s)
+{
+#ifdef STARPU_USE_CPU
+	FPRINTF(stderr, "cpu         : %d\n", s->cpu);
+#endif /* !STARPU_USE_CPU */
+#ifdef STARPU_USE_CUDA
+	FPRINTF(stderr, "cuda        : %d\n" 
+			"cpu->cuda   : %d\n"
+			"cuda->cpu   : %d\n",
+			s->cuda,
+			s->cpu_to_cuda,
+			s->cuda_to_cpu);
+#endif /* !STARPU_USE_CUDA */
+#ifdef STARPU_USE_OPENCL
+	FPRINTF(stderr, "opencl      : %d\n" 
+			"cpu->opencl : %d\n"
+			"opencl->cpu : %d\n",
+			s->opencl,
+			s->cpu_to_opencl,
+			s->opencl_to_cpu);
+#endif /* !STARPU_USE_OPENCL */
+}
+
+void reset_stats(struct stats *s)
+{
+#ifdef STARPU_USE_CPU
+	s->cpu = 0;
+#endif /* !STARPU_USE_CPU */
+#ifdef STARPU_USE_CUDA
+	s->cuda = 0;
+	s->cpu_to_cuda = 0;
+	s->cuda_to_cpu = 0;
+#endif /* !STARPU_USE_CUDA */
+#ifdef STARPU_USE_OPENCL
+	s->opencl = 0;
+	s->cpu_to_opencl = 0;
+	s->opencl_to_cpu = 0;
+#endif /* !STARPU_USE_OPENCL */
+}
+
+int
+compare_stats(struct stats *s1, struct stats *s2)
+{
+	if (
+#ifdef STARPU_USE_CPU
+	    s1->cpu == s2->cpu &&
+#endif /* !STARPU_USE_CPU */
+#ifdef STARPU_USE_CUDA
+	    s1->cuda == s2->cuda &&
+	    s1->cpu_to_cuda == s2->cpu_to_cuda &&
+	    s1->cuda_to_cpu == s2->cuda_to_cpu &&
+#endif /* !STARPU_USE_CUDA */
+#ifdef STARPU_USE_OPENCL
+	    s1->opencl == s2->opencl &&
+	    s1->cpu_to_opencl == s2->cpu_to_opencl &&
+	    s1->opencl_to_cpu == s2->opencl_to_cpu &&
+#endif /* !STARPU_USE_OPENCL */
+	    1 /* Just so the build does not fail if we disable EVERYTHING */
+	)
+		return 0;
+	else
+		return 1;
+
+}

+ 55 - 0
tests/datawizard/interfaces/multiformat/advanced/generic.h

@@ -0,0 +1,55 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011  Institut National de Recherche en Informatique et Automatique
+ *
+ * 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.
+ */
+#ifndef MULTIFORMAT_GENERIC_H
+#define MULTIFORMAT_GENERIC_H
+
+#define NX 16
+
+#ifdef STARPU_USE_CPU
+void cpu_func(void *buffers[], void *args);
+#endif /* !STARPU_USE_CPU */
+
+#ifdef STARPU_USE_CUDA
+void cuda_func(void *buffers[], void *args);
+#endif /* !STARPU_USE_CUDA */
+
+#ifdef STARPU_USE_OPENCL
+void opencl_func(void *buffers[], void *args);
+#endif /* !STARPU_USE_OPENCL */
+extern struct starpu_multiformat_data_interface_ops ops;
+/* Counting the calls to the codelets */
+struct stats
+{
+#ifdef STARPU_USE_CPU
+	unsigned int cpu;
+#endif
+#ifdef STARPU_USE_CUDA
+	unsigned int cuda;
+	unsigned int cpu_to_cuda;
+	unsigned int cuda_to_cpu;
+#endif
+#ifdef STARPU_USE_OPENCL
+	unsigned int opencl;
+	unsigned int cpu_to_opencl;
+	unsigned int opencl_to_cpu;
+#endif
+};
+
+void print_stats(struct stats *);
+void reset_stats(struct stats *);
+int  compare_stats(struct stats *, struct stats *);
+
+#endif /* !MULTIFORMAT_GENERIC_H */

+ 159 - 0
tests/datawizard/interfaces/multiformat/advanced/multiformat_cuda_opencl.c

@@ -0,0 +1,159 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011  Institut National de Recherche en Informatique et Automatique
+ *
+ * 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 "generic.h"
+#include "../../../../helper.h"
+
+#if defined(STARPU_USE_CUDA) && defined(STARPU_USE_OPENCL)
+
+extern struct stats global_stats;
+static int vector[NX];
+static starpu_data_handle_t handle;
+
+/*
+ * Initially, our vector should be in RAM. It is then used on a CUDA device,
+ * then on an OpenCL device, and finally, on a CUDA device again.
+ * The following operations should be performed, in this specific order :
+ * - CPU -> CUDA conversion
+ * - CUDA kernel execution
+ * - OpenCL kernel execution
+ * - CUDA kernel execution
+ * - CUDA -> CPU conversion
+ *
+ * Note that we will not run any conversion between CUDA and OpenCL, because
+ * StarPU assumes that the data structures used on CUDA and OpenCL devices are
+ * the same.
+ */
+static int
+test(void)
+{
+	int ret;
+	struct starpu_task *task_cuda, *task_cuda2, *task_opencl;
+
+	static struct starpu_codelet cl_cuda =
+	{
+		.where     = STARPU_CUDA,
+		.cuda_funcs = {cuda_func, NULL},
+		.nbuffers  = 1,
+		.modes = {STARPU_RW}
+	};
+
+	task_cuda = starpu_task_create();
+	task_cuda->cl = &cl_cuda;
+	task_cuda->handles[0] = handle;
+	ret = starpu_task_submit(task_cuda);
+	if (ret != 0)
+		return 1;
+
+	static struct starpu_codelet cl_opencl =
+	{
+		.where       = STARPU_OPENCL,
+		.opencl_funcs = {opencl_func, NULL},
+		.nbuffers    = 1,
+		.modes = {STARPU_RW}
+	};
+
+	task_opencl = starpu_task_create();
+	task_opencl->cl = &cl_opencl;
+	task_opencl->handles[0] = handle;
+	ret = starpu_task_submit(task_opencl);
+	if (ret != 0)
+		return 1;
+
+	task_cuda2 = starpu_task_create();
+	task_cuda2->cl = &cl_cuda;
+	task_cuda2->handles[0] = handle;
+	ret = starpu_task_submit(task_cuda2);
+	if (ret != 0)
+		return 1;
+
+	return 0;
+}
+
+static void
+register_handle(void)
+{
+	int i;
+	for (i = 0; i < NX; i++)
+		vector[i] = i;
+	starpu_multiformat_data_register(&handle, 0, vector, NX, &ops);
+}
+
+static void
+unregister_handle(void)
+{
+	starpu_data_unregister(handle);
+}
+#endif /* !(STARPU_USE_CUDA && STARPU_USE_OPENCL) */
+
+int
+main(void)
+{
+#if defined(STARPU_USE_CUDA) && defined(STARPU_USE_OPENCL)
+	int ret;
+	struct starpu_conf conf =
+	{
+		.ncpus   = -1,
+		.ncuda   = 1,
+		.nopencl = 1
+	};
+
+	ret = starpu_init(&conf);
+	if (ret == -ENODEV)
+		goto enodev;
+
+	reset_stats(&global_stats);
+	register_handle();
+	ret = test();
+	unregister_handle();
+	starpu_shutdown();
+
+	if (ret != 0)
+		return STARPU_TEST_SKIPPED;
+
+	struct stats expected_stats =
+	{
+#ifdef STARPU_USE_CPU
+		.cpu           = 0,
+#endif
+#ifdef STARPU_USE_CUDA
+		.cuda          = 2,
+		.cpu_to_cuda   = 1,
+		.cuda_to_cpu   = 1,
+#endif
+#ifdef STARPU_USE_OPENCL
+		.opencl        = 1,
+		.cpu_to_opencl = 0,
+		.opencl_to_cpu = 0
+#endif
+	};
+
+	ret = compare_stats(&global_stats, &expected_stats);
+	if (ret != 0)
+	{
+		print_stats(&global_stats);
+		print_stats(&expected_stats);
+		return EXIT_FAILURE;
+	}
+
+	return EXIT_SUCCESS;
+enodev:
+	return STARPU_TEST_SKIPPED;
+#else
+	return STARPU_TEST_SKIPPED;
+#endif
+}

+ 157 - 0
tests/datawizard/interfaces/multiformat/advanced/multiformat_data_release.c

@@ -0,0 +1,157 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011-2012  INRIA
+ * Copyright (C) 2011, 2012  Centre National de la Recherche Scientifique
+ *
+ * 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 "generic.h"
+#include "../../../../helper.h"
+
+static int vector[NX];
+static starpu_data_handle_t handle;
+
+#define ENTER() do { FPRINTF(stderr, "Entering %s\n", __func__); } while (0)
+
+extern struct stats global_stats;
+
+
+static void
+register_handle(void)
+{
+	int i;
+	for (i = 0; i < NX; i++)
+		vector[i] = i;
+	starpu_multiformat_data_register(&handle, 0, vector, NX, &ops);
+}
+
+static void
+unregister_handle(void)
+{
+	starpu_data_unregister(handle);
+}
+
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+static void
+create_and_submit(int where)
+{
+	static struct starpu_codelet cl =
+	{
+		.modes = { STARPU_RW },
+#ifdef STARPU_USE_CUDA
+		.cuda_funcs   = {cuda_func, NULL},
+#endif
+#ifdef STARPU_USE_OPENCL
+		.opencl_funcs = {opencl_func, NULL},
+#endif
+		.nbuffers    = 1
+	};
+	cl.where = where;
+
+	struct starpu_task *task = starpu_task_create();
+	task->cl = &cl;
+	task->handles[0] = handle;
+
+	/* We need to be sure the data has been copied to the GPU at the end 
+	 * of this function */
+	task->synchronous = 1;
+	starpu_task_submit(task);
+}
+#endif
+
+static int
+test(void)
+{
+	struct stats expected_stats;
+	memset(&expected_stats, 0, sizeof(expected_stats));
+
+#ifdef STARPU_USE_CUDA
+	create_and_submit(STARPU_CUDA);
+	starpu_data_acquire(handle, STARPU_RW);
+
+	expected_stats.cuda = 1;
+	expected_stats.cpu_to_cuda = 1;
+	expected_stats.cuda_to_cpu = 1;
+
+	starpu_data_release(handle);
+	if (compare_stats(&global_stats, &expected_stats) != 0)
+	{
+		FPRINTF(stderr, "CUDA failed\n");
+		print_stats(&global_stats);
+		FPRINTF(stderr ,"\n");
+		print_stats(&expected_stats);
+		return -ENODEV;
+	}
+#endif /* !STARPU_USE_CUDA */
+
+#ifdef STARPU_USE_OPENCL
+	create_and_submit(STARPU_OPENCL);
+	starpu_data_acquire(handle, STARPU_RW);
+	expected_stats.opencl = 1;
+	expected_stats.cpu_to_opencl = 1;
+	expected_stats.opencl_to_cpu = 1;
+
+	starpu_data_release(handle);
+	if (compare_stats(&global_stats, &expected_stats) != 0)
+	{
+		FPRINTF(stderr, "OPENCL failed\n");
+		print_stats(&global_stats);
+		FPRINTF(stderr ,"\n");
+		print_stats(&expected_stats);
+		return -ENODEV;
+	}
+#endif /* !STARPU_USE_OPENCL */
+
+	return 0;
+}
+
+int
+main(void)
+{
+#ifdef STARPU_USE_CPU
+	int ret;
+	struct starpu_conf conf =
+	{
+		.ncpus = -1,
+		.ncuda = 1,
+		.nopencl = 1
+	};
+	memset(&global_stats, 0, sizeof(global_stats));
+	ret = starpu_init(&conf);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	register_handle();
+
+	int err = test();
+
+	unregister_handle();
+	starpu_shutdown();
+
+	switch (err)
+	{
+		case -ENODEV:
+			return STARPU_TEST_SKIPPED;
+		case 0:
+			return EXIT_SUCCESS;
+		default:
+			return EXIT_FAILURE;
+	}
+#else /* ! STARPU_USE_CPU */
+	/* Without the CPU, there is no point in using the multiformat
+	 * interface, so this test is pointless. */
+	return STARPU_TEST_SKIPPED;
+#endif
+}

+ 253 - 0
tests/datawizard/interfaces/multiformat/advanced/multiformat_handle_conversion.c

@@ -0,0 +1,253 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011-2012  INRIA
+ * Copyright (C) 2011, 2012  Centre National de la Recherche Scientifique
+ *
+ * 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 "generic.h"
+#include "../../../../helper.h"
+
+#define DEBUG 0
+
+#if DEBUG
+#define SYNCHRONOUS 1 /* Easier to debug with synchronous tasks */
+#define ENTER() do { FPRINTF(stderr, "Entering %s\n", __func__); } while (0)
+#else
+#define SYNCHRONOUS 0
+#define ENTER()
+#endif
+
+extern struct stats global_stats;
+
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+static void
+create_and_submit_tasks(int where, starpu_data_handle_t handles[])
+{
+	FPRINTF(stderr, "***** Starting Task 1\n");
+	struct starpu_codelet cl =
+	{
+		.modes        = { STARPU_RW },
+		.nbuffers     = 1,
+		.where        = where
+	};
+
+#ifdef STARPU_USE_CUDA
+	if (where & STARPU_CUDA)
+		cl.cuda_funcs[0] = cuda_func;
+#endif
+#ifdef STARPU_USE_OPENCL
+	if (where & STARPU_OPENCL)
+		cl.opencl_funcs[0] = opencl_func;
+#endif
+
+	struct starpu_task *task = starpu_task_create();
+	task->synchronous = SYNCHRONOUS;
+	task->cl = &cl;
+	task->handles[0] = handles[0];
+	assert(starpu_task_submit(task) == 0);
+
+#ifdef STARPU_USE_CPU
+	FPRINTF(stderr, "***** Starting Task 2\n");
+	struct starpu_codelet cl2 =
+	{
+		.modes = { STARPU_RW },
+		.cpu_funcs = {cpu_func, NULL},
+		.nbuffers = 1,
+		.where = STARPU_CPU,
+	};
+
+	struct starpu_task *task2 = starpu_task_create();
+	task2->synchronous = SYNCHRONOUS;
+	task2->cl = &cl2;
+	task2->handles[0] = handles[1];
+	assert(starpu_task_submit(task2) == 0);
+#endif /* !STARPU_USE_CPU */
+
+	FPRINTF(stderr, "***** Starting Task 3\n");
+	struct starpu_codelet cl3 =
+	{
+		.modes = { STARPU_RW, STARPU_RW },
+		.nbuffers    = 2,
+		.where       = where
+	};
+
+#ifdef STARPU_USE_CUDA
+	if (where & STARPU_CUDA)
+		cl3.cuda_funcs[0] = cuda_func;
+#endif
+#ifdef STARPU_USE_OPENCL
+	if (where & STARPU_OPENCL)
+		cl3.opencl_funcs[0] = opencl_func;
+#endif
+
+	struct starpu_task *task3 = starpu_task_create();
+	task3->synchronous = SYNCHRONOUS;
+	task3->cl = &cl3;
+	task3->handles[0] = handles[0];
+	task3->handles[1] = handles[1];
+	assert(starpu_task_submit(task3) == 0);
+
+	assert(starpu_task_wait_for_all() == 0);
+
+	FPRINTF(stderr, "***** End of all tasks\n");
+	return;
+}
+#endif
+
+/* XXX Just a little bit of copy/pasta here... */
+#ifdef STARPU_USE_CUDA
+static int
+test_cuda(void)
+{
+	int i;
+	int vector1[NX];
+	int vector2[NX];
+	starpu_data_handle_t handles[2];
+
+	for (i = 0; i < NX; i++)
+	{
+		vector1[i] = i;
+		vector2[i] = i;
+	}
+
+	starpu_multiformat_data_register(&handles[0], 0, vector1, NX, &ops);
+	starpu_multiformat_data_register(&handles[1], 0, vector2, NX, &ops);
+
+	memset(&global_stats, 0, sizeof(global_stats));
+	create_and_submit_tasks(STARPU_CUDA, handles);
+
+	starpu_data_unregister(handles[0]);
+	starpu_data_unregister(handles[1]);
+
+#if DEBUG
+	print_stats(&global_stats);
+#endif
+
+	struct stats expected_stats;
+#ifdef STARPU_USE_CPU
+	expected_stats.cpu = 1;
+#endif /* !STARPU_USE_CPU */
+#ifdef STARPU_USE_OPENCL
+	expected_stats.opencl = 0;
+	expected_stats.cpu_to_opencl = 0;
+	expected_stats.opencl_to_cpu = 0;
+#endif /* !STARPU_USE_OPENCL */
+	expected_stats.cuda = 2;
+	expected_stats.cpu_to_cuda = 2;
+	expected_stats.cuda_to_cpu = 2;
+
+	return compare_stats(&expected_stats, &global_stats);
+}
+#endif /* !STARPU_USE_CUDA */
+
+#ifdef STARPU_USE_OPENCL
+static int
+test_opencl(void)
+{
+	int i;
+	int vector1[NX];
+	int vector2[NX];
+	starpu_data_handle_t handles[2];
+
+	for (i = 0; i < NX; i++)
+	{
+		vector1[i] = i;
+		vector2[i] = i;
+	}
+
+	starpu_multiformat_data_register(&handles[0], 0, vector1, NX, &ops);
+	starpu_multiformat_data_register(&handles[1], 0, vector2, NX, &ops);
+
+	memset(&global_stats, 0, sizeof(global_stats));
+	create_and_submit_tasks(STARPU_OPENCL, handles);
+
+	starpu_data_unregister(handles[0]);
+	starpu_data_unregister(handles[1]);
+
+#if DEBUG
+	print_stats(&global_stats);
+#endif
+
+	struct stats expected_stats;
+#ifdef STARPU_USE_CPU
+	expected_stats.cpu = 1;
+#endif /* !STARPU_USE_CPU */
+#ifdef STARPU_USE_CUDA
+	expected_stats.cuda = 0;
+	expected_stats.cpu_to_cuda = 0;
+	expected_stats.cuda_to_cpu = 0;
+#endif /* !STARPU_USE_CUDA */
+	expected_stats.opencl = 2;
+	expected_stats.cpu_to_opencl = 2;
+	expected_stats.opencl_to_cpu = 2;
+
+	return compare_stats(&expected_stats, &global_stats);
+}
+#endif /* !STARPU_USE_OPENCL */
+
+int
+main(void)
+{
+#ifdef STARPU_USE_CPU
+	int ret;
+	struct starpu_conf conf =
+	{
+		.ncpus   = -1,
+		.ncuda   = 2,
+		.nopencl = 1
+	};
+
+	ret = starpu_init(&conf);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	unsigned int ncpu  = starpu_cpu_worker_get_count();
+	if (ncpu == 0)
+	{
+		FPRINTF(stderr, "No CPUS, cannot run this test.\n");
+		return STARPU_TEST_SKIPPED;
+	}
+	unsigned int ncuda = starpu_cuda_worker_get_count();
+	unsigned int nopencl = starpu_opencl_worker_get_count();
+
+#ifdef STARPU_USE_OPENCL
+	if (nopencl > 0 && test_opencl() != 0)
+	{
+		FPRINTF(stderr, "OPENCL FAILED\n");
+		return EXIT_FAILURE;
+	}
+#endif
+#ifdef STARPU_USE_CUDA
+	if (ncuda > 0 && test_cuda() != 0)
+	{
+		FPRINTF(stderr, "CUDA FAILED \n");
+		return EXIT_FAILURE;
+	}
+#endif
+
+	starpu_shutdown();
+
+	if (ncuda == 0 && nopencl == 0)
+		return STARPU_TEST_SKIPPED;
+	else
+		return EXIT_SUCCESS;
+#else /* !STARPU_USE_CPU */
+	/* Without the CPU, there is no point in using the multiformat
+	 * interface, so this test is pointless. */
+
+	return STARPU_TEST_SKIPPED;
+#endif
+}

+ 155 - 0
tests/datawizard/interfaces/multiformat/advanced/multiformat_worker.c

@@ -0,0 +1,155 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2012 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 "generic.h"
+#include "../../../../helper.h"
+
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+extern struct stats global_stats;
+static int vector[NX]; static starpu_data_handle_t handle;
+#endif
+
+#ifdef STARPU_USE_CUDA
+static int ncuda;
+static int cuda_worker;
+#endif
+#ifdef STARPU_USE_OPENCL
+static int nopencl;
+static int opencl_worker;
+#endif
+
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+static struct starpu_codelet cl =
+{
+	.where = STARPU_CUDA|STARPU_OPENCL,
+	.modes = { STARPU_RW },
+#ifdef STARPU_USE_CUDA
+	.cuda_funcs = { cuda_func, NULL },
+#endif
+#ifdef STARPU_USE_OPENCL
+	.opencl_funcs = { opencl_func, NULL },
+#endif
+	.nbuffers = 1,
+};
+
+static void
+register_handle(void)
+{
+	int i;
+	for (i = 0; i < NX; i++)
+		vector[i] = i;
+	starpu_multiformat_data_register(&handle, 0, vector, NX, &ops);
+}
+
+static void
+unregister_handle(void)
+{
+	starpu_data_unregister(handle);
+}
+
+static int
+create_and_submit_tasks(void)
+{
+	struct starpu_task *task;
+
+	task = starpu_task_create();
+	task->cl = &cl;
+	task->handles[0] = handle;
+	task->execute_on_a_specific_worker = 1;
+
+#ifdef STARPU_USE_CUDA
+	if (ncuda > 0)
+	{
+		task->workerid = cuda_worker;
+	}
+	else
+#endif
+#ifdef STARPU_USE_OPENCL
+	if (nopencl > 0)
+	{
+		task->workerid = opencl_worker;
+	}
+	else
+#endif
+	{
+		return -ENODEV;
+	}
+
+	return starpu_task_submit(task);
+}
+#endif
+
+int
+main(void)
+{
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+	int err;
+	err = starpu_init(NULL);
+	if (err == -ENODEV)
+		goto enodev;
+
+#ifdef STARPU_USE_CUDA
+	ncuda = starpu_worker_get_ids_by_type(STARPU_CUDA_WORKER,
+						&cuda_worker, 1);
+	if (ncuda < 0)
+		ncuda = 1;
+#endif
+#ifdef STARPU_USE_OPENCL
+	nopencl = starpu_worker_get_ids_by_type(STARPU_OPENCL_WORKER,
+						&opencl_worker, 1);
+	if (nopencl < 0)
+		nopencl = 1;
+#endif
+
+	reset_stats(&global_stats);
+	register_handle();
+	err = create_and_submit_tasks();
+	unregister_handle();
+	starpu_shutdown();
+
+	if (err == -ENODEV)
+		goto enodev;
+
+#if defined(STARPU_USE_CUDA)
+	if (global_stats.cuda == 1)
+	{
+		if (global_stats.cpu_to_cuda == 1 &&
+		    global_stats.cuda_to_cpu == 1)
+			return EXIT_SUCCESS;
+		else
+			return EXIT_FAILURE;
+	}
+#endif /* !STARPU_USE_CUDA */
+#if defined(STARPU_USE_OPENCL)
+	if (global_stats.opencl == 1)
+	{
+		if (global_stats.cpu_to_opencl == 1 &&
+		    global_stats.opencl_to_cpu == 1)
+			return EXIT_SUCCESS;
+		else
+			return EXIT_FAILURE;
+
+	}
+#endif /* !STARPU_USE_OPENCL */
+
+	/* We should not get here */
+	return EXIT_FAILURE;
+
+enodev:
+#endif
+	return STARPU_TEST_SKIPPED;
+}

+ 132 - 0
tests/datawizard/interfaces/multiformat/advanced/same_handle.c

@@ -0,0 +1,132 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 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 "generic.h"
+#include "../../../../helper.h"
+
+/*
+ * A single handle can be given twice to a given kernel. In this case, it
+ * should only be converted once.
+ */
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+extern struct stats global_stats;
+static int vector[NX]; static starpu_data_handle_t handle;
+
+static struct starpu_codelet cl =
+{
+	.modes = { STARPU_RW, STARPU_RW },
+#ifdef STARPU_USE_CUDA
+	.cuda_funcs = { cuda_func, NULL },
+#endif
+#ifdef STARPU_USE_OPENCL
+	.opencl_funcs = { opencl_func, NULL },
+#endif
+	.nbuffers = 2,
+};
+
+static void
+register_handle(void)
+{
+	int i;
+	for (i = 0; i < NX; i++)
+		vector[i] = i;
+	starpu_multiformat_data_register(&handle, 0, vector, NX, &ops);
+}
+
+static void
+unregister_handle(void)
+{
+	starpu_data_unregister(handle);
+}
+
+static int
+create_and_submit_tasks(void)
+{
+	int ret;
+	struct starpu_task *task;
+
+	cl.where = 0;
+#ifdef STARPU_USE_CUDA
+	cl.where |= STARPU_CUDA;
+#endif
+#ifdef STARPU_USE_OPENCL
+	cl.where |= STARPU_OPENCL;
+#endif
+
+	task = starpu_task_create();
+	task->cl = &cl;
+	task->handles[0] = handle;
+	task->handles[1] = handle;
+
+	ret = starpu_task_submit(task);
+	if (ret == -ENODEV)
+		return -ENODEV;
+
+	return 0;
+}
+#endif
+
+int
+main(void)
+{
+#if defined(STARPU_USE_CUDA) || defined(STARPU_USE_OPENCL)
+	int err;
+	err = starpu_init(NULL);
+	if (err == -ENODEV)
+		goto enodev;
+
+	reset_stats(&global_stats);
+	register_handle();
+	err = create_and_submit_tasks();
+	unregister_handle();
+	starpu_shutdown();
+
+	if (err == -ENODEV)
+		goto enodev;
+
+#if defined(STARPU_USE_CUDA)
+	if (global_stats.cuda == 1)
+	{
+		if (global_stats.cpu_to_cuda == 1 &&
+		    global_stats.cuda_to_cpu == 1)
+			return EXIT_SUCCESS;
+		else
+			return EXIT_FAILURE;
+	}
+	else
+#endif
+#if defined(STARPU_USE_OPENCL)
+	if (global_stats.opencl == 1)
+	{
+		if (global_stats.cpu_to_opencl == 1 &&
+		    global_stats.opencl_to_cpu == 1)
+			return EXIT_SUCCESS;
+		else
+			return EXIT_FAILURE;
+
+	}
+	else
+#endif
+	{
+		/* We should not get here */
+		return EXIT_FAILURE;
+	}
+
+enodev:
+#endif
+	return STARPU_TEST_SKIPPED;
+}