[Openmp-commits] [openmp] 028cf8c - [OpenMP] Implement printing TDGs to dot files

Jose M Monsalve Diaz via Openmp-commits openmp-commits at lists.llvm.org
Mon Jun 19 06:30:00 PDT 2023


Author: Adrian Munera
Date: 2023-06-19T08:27:38-05:00
New Revision: 028cf8c016b21961bd229f24ddffcad1cb95aa7a

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

LOG: [OpenMP] Implement printing TDGs to dot files

This patch implements the "__kmp_print_tdg_dot" function, that prints a task dependency graph into a dot file containing the tasks and their dependencies.

It is activated through a new environment variable "KMP_TDG_DOT"

Reviewed By: tianshilei1992

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

Added: 
    openmp/runtime/test/tasking/omp_record_replay_print_dot.cpp

Modified: 
    openmp/runtime/src/kmp.h
    openmp/runtime/src/kmp_global.cpp
    openmp/runtime/src/kmp_settings.cpp
    openmp/runtime/src/kmp_tasking.cpp

Removed: 
    


################################################################################
diff  --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index 251a5f0ce76fd..f50fb01f793f0 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -2535,6 +2535,7 @@ typedef struct kmp_tdg_info {
   kmp_int32 rec_num_taskred;
 } kmp_tdg_info_t;
 
+extern int __kmp_tdg_dot;
 extern kmp_int32 __kmp_max_tdgs;
 extern kmp_tdg_info_t **__kmp_global_tdgs;
 extern kmp_int32 __kmp_curr_tdg_idx;

diff  --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp
index 9557c519f835a..4ce0691abf8d6 100644
--- a/openmp/runtime/src/kmp_global.cpp
+++ b/openmp/runtime/src/kmp_global.cpp
@@ -559,6 +559,7 @@ int *__kmp_nesting_nth_level;
 
 #if OMPX_TASKGRAPH
 // TDG record & replay
+int __kmp_tdg_dot = 0;
 kmp_int32 __kmp_max_tdgs = 100;
 kmp_tdg_info_t **__kmp_global_tdgs = NULL;
 kmp_int32 __kmp_curr_tdg_idx =

diff  --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp
index 7092d6eb9104c..181db20a5f58d 100644
--- a/openmp/runtime/src/kmp_settings.cpp
+++ b/openmp/runtime/src/kmp_settings.cpp
@@ -1267,6 +1267,16 @@ static void __kmp_std_print_max_tdgs(kmp_str_buf_t *buffer, char const *name,
                                      void *data) {
   __kmp_stg_print_int(buffer, name, __kmp_max_tdgs);
 } // __kmp_std_print_max_tdgs
