浏览代码

Add a memory bandwidth benchmark

Samuel Thibault 4 年之前
父节点
当前提交
5d648b6f72
共有 2 个文件被更改,包括 172 次插入1 次删除
  1. 3 1
      tests/Makefile.am
  2. 169 0
      tests/microbenchs/bandwidth.c

+ 3 - 1
tests/Makefile.am

@@ -173,6 +173,7 @@ myPROGRAMS +=					\
 	helper/execute_on_all			\
 	microbenchs/display_structures_size	\
 	microbenchs/local_pingpong		\
+	microbenchs/bandwidth			\
 	overlap/overlap				\
 	sched_ctx/sched_ctx_list		\
 	sched_ctx/sched_ctx_policy_data		\
@@ -412,7 +413,8 @@ examplebin_PROGRAMS = \
 	microbenchs/sync_tasks_overhead		\
 	microbenchs/tasks_overhead		\
 	microbenchs/tasks_size_overhead		\
-	microbenchs/local_pingpong
+	microbenchs/local_pingpong		\
+	microbenchs/bandwidth
 examplebin_SCRIPTS = \
 	microbenchs/tasks_data_overhead.sh \
 	microbenchs/sync_tasks_data_overhead.sh \

+ 169 - 0
tests/microbenchs/bandwidth.c

@@ -0,0 +1,169 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2009-2020  Université de Bordeaux, CNRS (LaBRI UMR 5800), 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 <stdio.h>
+#include <unistd.h>
+
+#include <starpu.h>
+#include "../helper.h"
+
+/*
+ * Measure the memory bandwidth available to kernels depending on the number of
+ * kernels and number of idle workers.
+ */
+
+/* Must be bigger than available cache size per core, 64MiB should be enough */
+static size_t size = 64UL << 20;
+
+static int iter = 30;
+static int ncpus;
+static starpu_pthread_barrier_t barrier;
+static float *result;
+
+void bw_func(void *descr[], void *arg)
+{
+	void *src = malloc(size);
+	void *dst = malloc(size);
+	unsigned i;
+	double start, stop;
+
+	memset(src, 0, size);
+
+	STARPU_PTHREAD_BARRIER_WAIT(&barrier);
+	start = starpu_timing_now();
+	for (i = 0; i < iter; i++)
+		memcpy(dst, src, size);
+	stop = starpu_timing_now();
+	STARPU_PTHREAD_BARRIER_WAIT(&barrier);
+
+	result[starpu_worker_get_id()] = (size*iter) / (stop - start);
+
+	free(src);
+	free(dst);
+}
+
+static struct starpu_codelet bw_codelet =
+{
+	.cpu_funcs = {bw_func},
+	.model = NULL,
+	.nbuffers = 0,
+};
+
+static void usage(char **argv)
+{
+	fprintf(stderr, "Usage: %s [-n iter] [-s size (MB)]]\n", argv[0]);
+	exit(EXIT_FAILURE);
+}
+
+static void parse_args(int argc, char **argv)
+{
+	int c;
+	while ((c = getopt(argc, argv, "n:s:b:i:h")) != -1)
+	switch(c)
+	{
+		case 'n':
+			iter = atoi(optarg);
+			break;
+		case 's':
+			size = (long)atoi(optarg) << 20;
+			break;
+		case 'h':
+			usage(argv);
+			break;
+	}
+}
+
+static float bench(int *argc, char ***argv, unsigned nbusy, unsigned nidle)
+{
+	int ret;
+	unsigned i;
+	struct starpu_conf conf;
+	float bw;
+
+	starpu_conf_init(&conf);
+	conf.ncuda = 0;
+	conf.nopencl = 0;
+	conf.nmic = 0;
+	conf.nmpi_ms = 0;
+	conf.ncpus = nbusy + nidle;
+
+	ret = starpu_initialize(&conf, argc, argv);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	STARPU_PTHREAD_BARRIER_INIT(&barrier, NULL, nbusy);
+
+	for (i = 0; i < nbusy; i++)
+	{
+		struct starpu_task *task = starpu_task_create();
+		task->cl = &bw_codelet;
+		task->execute_on_a_specific_worker = 1;
+		task->workerid = i;
+		ret = starpu_task_submit(task);
+		STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
+	}
+
+	starpu_task_wait_for_all();
+	starpu_shutdown();
+
+	for (bw = 0., i = 0; i < nbusy; i++)
+	{
+		bw += result[i];
+	}
+	return bw;
+}
+
+int main(int argc, char **argv)
+{
+	int ret;
+	unsigned n;
+	struct starpu_conf conf;
+	float alone, idle;
+
+	parse_args(argc, argv);
+
+	starpu_conf_init(&conf);
+	conf.ncuda = 0;
+	conf.nopencl = 0;
+	conf.nmic = 0;
+	conf.nmpi_ms = 0;
+
+	ret = starpu_initialize(&conf, &argc, &argv);
+	if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+	ncpus = starpu_cpu_worker_get_count();
+	starpu_shutdown();
+
+	result = malloc(ncpus * sizeof(result[0]));
+
+	printf("# nw\talone\t\t+idle\t\tidle efficiency\n");
+	for (n = 1; n <= ncpus; n++)
+	{
+		alone = bench(&argc, &argv, n, 0);
+		idle = bench(&argc, &argv, n, ncpus-n);
+		printf("%d\t%f\t%f\t%f\n", n, alone/1000, idle/1000, idle*100/alone);
+	}
+
+	free(result);
+
+	return EXIT_SUCCESS;
+
+enodev:
+	fprintf(stderr, "WARNING: No one can execute this task\n");
+	free(result);
+	starpu_shutdown();
+	return STARPU_TEST_SKIPPED;
+}