brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · e781a89 Raw
319 lines · cpp
1// RUN: %libomp-cxx-compile2// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=0 %libomp-run3// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=1 KMP_HOT_TEAMS_MODE=0 %libomp-run4// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=1 KMP_HOT_TEAMS_MODE=1 %libomp-run5// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=2 %libomp-run6// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=3 %libomp-run7// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=4 %libomp-run8// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=5 %libomp-run9//10// RUN: %libomp-cxx-compile -DUSE_HIDDEN_HELPERS=111// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=0 %libomp-run12// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=1 KMP_HOT_TEAMS_MODE=0 %libomp-run13// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=1 KMP_HOT_TEAMS_MODE=1 %libomp-run14// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=2 %libomp-run15// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=3 %libomp-run16// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=4 %libomp-run17// RUN: env KMP_HOT_TEAMS_MAX_LEVEL=5 %libomp-run18 19// This test stresses the task team mechanism by running a simple20// increment task over and over with varying number of threads and nesting.21// The test covers nested serial teams and mixing serial teams with22// normal active teams.23 24#include <assert.h>25#include <stdio.h>26#include <stdlib.h>27#include <omp.h>28 29// The number of times to run each test30#define NTIMES 531 32// Regular single increment task33void task_inc_a(int *a) {34#pragma omp task35  {36#pragma omp atomic37    (*a)++;38  }39}40 41// Splitting increment task that binary splits the incrementing task42void task_inc_split_a(int *a, int low, int high) {43#pragma omp task firstprivate(low, high)44  {45    if (low == high) {46#pragma omp atomic47      (*a)++;48    } else if (low < high) {49      int mid = (high - low) / 2 + low;50      task_inc_split_a(a, low, mid);51      task_inc_split_a(a, mid + 1, high);52    }53  }54}55 56#ifdef USE_HIDDEN_HELPERS57// Hidden helper tasks force serial regions to create task teams58void task_inc_a_hidden_helper(int *a) {59#pragma omp target map(tofrom : a[0]) nowait60  {61#pragma omp atomic62    (*a)++;63  }64}65#else66// Detached tasks force serial regions to create task teams67void task_inc_a_detached(int *a, omp_event_handle_t handle) {68#pragma omp task detach(handle)69  {70#pragma omp atomic71    (*a)++;72    omp_fulfill_event(handle);73  }74}75#endif76 77void check_a(int *a, int expected) {78  if (*a != expected) {79    fprintf(stderr,80            "FAIL: a = %d instead of expected = %d. Compile with "81            "-DVERBOSE for more verbose output.\n",82            *a, expected);83    exit(EXIT_FAILURE);84  }85}86 87// Every thread creates a single "increment" task88void test_tasks(omp_event_handle_t *handles, int expected, int *a) {89  int tid = omp_get_thread_num();90 91  task_inc_a(a);92 93#pragma omp barrier94  check_a(a, expected);95#pragma omp barrier96  check_a(a, expected);97#pragma omp barrier98 99#ifdef USE_HIDDEN_HELPERS100  task_inc_a_hidden_helper(a);101#else102  task_inc_a_detached(a, handles[tid]);103#endif104 105#pragma omp barrier106  check_a(a, 2 * expected);107#pragma omp barrier108  task_inc_a(a);109#pragma omp barrier110  check_a(a, 3 * expected);111}112 113// Testing single level of parallelism with increment tasks114void test_base(int nthreads) {115#ifdef VERBOSE116#pragma omp master117  printf("    test_base(%d)\n", nthreads);118#endif119  int a = 0;120  omp_event_handle_t *handles;121  handles = (omp_event_handle_t *)malloc(sizeof(omp_event_handle_t) * nthreads);122#pragma omp parallel num_threads(nthreads) shared(a)123  { test_tasks(handles, nthreads, &a); }124  free(handles);125}126 127// Testing nested parallel with increment tasks128// first = nthreads of outer parallel129// second = nthreads of nested parallel130void test_nest(int first, int second) {131#ifdef VERBOSE132#pragma omp master133  printf("   test_nest(%d, %d)\n", first, second);134#endif135#pragma omp parallel num_threads(first)136  { test_base(second); }137}138 139// Testing 2-level nested parallels with increment tasks140// first = nthreads of outer parallel141// second = nthreads of nested parallel142// third = nthreads of second nested parallel143void test_nest2(int first, int second, int third) {144#ifdef VERBOSE145#pragma omp master146  printf("  test_nest2(%d, %d, %d)\n", first, second, third);147#endif148#pragma omp parallel num_threads(first)149  { test_nest(second, third); }150}151 152// Testing 3-level nested parallels with increment tasks153// first = nthreads of outer parallel154// second = nthreads of nested parallel155// third = nthreads of second nested parallel156// fourth = nthreads of third nested parallel157void test_nest3(int first, int second, int third, int fourth) {158#ifdef VERBOSE159#pragma omp master160  printf(" test_nest3(%d, %d, %d, %d)\n", first, second, third, fourth);161#endif162#pragma omp parallel num_threads(first)163  { test_nest2(second, third, fourth); }164}165 166// Testing 4-level nested parallels with increment tasks167// first = nthreads of outer parallel168// second = nthreads of nested parallel169// third = nthreads of second nested parallel170// fourth = nthreads of third nested parallel171// fifth = nthreads of fourth nested parallel172void test_nest4(int first, int second, int third, int fourth, int fifth) {173#ifdef VERBOSE174#pragma omp master175  printf("test_nest4(%d, %d, %d, %d, %d)\n", first, second, third, fourth,176         fifth);177#endif178#pragma omp parallel num_threads(first)179  { test_nest3(second, third, fourth, fifth); }180}181 182// Single thread starts a binary splitting "increment" task183// Detached tasks are still single "increment" task184void test_tasks_split(omp_event_handle_t *handles, int expected, int *a) {185  int tid = omp_get_thread_num();186 187#pragma omp single188  task_inc_split_a(a, 1, expected); // task team A189 190#pragma omp barrier191  check_a(a, expected);192#pragma omp barrier193  check_a(a, expected);194#pragma omp barrier195 196#ifdef USE_HIDDEN_HELPERS197  task_inc_a_hidden_helper(a);198#else199  task_inc_a_detached(a, handles[tid]);200#endif201 202#pragma omp barrier203  check_a(a, 2 * expected);204#pragma omp barrier205#pragma omp single206  task_inc_split_a(a, 1, expected); // task team B207#pragma omp barrier208  check_a(a, 3 * expected);209}210 211// Testing single level of parallelism with splitting incrementing tasks212void test_base_split(int nthreads) {213#ifdef VERBOSE214#pragma omp master215  printf("  test_base_split(%d)\n", nthreads);216#endif217  int a = 0;218  omp_event_handle_t *handles;219  handles = (omp_event_handle_t *)malloc(sizeof(omp_event_handle_t) * nthreads);220#pragma omp parallel num_threads(nthreads) shared(a)221  { test_tasks_split(handles, nthreads, &a); }222  free(handles);223}224 225// Testing nested parallels with splitting tasks226// first = nthreads of outer parallel227// second = nthreads of nested parallel228void test_nest_split(int first, int second) {229#ifdef VERBOSE230#pragma omp master231  printf(" test_nest_split(%d, %d)\n", first, second);232#endif233#pragma omp parallel num_threads(first)234  { test_base_split(second); }235}236 237// Testing doubly nested parallels with splitting tasks238// first = nthreads of outer parallel239// second = nthreads of nested parallel240// third = nthreads of second nested parallel241void test_nest2_split(int first, int second, int third) {242#ifdef VERBOSE243#pragma omp master244  printf("test_nest2_split(%d, %d, %d)\n", first, second, third);245#endif246#pragma omp parallel num_threads(first)247  { test_nest_split(second, third); }248}249 250template <typename... Args>251void run_ntimes(int n, void (*func)(Args...), Args... args) {252  for (int i = 0; i < n; ++i) {253    func(args...);254  }255}256 257int main() {258  omp_set_max_active_levels(5);259 260  run_ntimes(NTIMES, test_base, 4);261  run_ntimes(NTIMES, test_base, 1);262  run_ntimes(NTIMES, test_base, 8);263  run_ntimes(NTIMES, test_base, 2);264  run_ntimes(NTIMES, test_base, 6);265  run_ntimes(NTIMES, test_nest, 1, 1);266  run_ntimes(NTIMES, test_nest, 1, 5);267  run_ntimes(NTIMES, test_nest, 2, 6);268  run_ntimes(NTIMES, test_nest, 1, 1);269  run_ntimes(NTIMES, test_nest, 4, 3);270  run_ntimes(NTIMES, test_nest, 3, 2);271  run_ntimes(NTIMES, test_nest, 1, 1);272  run_ntimes(NTIMES, test_nest2, 1, 1, 2);273  run_ntimes(NTIMES, test_nest2, 1, 2, 1);274  run_ntimes(NTIMES, test_nest2, 2, 2, 1);275  run_ntimes(NTIMES, test_nest2, 2, 1, 1);276  run_ntimes(NTIMES, test_nest2, 4, 2, 1);277  run_ntimes(NTIMES, test_nest2, 4, 2, 2);278  run_ntimes(NTIMES, test_nest2, 1, 1, 1);279  run_ntimes(NTIMES, test_nest2, 4, 2, 2);280  run_ntimes(NTIMES, test_nest3, 1, 1, 1, 1);281  run_ntimes(NTIMES, test_nest3, 1, 2, 1, 1);282  run_ntimes(NTIMES, test_nest3, 1, 1, 2, 1);283  run_ntimes(NTIMES, test_nest3, 1, 1, 1, 2);284  run_ntimes(NTIMES, test_nest3, 2, 1, 1, 1);285  run_ntimes(NTIMES, test_nest4, 1, 1, 1, 1, 1);286  run_ntimes(NTIMES, test_nest4, 2, 1, 1, 1, 1);287  run_ntimes(NTIMES, test_nest4, 1, 2, 1, 1, 1);288  run_ntimes(NTIMES, test_nest4, 1, 1, 2, 1, 1);289  run_ntimes(NTIMES, test_nest4, 1, 1, 1, 2, 1);290  run_ntimes(NTIMES, test_nest4, 1, 1, 1, 1, 2);291  run_ntimes(NTIMES, test_nest4, 1, 1, 1, 1, 1);292  run_ntimes(NTIMES, test_nest4, 1, 2, 1, 2, 1);293 294  run_ntimes(NTIMES, test_base_split, 4);295  run_ntimes(NTIMES, test_base_split, 2);296 297  run_ntimes(NTIMES, test_base_split, 7);298 299  run_ntimes(NTIMES, test_base_split, 1);300  run_ntimes(NTIMES, test_nest_split, 4, 2);301  run_ntimes(NTIMES, test_nest_split, 2, 1);302 303  run_ntimes(NTIMES, test_nest_split, 7, 2);304  run_ntimes(NTIMES, test_nest_split, 1, 1);305  run_ntimes(NTIMES, test_nest_split, 1, 4);306 307  run_ntimes(NTIMES, test_nest2_split, 1, 1, 2);308  run_ntimes(NTIMES, test_nest2_split, 1, 2, 1);309  run_ntimes(NTIMES, test_nest2_split, 2, 2, 1);310  run_ntimes(NTIMES, test_nest2_split, 2, 1, 1);311  run_ntimes(NTIMES, test_nest2_split, 4, 2, 1);312  run_ntimes(NTIMES, test_nest2_split, 4, 2, 2);313  run_ntimes(NTIMES, test_nest2_split, 1, 1, 1);314  run_ntimes(NTIMES, test_nest2_split, 4, 2, 2);315 316  printf("PASS\n");317  return EXIT_SUCCESS;318}319