+
+static void __kmp_stg_parse_tdg_dot(char const *name, char const *value,
+                                   void *data) {
+  __kmp_stg_parse_bool(name, value, &__kmp_tdg_dot);
+} // __kmp_stg_parse_tdg_dot
+
+static void __kmp_stg_print_tdg_dot(kmp_str_buf_t *buffer, char const *name,
+                                   void *data) {
+  __kmp_stg_print_bool(buffer, name, __kmp_tdg_dot);
+} // __kmp_stg_print_tdg_dot
 #endif
 
 static void __kmp_stg_parse_num_hidden_helper_threads(char const *name,
@@ -5624,6 +5634,7 @@ static kmp_setting_t __kmp_stg_table[] = {
 #if OMPX_TASKGRAPH
     {"KMP_MAX_TDGS", __kmp_stg_parse_max_tdgs, __kmp_std_print_max_tdgs, NULL,
      0, 0},
+    {"KMP_TDG_DOT", __kmp_stg_parse_tdg_dot, __kmp_stg_print_tdg_dot, NULL, 0, 0},
 #endif
 
 #if OMPT_SUPPORT

diff  --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp
index ee452440176bf..fefa609927e89 100644
--- a/openmp/runtime/src/kmp_tasking.cpp
+++ b/openmp/runtime/src/kmp_tasking.cpp
@@ -5467,6 +5467,39 @@ static kmp_tdg_info_t *__kmp_find_tdg(kmp_int32 tdg_id) {
   return res;
 }
 
+// __kmp_print_tdg_dot: prints the TDG to a dot file
+// tdg:    ID of the TDG
+void __kmp_print_tdg_dot(kmp_tdg_info_t *tdg) {
+  kmp_int32 tdg_id = tdg->tdg_id;
+  KA_TRACE(10, ("__kmp_print_tdg_dot(enter): T#%d tdg_id=%d \n", gtid, tdg_id));
+
+  char file_name[20];
+  sprintf(file_name, "tdg_%d.dot", tdg_id);
+  kmp_safe_raii_file_t tdg_file(file_name, "w");
+
+  kmp_int32 num_tasks = KMP_ATOMIC_LD_RLX(&tdg->num_tasks);
+  fprintf(tdg_file,
+          "digraph TDG {\n"
+          "   compound=true\n"
+          "   subgraph cluster {\n"
+          "      label=TDG_%d\n",
+          tdg_id);
+  for (kmp_int32 i = 0; i < num_tasks; i++) {
+    fprintf(tdg_file, "      %d[style=bold]\n", i);
+  }
+  fprintf(tdg_file, "   }\n");
+  for (kmp_int32 i = 0; i < num_tasks; i++) {
+    kmp_int32 nsuccessors = tdg->record_map[i].nsuccessors;
+    kmp_int32 *successors = tdg->record_map[i].successors;
+    if (nsuccessors > 0) {
+      for (kmp_int32 j = 0; j < nsuccessors; j++)
+        fprintf(tdg_file, "   %d -> %d \n", i, successors[j]);
+    }
+  }
+  fprintf(tdg_file, "}");
+  KA_TRACE(10, ("__kmp_print_tdg_dot(exit): T#%d tdg_id=%d \n", gtid, tdg_id));
+}
+
 // __kmp_start_record: launch the execution of a previous
 // recorded TDG
 // gtid:   Global Thread ID
@@ -5636,6 +5669,9 @@ void __kmp_end_record(kmp_int32 gtid, kmp_tdg_info_t *tdg) {
                       this_record_map[i].npredecessors);
   }
   KMP_ATOMIC_ST_RLX(&__kmp_tdg_task_id, 0);
+
+  if (__kmp_tdg_dot)
+    __kmp_print_tdg_dot(tdg);
 }
 
 // __kmpc_end_record_task: wrapper around __kmp_end_record to mark

diff  --git a/openmp/runtime/test/tasking/omp_record_replay_print_dot.cpp b/openmp/runtime/test/tasking/omp_record_replay_print_dot.cpp
new file mode 100644
index 0000000000000..2fe55f0815429
--- /dev/null
+++ b/openmp/runtime/test/tasking/omp_record_replay_print_dot.cpp
@@ -0,0 +1,80 @@
+// REQUIRES: ompx_taskgraph
+// RUN: %libomp-cxx-compile-and-run
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cassert>
+
+// Compiler-generated code (emulation)
+typedef struct ident {
+    void* dummy;
+} ident_t;
+
+#ifdef __cplusplus
+extern "C" {
+  int __kmpc_global_thread_num(ident_t *);
+  int __kmpc_start_record_task(ident_t *, int, int, int);
+  void __kmpc_end_record_task(ident_t *, int, int , int);
+}
+#endif
+
+void func(int *num_exec) {
+  #pragma omp atomic
+  (*num_exec)++;
+}
+
+std::string tdg_string= "digraph TDG {\n"
+"   compound=true\n"
+"   subgraph cluster {\n"
+"      label=TDG_0\n"
+"      0[style=bold]\n"
+"      1[style=bold]\n"
+"      2[style=bold]\n"
+"      3[style=bold]\n"
+"   }\n"
+"   0 -> 1 \n"
+"   1 -> 2 \n"
+"   1 -> 3 \n"
+"}";
+
+int main() {
+  int num_exec = 0;
+  int x, y;
+
+  setenv("KMP_TDG_DOT","TRUE",1);
+  remove("tdg_0.dot");
+
+  #pragma omp parallel
+  #pragma omp single
+  {
+    int gtid = __kmpc_global_thread_num(nullptr);
+    int res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
+    if (res) {
+      #pragma omp task depend(out : x)
+      func(&num_exec);
+      #pragma omp task depend(in : x) depend(out : y)
+      func(&num_exec);
+      #pragma omp task depend(in : y)
+      func(&num_exec);
+      #pragma omp task depend(in : y)
+      func(&num_exec);
+    }
+
+    __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
+  }
+
+  assert(num_exec == 4);
+
+  std::ifstream tdg_file("tdg_0.dot");
+  assert(tdg_file.is_open());
+
+  std::stringstream tdg_file_stream;
+  tdg_file_stream << tdg_file.rdbuf();
+  int equal = tdg_string.compare(tdg_file_stream.str());
+
+  assert(equal == 0);
+
+  std::cout << "Passed" << std::endl;
+  return 0;
+}
+// CHECK: Passed


        


More information about the Openmp-commits mailing list