Ver código fonte

Add a variable size interface test that triggers eviction

Samuel Thibault 8 anos atrás
pai
commit
c89d036504
2 arquivos alterados com 325 adições e 0 exclusões
  1. 1 0
      tests/Makefile.am
  2. 324 0
      tests/datawizard/variable_size.c

+ 1 - 0
tests/Makefile.am

@@ -151,6 +151,7 @@ myPROGRAMS +=					\
 	datawizard/interfaces/copy_interfaces	\
 	datawizard/locality			\
 	datawizard/simgrid-locality		\
+	datawizard/variable_size		\
 	errorcheck/starpu_init_noworker		\
 	errorcheck/invalid_tasks		\
 	helper/cublas_init			\

+ 324 - 0
tests/datawizard/variable_size.c

@@ -0,0 +1,324 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2017  Université de 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"
+
+/*
+ * This is a dumb test for variable size
+ * We defined a dumb interface for data whose size increase over kernel execution
+ */
+
+#define FULLSIZE (5*1024*1024)
+#define INCREASE 0.80
+#ifdef STARPU_QUICK_CHECK
+#define N 5
+#define LIMIT "60"
+#else
+#define N 20
+#define LIMIT "1000"
+#endif
+
+/* Define the interface */
+
+#if !defined(STARPU_HAVE_SETENV)
+#warning setenv is not defined. Skipping test
+int main(int argc, char **argv)
+{
+	return STARPU_TEST_SKIPPED;
+}
+#else
+
+struct variable_size_interface
+{
+	enum starpu_data_interface_id id;
+
+	uintptr_t ptr;
+	size_t size;
+
+	/* Coordinates of the represented object, to model growth */
+	unsigned x, y;
+};
+
+static struct starpu_data_interface_ops starpu_interface_variable_size_ops;
+
+static void register_variable_size(starpu_data_handle_t handle, unsigned home_node, void *data_interface)
+{
+	struct variable_size_interface *variable_size_interface = data_interface;
+	unsigned node;
+	for (node = 0; node < STARPU_MAXNODES; node++)
+	{
+		struct variable_size_interface *local_interface =
+			starpu_data_get_interface_on_node(handle, node);
+
+		if (node == home_node)
+			local_interface->ptr = variable_size_interface->ptr;
+
+		local_interface->id = variable_size_interface->id;
+		local_interface->size = variable_size_interface->size;
+		local_interface->x = variable_size_interface->x;
+		local_interface->y = variable_size_interface->y;
+	}
+}
+
+void variable_size_data_register(starpu_data_handle_t *handleptr, unsigned x, unsigned y)
+{
+	if (starpu_interface_variable_size_ops.interfaceid == STARPU_UNKNOWN_INTERFACE_ID)
+	{
+		starpu_interface_variable_size_ops.interfaceid = starpu_data_interface_get_next_id();
+	}
+	struct variable_size_interface interface =
+	{
+		.id = starpu_interface_variable_size_ops.interfaceid,
+		.x = x,
+		.y = y,
+	};
+
+	/* Simulate that tiles close to the diagonal are more dense */
+	interface.size = FULLSIZE * (random() % 1024 + 1024) / 2048 * (N-sqrt(abs(x-y)*N)) / N;
+	/* Round to page size */
+	interface.size -= interface.size & (4096-1);
+
+	starpu_data_register(handleptr, -1, &interface, &starpu_interface_variable_size_ops);
+}
+
+static size_t variable_size_get_size(starpu_data_handle_t handle STARPU_ATTRIBUTE_UNUSED)
+{
+	struct variable_size_interface *interface =
+		starpu_data_get_interface_on_node(handle, STARPU_MAIN_RAM);
+	return interface->size;
+}
+
+static uint32_t variable_size_footprint(starpu_data_handle_t handle)
+{
+	return starpu_hash_crc32c_be(variable_size_get_size(handle), 0);
+}
+
+static int variable_size_compare(void *data_interface_a, void *data_interface_b)
+{
+	struct variable_size_interface *variable_a = data_interface_a;
+	struct variable_size_interface *variable_b = data_interface_b;
+
+	/* Two variables are considered compatible if they have the same size */
+	return (variable_a->size == variable_b->size);
+}
+
+static void display_variable_size(starpu_data_handle_t handle, FILE *f)
+{
+	struct variable_size_interface *variable_interface =
+		starpu_data_get_interface_on_node(handle, STARPU_MAIN_RAM);
+
+	fprintf(f, "%lu\t", (unsigned long) variable_interface->size);
+}
+
+static starpu_ssize_t describe_variable_size(void *data_interface, char *buf, size_t size)
+{
+	struct variable_size_interface *variable_interface = data_interface;
+	return snprintf(buf, size, "vv%lu\t", (unsigned long) variable_interface->size);
+}
+
+/* returns the size of the allocated area */
+static starpu_ssize_t allocate_variable_size_on_node(void *data_interface,
+						   unsigned dst_node)
+{
+	struct variable_size_interface *variable_interface = data_interface;
+	variable_interface->ptr = starpu_malloc_on_node_flags(dst_node, variable_interface->size, STARPU_MALLOC_PINNED | STARPU_MALLOC_COUNT | STARPU_MEMORY_OVERFLOW);
+	STARPU_ASSERT(variable_interface->ptr);
+	return 0;
+}
+
+static void free_variable_size_on_node(void *data_interface,
+					unsigned node)
+{
+	struct variable_size_interface *variable_interface = data_interface;
+	starpu_free_on_node(node, variable_interface->ptr, variable_interface->size);
+}
+
+static int variable_size_copy(void *src_interface, unsigned src_node, void *dst_interface, unsigned dst_node, void *async_data)
+{
+	struct variable_size_interface *src = src_interface;
+	struct variable_size_interface *dst = dst_interface;
+	return starpu_interface_copy(src->ptr, 0, src_node,
+				    dst->ptr, 0, dst_node,
+				    src->size, async_data);
+}
+
+static const struct starpu_data_copy_methods variable_size_copy_data_methods =
+{
+	.any_to_any = variable_size_copy,
+};
+
+static struct starpu_data_interface_ops starpu_interface_variable_size_ops =
+{
+	.register_data_handle = register_variable_size,
+	.allocate_data_on_node = allocate_variable_size_on_node,
+	.free_data_on_node = free_variable_size_on_node,
+	.copy_methods = &variable_size_copy_data_methods,
+	.get_size = variable_size_get_size,
+	.footprint = variable_size_footprint,
+	.compare = variable_size_compare,
+	.interfaceid = STARPU_UNKNOWN_INTERFACE_ID,
+	.interface_size = sizeof(struct variable_size_interface),
+	.display = display_variable_size,
+	.pack_data = NULL,
+	.unpack_data = NULL,
+	.describe = describe_variable_size,
+};
+
+
+
+static void kernel(void *descr[], void *cl_arg)
+{
+	struct variable_size_interface *variable_interface = descr[0];
+	unsigned workerid = starpu_worker_get_id_check();
+	uintptr_t old = variable_interface->ptr;
+	unsigned dst_node = starpu_worker_get_memory_node(workerid);
+
+	/* Simulate that tiles close to the diagonal fill up faster */
+	size_t increase = (FULLSIZE - variable_interface->size) * (random() % 1024 + 1024) / 2048 * INCREASE;
+	/* Round to page size */
+	increase -= increase & (4096-1);
+	variable_interface->ptr = starpu_malloc_on_node_flags(dst_node, variable_interface->size + increase, STARPU_MALLOC_PINNED | STARPU_MALLOC_COUNT | STARPU_MEMORY_OVERFLOW);
+	STARPU_ASSERT(variable_interface->ptr);
+	/* fprintf(stderr,"increase from %lu by %lu\n", variable_interface->size, increase); */
+	starpu_free_on_node_flags(dst_node, old, variable_interface->size, STARPU_MALLOC_PINNED | STARPU_MALLOC_COUNT | STARPU_MEMORY_OVERFLOW);
+	variable_interface->size += increase;
+	starpu_sleep(0.010);
+}
+
+static double cost_function(struct starpu_task *t, struct starpu_perfmodel_arch *a, unsigned i)
+{
+	return 10000;
+}
+
+static struct starpu_perfmodel perf_model =
+{
+	.type = STARPU_PER_ARCH,
+	.arch_cost_function = cost_function,
+};
+
+static struct starpu_codelet cl =
+{
+	.cpu_funcs = {kernel},
+
+	/* dynamic size doesn't work on MIC */
+	/*.cpu_funcs_name = {"kernel"},*/
+	.nbuffers = 1,
+	.modes = {STARPU_RW},
+	.model = &perf_model,
+	.flags = STARPU_CODELET_SIMGRID_EXECUTE,
+};
+
+static void nop(void *descr[], void *cl_arg)
+{
+}
+
+static double nop_cost_function(struct starpu_task *t, struct starpu_perfmodel_arch *a, unsigned i)
+{
+	return 0.001;
+}
+
+static struct starpu_perfmodel nop_perf_model =
+{
+	.type = STARPU_PER_ARCH,
+	.arch_cost_function = nop_cost_function,
+};
+
+static struct starpu_codelet cl_init =
+{
+	.cpu_funcs = {nop},
+
+	/* dynamic size doesn't work on MIC */
+	/*.cpu_funcs_name = {"kernel"},*/
+	.nbuffers = 1,
+	.modes = {STARPU_W},
+	.model = &nop_perf_model,
+};
+
+int main(int argc, char **argv)
+{
+	int ret;
+	int i;
+	int x, y;
+	starpu_data_handle_t handles[N][N];
+
+	setenv("STARPU_LIMIT_CPU_MEM", LIMIT, 1);
+	setenv("STARPU_DISK_SWAP", "/tmp/starpu-variable_size", 0);
+	setenv("STARPU_DISK_SWAP_SIZE", "100000", 1);
+#ifdef STARPU_LINUX_SYS
+	setenv("STARPU_DISK_SWAP_BACKEND", "unistd_o_direct", 0);
+#else
+	setenv("STARPU_DISK_SWAP_BACKEND", "unistd", 0);
+#endif
+
+	ret = starpu_init(NULL);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	for (x = 0; x < N; x++)
+		for (y = 0; y < N; y++)
+		{
+			variable_size_data_register(&handles[x][y], x, y);
+
+			ret = starpu_task_insert(&cl_init, STARPU_W, handles[x][y], 0);
+			if (ret == ENODEV)
+				goto enodev;
+#ifdef STARPU_SIMGRID
+			starpu_sleep(0.0005);
+#endif
+		}
+
+	starpu_task_wait_for_all();
+
+	/* Cholesky-like accesses */
+	for (i = 0; i < 100; i++)
+		for (x = i; x < N; x++)
+			for (y = x; y < N; y++)
+				starpu_task_insert(&cl, STARPU_RW, handles[x][y], STARPU_PRIORITY, (2*N-x-y), 0);
+
+	starpu_task_wait_for_all();
+
+#if 0
+	/* Look at the values */
+	for (x = 0; x < N; x++)
+		for (y = 0; y < N; y++)
+		{
+			starpu_data_acquire(handles[x][y], STARPU_R);
+			starpu_data_release(handles[x][y]);
+		}
+#endif
+
+	for (x = 0; x < N; x++)
+		for (y = 0; y < N; y++)
+			starpu_data_unregister(handles[x][y]);
+
+	starpu_shutdown();
+
+	return EXIT_SUCCESS;
+
+enodev:
+	for (x = 0; x < N; x++)
+		for (y = 0; y < N; y++)
+			starpu_data_unregister(handles[x][y]);
+
+	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 */
+	starpu_shutdown();
+	return STARPU_TEST_SKIPPED;
+}
+#endif