diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -2535,6 +2535,7 @@ 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 --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/runtime/src/kmp_global.cpp @@ -559,6 +559,7 @@ #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 --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -1248,6 +1248,16 @@ 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, @@ -5607,6 +5617,7 @@ #if OMPX_TASKGRAPH {"KMP_MAX_TDGS", __kmp_stg_parse_max_tdgs, __kmp_std_print_max_tdgs, NULL, 0, 0}, + {"OMP_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 --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -5466,6 +5466,37 @@ 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 @@ -5635,6 +5666,9 @@ 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