[Openmp-commits] [openmp] ee1c04a - [OpenMP] Fix if0 task with dependencies in the runtime

via Openmp-commits openmp-commits at lists.llvm.org
Thu Sep 24 07:50:16 PDT 2020


Author: Peyton, Jonathan L
Date: 2020-09-24T09:47:53-05:00
New Revision: ee1c04a926904b34525e4577742d8c10a23db814

URL: https://github.com/llvm/llvm-project/commit/ee1c04a926904b34525e4577742d8c10a23db814
DIFF: https://github.com/llvm/llvm-project/commit/ee1c04a926904b34525e4577742d8c10a23db814.diff

LOG: [OpenMP] Fix if0 task with dependencies in the runtime

The current GOMP interface for serialized tasks does not take into
account task dependencies. Add the check and wait for dependencies.

Fixes: https://bugs.llvm.org/show_bug.cgi?id=46573

Differential Revision: https://reviews.llvm.org/D87271

Added: 
    openmp/runtime/test/tasking/taskdep_if0.c
    openmp/runtime/test/tasking/taskdep_if0_2.c

Modified: 
    openmp/runtime/src/kmp_gsupport.cpp

Removed: 
    


################################################################################
diff  --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp
index b02e18b9a98e..4312e25499d8 100644
--- a/openmp/runtime/src/kmp_gsupport.cpp
+++ b/openmp/runtime/src/kmp_gsupport.cpp
@@ -17,6 +17,12 @@
 #include "ompt-specific.h"
 #endif
 
+enum {
+  KMP_GOMP_TASK_UNTIED_FLAG = 1,
+  KMP_GOMP_TASK_FINAL_FLAG = 2,
+  KMP_GOMP_TASK_DEPENDS_FLAG = 8
+};
+
 // This class helps convert gomp dependency info into
 // kmp_depend_info_t structures
 class kmp_gomp_depends_info_t {
@@ -1181,11 +1187,11 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
   KA_TRACE(20, ("GOMP_task: T#%d\n", gtid));
 
   // The low-order bit is the "untied" flag
-  if (!(gomp_flags & 1)) {
+  if (!(gomp_flags & KMP_GOMP_TASK_UNTIED_FLAG)) {
     input_flags->tiedness = 1;
   }
   // The second low-order bit is the "final" flag
-  if (gomp_flags & 2) {
+  if (gomp_flags & KMP_GOMP_TASK_FINAL_FLAG) {
     input_flags->final = 1;
   }
   input_flags->native = 1;
@@ -1223,7 +1229,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
 #endif
 
   if (if_cond) {
-    if (gomp_flags & 8) {
+    if (gomp_flags & KMP_GOMP_TASK_DEPENDS_FLAG) {
       KMP_ASSERT(depend);
       kmp_gomp_depends_info_t gomp_depends(depend);
       kmp_int32 ndeps = gomp_depends.get_num_deps();
@@ -1250,6 +1256,15 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
       OMPT_STORE_RETURN_ADDRESS(gtid);
     }
 #endif
+    if (gomp_flags & KMP_GOMP_TASK_DEPENDS_FLAG) {
+      KMP_ASSERT(depend);
+      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);
+    }
 
     __kmpc_omp_task_begin_if0(&loc, gtid, task);
     func(data);

diff  --git a/openmp/runtime/test/tasking/taskdep_if0.c b/openmp/runtime/test/tasking/taskdep_if0.c
new file mode 100644
index 000000000000..9e44d5542163
--- /dev/null
+++ b/openmp/runtime/test/tasking/taskdep_if0.c
@@ -0,0 +1,39 @@
+// RUN: %libomp-compile-and-run
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+#include "omp_my_sleep.h"
+
+int a = 0;
+
+void task1() {
+  my_sleep(0.5);
+  a = 10;
+}
+
+void task2() {
+  a++;
+}
+
+int main(int argc, char** argv)
+{
+  #pragma omp parallel shared(argc) num_threads(2)
+  {
+    #pragma omp single
+    {
+      #pragma omp task depend(out: a)
+      task1();
+
+      #pragma omp task if(0) depend(inout: a)
+      task2();
+    }
+  }
+  if (a != 11) {
+    fprintf(stderr, "fail: expected 11, but a is %d\n", a);
+    exit(1);
+  } else {
+    printf("pass\n");
+  }
+  return 0;
+}

diff  --git a/openmp/runtime/test/tasking/taskdep_if0_2.c b/openmp/runtime/test/tasking/taskdep_if0_2.c
new file mode 100644
index 000000000000..6f0dff4bb755
--- /dev/null
+++ b/openmp/runtime/test/tasking/taskdep_if0_2.c
@@ -0,0 +1,104 @@
+// RUN: %libomp-compile-and-run
+
+#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 task if(0) 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 task if(0) 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 task if(0) 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