LCOV - code coverage report
Current view: top level - src/base - openmp_trace.c (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 1 1 100.0 %
Date: 2024-11-21 06:45:46 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*----------------------------------------------------------------------------*/
       2             : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3             : /*  Copyright 2000-2024 CP2K developers group <https://cp2k.org>              */
       4             : /*                                                                            */
       5             : /*  SPDX-License-Identifier: GPL-2.0-or-later                                 */
       6             : /*----------------------------------------------------------------------------*/
       7             : #define OPENMP_TRACE_DISABLED ((unsigned int)-1)
       8             : 
       9             : /* routine is exposed in Fortran, hence must be present */
      10             : int openmp_trace_issues(void);
      11             : 
      12             : /**
      13             :  * Simple compile-time check if OMPT is available (omp/iomp, not gomp).
      14             :  * __clang__: omp and iomp/icx, __INTEL_COMPILER: iomp/icc
      15             :  * __INTEL_LLVM_COMPILER: already covered by __clang__
      16             :  */
      17             : #if defined(_OPENMP) && (defined(__clang__) || defined(__INTEL_COMPILER))
      18             : 
      19             : #include <assert.h>
      20             : #include <omp-tools.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : 
      25             : #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(OPENMP_TRACE_SYMBOL)
      26             : #define OPENMP_TRACE_SYMBOL
      27             : #include <execinfo.h>
      28             : #include <unistd.h>
      29             : #endif
      30             : 
      31             : #define OPENMP_TRACE_UNUSED(VAR) (void)VAR
      32             : 
      33             : #define OPENMP_TRACE_SET_CALLBACK(PREFIX, NAME)                                \
      34             :   if (ompt_set_never ==                                                        \
      35             :       set_callback(ompt_callback_##NAME, (ompt_callback_t)PREFIX##_##NAME)) {  \
      36             :     ++openmp_trace_issues_count;                                               \
      37             :   }
      38             : 
      39             : static unsigned int openmp_trace_level;
      40             : static unsigned int openmp_trace_issues_count;
      41             : static unsigned int openmp_trace_parallel_count;
      42             : static unsigned int openmp_trace_parallel_count_max;
      43             : 
      44             : static const void *openmp_trace_parallel_nested_codeptr;
      45             : static const void *openmp_trace_master_codeptr;
      46             : 
      47             : int openmp_trace_issues(void) { return (int)openmp_trace_issues_count; }
      48             : 
      49             : /* attempt to translate symbol/address to character string */
      50             : static void openmp_trace_symbol(const void *symbol, char *buffer, size_t size,
      51             :                                 int cleanup) {
      52             : #if !defined(OPENMP_TRACE_SYMBOL)
      53             :   OPENMP_TRACE_UNUSED(symbol);
      54             :   if (0 < size) {
      55             :     buffer[0] = '\0';
      56             :   }
      57             : #else
      58             :   int pipefd[2];
      59             :   if (NULL != symbol && NULL != buffer && 0 < size && 0 == pipe(pipefd)) {
      60             :     void *const backtrace[] = {(void *)symbol};
      61             :     backtrace_symbols_fd(backtrace, 1, pipefd[1]);
      62             :     close(pipefd[1]);
      63             :     if (0 < read(pipefd[0], buffer, size)) {
      64             :       if (0 != cleanup) {
      65             :         char *const str = (char *)memchr(buffer, '(', size);
      66             :         if (NULL != str) {
      67             :           char *const end = (char *)memchr(str + 1, '+', size - (str - buffer));
      68             :           if (NULL != end) {
      69             :             *end = '\0';
      70             :             memmove(buffer, str + 1, end - str);
      71             :           }
      72             :         }
      73             :       } else {
      74             :         char *const str = (char *)memchr(buffer, '\n', size);
      75             :         if (NULL != str) {
      76             :           *str = '\0';
      77             :         }
      78             :       }
      79             :     } else {
      80             :       buffer[0] = '\0';
      81             :     }
      82             :     close(pipefd[0]);
      83             :   }
      84             : #endif
      85             : }
      86             : 
      87             : /* https://www.openmp.org/spec-html/5.0/openmpsu187.html */
      88             : static void openmp_trace_parallel_begin(
      89             :     ompt_data_t *encountering_task_data,
      90             :     const ompt_frame_t *encountering_task_frame, ompt_data_t *parallel_data,
      91             :     unsigned int requested_parallelism, int flags, const void *codeptr_ra) {
      92             :   OPENMP_TRACE_UNUSED(encountering_task_data);
      93             :   OPENMP_TRACE_UNUSED(encountering_task_frame);
      94             :   OPENMP_TRACE_UNUSED(parallel_data);
      95             :   OPENMP_TRACE_UNUSED(requested_parallelism);
      96             :   OPENMP_TRACE_UNUSED(flags);
      97             :   ++openmp_trace_parallel_count;
      98             :   if (openmp_trace_parallel_count_max < openmp_trace_parallel_count) {
      99             :     openmp_trace_parallel_count_max = openmp_trace_parallel_count;
     100             :     openmp_trace_parallel_nested_codeptr = codeptr_ra;
     101             :   }
     102             :   if (NULL != openmp_trace_master_codeptr) {
     103             :     ++openmp_trace_issues_count;
     104             :     if (2 <= openmp_trace_level || 0 > openmp_trace_level) {
     105             :       char sym_master[1024], sym_parallel[1024];
     106             :       openmp_trace_symbol(openmp_trace_master_codeptr, sym_master,
     107             :                           sizeof(sym_master), 1 /*cleanup*/);
     108             :       openmp_trace_symbol(codeptr_ra, sym_parallel, sizeof(sym_parallel),
     109             :                           1 /*cleanup*/);
     110             :       if ('\0' != *sym_master && '\0' != *sym_parallel) {
     111             :         fprintf(stderr,
     112             :                 "OMP TRACE ERROR: parallel region \"%s\""
     113             :                 " opened in master section \"%s\"\n",
     114             :                 sym_parallel, sym_master);
     115             :       } else {
     116             :         fprintf(stderr,
     117             :                 "OMP TRACE ERROR: parallel region opened in master section\n");
     118             :       }
     119             :     } else {
     120             :       assert(0);
     121             :     }
     122             :   }
     123             : }
     124             : 
     125             : /* https://www.openmp.org/spec-html/5.0/openmpsu187.html */
     126             : static void openmp_trace_parallel_end(ompt_data_t *parallel_data,
     127             :                                       ompt_data_t *encountering_task_data,
     128             :                                       int flags, const void *codeptr_ra) {
     129             :   OPENMP_TRACE_UNUSED(parallel_data);
     130             :   OPENMP_TRACE_UNUSED(encountering_task_data);
     131             :   OPENMP_TRACE_UNUSED(flags);
     132             :   OPENMP_TRACE_UNUSED(codeptr_ra);
     133             :   if (0 < openmp_trace_parallel_count) {
     134             :     --openmp_trace_parallel_count;
     135             :   }
     136             : }
     137             : 
     138             : /* https://www.openmp.org/spec-html/5.0/openmpsu187.html */
     139             : static void openmp_trace_master(ompt_scope_endpoint_t endpoint,
     140             :                                 ompt_data_t *parallel_data,
     141             :                                 ompt_data_t *task_data,
     142             :                                 const void *codeptr_ra) {
     143             :   OPENMP_TRACE_UNUSED(parallel_data);
     144             :   OPENMP_TRACE_UNUSED(task_data);
     145             :   switch (endpoint) {
     146             :   case ompt_scope_begin: {
     147             :     openmp_trace_master_codeptr = codeptr_ra;
     148             :   } break;
     149             :   case ompt_scope_end: {
     150             :     openmp_trace_master_codeptr = NULL;
     151             :   } break;
     152             :   default:; /* ompt_scope_beginend */
     153             :   }
     154             : }
     155             : 
     156             : /* initially, events of interest are registered */
     157             : static int openmp_trace_initialize(ompt_function_lookup_t lookup,
     158             :                                    int initial_device_num,
     159             :                                    ompt_data_t *tool_data) {
     160             :   const ompt_set_callback_t set_callback =
     161             :       (ompt_set_callback_t)lookup("ompt_set_callback");
     162             :   OPENMP_TRACE_UNUSED(initial_device_num);
     163             :   OPENMP_TRACE_UNUSED(tool_data);
     164             :   OPENMP_TRACE_SET_CALLBACK(openmp_trace, parallel_begin);
     165             :   OPENMP_TRACE_SET_CALLBACK(openmp_trace, parallel_end);
     166             :   OPENMP_TRACE_SET_CALLBACK(openmp_trace, master);
     167             :   return 0 == openmp_trace_issues();
     168             : }
     169             : 
     170             : /* here tool_data might be freed and analysis concludes */
     171             : static void openmp_trace_finalize(ompt_data_t *tool_data) {
     172             :   OPENMP_TRACE_UNUSED(tool_data);
     173             :   if (3 <= openmp_trace_level || 0 > openmp_trace_level) {
     174             :     if (1 < openmp_trace_parallel_count_max) { /* nested */
     175             :       char sym_parallel[1024];
     176             :       openmp_trace_symbol(openmp_trace_parallel_nested_codeptr, sym_parallel,
     177             :                           sizeof(sym_parallel), 1 /*cleanup*/);
     178             :       if ('\0' != *sym_parallel) {
     179             :         fprintf(stderr,
     180             :                 "OMP TRACE INFO: maximal nested parallelism "
     181             :                 "in \"%s\" has depth %u\n",
     182             :                 sym_parallel, openmp_trace_parallel_count_max);
     183             :       } else {
     184             :         fprintf(stderr,
     185             :                 "OMP TRACE INFO: maximal nested parallelism has depth %u\n",
     186             :                 openmp_trace_parallel_count_max);
     187             :       }
     188             :     }
     189             :   }
     190             : }
     191             : 
     192             : /* entry point which is automatically called by the OpenMP runtime */
     193             : ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version,
     194             :                                           const char *runtime_version) {
     195             :   static ompt_start_tool_result_t openmp_start_tool = {
     196             :       openmp_trace_initialize, openmp_trace_finalize, {0}};
     197             :   const char *const enabled_env = getenv("CP2K_OMP_TRACE");
     198             :   ompt_start_tool_result_t *result = NULL;
     199             :   openmp_trace_level = (NULL == enabled_env ? 0 : atoi(enabled_env));
     200             :   OPENMP_TRACE_UNUSED(omp_version);
     201             :   OPENMP_TRACE_UNUSED(runtime_version);
     202             :   if (0 == openmp_trace_level) { /* not enabled */
     203             :     openmp_trace_issues_count = OPENMP_TRACE_DISABLED;
     204             :     assert(NULL == result);
     205             :   } else { /* trace OpenMP constructs */
     206             :     assert(0 == openmp_trace_issues_count);
     207             :     result = &openmp_start_tool;
     208             :   }
     209             :   return result;
     210             : }
     211             : 
     212             : #else
     213             : 
     214        9334 : int openmp_trace_issues(void) { return OPENMP_TRACE_DISABLED; }
     215             : 
     216             : #endif

Generated by: LCOV version 1.15