diff options
Diffstat (limited to 'testsuites/smptests')
-rw-r--r-- | testsuites/smptests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/smptests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/smptests/smpopenmp01/Makefile.am | 20 | ||||
-rw-r--r-- | testsuites/smptests/smpopenmp01/init.c | 354 | ||||
-rw-r--r-- | testsuites/smptests/smpopenmp01/smpopenmp01.doc | 11 | ||||
-rw-r--r-- | testsuites/smptests/smpopenmp01/smpopenmp01.py | 42 | ||||
-rw-r--r-- | testsuites/smptests/smpopenmp01/smpopenmp01.scn | 81 |
7 files changed, 510 insertions, 0 deletions
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index 08228ed5b5..03b29a1d71 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -30,6 +30,7 @@ _SUBDIRS += smpmigration02 _SUBDIRS += smpmrsp01 _SUBDIRS += smpmutex01 _SUBDIRS += smpmutex02 +_SUBDIRS += smpopenmp01 _SUBDIRS += smpschedaffinity03 _SUBDIRS += smpschedaffinity04 _SUBDIRS += smpschedaffinity05 diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index 78996b23ab..f8b5fe28b2 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -55,6 +55,7 @@ AC_CHECK_DECLS([pthread_getattr_np],[],[],[[ # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +smpopenmp01/Makefile smp01/Makefile smp02/Makefile smp03/Makefile diff --git a/testsuites/smptests/smpopenmp01/Makefile.am b/testsuites/smptests/smpopenmp01/Makefile.am new file mode 100644 index 0000000000..08505791d6 --- /dev/null +++ b/testsuites/smptests/smpopenmp01/Makefile.am @@ -0,0 +1,20 @@ +rtems_tests_PROGRAMS = smpopenmp01 +smpopenmp01_SOURCES = init.c + +dist_rtems_tests_DATA = smpopenmp01.scn smpopenmp01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include +AM_CFLAGS += -fopenmp + +LINK_OBJS = $(smpopenmp01_OBJECTS) +LINK_LIBS = $(smpopenmp01_LDLIBS) + +smpopenmp01$(EXEEXT): $(smpopenmp01_OBJECTS) $(smpopenmp01_DEPENDENCIES) + @rm -f smpopenmp01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smpopenmp01/init.c b/testsuites/smptests/smpopenmp01/init.c new file mode 100644 index 0000000000..5d4ab1243d --- /dev/null +++ b/testsuites/smptests/smpopenmp01/init.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* + * This OpenMP micro benchmark is based on mailing list posts from Jakub + * Jelinek. + * + * Subject: [gomp3] libgomp performance improvements + * https://gcc.gnu.org/ml/gcc-patches/2008-03/msg00930.html + * + * Subject: [gomp3] Use private futexes if possible + * https://gcc.gnu.org/ml/gcc-patches/2008-03/msg01126.html + * + * This file can be compiled on Linux, etc. using: + * + * cc -std=c11 -O2 -fopenmp init.c + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <omp.h> +#include <stdio.h> + +#ifdef __rtems__ +#include <pthread.h> +#include <tmacros.h> + +const char rtems_test_name[] = "SMPOPENMP 1"; + +#define CPU_COUNT_MAX 32 +#endif /* __rtems__ */ + +static void work(void) +{ + __asm__ volatile ("" : : : "memory"); +} + +static void barrier_bench(void) +{ + #pragma omp parallel + for (int i = 0; i < 10000; ++i) { + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + #pragma omp barrier + work(); + } +} + +static void parallel_bench(void) +{ + for (int i = 0; i < 20000; ++i) { + #pragma omp parallel + work(); + } +} + +static void static_bench(void) +{ + for (int i = 0; i < 1000; ++i) { + #pragma omp parallel for schedule (static) + for (int j = 0; j < 100; ++j) { + work(); + } + } +} + +static void dynamic_bench(void) +{ + #pragma omp parallel for schedule (dynamic) + for (int i = 0; i < 100000; ++i) { + work(); + } +} + +static void guided_bench(void) +{ + #pragma omp parallel for schedule (guided) + for (int i = 0; i < 100000; ++i) { + work(); + } +} + +static void runtime_bench(void) +{ + #pragma omp parallel for schedule (runtime) + for (int i = 0; i < 100000; ++i) { + work(); + } +} + +static void single_bench(void) +{ + #pragma omp parallel + for (int i = 0; i < 10000; ++i) { + #pragma omp single + work(); + } +} + +static void all(void) +{ + barrier_bench(); + parallel_bench(); + static_bench(); + dynamic_bench(); + guided_bench(); + runtime_bench(); + single_bench(); +} + +static void do_bench(const char *name, void (*bench)(void), int n) +{ + double start; + double delta; + + (*bench)(); + start = omp_get_wtime(); + for (int i = 0; i < n; ++i) { + (*bench)(); + } + delta = omp_get_wtime() - start; + printf("\t\t<%sBench unit=\"s\">%f</%sBench>\n", name, delta, name); +} + +static void microbench(int num_threads, int n) +{ + printf("\t<Microbench numThreads=\"%i\" majorLoopCount=\"%i\">\n", num_threads, n); + omp_set_num_threads(num_threads); + do_bench("Barrier", barrier_bench, n); + do_bench("Parallel", parallel_bench, n); + do_bench("Static", static_bench, n); + do_bench("Dynamic", dynamic_bench, n); + do_bench("Guided", guided_bench, n); + do_bench("Runtime", runtime_bench, n); + do_bench("Single", single_bench, n); + printf("\t</Microbench>\n"); +} + +static int estimate_3s_runtime_with_one_proc(void) +{ + double start; + double delta; + int n; + + omp_set_num_threads(1); + all(); + start = omp_get_wtime(); + all(); + delta = omp_get_wtime() - start; + + if (delta > 0.0 && delta <= 1.0) { + n = (int) (3.0 / delta); + } else { + n = 1; + } + + return n; +} + +static void test(void) +{ + int num_procs; + int n; + + printf("<SMPOpenMP01>\n"); + + n = estimate_3s_runtime_with_one_proc(); + num_procs = omp_get_num_procs(); + omp_set_num_threads(num_procs); + + for (int i = 1; i <= num_procs; ++i) { + microbench(i, n); + } + + printf("</SMPOpenMP01>\n"); +} + +#ifdef __rtems__ + +static void Init(rtems_task_argument arg) +{ + rtems_status_code sc; + cpu_set_t cpu_set; + + rtems_print_printer_fprintf_putc(&rtems_test_printer); + TEST_BEGIN(); + + CPU_ZERO(&cpu_set); + CPU_SET(0, &cpu_set); + + sc = rtems_task_set_affinity(RTEMS_SELF, sizeof(cpu_set), &cpu_set); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + test(); + TEST_END(); + rtems_test_exit(0); +} + +typedef struct { + pthread_mutex_t mtx; + pthread_cond_t cnd; + bool cpus_used[CPU_COUNT_MAX]; +} test_context; + +static test_context test_instance; + +static uint32_t find_free_cpu(test_context *ctx) +{ + uint32_t i; + uint32_t n; + + n = rtems_get_processor_count(); + + pthread_mutex_lock(&ctx->mtx); + + do { + for (i = 1; i < n; ++i) { + if (!ctx->cpus_used[i]) { + ctx->cpus_used[i] = true; + break; + } + } + + if (i == n) { + pthread_cond_wait(&ctx->cnd, &ctx->mtx); + } + } while (i == n); + + pthread_mutex_unlock(&ctx->mtx); + + return i; +} + +static void begin_extension(Thread_Control *th) +{ + rtems_id th_id; + + th_id = th->Object.id; + + if (rtems_object_id_get_api(th_id) == OBJECTS_POSIX_API) { + rtems_status_code sc; + rtems_id sched_id; + uint32_t cpu_index; + cpu_set_t cpu_set; + rtems_task_priority prio; + + cpu_index = find_free_cpu(&test_instance); + + sc = rtems_scheduler_ident_by_processor(cpu_index, &sched_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_set_priority(th_id, RTEMS_CURRENT_PRIORITY, &prio); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_set_scheduler(th_id, sched_id, prio); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + CPU_ZERO(&cpu_set); + CPU_SET((int) cpu_index, &cpu_set); + + sc = rtems_task_set_affinity(th_id, sizeof(cpu_set), &cpu_set); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + } +} + +static void terminate_extension(Thread_Control *th) +{ + rtems_id th_id; + + th_id = th->Object.id; + + if (rtems_object_id_get_api(th_id) == OBJECTS_POSIX_API) { + rtems_status_code sc; + cpu_set_t cpu_set; + uint32_t cpu_index; + test_context *ctx; + + sc = rtems_task_get_affinity(th_id, sizeof(cpu_set), &cpu_set); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + cpu_index = CPU_FFS(&cpu_set) - 1; + + ctx = &test_instance; + + pthread_mutex_lock(&ctx->mtx); + rtems_test_assert(ctx->cpus_used[cpu_index]); + ctx->cpus_used[cpu_index] = false; + pthread_cond_broadcast(&ctx->cnd); + pthread_mutex_unlock(&ctx->mtx); + } +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT_MAX + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_INITIAL_EXTENSIONS \ + { \ + .thread_begin = begin_extension, \ + .thread_terminate = terminate_extension \ + }, \ + RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> + +#else /* __rtems__ */ + +int main(void) +{ + test(); + return 0; +} + +#endif /* __rtems__ */ diff --git a/testsuites/smptests/smpopenmp01/smpopenmp01.doc b/testsuites/smptests/smpopenmp01/smpopenmp01.doc new file mode 100644 index 0000000000..688cccd03a --- /dev/null +++ b/testsuites/smptests/smpopenmp01/smpopenmp01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smpopenmp01 + +directives: + + - None + +concepts: + + - OpenMP micro benchmark. diff --git a/testsuites/smptests/smpopenmp01/smpopenmp01.py b/testsuites/smptests/smpopenmp01/smpopenmp01.py new file mode 100644 index 0000000000..139aedd4af --- /dev/null +++ b/testsuites/smptests/smpopenmp01/smpopenmp01.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2017 embedded brains GmbH. All rights reserved. +# +# The license and distribution terms for this file may be +# found in the file LICENSE in this distribution or at +# http://www.rtems.org/license/LICENSE. +# + +import re +import libxml2 +from libxml2 import xmlNode +import matplotlib.pyplot as plt +data = open('smpopenmp01.scn').read() +data = re.sub(r'\*\*\*.*', '', data) +doc = libxml2.parseDoc(data) +ctx = doc.xpathNewContext() + +plt.title('OpenMP Microbench') +plt.xlabel('Number of Threads') +plt.ylabel('Relative Duration') + +def m(n): + return float(n.getContent()) + +def p(bench): + d = map(m, ctx.xpathEval('/SMPOpenMP01/Microbench/' + bench)) + y = [x / d[0] for x in d] + x = range(1, len(y) + 1) + plt.xticks(x) + plt.plot(x, y, label = bench, marker = 'o') + +p('BarrierBench') +p('ParallelBench') +p('StaticBench') +p('DynamicBench') +p('GuidedBench') +p('RuntimeBench') +p('SingleBench') +plt.legend(loc = 'best') +plt.show() diff --git a/testsuites/smptests/smpopenmp01/smpopenmp01.scn b/testsuites/smptests/smpopenmp01/smpopenmp01.scn new file mode 100644 index 0000000000..9a21ff5a9a --- /dev/null +++ b/testsuites/smptests/smpopenmp01/smpopenmp01.scn @@ -0,0 +1,81 @@ +*** BEGIN OF TEST SMPOPENMP 1 *** +*** TEST VERSION: 5.0.0.4c8cffc19865eaa3b033ce2776bcce9992f24b18 +*** TEST STATE: EXPECTED-PASS +*** TEST BUILD: RTEMS_POSIX_API RTEMS_SMP +*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 6d9c77c77d271d1fc2dfe8493d6713930b52a6dd, Newlib 3.0.0) +<SMPOpenMP01> + <Microbench numThreads="1" majorLoopCount="20"> + <BarrierBench unit="s">0.720318</BarrierBench> + <ParallelBench unit="s">1.121403</ParallelBench> + <StaticBench unit="s">0.059288</StaticBench> + <DynamicBench unit="s">0.440113</DynamicBench> + <GuidedBench unit="s">0.003230</GuidedBench> + <RuntimeBench unit="s">0.440121</RuntimeBench> + <SingleBench unit="s">0.116486</SingleBench> + </Microbench> + <Microbench numThreads="2" majorLoopCount="20"> + <BarrierBench unit="s">0.416734</BarrierBench> + <ParallelBench unit="s">0.259013</ParallelBench> + <StaticBench unit="s">0.015311</StaticBench> + <DynamicBench unit="s">0.196751</DynamicBench> + <GuidedBench unit="s">0.002367</GuidedBench> + <RuntimeBench unit="s">0.199640</RuntimeBench> + <SingleBench unit="s">0.077629</SingleBench> + </Microbench> + <Microbench numThreads="3" majorLoopCount="20"> + <BarrierBench unit="s">0.748332</BarrierBench> + <ParallelBench unit="s">0.387318</ParallelBench> + <StaticBench unit="s">0.021244</StaticBench> + <DynamicBench unit="s">0.141558</DynamicBench> + <GuidedBench unit="s">0.001544</GuidedBench> + <RuntimeBench unit="s">0.142693</RuntimeBench> + <SingleBench unit="s">0.117683</SingleBench> + </Microbench> + <Microbench numThreads="4" majorLoopCount="20"> + <BarrierBench unit="s">0.552830</BarrierBench> + <ParallelBench unit="s">0.323241</ParallelBench> + <StaticBench unit="s">0.017796</StaticBench> + <DynamicBench unit="s">0.099475</DynamicBench> + <GuidedBench unit="s">0.001259</GuidedBench> + <RuntimeBench unit="s">0.100053</RuntimeBench> + <SingleBench unit="s">0.091069</SingleBench> + </Microbench> + <Microbench numThreads="5" majorLoopCount="20"> + <BarrierBench unit="s">0.882791</BarrierBench> + <ParallelBench unit="s">0.452561</ParallelBench> + <StaticBench unit="s">0.023620</StaticBench> + <DynamicBench unit="s">0.094107</DynamicBench> + <GuidedBench unit="s">0.000989</GuidedBench> + <RuntimeBench unit="s">0.093911</RuntimeBench> + <SingleBench unit="s">0.130070</SingleBench> + </Microbench> + <Microbench numThreads="6" majorLoopCount="20"> + <BarrierBench unit="s">0.670385</BarrierBench> + <ParallelBench unit="s">0.393587</ParallelBench> + <StaticBench unit="s">0.021141</StaticBench> + <DynamicBench unit="s">0.072322</DynamicBench> + <GuidedBench unit="s">0.000937</GuidedBench> + <RuntimeBench unit="s">0.069804</RuntimeBench> + <SingleBench unit="s">0.104107</SingleBench> + </Microbench> + <Microbench numThreads="7" majorLoopCount="20"> + <BarrierBench unit="s">1.031511</BarrierBench> + <ParallelBench unit="s">0.466571</ParallelBench> + <StaticBench unit="s">0.024944</StaticBench> + <DynamicBench unit="s">0.069194</DynamicBench> + <GuidedBench unit="s">0.000814</GuidedBench> + <RuntimeBench unit="s">0.069596</RuntimeBench> + <SingleBench unit="s">0.133137</SingleBench> + </Microbench> + <Microbench numThreads="8" majorLoopCount="20"> + <BarrierBench unit="s">0.761015</BarrierBench> + <ParallelBench unit="s">0.452577</ParallelBench> + <StaticBench unit="s">0.023979</StaticBench> + <DynamicBench unit="s">0.061193</DynamicBench> + <GuidedBench unit="s">0.000799</GuidedBench> + <RuntimeBench unit="s">0.061519</RuntimeBench> + <SingleBench unit="s">0.114285</SingleBench> + </Microbench> +</SMPOpenMP01> + +*** END OF TEST SMPOPENMP 1 *** |