[Openmp-commits] [openmp] 9089b4a - [OpenMP] Introduce GOMP taskwait depend in the runtime
via Openmp-commits
openmp-commits at lists.llvm.org
Thu Sep 24 07:50:15 PDT 2020
Author: Peyton, Jonathan L
Date: 2020-09-24T09:45:14-05:00
New Revision: 9089b4a5c5b4271e6b8300cf5d7471d4ddd93bec
URL: https://github.com/llvm/llvm-project/commit/9089b4a5c5b4271e6b8300cf5d7471d4ddd93bec
DIFF: https://github.com/llvm/llvm-project/commit/9089b4a5c5b4271e6b8300cf5d7471d4ddd93bec.diff
LOG: [OpenMP] Introduce GOMP taskwait depend in the runtime
This change introduces the GOMP_taskwait_depend() function. It implements
the OpenMP 5.0 feature of #pragma omp taskwait with depend() clause by
wrapping around __kmpc_omp_wait_deps().
Differential Revision: https://reviews.llvm.org/D87269
Added:
openmp/runtime/test/tasking/omp50_taskwait_depend.c
Modified:
openmp/runtime/src/kmp_ftn_os.h
openmp/runtime/src/kmp_gsupport.cpp
Removed:
################################################################################
diff --git a/openmp/runtime/src/kmp_ftn_os.h b/openmp/runtime/src/kmp_ftn_os.h
index d8fdd83f29e4..39958e2dbc3a 100644
--- a/openmp/runtime/src/kmp_ftn_os.h
+++ b/openmp/runtime/src/kmp_ftn_os.h
@@ -680,5 +680,6 @@
#define KMP_API_NAME_GOMP_PARALLEL_LOOP_MAYBE_NONMONOTONIC_RUNTIME \
GOMP_parallel_loop_maybe_nonmonotonic_runtime
#define KMP_API_NAME_GOMP_TEAMS_REG GOMP_teams_reg
+#define KMP_API_NAME_GOMP_TASKWAIT_DEPEND GOMP_taskwait_depend
#endif /* KMP_FTN_OS_H */
diff --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp
index b2d1419c8da1..b02e18b9a98e 100644
--- a/openmp/runtime/src/kmp_gsupport.cpp
+++ b/openmp/runtime/src/kmp_gsupport.cpp
@@ -1867,6 +1867,19 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TEAMS_REG)(void (*fn)(void *),
KA_TRACE(20, ("GOMP_teams_reg exit: T#%d\n", gtid));
}
+void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKWAIT_DEPEND)(void **depend) {
+ MKLOC(loc, "GOMP_taskwait_depend");
+ int gtid = __kmp_entry_gtid();
+ KA_TRACE(20, ("GOMP_taskwait_depend: T#%d\n", gtid));
+ kmp_gomp_depends_info_t gomp_depends(depend);
+ kmp_int32 ndeps = gomp_depends.get_num_deps();
+ kmp_depend_info_t dep_list[ndeps];
+ for (kmp_int32 i = 0; i < ndeps; i++)
+ dep_list[i] = gomp_depends.get_kmp_depend(i);
+ __kmpc_omp_wait_deps(&loc, gtid, ndeps, dep_list, 0, NULL);
+ KA_TRACE(20, ("GOMP_taskwait_depend exit: T#%d\n", gtid));
+}
+
/* The following sections of code create aliases for the GOMP_* functions, then
create versioned symbols using the assembler directive .symver. This is only
pertinent for ELF .so library. The KMP_VERSION_SYMBOL macro is defined in
@@ -2039,6 +2052,7 @@ KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_PARALLEL_LOOP_NONMONOTONIC_RUNTIME, 50,
KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_PARALLEL_LOOP_MAYBE_NONMONOTONIC_RUNTIME,
50, "GOMP_5.0");
KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TEAMS_REG, 50, "GOMP_5.0");
+KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TASKWAIT_DEPEND, 50, "GOMP_5.0");
#endif // KMP_USE_VERSION_SYMBOLS
diff --git a/openmp/runtime/test/tasking/omp50_taskwait_depend.c b/openmp/runtime/test/tasking/omp50_taskwait_depend.c
new file mode 100644
index 000000000000..ee134e9a3826
--- /dev/null
+++ b/openmp/runtime/test/tasking/omp50_taskwait_depend.c
@@ -0,0 +1,108 @@
+// RUN: %libomp-compile-and-run
+// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
+// clang does not yet support taskwait with depend clause
+// clang-12 introduced parsing, but no codegen
+// TODO: update expected result when codegen in clang is added
+// icc does not yet support taskwait with depend clause
+// TODO: update expected result when support for icc is added
+// XFAIL: clang, icc
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+#include "omp_my_sleep.h"
+
+int a = 0, b = 0;
+int task_grabbed = 0, task_can_proceed = 0;
+int task2_grabbed = 0, task2_can_proceed = 0;
+
+static void wait_on_flag(int *flag) {
+ int flag_value;
+ int timelimit = 30;
+ int secs = 0;
+ do {
+ #pragma omp atomic read
+ flag_value = *flag;
+ my_sleep(1.0);
+ secs++;
+ if (secs == timelimit) {
+ fprintf(stderr, "error: timeout in wait_on_flag()\n");
+ exit(EXIT_FAILURE);
+ }
+ } while (flag_value == 0);
+}
+
+static void signal_flag(int *flag) {
+ #pragma omp atomic
+ (*flag)++;
+}
+
+int main(int argc, char** argv) {
+
+ // Ensure two threads are running
+ int num_threads = omp_get_max_threads();
+ if (num_threads < 2)
+ omp_set_num_threads(2);
+
+ #pragma omp parallel shared(a)
+ {
+ int a_value;
+ // Let us be extra safe here
+ if (omp_get_num_threads() > 1) {
+ #pragma omp single nowait
+ {
+ // Schedule independent child task that
+ // waits to be flagged after sebsequent taskwait depend()
+ #pragma omp task
+ {
+ signal_flag(&task_grabbed);
+ wait_on_flag(&task_can_proceed);
+ }
+ // Let another worker thread grab the task to execute
+ wait_on_flag(&task_grabbed);
+ // This should be ignored since the task above has
+ // no dependency information
+ #pragma omp taskwait depend(inout: a)
+ // Signal the independent task to proceed
+ signal_flag(&task_can_proceed);
+
+ // Schedule child task with dependencies that taskwait does
+ // not care about
+ #pragma omp task depend(inout: b)
+ {
+ signal_flag(&task2_grabbed);
+ wait_on_flag(&task2_can_proceed);
+ #pragma omp atomic
+ b++;
+ }
+ // Let another worker thread grab the task to execute
+ wait_on_flag(&task2_grabbed);
+ // This should be ignored since the task above has
+ // dependency information on b instead of a
+ #pragma omp taskwait depend(inout: a)
+ // Signal the task to proceed
+ signal_flag(&task2_can_proceed);
+
+ // Generate one child task for taskwait
+ #pragma omp task shared(a) depend(inout: a)
+ {
+ my_sleep(1.0);
+ #pragma omp atomic
+ a++;
+ }
+ #pragma omp taskwait depend(inout: a)
+
+ #pragma omp atomic read
+ a_value = a;
+
+ if (a_value != 1) {
+ fprintf(stderr, "error: dependent task was not executed before "
+ "taskwait finished\n");
+ exit(EXIT_FAILURE);
+ }
+ } // #pragma omp single
+ } // if (num_threads > 1)
+ } // #pragma omp parallel
+
+ return EXIT_SUCCESS;
+}
More information about the Openmp-commits
mailing list