User API + reorganized lib folders (#30)

* User API + reorganized lib folders

- omnitrace_user_start_trace
- omnitrace_user_stop_trace
- omnitrace_user_start_thread_trace
- omnitrace_user_stop_thread_trace
- omnitrace_user_push_region
- omnitrace_user_pop_region

* New OpenMP examples/tests

* Fix to KokkosP

* OMPT support

- fixed omnitrace instrumenting reporting
- common invoke improvements
- component::user_region

* exclude kmp_threadprivate_

* Separate omnitrace into multiple files

* PTL and timemory submodule updates

* Active guards + USE_OMPT guards in omnitrace-dl

* Tweak transpose default iterations

* omnitrace-precommit build target

* Omnitrace exe restructuring pt 2

- Never instrument functions with less than 4 instructions
- Never instrument ompt_start_tool or nanosleep
- module_function serializes heuristics
- removed hash stuff from omnitrace
- removed instr_procedures lambda
- WAITPID_DEBUG_MESSAGE

* set_state, "_hidden" fix, CI exceptions, backtrace fix

- set_state function
- fixed "_hidden" from appearing in print macros using __FUNCTION__
- OMNITRACE_CI_THROW
- more CI checks in library
- fixed backtrace init value sample issue being ignored

* Tweaks to OMPT tests

* cmake-formatting

* Removed debug output from backtrace processing

* Fix warnings and verbosity

* omnitrace-dl fix for libomp

* omnitrace-avail fixes

- remove second omnitrace_init_library call
- fix -r option not working

* Additional testing

- source/bin/tests
- tests for omnitrace-exe
- tests for omnitrace-avail

* cmake-format

* Reduce runtime of openmp-lu

* Update openmp-lu and tests timeout

* openmp-lu and CI tweaks

- decrease iterations
- OMP_NUM_THREADS=2
- install clang and libomp-dev in linux-ci
- fix data-files in linux-ci
Cette révision appartient à :
Jonathan R. Madsen
2022-03-07 20:40:48 -06:00
révisé par GitHub
Parent 2acaa7aa9f
révision d80752bc69
106 fichiers modifiés avec 9180 ajouts et 1947 suppressions
+17
Voir le fichier
@@ -35,6 +35,23 @@ parse:
PUBLIC: '*'
PRIVATE: '*'
INTERFACE: '*'
omnitrace_add_bin_test:
flags:
- WILL_FAIL
kwargs:
NAME: '*'
ARGS: '*'
LABELS: '*'
TARGET: '*'
DEPENDS: '*'
COMMAND: '*'
TIMEOUT: '*'
PROPERTIES: '*'
ENVIRONMENT: '*'
WORKING_DIRECTORY: '*'
PASS_REGULAR_EXPRESSION: '*'
FAIL_REGULAR_EXPRESSION: '*'
SKIP_REGULAR_EXPRESSION: '*'
override_spec: {}
vartags: []
proptags: []
+8 -8
Voir le fichier
@@ -28,7 +28,7 @@ jobs:
timeout-minutes: 5
run:
sudo apt-get update &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libtbb-dev libboost-{atomic,system,thread,date-time,filesystem,timer}-dev ${{ matrix.compiler }} ${{ matrix.mpi }} &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libtbb-dev libboost-{atomic,system,thread,date-time,filesystem,timer}-dev clang libomp-dev ${{ matrix.compiler }} ${{ matrix.mpi }} &&
python3 -m pip install --upgrade pip &&
python3 -m pip install 'cmake==3.16.3'
@@ -107,7 +107,7 @@ jobs:
with:
name: data-files
path: |
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
ubuntu-bionic:
runs-on: ubuntu-18.04
@@ -202,7 +202,7 @@ jobs:
with:
name: data-files
path: |
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
ubuntu-focal-external:
runs-on: ubuntu-20.04
@@ -217,7 +217,7 @@ jobs:
timeout-minutes: 5
run:
sudo apt-get update &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev clang libomp-dev ${{ matrix.compiler }} &&
sudo python3 -m pip install --upgrade pip &&
python3 -m pip install 'cmake==3.16.3'
@@ -321,7 +321,7 @@ jobs:
with:
name: data-files
path: |
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
ubuntu-focal-dyninst-package:
runs-on: ubuntu-20.04
@@ -336,7 +336,7 @@ jobs:
timeout-minutes: 5
run:
sudo apt-get update &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip ${{ matrix.compiler }} &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip clang libomp-dev ${{ matrix.compiler }} &&
sudo python3 -m pip install --upgrade pip &&
python3 -m pip install 'cmake==3.16.3'
@@ -432,7 +432,7 @@ jobs:
with:
name: data-files
path: |
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
ubuntu-focal-external-rocm:
runs-on: ubuntu-20.04
@@ -454,7 +454,7 @@ jobs:
sudo wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | sudo apt-key add - &&
echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/${{ matrix.rocm_version }}/ ubuntu main" | sudo tee /etc/apt/sources.list.d/rocm.list &&
sudo apt-get update &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} libudev-dev libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev clang libomp-dev ${{ matrix.compiler }} libudev-dev libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
sudo python3 -m pip install --upgrade pip &&
python3 -m pip install 'cmake==3.16.3'
+14 -4
Voir le fichier
@@ -74,7 +74,9 @@ omnitrace_add_option(
${OMNITRACE_USE_HIP})
omnitrace_add_option(OMNITRACE_USE_MPI_HEADERS
"Enable wrapping MPI functions w/o enabling MPI dependency" OFF)
omnitrace_add_option(OMNITRACE_USE_OMPT "Enable OpenMP tools support" OFF)
omnitrace_add_option(OMNITRACE_BUILD_DYNINST "Build dyninst from submodule" OFF)
omnitrace_add_option(OMNITRACE_BUILD_EXAMPLES "Enable building the examples" OFF)
omnitrace_add_option(OMNITRACE_BUILD_TESTING "Enable building the testing suite" OFF)
omnitrace_add_option(OMNITRACE_CUSTOM_DATA_SOURCE "Enable custom data source" OFF)
omnitrace_add_option(OMNITRACE_BUILD_HIDDEN_VISIBILITY
@@ -98,6 +100,12 @@ if(NOT OMNITRACE_USE_HIP)
CACHE BOOL "Disabled via OMNITRACE_USE_HIP=OFF" FORCE)
endif()
if(OMNITRACE_BUILD_TESTING)
set(OMNITRACE_BUILD_EXAMPLES
ON
CACHE BOOL "Enable building the examples" FORCE)
endif()
include(ProcessorCount)
processorcount(OMNITRACE_PROCESSOR_COUNT)
math(EXPR OMNITRACE_THREAD_COUNT "16 * ${OMNITRACE_PROCESSOR_COUNT}")
@@ -151,6 +159,11 @@ if(OMNITRACE_BUILD_HIDDEN_VISIBILITY)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
endif()
if(OMNITRACE_BUILD_TESTING)
include(CTest)
enable_testing()
endif()
# ------------------------------------------------------------------------------#
#
# library and executables
@@ -193,7 +206,7 @@ if(OMNITRACE_BUILD_LTO)
omnitrace_restore_variables(LTO VARIABLES CMAKE_INTERPROCEDURAL_OPTIMIZATION)
endif()
if(OMNITRACE_BUILD_TESTING)
if(OMNITRACE_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
@@ -204,9 +217,6 @@ endif()
# ------------------------------------------------------------------------------#
if(OMNITRACE_BUILD_TESTING)
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
+25 -5
Voir le fichier
@@ -40,25 +40,45 @@ endmacro()
find_program(OMNITRACE_CLANG_FORMAT_EXE NAMES clang-format-11 clang-format-mp-11
clang-format)
find_program(OMNITRACE_CMAKE_FORMAT_EXE NAMES cmake-format)
if(OMNITRACE_CLANG_FORMAT_EXE)
file(GLOB_RECURSE sources ${PROJECT_SOURCE_DIR}/source/*.cpp)
file(GLOB_RECURSE headers ${PROJECT_SOURCE_DIR}/source/*.hpp
${PROJECT_SOURCE_DIR}/source/*.hpp.in)
${PROJECT_SOURCE_DIR}/source/*.hpp.in ${PROJECT_SOURCE_DIR}/source/*.h
${PROJECT_SOURCE_DIR}/source/*.h.in)
file(GLOB_RECURSE examples ${PROJECT_SOURCE_DIR}/examples/*.cpp
${PROJECT_SOURCE_DIR}/examples/*.hpp)
file(GLOB_RECURSE external ${PROJECT_SOURCE_DIR}/examples/lulesh/external/*.cpp
${PROJECT_SOURCE_DIR}/examples/lulesh/external/*.hpp)
file(GLOB_RECURSE external ${PROJECT_SOURCE_DIR}/examples/lulesh/external/kokkos/*)
file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/source/*CMakeLists.txt
${PROJECT_SOURCE_DIR}/examples/*CMakeLists.txt
${PROJECT_SOURCE_DIR}/tests/*CMakeLists.txt ${PROJECT_SOURCE_DIR}/cmake/*.cmake)
list(APPEND cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt)
if(external)
list(REMOVE_ITEM examples ${external})
list(REMOVE_ITEM cmake_files ${external})
endif()
add_custom_target(
format-omnitrace
format-omnitrace-source
${OMNITRACE_CLANG_FORMAT_EXE} -i ${sources} ${headers} ${examples}
COMMENT "Running C++ formatter ${OMNITRACE_CLANG_FORMAT_EXE}...")
COMMENT "[omnitrace] Running C++ formatter ${OMNITRACE_CLANG_FORMAT_EXE}...")
add_custom_target(format-omnitrace)
add_dependencies(format-omnitrace format-omnitrace-source)
if(NOT TARGET format)
add_custom_target(format)
endif()
add_dependencies(format format-omnitrace)
if(OMNITRACE_CMAKE_FORMAT_EXE)
add_custom_target(
format-omnitrace-cmake
${OMNITRACE_CMAKE_FORMAT_EXE} -i ${cmake_files}
COMMENT "[omnitrace] Running CMake formatter ${OMNITRACE_CMAKE_FORMAT_EXE}..."
)
if(NOT TARGET format-cmake)
add_custom_target(format-cmake)
endif()
add_dependencies(format-cmake format-omnitrace-cmake)
endif()
else()
message(
AUTHOR_WARNING
+17 -7
Voir le fichier
@@ -350,6 +350,9 @@ set(TIMEMORY_USE_GOTCHA
set(TIMEMORY_USE_PERFETTO
OFF
CACHE BOOL "Disable perfetto support in timemory")
set(TIMEMORY_USE_OMPT
${OMNITRACE_USE_OMPT}
CACHE BOOL "Enable OMPT support in timemory" FORCE)
set(TIMEMORY_USE_LIBUNWIND
ON
CACHE BOOL "Enable libunwind support in timemory")
@@ -369,7 +372,9 @@ set(TIMEMORY_BUILD_EXTRA_OPTIMIZATIONS
set(TIMEMORY_TLS_MODEL
"global-dynamic"
CACHE STRING "Thread-local static model" FORCE)
set(TIMEMORY_MAX_THREADS
"${OMNITRACE_MAX_THREADS}"
CACHE STRING "Max statically-allocated threads" FORCE)
set(TIMEMORY_SETTINGS_PREFIX
"OMNITRACE_"
CACHE STRING "Prefix used for settings and environment variables")
@@ -430,19 +435,24 @@ if(NOT TARGET PTL::ptl-shared)
omnitrace_save_variables(
BUILD_CONFIG
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS CMAKE_POSITION_INDEPENDENT_CODE
CMAKE_CXX_VISIBILITY_PRESET CMAKE_VISIBILITY_INLINES_HIDDEN)
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS BUILD_OBJECT_LIBS
CMAKE_POSITION_INDEPENDENT_CODE CMAKE_CXX_VISIBILITY_PRESET
CMAKE_VISIBILITY_INLINES_HIDDEN)
set(BUILD_SHARED_LIBS ON)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS OFF)
set(BUILD_OBJECT_LIBS ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_subdirectory(external/PTL)
omnitrace_restore_variables(
BUILD_CONFIG
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS CMAKE_POSITION_INDEPENDENT_CODE
CMAKE_CXX_VISIBILITY_PRESET CMAKE_VISIBILITY_INLINES_HIDDEN)
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS BUILD_OBJECT_LIBS
CMAKE_POSITION_INDEPENDENT_CODE CMAKE_CXX_VISIBILITY_PRESET
CMAKE_VISIBILITY_INLINES_HIDDEN)
endif()
target_link_libraries(omnitrace-ptl INTERFACE PTL::ptl-shared)
target_sources(omnitrace-ptl INTERFACE $<TARGET_OBJECTS:PTL::ptl-object>)
target_link_libraries(omnitrace-ptl INTERFACE PTL::ptl-object)
+2
Voir le fichier
@@ -7,6 +7,8 @@ set(CMAKE_CXX_VISIBILITY_PRESET "default")
add_subdirectory(transpose)
add_subdirectory(parallel-overhead)
add_subdirectory(user-api)
add_subdirectory(openmp)
option(BUILD_SHARED_LIBS "Build dynamic libraries" ON)
-14
Voir le fichier
@@ -55,17 +55,3 @@ if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR})
endif()
enable_testing()
if(LULESH_USE_MPI)
add_test(
NAME lulesh
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 8
$<TARGET_FILE:${PROJECT_NAME}> -i 100 -s 20 -p
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
else()
add_test(
NAME lulesh
COMMAND $<TARGET_FILE:${PROJECT_NAME}> -i 100 -s 20 -p
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
endif()
+1055
Voir le fichier
Fichier diff supprimé car celui-ci est trop grand Voir la Diff
+23
Voir le fichier
@@ -0,0 +1,23 @@
/* CLASS = B */
/*
c This file is generated automatically by the setparams utility.
c It sets the number of processors and the class_npb of the NPB
c in this directory. Do not modify it by hand.
*/
#define NA 75000
#define NONZER 13
#define NITER 75
#define SHIFT 60.0
#define RCOND 1.0e-1
#define CONVERTDOUBLE FALSE
#define COMPILETIME "01 Mar 2022"
#define NPBVERSION "4.1"
#define LIBVERSION "201511"
#define COMPILERVERSION "11.1.0"
#define CS1 "g++ -std=c++14"
#define CS2 "$(CC)"
#define CS3 "-lm"
#define CS4 "-I../common "
#define CS5 "-O3 -fopenmp -mcmodel=medium"
#define CS6 "-O3 -fopenmp -mcmodel=medium"
#define CS7 "randdp"
+27
Voir le fichier
@@ -0,0 +1,27 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
file(GLOB common_source ${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp)
add_library(openmp-common OBJECT ${common_source})
target_include_directories(openmp-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/common)
add_executable(openmp-cg ${CMAKE_CURRENT_SOURCE_DIR}/CG/cg.cpp
$<TARGET_OBJECTS:openmp-common>)
add_executable(openmp-lu ${CMAKE_CURRENT_SOURCE_DIR}/LU/lu.cpp
$<TARGET_OBJECTS:openmp-common>)
find_program(CLANGXX_EXECUTABLE NAMES clang++)
if(CLANGXX_EXECUTABLE)
target_compile_options(openmp-common PUBLIC -W -Wall -fopenmp=libomp)
target_compile_options(openmp-cg PRIVATE -W -Wall -fopenmp=libomp)
target_link_libraries(openmp-cg PRIVATE omp)
target_compile_options(openmp-lu PRIVATE -W -Wall -fopenmp=libomp)
target_link_libraries(openmp-lu PRIVATE omp)
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-common)
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-cg)
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-lu)
else()
find_package(OpenMP REQUIRED)
target_link_libraries(openmp-common PUBLIC OpenMP::OpenMP_CXX)
endif()
+3563
Voir le fichier
Fichier diff supprimé car celui-ci est trop grand Voir la Diff
+27
Voir le fichier
@@ -0,0 +1,27 @@
/* CLASS = W */
/*
c This file is generated automatically by the setparams utility.
c It sets the number of processors and the class_npb of the NPB
c in this directory. Do not modify it by hand.
*/
/* full problem size */
#define ISIZ1 25
#define ISIZ2 25
#define ISIZ3 25
/* number of iterations and how often to print the norm */
#define ITMAX_DEFAULT 150
#define INORM_DEFAULT 150
#define DT_DEFAULT 1.5e-3
#define CONVERTDOUBLE FALSE
#define COMPILETIME "07 Mar 2022"
#define NPBVERSION "4.1"
#define LIBVERSION "201511"
#define COMPILERVERSION "11.1.0"
#define CS1 "g++ -std=c++14"
#define CS2 "$(CC)"
#define CS3 "-lm"
#define CS4 "-I../common "
#define CS5 "-O3 -fopenmp -mcmodel=medium"
#define CS6 "-O3 -fopenmp -mcmodel=medium"
#define CS7 "randdp"
+159
Voir le fichier
@@ -0,0 +1,159 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
/*****************************************************************/
/****** C _ P R I N T _ R E S U L T S ******/
/*****************************************************************/
void
c_print_results(char* name, char class_npb, int n1, int n2, int n3, int niter, double t,
double mops, char* optype, int passed_verification, char* npbversion,
char* compiletime, char* compilerversion, char* libversion,
char* totalthreads, char* cc, char* clink, char* c_lib, char* c_inc,
char* cflags, char* clinkflags, char* rand)
{
printf("\n\n %s Benchmark Completed\n", name);
printf(" class_npb = %c\n", class_npb);
if((name[0] == 'I') && (name[1] == 'S'))
{
if(n3 == 0)
{
long nn = n1;
if(n2 != 0)
{
nn *= n2;
}
printf(" Size = %12ld\n", nn); /* as in IS */
}
else
{
printf(" Size = %4dx%4dx%4d\n", n1, n2, n3);
}
}
else
{
char size[16];
int j;
if((n2 == 0) && (n3 == 0))
{
if((name[0] == 'E') && (name[1] == 'P'))
{
sprintf(size, "%15.0lf", pow(2.0, n1));
j = 14;
if(size[j] == '.')
{
size[j] = ' ';
j--;
}
size[j + 1] = '\0';
printf(" Size = %15s\n", size);
}
else
{
printf(" Size = %12d\n", n1);
}
}
else
{
printf(" Size = %4dx%4dx%4d\n", n1, n2, n3);
}
}
printf(" Total threads = %12s\n", totalthreads);
printf(" Iterations = %12d\n", niter);
printf(" Time in seconds = %12.2f\n", t);
printf(" Mop/s total = %12.2f\n", mops);
printf(" Operation type = %24s\n", optype);
if(passed_verification < 0)
{
printf(" Verification = NOT PERFORMED\n");
}
else if(passed_verification)
{
printf(" Verification = SUCCESSFUL\n");
}
else
{
printf(" Verification = UNSUCCESSFUL\n");
}
printf(" Version = %12s\n", npbversion);
printf(" Compile date = %12s\n", compiletime);
printf(" Compiler ver = %12s\n", compilerversion);
printf(" OpenMP version = %12s\n", libversion);
printf("\n Compile options:\n");
printf(" CC = %s\n", cc);
printf(" CLINK = %s\n", clink);
printf(" C_LIB = %s\n", c_lib);
printf(" C_INC = %s\n", c_inc);
printf(" CFLAGS = %s\n", cflags);
printf(" CLINKFLAGS = %s\n", clinkflags);
printf(" RAND = %s\n", rand);
#ifdef SMP
evalue = getenv("MP_SET_NUMTHREADS");
printf(" MULTICPUS = %s\n", evalue);
#endif
/*
* printf(" Please send the results of this run to:\n\n");
* printf(" NPB Development Team\n");
* printf(" Internet: npb@nas.nasa.gov\n \n");
* printf(" If email is not available, send this to:\n\n");
* printf(" MS T27A-1\n");
* printf(" NASA Ames Research Center\n");
* printf(" Moffett Field, CA 94035-1000\n\n");
* printf(" Fax: 650-604-3957\n\n");
*/
printf("\n\n");
printf("----------------------------------------------------------------------\n");
printf(" NPB-CPP is developed by: \n");
printf(" Dalvan Griebler\n");
printf(" Gabriell Araujo (Sequential Porting)\n");
printf(" Júnior Löff (Parallel Implementation)\n");
printf("\n");
printf(" In case of questions or problems, please send an e-mail to us:\n");
printf(" dalvan.griebler; gabriell.araujo; junior.loff@edu.pucrs.br\n");
printf("----------------------------------------------------------------------\n");
printf("\n");
}
+184
Voir le fichier
@@ -0,0 +1,184 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
#if defined(USE_POW)
# define r23 pow(0.5, 23.0)
# define r46 (r23 * r23)
# define t23 pow(2.0, 23.0)
# define t46 (t23 * t23)
#else
# define r23 \
(0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * \
0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5)
# define r46 (r23 * r23)
# define t23 \
(2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * \
2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0)
# define t46 (t23 * t23)
#endif
/*
* ---------------------------------------------------------------------
*
* this routine returns a uniform pseudorandom double precision number in the
* range (0, 1) by using the linear congruential generator
*
* x_{k+1} = a x_k (mod 2^46)
*
* where 0 < x_k < 2^46 and 0 < a < 2^46. this scheme generates 2^44 numbers
* before repeating. the argument A is the same as 'a' in the above formula,
* and X is the same as x_0. A and X must be odd double precision integers
* in the range (1, 2^46). the returned value RANDLC is normalized to be
* between 0 and 1, i.e. RANDLC = 2^(-46) * x_1. X is updated to contain
* the new seed x_1, so that subsequent calls to RANDLC using the same
* arguments will generate a continuous sequence.
*
* this routine should produce the same results on any computer with at least
* 48 mantissa bits in double precision floating point data. On 64 bit
* systems, double precision should be disabled.
*
* David H. Bailey, October 26, 1990
*
* ---------------------------------------------------------------------
*/
double
randlc(double* x, double a)
{
double t1, t2, t3, t4, a1, a2, x1, x2, z;
/*
* ---------------------------------------------------------------------
* break A into two parts such that A = 2^23 * A1 + A2.
* ---------------------------------------------------------------------
*/
t1 = r23 * a;
a1 = (int) t1;
a2 = a - t23 * a1;
/*
* ---------------------------------------------------------------------
* break X into two parts such that X = 2^23 * X1 + X2, compute
* Z = A1 * X2 + A2 * X1 (mod 2^23), and then
* X = 2^23 * Z + A2 * X2 (mod 2^46).
* ---------------------------------------------------------------------
*/
t1 = r23 * (*x);
x1 = (int) t1;
x2 = (*x) - t23 * x1;
t1 = a1 * x2 + a2 * x1;
t2 = (int) (r23 * t1);
z = t1 - t23 * t2;
t3 = t23 * z + a2 * x2;
t4 = (int) (r46 * t3);
(*x) = t3 - t46 * t4;
return (r46 * (*x));
}
/*
* ---------------------------------------------------------------------
*
* this routine generates N uniform pseudorandom double precision numbers in
* the range (0, 1) by using the linear congruential generator
*
* x_{k+1} = a x_k (mod 2^46)
*
* where 0 < x_k < 2^46 and 0 < a < 2^46. this scheme generates 2^44 numbers
* before repeating. the argument A is the same as 'a' in the above formula,
* and X is the same as x_0. A and X must be odd double precision integers
* in the range (1, 2^46). the N results are placed in Y and are normalized
* to be between 0 and 1. X is updated to contain the new seed, so that
* subsequent calls to VRANLC using the same arguments will generate a
* continuous sequence. if N is zero, only initialization is performed, and
* the variables X, A and Y are ignored.
*
* this routine is the standard version designed for scalar or RISC systems.
* however, it should produce the same results on any single processor
* computer with at least 48 mantissa bits in double precision floating point
* data. on 64 bit systems, double precision should be disabled.
*
* ---------------------------------------------------------------------
*/
void
vranlc(int n, double* x_seed, double a, double y[])
{
int i;
double x, t1, t2, t3, t4, a1, a2, x1, x2, z;
/*
* ---------------------------------------------------------------------
* break A into two parts such that A = 2^23 * A1 + A2.
* ---------------------------------------------------------------------
*/
t1 = r23 * a;
a1 = (int) t1;
a2 = a - t23 * a1;
x = *x_seed;
/*
* ---------------------------------------------------------------------
* generate N results. this loop is not vectorizable.
* ---------------------------------------------------------------------
*/
for(i = 0; i < n; i++)
{
/*
* ---------------------------------------------------------------------
* break X into two parts such that X = 2^23 * X1 + X2, compute
* Z = A1 * X2 + A2 * X1 (mod 2^23), and then
* X = 2^23 * Z + A2 * X2 (mod 2^46).
* ---------------------------------------------------------------------
*/
t1 = r23 * x;
x1 = (int) t1;
x2 = x - t23 * x1;
t1 = a1 * x2 + a2 * x1;
t2 = (int) (r23 * t1);
z = t1 - t23 * t2;
t3 = t23 * z + a2 * x2;
t4 = (int) (r46 * t3);
x = t3 - t46 * t4;
y[i] = r46 * x;
}
*x_seed = x;
}
+101
Voir le fichier
@@ -0,0 +1,101 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
#include "wtime.hpp"
#include <cstdlib>
/* prototype */
void
wtime(double*);
/*****************************************************************/
/****** E L A P S E D _ T I M E ******/
/*****************************************************************/
double
elapsed_time(void)
{
double t;
wtime(&t);
return (t);
}
double start[64], elapsed[64];
/*****************************************************************/
/****** T I M E R _ C L E A R ******/
/*****************************************************************/
void
timer_clear(int n)
{
elapsed[n] = 0.0;
}
/*****************************************************************/
/****** T I M E R _ S T A R T ******/
/*****************************************************************/
void
timer_start(int n)
{
start[n] = elapsed_time();
}
/*****************************************************************/
/****** T I M E R _ S T O P ******/
/*****************************************************************/
void
timer_stop(int n)
{
double t, now;
now = elapsed_time();
t = now - start[n];
elapsed[n] += t;
}
/*****************************************************************/
/****** T I M E R _ R E A D ******/
/*****************************************************************/
double
timer_read(int n)
{
return (elapsed[n]);
}
+124
Voir le fichier
@@ -0,0 +1,124 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
typedef int boolean;
typedef struct
{
double real;
double imag;
} dcomplex;
#define TRUE 1
#define FALSE 0
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define pow2(a) ((a) * (a))
/* old version of the complex number operations */
#define get_real(c) c.real
#define get_imag(c) c.imag
#define cadd(c, a, b) (c.real = a.real + b.real, c.imag = a.imag + b.imag)
#define csub(c, a, b) (c.real = a.real - b.real, c.imag = a.imag - b.imag)
#define cmul(c, a, b) \
(c.real = a.real * b.real - a.imag * b.imag, \
c.imag = a.real * b.imag + a.imag * b.real)
#define crmul(c, a, b) (c.real = a.real * b, c.imag = a.imag * b)
/* latest version of the complex number operations */
#define dcomplex_create(r, i) \
(dcomplex) { r, i }
#define dcomplex_add(a, b) \
(dcomplex) { (a).real + (b).real, (a).imag + (b).imag }
#define dcomplex_sub(a, b) \
(dcomplex) { (a).real - (b).real, (a).imag - (b).imag }
#define dcomplex_mul(a, b) \
(dcomplex) \
{ \
((a).real * (b).real) - ((a).imag * (b).imag), \
((a).real * (b).imag) + ((a).imag * (b).real) \
}
#define dcomplex_mul2(a, b) \
(dcomplex) { (a).real*(b), (a).imag*(b) }
static inline dcomplex
dcomplex_div(dcomplex z1, dcomplex z2)
{
double a = z1.real;
double b = z1.imag;
double c = z2.real;
double d = z2.imag;
double divisor = c * c + d * d;
double real = (a * c + b * d) / divisor;
double imag = (b * c - a * d) / divisor;
dcomplex result = (dcomplex){ real, imag };
return result;
}
#define dcomplex_div2(a, b) \
(dcomplex) { (a).real / (b), (a).imag / (b) }
#define dcomplex_abs(x) sqrt(((x).real * (x).real) + ((x).imag * (x).imag))
#define dconjg(x) \
(dcomplex) { (x).real, -1.0 * (x).imag }
extern double
randlc(double*, double);
extern void
vranlc(int, double*, double, double*);
extern void
timer_clear(int);
extern void
timer_start(int);
extern void
timer_stop(int);
extern double
timer_read(int);
extern void
c_print_results(char* name, char class_npb, int n1, int n2, int n3, int niter, double t,
double mops, char* optype, int passed_verification, char* npbversion,
char* compiletime, char* compilerversion, char* libversion,
char* totalthreads, char* cc, char* clink, char* c_lib, char* c_inc,
char* cflags, char* clinkflags, char* rand);
+55
Voir le fichier
@@ -0,0 +1,55 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
#include "wtime.hpp"
#include <sys/time.h>
void
wtime(double* t)
{
static int sec = -1;
struct timeval tv;
gettimeofday(&tv, 0);
if(sec < 0) sec = tv.tv_sec;
*t = (tv.tv_sec - sec) + 1.0e-6 * tv.tv_usec;
}
+54
Voir le fichier
@@ -0,0 +1,54 @@
/*
MIT License
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
GMAP website: https://gmap.pucrs.br
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
The original NPB 3.4.1 version was written in Fortran and belongs to:
http://www.nas.nasa.gov/Software/NPB/
------------------------------------------------------------------------------
The serial C++ version is a translation of the original NPB 3.4.1
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
Authors of the C++ code:
Dalvan Griebler <dalvangriebler@gmail.com>
Gabriell Araujo <hexenoften@gmail.com>
Júnior Löff <loffjh@gmail.com>
*/
/*
* C/Fortran interface is different on different machines.
* you may need to tweak this.
*/
#if defined(IBM)
# define wtime wtime
#elif defined(CRAY)
# define wtime WTIME
#else
# define wtime wtime_
#endif
Voir le fichier
+1 -1
Voir le fichier
@@ -95,7 +95,7 @@ transpose_a(int* in, int* out, int M, int N)
void
run(int rank, int tid, hipStream_t stream, int argc, char** argv)
{
size_t nitr = 5000;
size_t nitr = 500;
unsigned int M = 4960 * 2;
unsigned int N = 4960 * 2;
if(argc > 2) nitr = atoll(argv[2]);
+13
Voir le fichier
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
project(omnitrace-user-api LANGUAGES CXX)
set(CMAKE_BUILD_TYPE "Release")
find_package(Threads REQUIRED)
add_executable(user-api user-api.cpp)
target_link_libraries(user-api PRIVATE Threads::Threads omnitrace::omnitrace-user-library)
if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set_target_properties(user-api PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR})
endif()
+80
Voir le fichier
@@ -0,0 +1,80 @@
#include <omnitrace/user.h>
#include <atomic>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <thread>
#include <vector>
std::atomic<long> total{ 0 };
long
fib(long n) __attribute__((noinline));
void
run(size_t nitr, long) __attribute__((noinline));
long
fib(long n)
{
return (n < 2) ? n : fib(n - 1) + fib(n - 2);
}
#define RUN_LABEL \
std::string{ std::string{ __FUNCTION__ } + "(" + std::to_string(n) + ") x " + \
std::to_string(nitr) } \
.c_str()
void
run(size_t nitr, long n)
{
omnitrace_user_stop_thread_trace();
omnitrace_user_push_region(RUN_LABEL);
long local = 0;
for(size_t i = 0; i < nitr; ++i)
local += fib(n);
total += local;
omnitrace_user_pop_region(RUN_LABEL);
omnitrace_user_start_thread_trace();
}
int
main(int argc, char** argv)
{
omnitrace_user_push_region(argv[0]);
omnitrace_user_push_region("initialization");
size_t nthread = std::min<size_t>(16, std::thread::hardware_concurrency());
size_t nitr = 50000;
long nfib = 10;
if(argc > 1) nfib = atol(argv[1]);
if(argc > 2) nthread = atol(argv[2]);
if(argc > 3) nitr = atol(argv[3]);
omnitrace_user_pop_region("initialization");
printf("[%s] Threads: %zu\n[%s] Iterations: %zu\n[%s] fibonacci(%li)...\n", argv[0],
nthread, argv[0], nitr, argv[0], nfib);
omnitrace_user_push_region("thread_creation");
std::vector<std::thread> threads{};
threads.reserve(nthread);
for(size_t i = 0; i < nthread; ++i)
{
size_t _nitr = ((i % 2) == 1) ? (nitr - (0.1 * nitr)) : (nitr + (0.1 * nitr));
threads.emplace_back(&run, _nitr, nfib);
}
omnitrace_user_pop_region("thread_creation");
run(nitr - 0.25 * nitr, nfib - 0.1 * nfib);
omnitrace_user_push_region("thread_wait");
for(auto& itr : threads)
itr.join();
omnitrace_user_pop_region("thread_wait");
printf("[%s] fibonacci(%li) x %lu = %li\n", argv[0], nfib, nthread, total.load());
omnitrace_user_pop_region(argv[0]);
return 0;
}
+1 -1
Sous-module external/PTL mis-à-jour : 61f873cf79...4afd2bdeb9
+1 -1
Sous-module external/timemory mis-à-jour : b8d3b3e1fd...1ea2511833
+10
Voir le fichier
@@ -12,3 +12,13 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
add_subdirectory(lib)
add_subdirectory(bin)
if(OMNITRACE_BUILD_DEVELOPER)
add_custom_target(omnitrace-precommit)
foreach(_TARGET format-omnitrace-source format-omnitrace-cmake format-timemory-source
format-timemory-cmake)
if(TARGET ${_TARGET})
add_dependencies(omnitrace-precommit ${_TARGET})
endif()
endforeach()
endif()
+4
Voir le fichier
@@ -1,3 +1,7 @@
add_subdirectory(omnitrace-avail)
add_subdirectory(omnitrace-critical-trace)
add_subdirectory(omnitrace)
if(OMNITRACE_BUILD_TESTING)
add_subdirectory(tests)
endif()
+6 -4
Voir le fichier
@@ -30,6 +30,7 @@
#include "library/components/omnitrace.hpp"
#include "library/components/pthread_gotcha.hpp"
#include "library/components/roctracer.hpp"
#include "library/components/user_region.hpp"
#include "library/config.hpp"
#include <timemory/components.hpp>
@@ -613,8 +614,6 @@ main(int argc, char** argv)
if(!os) os = &std::cout;
omnitrace_init_library();
if(include_components) write_component_info(*os, options, use_mark, fields);
dump_log();
@@ -766,7 +765,9 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
_mark.at(i));
}
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(!category_regex_keys.empty())
_selected +=
(is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(_selected == 0) continue;
}
@@ -834,7 +835,8 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
_mark.at(i));
}
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(!category_regex_keys.empty())
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(_selected > 0)
{
+12 -3
Voir le fichier
@@ -4,10 +4,19 @@
#
# ------------------------------------------------------------------------------#
add_executable(
add_executable(omnitrace-exe ${_EXCLUDE})
target_sources(
omnitrace-exe
${_EXCLUDE} ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp ${CMAKE_CURRENT_LIST_DIR}/details.cpp)
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/details.cpp
${CMAKE_CURRENT_LIST_DIR}/function_signature.cpp
${CMAKE_CURRENT_LIST_DIR}/module_function.cpp
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/info.hpp
${CMAKE_CURRENT_LIST_DIR}/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/function_signature.hpp
${CMAKE_CURRENT_LIST_DIR}/module_function.hpp)
target_link_libraries(
omnitrace-exe
+85 -87
Voir le fichier
@@ -40,7 +40,7 @@ get_whole_function_names()
"backtrace", "backtrace_symbols", "backtrace_symbols_fd", "sigaddset",
"sigandset", "sigdelset", "sigemptyset", "sigfillset", "sighold", "sigisemptyset",
"sigismember", "sigorset", "sigrelse", "sigvec", "strtok", "strstr", "sbrk",
"strxfrm",
"strxfrm", "atexit", "ompt_start_tool", "nanosleep",
// below are functions which never terminate
"rocr::core::Signal::WaitAny", "rocr::core::Runtime::AsyncEventsLoop",
"rocr::core::BusyWaitSignal::WaitAcquire",
@@ -525,10 +525,32 @@ are_file_include_exclude_lists_empty()
// the instrumented loop and formats it properly.
//
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument)
{
if(!cfGraph || !loopToInstrument || !f) return function_signature{ "", "", "" };
if(!cfGraph || !loopToInstrument || !func) return function_signature{ "", "", "" };
std::vector<BPatch_basicBlock*> basic_blocks{};
loopToInstrument->getLoopBasicBlocksExclusive(basic_blocks);
if(basic_blocks.empty()) return function_signature{ "", "", "" };
auto base_addr = basic_blocks.front()->getStartAddress();
auto last_addr = basic_blocks.front()->getEndAddress();
basic_block_t* block = basic_blocks.front();
for(const auto& itr : basic_blocks)
{
if(itr == block) continue;
if(itr->dominates(block))
{
base_addr = itr->getStartAddress();
last_addr = itr->getEndAddress();
block = itr;
}
}
verbprintf(4, "Loop: size = %lu: base_addr = %lu, last_addr = %lu\n",
(unsigned long) (last_addr - base_addr), base_addr, last_addr);
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
@@ -537,32 +559,14 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
memset(fname, '\0', FUNCNAMELEN + 1);
memset(mname, '\0', FUNCNAMELEN + 1);
mutatee_module->getName(mname, FUNCNAMELEN);
module->getName(mname, FUNCNAMELEN);
func->getName(fname, FUNCNAMELEN);
bpvector_t<point_t*>* loopStartInst =
cfGraph->findLoopInstPoints(BPatch_locLoopStartIter, loopToInstrument);
bpvector_t<point_t*>* loopExitInst =
cfGraph->findLoopInstPoints(BPatch_locLoopEndIter, loopToInstrument);
auto* returnType = func->getReturnType();
if(!loopStartInst || !loopExitInst) return function_signature{ "", "", "" };
if(returnType) typeName = returnType->getName();
unsigned long baseAddr = (unsigned long) (*loopStartInst)[0]->getAddress();
unsigned long lastAddr =
(unsigned long) (*loopExitInst)[loopExitInst->size() - 1]->getAddress();
verbprintf(3, "Loop: size of lastAddr = %lu: baseAddr = %lu, lastAddr = %lu\n",
(unsigned long) loopExitInst->size(), (unsigned long) baseAddr,
(unsigned long) lastAddr);
f->getName(fname, FUNCNAMELEN);
auto* returnType = f->getReturnType();
if(returnType)
{
typeName = returnType->getName();
}
auto* params = f->getParams();
auto* params = func->getParams();
std::vector<string_t> _params;
if(params)
{
@@ -574,36 +578,51 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
}
}
bpvector_t<BPatch_statement> lines;
bpvector_t<BPatch_statement> linesEnd;
bpvector_t<BPatch_statement> lines{};
bpvector_t<BPatch_statement> linesEnd{};
bool info1 = mutatee_module->getSourceLines(baseAddr, lines);
bool info1 = module->getSourceLines(base_addr, lines);
string_t filename = mname;
if(info1)
{
// filename = lines[0].fileName();
auto row1 = lines[0].lineNumber();
auto col1 = lines[0].lineOffset();
int row1 = 0;
int col1 = 0;
for(auto& itr : lines)
{
if(itr.lineNumber() > 0)
{
row1 = itr.lineNumber();
col1 = itr.lineOffset();
break;
}
}
if(row1 == 0 && col1 == 0)
return function_signature(typeName, fname, filename, _params);
int row2 = 0;
int col2 = 0;
for(auto& itr : lines)
{
row2 = std::max(row2, itr.lineNumber());
col2 = std::max(col2, itr.lineOffset());
}
if(col1 < 0) col1 = 0;
// This following section is attempting to remedy the limitations of
// getSourceLines for loops. As the program goes through the loop, the resulting
// lines go from the loop head, through the instructions present in the loop, to
// the last instruction in the loop, back to the loop head, then to the next
// instruction outside of the loop. What this section does is starts at the last
// instruction in the loop, then goes through the addresses until it reaches the
// next instruction outside of the loop. We then bump back a line. This is not a
// perfect solution, but we will work with the Dyninst team to find something
// better.
bool info2 = mutatee_module->getSourceLines((unsigned long) lastAddr, linesEnd);
verbprintf(3, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
bool info2 = module->getSourceLines(last_addr, linesEnd);
verbprintf(4, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
if(info2)
{
auto row2 = linesEnd[0].lineNumber();
auto col2 = linesEnd[0].lineOffset();
for(auto& itr : linesEnd)
{
row2 = std::max(row2, itr.lineNumber());
col2 = std::max(col2, itr.lineOffset());
}
if(col2 < 0) col2 = 0;
if(row2 < row1) row1 = row2; // Fix for wrong line numbers
@@ -627,35 +646,30 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
// We create a new name that embeds the file and line information in the name
//
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
get_func_file_line_info(module_t* module, procedure_t* func)
{
bool info1, info2;
unsigned long baseAddr, lastAddr;
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
int row1, col1, row2, col2;
string_t filename = {};
string_t typeName = {};
using address_t = Dyninst::Address;
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
string_t typeName = {};
memset(fname, '\0', FUNCNAMELEN + 1);
memset(mname, '\0', FUNCNAMELEN + 1);
mutatee_module->getName(mname, FUNCNAMELEN);
module->getName(mname, FUNCNAMELEN);
func->getName(fname, FUNCNAMELEN);
baseAddr = (unsigned long) (f->getBaseAddr());
f->getAddressRange(baseAddr, lastAddr);
bpvector_t<BPatch_statement> lines;
f->getName(fname, FUNCNAMELEN);
address_t base_addr{};
address_t last_addr{};
func->getAddressRange(base_addr, last_addr);
auto* returnType = f->getReturnType();
auto* returnType = func->getReturnType();
if(returnType)
{
typeName = returnType->getName();
}
if(returnType) typeName = returnType->getName();
auto* params = f->getParams();
std::vector<string_t> _params;
auto* params = func->getParams();
std::vector<string_t> _params = {};
if(params)
{
for(auto* itr : *params)
@@ -666,32 +680,16 @@ get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
}
}
info1 = mutatee_module->getSourceLines((unsigned long) baseAddr, lines);
bpvector_t<BPatch_statement> lines = {};
bool info = module->getSourceLines(base_addr, lines);
filename = mname;
string_t filename = mname;
if(info1)
if(info && !lines.empty())
{
// filename = lines[0].fileName();
row1 = lines[0].lineNumber();
col1 = lines[0].lineOffset();
if(col1 < 0) col1 = 0;
info2 = mutatee_module->getSourceLines((unsigned long) (lastAddr - 1), lines);
if(info2)
{
row2 = lines[1].lineNumber();
col2 = lines[1].lineOffset();
if(col2 < 0) col2 = 0;
if(row2 < row1) row1 = row2;
return function_signature(typeName, fname, filename, _params, { row1, 0 },
{ 0, 0 }, false, info1, info2);
}
else
{
return function_signature(typeName, fname, filename, _params, { row1, 0 },
{ 0, 0 }, false, info1, info2);
}
auto row = lines.front().lineNumber();
return function_signature(typeName, fname, filename, _params, { row, 0 },
{ 0, 0 }, false, info, false);
}
else
{
+99
Voir le fichier
@@ -0,0 +1,99 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "function_signature.hpp"
function_signature::function_signature(string_t _ret, const string_t& _name,
string_t _file, location_t _row, location_t _col,
bool _loop, bool _info_beg, bool _info_end)
: m_loop(_loop)
, m_info_beg(_info_beg)
, m_info_end(_info_end)
, m_row(std::move(_row))
, m_col(std::move(_col))
, m_return(std::move(_ret))
, m_name(tim::demangle(_name))
, m_file(std::move(_file))
{
if(m_file.find('/') != string_t::npos)
m_file = m_file.substr(m_file.find_last_of('/') + 1);
}
function_signature::function_signature(const string_t& _ret, const string_t& _name,
const string_t& _file,
const std::vector<string_t>& _params,
location_t _row, location_t _col, bool _loop,
bool _info_beg, bool _info_end)
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
{
m_params = "(";
for(const auto& itr : _params)
m_params.append(itr + ", ");
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
m_params += ")";
}
string_t
function_signature::get(function_signature& sig)
{
return sig.get();
}
string_t
function_signature::get() const
{
std::stringstream ss;
if(use_return_info && !m_return.empty()) ss << m_return << " ";
ss << m_name;
if(use_args_info) ss << m_params;
if(m_loop && m_info_beg)
{
auto _row_col_str = [](unsigned long _row, unsigned long _col) {
std::stringstream _ss{};
if(_row == 0 && _col == 0) return std::string{};
if(_col > 0)
_ss << "{" << _row << "," << _col << "}";
else
_ss << "{" << _row << "}";
return _ss.str();
};
auto _rc1 = _row_col_str(m_row.first, m_col.first);
auto _rc2 = _row_col_str(m_row.second, m_col.second);
if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 != _rc2)
ss << " [" << _rc1 << "-" << _rc2 << "]";
else if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 == _rc2)
ss << " [" << _rc1 << "]";
else if(m_info_end && !_rc1.empty() && _rc2.empty())
ss << " [" << _rc1 << "]";
else if(!m_info_end && !_rc1.empty())
ss << " [" << _rc1 << "]";
else
errprintf(1, "loop line info is empty!");
}
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
if(use_file_info && m_file.length() > 0) ss << "]";
m_signature = ss.str();
return m_signature;
}
+74
Voir le fichier
@@ -0,0 +1,74 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "fwd.hpp"
struct function_signature
{
using location_t = std::pair<unsigned long, unsigned long>;
TIMEMORY_DEFAULT_OBJECT(function_signature)
function_signature(string_t _ret, const string_t& _name, string_t _file,
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
bool _loop = false, bool _info_beg = false,
bool _info_end = false);
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
location_t _col = { 0, 0 }, bool _loop = false,
bool _info_beg = false, bool _info_end = false);
static string_t get(function_signature& sig);
string_t get() const;
bool m_loop = false;
bool m_info_beg = false;
bool m_info_end = false;
location_t m_row = { 0, 0 };
location_t m_col = { 0, 0 };
string_t m_return = {};
string_t m_name = {};
string_t m_params = "()";
string_t m_file = {};
mutable string_t m_signature = {};
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
{
return lhs.get() == rhs.get();
}
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
(void) get();
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
(void) get();
}
};
+273
Voir le fichier
@@ -0,0 +1,273 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <string_view>
#include <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/mpl/apply.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/mpl/policy.hpp>
#include <timemory/tpls/cereal/archives.hpp>
#include <timemory/tpls/cereal/cereal.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/popen.hpp>
#include <timemory/variadic/macros.hpp>
#include <BPatch.h>
#include <BPatch_Vector.h>
#include <BPatch_addressSpace.h>
#include <BPatch_basicBlock.h>
#include <BPatch_basicBlockLoop.h>
#include <BPatch_callbacks.h>
#include <BPatch_function.h>
#include <BPatch_instruction.h>
#include <BPatch_point.h>
#include <BPatch_process.h>
#include <BPatch_snippet.h>
#include <BPatch_statement.h>
#include <Instruction.h>
#include <dyntypes.h>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <exception>
#include <fstream>
#include <limits>
#include <memory>
#include <numeric>
#include <ostream>
#include <regex>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>
#include <vector>
#define MUTNAMELEN 1024
#define FUNCNAMELEN 32 * 1024
#define NO_ERROR -1
#define TIMEMORY_BIN_DIR "bin"
#if !defined(PATH_MAX)
# define PATH_MAX std::numeric_limits<int>::max();
#endif
struct function_signature;
struct module_function;
template <typename Tp>
using bpvector_t = BPatch_Vector<Tp>;
using string_t = std::string;
using string_view_t = std::string_view;
using stringstream_t = std::stringstream;
using strvec_t = std::vector<string_t>;
using strset_t = std::set<string_t>;
using regexvec_t = std::vector<std::regex>;
using fmodset_t = std::set<module_function>;
using fixed_modset_t = std::map<fmodset_t*, bool>;
using exec_callback_t = BPatchExecCallback;
using exit_callback_t = BPatchExitCallback;
using fork_callback_t = BPatchForkCallback;
using patch_t = BPatch;
using process_t = BPatch_process;
using thread_t = BPatch_thread;
using binary_edit_t = BPatch_binaryEdit;
using image_t = BPatch_image;
using module_t = BPatch_module;
using procedure_t = BPatch_function;
using snippet_t = BPatch_snippet;
using call_expr_t = BPatch_funcCallExpr;
using address_space_t = BPatch_addressSpace;
using flow_graph_t = BPatch_flowGraph;
using basic_block_t = BPatch_basicBlock;
using basic_loop_t = BPatch_basicBlockLoop;
using procedure_loc_t = BPatch_procedureLocation;
using point_t = BPatch_point;
using local_var_t = BPatch_localVar;
using const_expr_t = BPatch_constExpr;
using error_level_t = BPatchErrorLevel;
using patch_pointer_t = std::shared_ptr<patch_t>;
using snippet_pointer_t = std::shared_ptr<snippet_t>;
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
using snippet_vec_t = bpvector_t<snippet_t*>;
using procedure_vec_t = bpvector_t<procedure_t*>;
using basic_block_set_t = std::set<basic_block_t*>;
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
using instruction_t = Dyninst::InstructionAPI::Instruction;
void
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
//======================================================================================//
//
// Global Variables
//
//======================================================================================//
//
// label settings
//
extern bool use_return_info;
extern bool use_args_info;
extern bool use_file_info;
extern bool use_line_info;
//
// heuristic settings
//
extern bool allow_overlapping;
extern bool loop_level_instr;
extern bool instr_dynamic_callsites;
extern bool instr_traps;
extern bool instr_loop_traps;
extern size_t min_address_range;
extern size_t min_loop_address_range;
extern size_t min_instructions;
//
// debug settings
//
extern bool werror;
extern bool debug_print;
extern int verbose_level;
//
// string settings
//
extern string_t main_fname;
extern string_t argv0;
extern string_t cmdv0;
extern string_t default_components;
extern string_t prefer_library;
//
// global variables
//
extern patch_pointer_t bpatch;
extern call_expr_t* terminate_expr;
extern snippet_vec_t init_names;
extern snippet_vec_t fini_names;
extern fmodset_t available_module_functions;
extern fmodset_t instrumented_module_functions;
extern fmodset_t overlapping_module_functions;
extern fmodset_t excluded_module_functions;
extern fixed_modset_t fixed_module_functions;
extern regexvec_t func_include;
extern regexvec_t func_exclude;
extern regexvec_t file_include;
extern regexvec_t file_exclude;
extern regexvec_t file_restrict;
extern regexvec_t func_restrict;
//
//======================================================================================//
// control debug printf statements
#define errprintf(LEVEL, ...) \
{ \
if(werror || LEVEL < 0) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
char _buff[FUNCNAMELEN]; \
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
throw std::runtime_error(std::string{ _buff }); \
} \
else \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
} \
fflush(stderr); \
}
// control verbose printf statements
#define verbprintf(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
fflush(stdout); \
}
#define verbprintf_bare(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
fflush(stdout); \
}
//======================================================================================//
template <typename... T>
void
consume_parameters(T&&...)
{}
//======================================================================================//
extern "C"
{
bool are_file_include_exclude_lists_empty();
bool instrument_module(const string_t& file_name);
bool instrument_entity(const string_t& function_name);
bool module_constraint(string_view_t fname);
bool routine_constraint(string_view_t fname);
}
//======================================================================================//
strset_t
get_whole_function_names();
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument);
std::tuple<size_t, size_t>
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr);
bool
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument, bool allow_traps);
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
void
errorFunc(error_level_t level, int num, const char** params);
procedure_t*
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
void
error_func_real(error_level_t level, int num, const char* const* params);
void
error_func_fake(error_level_t level, int num, const char* const* params);
+251
Voir le fichier
@@ -0,0 +1,251 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "fwd.hpp"
#include "module_function.hpp"
static inline void
dump_info(std::ostream& _os, const fmodset_t& _data)
{
module_function::reset_width();
for(const auto& itr : _data)
module_function::update_width(itr);
module_function::write_header(_os);
for(const auto& itr : _data)
_os << itr << '\n';
module_function::reset_width();
}
//
template <typename ArchiveT,
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
static inline void
dump_info(ArchiveT& _ar, const fmodset_t& _data)
{
_ar(tim::cereal::make_nvp("module_functions", _data));
}
//
static inline void
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
const fmodset_t& _data, int _level, bool _fail)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
_oname += "." + _ext;
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[dump_info] Error opening '" << _oname << " for output";
verbprintf(_level, "%s\n", _msg.str().c_str());
if(_fail)
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(!debug_print && verbose_level < _level) return;
if(_ext == "txt")
{
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
dump_info(ofs, _data);
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "xml")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
output_policy::indent() = true;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "json")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
"' does not have one of recognized file extensions: txt, json, xml"));
}
}
//
static inline void
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
const string_t& _type, const strset_t& _ext)
{
for(const auto& itr : _ext)
dump_info(_type, _oname, itr, _data, _level, _fail);
}
//
static inline void
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
auto _pos = _iname.find_last_of('.');
std::string _ext = {};
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[load_info] Error opening '" << _iname << " for input";
verbprintf(_level, "%s\n", _msg.str().c_str());
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(_ext == "xml")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else if(_ext == "json")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
}
}
//
static inline void
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
{
std::vector<std::string> _exceptions{};
_exceptions.reserve(_data.size());
for(auto& itr : _data)
{
try
{
fmodset_t _tmp{};
load_info(itr.first, _inp, _tmp, _level);
// add to the existing
itr.second->insert(_tmp.begin(), _tmp.end());
// if it did not throw it was successfully loaded
_exceptions.clear();
break;
} catch(std::exception& _e)
{
_exceptions.emplace_back(_e.what());
}
}
if(!_exceptions.empty())
{
std::stringstream _msg{};
for(auto& itr : _exceptions)
{
_msg << "[omnitrace][exe] " << itr << "\n";
}
throw std::runtime_error(_msg.str());
}
}
+511
Voir le fichier
@@ -0,0 +1,511 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "module_function.hpp"
#include "fwd.hpp"
#include "omnitrace.hpp"
module_function::width_t&
module_function::get_width()
{
static width_t _instance = []() {
width_t _tmp;
_tmp.fill(0);
return _tmp;
}();
return _instance;
}
void
module_function::reset_width()
{
get_width().fill(0);
}
void
module_function::update_width(const module_function& rhs)
{
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module_name.length());
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function_name.length());
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
}
module_function::module_function(module_t* mod, procedure_t* proc)
: module{ mod }
, function{ proc }
, flow_graph{ proc->getCFG() }
{
if(flow_graph)
{
flow_graph->getAllBasicBlocks(basic_blocks);
flow_graph->getOuterLoops(loop_blocks);
}
for(const auto& itr : basic_blocks)
{
std::vector<instruction_t> instructions{};
itr->getInstructions(instructions);
num_instructions += instructions.size();
}
char modname[FUNCNAMELEN];
char fname[FUNCNAMELEN];
module->getFullName(modname, FUNCNAMELEN);
function->getName(fname, FUNCNAMELEN);
module_name = modname;
function_name = fname;
signature = get_func_file_line_info(module, function);
if(!function->isInstrumentable())
{
verbprintf(0,
"Warning! module function generated for un-instrumentable "
"function: %s [%s]\n",
function_name.c_str(), module_name.c_str());
}
std::pair<address_t, address_t> _range{};
if(function->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
void
module_function::write_header(std::ostream& os)
{
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
std::stringstream ss;
ss << std::setw(14) << "AddressRange"
<< " " << std::setw(14) << "#Instructions"
<< " " << std::setw(6) << "Ratio"
<< " " << std::setw(w0 + 8) << std::left << "Module"
<< " " << std::setw(w1 + 8) << std::left << "Function"
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
<< "\n";
os << ss.str();
}
bool
module_function::should_instrument() const
{
// hard constraints
if(!is_instrumentable()) return false;
if(!can_instrument_entry()) return false;
if(!can_instrument_exit()) return false;
if(is_module_constrained()) return false;
if(is_routine_constrained()) return false;
// should be before user selection
constexpr int absolute_min_instructions = 4;
if(num_instructions < absolute_min_instructions)
{
messages.emplace_back(
2, "Skipping", "function",
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"));
return false;
}
// user selection
if(is_user_excluded()) return false;
if(is_user_restricted()) return true;
if(is_user_included()) return true;
// should be applied before dynamic-callsite check
if(is_overlapping_constrained()) return false;
if(is_entry_trap_constrained()) return false;
if(is_exit_trap_constrained()) return false;
// needs to be applied before address range and number of instruction constraints
if(is_dynamic_callsite_forced()) return true;
if(is_address_range_constrained()) return false;
if(is_num_instructions_constrained()) return false;
return true;
}
bool
module_function::is_instrumentable() const
{
if(!function->isInstrumentable())
{
messages.emplace_back(2, "Skipping", "module", "not-instrumentable");
return false;
}
return true;
}
namespace
{
bool
check_regex_restrictions(const std::string& _name, const regexvec_t& _regexes)
{
// NOLINTNEXTLINE
for(auto& itr : _regexes)
if(std::regex_search(_name, itr)) return true;
return false;
}
} // namespace
bool
module_function::is_user_restricted() const
{
if(!file_restrict.empty())
{
if(check_regex_restrictions(module_name, file_restrict))
{
messages.emplace_back(2, "Forcing", "module", "module-restrict-regex");
return false;
}
else
{
messages.emplace_back(3, "Skipping", "module", "module-restrict-regex");
return true;
}
}
if(!func_restrict.empty())
{
if(check_regex_restrictions(module_name, func_restrict))
{
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
return false;
}
else if(check_regex_restrictions(signature.get(), func_restrict))
{
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
return false;
}
else
{
messages.emplace_back(3, "Skipping", "function", "function-restrict-regex");
return true;
}
}
return false;
}
bool
module_function::is_user_included() const
{
if(!file_include.empty())
{
if(check_regex_restrictions(module_name, file_include))
{
messages.emplace_back(2, "Forcing", "module", "module-include-regex");
return true;
}
}
if(!func_include.empty())
{
if(check_regex_restrictions(function_name, func_include))
{
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
return true;
}
else if(check_regex_restrictions(signature.get(), func_include))
{
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
return true;
}
}
return false;
}
bool
module_function::is_user_excluded() const
{
if(!file_exclude.empty())
{
if(check_regex_restrictions(module_name, file_exclude))
{
messages.emplace_back(2, "Skipping", "module", "module-exclude-regex");
return true;
}
}
if(!func_exclude.empty())
{
if(check_regex_restrictions(function_name, func_exclude))
{
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
return true;
}
else if(check_regex_restrictions(signature.get(), func_exclude))
{
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
return true;
}
}
return false;
}
bool
module_function::is_overlapping() const
{
procedure_vec_t _overlapping{};
return function->findOverlapping(_overlapping);
}
bool
module_function::is_module_constrained() const
{
if(!instrument_module(module_name) || module_constraint(module_name.c_str()))
{
messages.emplace_back(2, "Skipping", "module", "module-constraint");
return true;
}
return false;
}
bool
module_function::is_routine_constrained() const
{
if(!instrument_entity(function_name) || !instrument_entity(signature.get()) ||
routine_constraint(function_name) || routine_constraint(signature.get()))
{
messages.emplace_back(2, "Skipping", "function", "function-constraint");
return true;
}
return false;
}
bool
module_function::is_overlapping_constrained() const
{
if(!allow_overlapping && is_overlapping())
{
messages.emplace_back(2, "Skipping", "function", "overlapping");
return true;
}
return false;
}
bool
module_function::contains_dynamic_callsites() const
{
if(flow_graph) return flow_graph->containsDynamicCallsites();
return false;
}
bool
module_function::is_dynamic_callsite_forced() const
{
if(instr_dynamic_callsites && contains_dynamic_callsites())
{
messages.emplace_back(2, "Forcing", "function", "dynamic-callsites");
return true;
}
return false;
}
bool
module_function::is_address_range_constrained() const
{
if(!loop_blocks.empty()) return is_loop_address_range_constrained();
if(address_range < min_address_range)
{
messages.emplace_back(2, "Skipping", "function", "min-address-range");
return true;
}
return false;
}
bool
module_function::is_loop_address_range_constrained() const
{
if(loop_blocks.empty()) return false;
if(address_range < min_loop_address_range)
{
messages.emplace_back(2, "Skipping", "function", "min-address-range-loop");
return true;
}
return false;
}
bool
module_function::is_num_instructions_constrained() const
{
if(num_instructions < min_instructions)
{
messages.emplace_back(2, "Skipping", "function", "min-instructions");
return true;
}
return false;
}
bool
module_function::can_instrument_entry() const
{
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
if(_num_points == 0)
{
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-entry-point");
return false;
}
return true;
}
bool
module_function::can_instrument_exit() const
{
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
if(_num_points == 0)
{
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-exit-point");
return false;
}
return true;
}
bool
module_function::is_entry_trap_constrained() const
{
if(instr_traps) return false;
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
if(!instr_traps && (_num_points - _num_traps) == 0)
{
messages.emplace_back(3, "Skipping", "function",
"entry-point-trap-instrumentation");
return true;
}
return false;
}
bool
module_function::is_exit_trap_constrained() const
{
if(instr_traps) return false;
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
if((_num_points - _num_traps) == 0)
{
messages.emplace_back(3, "Skipping", "function",
"exit-point-trap-instrumentation");
return true;
}
return false;
}
std::pair<size_t, size_t>
module_function::operator()(address_space_t* _addr_space, procedure_t* _entr_trace,
procedure_t* _exit_trace) const
{
std::pair<size_t, size_t> _count = { 0, 0 };
auto _name = signature.get();
auto _trace_entr = omnitrace_call_expr(_name.c_str());
auto _trace_exit = omnitrace_call_expr(_name.c_str());
auto _entr = _trace_entr.get(_entr_trace);
auto _exit = _trace_exit.get(_exit_trace);
if(insert_instr(_addr_space, function, _entr, BPatch_entry, nullptr, nullptr,
instr_traps) &&
insert_instr(_addr_space, function, _exit, BPatch_exit, nullptr, nullptr,
instr_traps))
{
messages.emplace_back(1, "Instrumenting", "function", "no-constraint");
++_count.first;
}
for(auto* itr : loop_blocks)
{
if(!loop_level_instr) continue;
auto _is_constrained = [this](bool _v, const std::string& _label) {
if(!_v)
{
messages.emplace_back(3, "Skipping", "function", _label);
return true;
}
return false;
};
size_t _points = 0;
size_t _ntraps = 0;
std::tie(_points, _ntraps) = query_instr(function, BPatch_entry, flow_graph, itr);
if(_is_constrained(_points == 0, "no-instrumentable-loop-entry-point")) continue;
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
"loop-entry-point-trap-instrumentation"))
continue;
std::tie(_points, _ntraps) = query_instr(function, BPatch_exit, flow_graph, itr);
if(_is_constrained(_points == 0, "no-instrumentable-loop-exit-point")) continue;
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
"loop-exit-point-trap-instrumentation"))
continue;
auto lname = get_loop_file_line_info(module, function, flow_graph, itr);
auto _lname = lname.get();
messages.emplace_back(1, "Loop Instrumenting", "function", "no-constraint");
++_count.second;
auto _ltrace_entr = omnitrace_call_expr(_lname.c_str());
auto _ltrace_exit = omnitrace_call_expr(_lname.c_str());
auto _lentr = _ltrace_entr.get(_entr_trace);
auto _lexit = _ltrace_exit.get(_exit_trace);
insert_instr(_addr_space, function, _lentr, BPatch_entry, flow_graph, itr,
instr_loop_traps);
insert_instr(_addr_space, function, _lexit, BPatch_exit, flow_graph, itr,
instr_loop_traps);
}
return _count;
}
+185
Voir le fichier
@@ -0,0 +1,185 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "function_signature.hpp"
#include "fwd.hpp"
#include <timemory/mpl/concepts.hpp>
#include <timemory/tpls/cereal/cereal/cereal.hpp>
struct module_function
{
using width_t = std::array<size_t, 4>;
using address_t = Dyninst::Address;
static constexpr size_t absolute_max_width = 80;
static width_t& get_width();
static void reset_width();
static void update_width(const module_function& rhs);
static void write_header(std::ostream& os);
TIMEMORY_DEFAULT_OBJECT(module_function)
module_function(module_t* mod, procedure_t* proc);
std::pair<size_t, size_t> operator()(address_space_t* _addr_space,
procedure_t* _entr_trace,
procedure_t* _exit_trace) const;
// applies logic for all "is_*" and "can_*" checks below
bool should_instrument() const;
// hard constraints
bool is_instrumentable() const; // checks whether can instrument
bool can_instrument_entry() const; // checks for entry points
bool can_instrument_exit() const; // checks for exit points
bool is_module_constrained() const; // checks module constraints
bool is_routine_constrained() const; // checks function constraints
// user bypass of heuristics
bool is_user_restricted() const; // checks user restrict regexes
bool is_user_included() const; // checks user include regexes
bool is_user_excluded() const; // checks user exclude regexes
// applied before dynamic-callsite constraint
bool is_overlapping_constrained() const; // checks overlapping constrains
bool is_entry_trap_constrained() const; // checks entry trap constraint
bool is_exit_trap_constrained() const; // checks exit trap constraint
// applied before address range and # instruction constraints
bool is_dynamic_callsite_forced() const; // checks dynamic callsites
// estimate the size/work of the function
bool is_address_range_constrained() const; // checks address range constraint
bool is_num_instructions_constrained() const; // check # instructions constraint
uint64_t address_range = 0;
uint64_t num_instructions = 0;
module_t* module = nullptr;
procedure_t* function = nullptr;
flow_graph_t* flow_graph = nullptr;
string_t module_name = {};
string_t function_name = {};
function_signature signature = {};
basic_block_set_t basic_blocks = {};
basic_loop_vec_t loop_blocks = {};
using str_msg_t = std::tuple<int, string_t, string_t, string_t>;
using str_msg_vec_t = std::vector<str_msg_t>;
mutable str_msg_vec_t messages = {};
bool is_overlapping() const; // checks if func overlaps
private:
bool is_loop_address_range_constrained() const; // checks loop addr range constraint
bool contains_dynamic_callsites() const;
public:
template <typename ArchiveT>
void serialize(ArchiveT& ar, const unsigned);
friend bool operator<(const module_function& lhs, const module_function& rhs)
{
return (lhs.module_name == rhs.module_name)
? ((lhs.function_name == rhs.function_name)
? (lhs.signature.get() < rhs.signature.get())
: (lhs.function_name < rhs.function_name))
: (lhs.module_name < rhs.module_name);
}
friend bool operator==(const module_function& lhs, const module_function& rhs)
{
return std::tie(lhs.module_name, lhs.function_name, lhs.signature,
lhs.address_range, lhs.num_instructions) ==
std::tie(rhs.module_name, rhs.function_name, rhs.signature,
rhs.address_range, rhs.num_instructions);
}
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
{
std::stringstream ss;
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
auto _get_str = [](const std::string& _inc) {
if(_inc.length() > absolute_max_width)
return _inc.substr(0, absolute_max_width - 3) + "...";
return _inc;
};
// clang-format off
ss << std::setw(14) << rhs.address_range << " "
<< std::setw(14) << rhs.num_instructions << " "
<< std::setw(6) << std::setprecision(2) << std::fixed << (rhs.address_range / static_cast<double>(rhs.num_instructions)) << " "
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module_name) << " "
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function_name) << " "
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
// clang-format on
os << ss.str();
return os;
}
};
template <typename ArchiveT>
void
module_function::serialize(ArchiveT& ar, const unsigned)
{
namespace cereal = tim::cereal;
ar(cereal::make_nvp("address_range", address_range),
cereal::make_nvp("instructions", num_instructions),
cereal::make_nvp("module", module_name),
cereal::make_nvp("function", function_name),
cereal::make_nvp("signature", signature));
if constexpr(tim::concepts::is_output_archive<ArchiveT>::value)
{
ar.setNextName("heuristics");
ar.startNode();
ar(cereal::make_nvp("should_instrument", should_instrument()),
cereal::make_nvp("is_instrumentable", is_instrumentable()),
cereal::make_nvp("can_instrument_entry", can_instrument_entry()),
cereal::make_nvp("can_instrument_exit", can_instrument_exit()),
cereal::make_nvp("contains_dynamic_callsites", contains_dynamic_callsites()),
cereal::make_nvp("is_module_constrained", is_module_constrained()),
cereal::make_nvp("is_routine_constrained", is_routine_constrained()),
cereal::make_nvp("is_user_restricted", is_user_restricted()),
cereal::make_nvp("is_user_included", is_user_included()),
cereal::make_nvp("is_user_excluded", is_user_excluded()),
cereal::make_nvp("is_overlapping_constrained", is_overlapping_constrained()),
cereal::make_nvp("is_entry_trap_constrained", is_entry_trap_constrained()),
cereal::make_nvp("is_exit_trap_constrained", is_exit_trap_constrained()),
cereal::make_nvp("is_dynamic_callsite_forced", is_dynamic_callsite_forced()),
cereal::make_nvp("is_address_range_constrained",
is_address_range_constrained()),
cereal::make_nvp("is_loop_address_range_constrained",
is_loop_address_range_constrained()),
cereal::make_nvp("is_num_instructions_constrained",
is_num_instructions_constrained()));
ar.finishNode();
}
}
+212 -575
Voir le fichier
Fichier diff supprimé car celui-ci est trop grand Voir la Diff
+79 -684
Voir le fichier
@@ -22,231 +22,10 @@
#pragma once
#include <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/mpl/apply.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/mpl/policy.hpp>
#include <timemory/tpls/cereal/archives.hpp>
#include <timemory/tpls/cereal/cereal.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/popen.hpp>
#include <timemory/variadic/macros.hpp>
#include <BPatch.h>
#include <BPatch_Vector.h>
#include <BPatch_addressSpace.h>
#include <BPatch_basicBlockLoop.h>
#include <BPatch_callbacks.h>
#include <BPatch_function.h>
#include <BPatch_point.h>
#include <BPatch_process.h>
#include <BPatch_snippet.h>
#include <BPatch_statement.h>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <exception>
#include <fstream>
#include <limits>
#include <memory>
#include <numeric>
#include <ostream>
#include <regex>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>
#include <vector>
#define MUTNAMELEN 1024
#define FUNCNAMELEN 32 * 1024
#define NO_ERROR -1
#define TIMEMORY_BIN_DIR "bin"
#if !defined(PATH_MAX)
# define PATH_MAX std::numeric_limits<int>::max();
#endif
struct function_signature;
struct module_function;
template <typename Tp>
using bpvector_t = BPatch_Vector<Tp>;
using string_t = std::string;
using stringstream_t = std::stringstream;
using strvec_t = std::vector<string_t>;
using strset_t = std::set<string_t>;
using regexvec_t = std::vector<std::regex>;
using fmodset_t = std::set<module_function>;
using fixed_modset_t = std::map<fmodset_t*, bool>;
using exec_callback_t = BPatchExecCallback;
using exit_callback_t = BPatchExitCallback;
using fork_callback_t = BPatchForkCallback;
using patch_t = BPatch;
using process_t = BPatch_process;
using thread_t = BPatch_thread;
using binary_edit_t = BPatch_binaryEdit;
using image_t = BPatch_image;
using module_t = BPatch_module;
using procedure_t = BPatch_function;
using snippet_t = BPatch_snippet;
using call_expr_t = BPatch_funcCallExpr;
using address_space_t = BPatch_addressSpace;
using flow_graph_t = BPatch_flowGraph;
using basic_loop_t = BPatch_basicBlockLoop;
using procedure_loc_t = BPatch_procedureLocation;
using point_t = BPatch_point;
using local_var_t = BPatch_localVar;
using const_expr_t = BPatch_constExpr;
using error_level_t = BPatchErrorLevel;
using patch_pointer_t = std::shared_ptr<patch_t>;
using snippet_pointer_t = std::shared_ptr<snippet_t>;
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
using snippet_vec_t = bpvector_t<snippet_t*>;
using procedure_vec_t = bpvector_t<procedure_t*>;
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
void
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
//======================================================================================//
//
// Global Variables
//
//======================================================================================//
//
// boolean settings
//
static bool use_return_info = false;
static bool use_args_info = false;
static bool use_file_info = false;
static bool use_line_info = false;
//
// integral settings
//
extern bool debug_print;
extern int verbose_level;
//
// string settings
//
static string_t main_fname = "main";
static string_t argv0 = {};
static string_t cmdv0 = {};
static string_t default_components = "wall_clock";
static string_t prefer_library = {};
//
// global variables
//
static patch_pointer_t bpatch = {};
static call_expr_t* terminate_expr = nullptr;
static snippet_vec_t init_names = {};
static snippet_vec_t fini_names = {};
static fmodset_t available_module_functions = {};
static fmodset_t instrumented_module_functions = {};
static fmodset_t overlapping_module_functions = {};
static fmodset_t excluded_module_functions = {};
static fixed_modset_t fixed_module_functions = {};
static regexvec_t func_include = {};
static regexvec_t func_exclude = {};
static regexvec_t file_include = {};
static regexvec_t file_exclude = {};
static regexvec_t file_restrict = {};
static regexvec_t func_restrict = {};
//
//======================================================================================//
// control debug printf statements
#define errprintf(LEVEL, ...) \
{ \
if(werror || LEVEL < 0) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
char _buff[FUNCNAMELEN]; \
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
throw std::runtime_error(std::string{ _buff }); \
} \
else \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
} \
fflush(stderr); \
}
// control verbose printf statements
#define verbprintf(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
fflush(stdout); \
}
#define verbprintf_bare(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
fflush(stdout); \
}
//======================================================================================//
template <typename... T>
void
consume_parameters(T&&...)
{}
//======================================================================================//
extern "C"
{
bool are_file_include_exclude_lists_empty();
bool instrument_module(const string_t& file_name);
bool instrument_entity(const string_t& function_name);
bool module_constraint(char* fname);
bool routine_constraint(const char* fname);
}
//======================================================================================//
strset_t
get_whole_function_names();
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument);
bool
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr,
bool allow_traps = true);
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
void
errorFunc(error_level_t level, int num, const char** params);
procedure_t*
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
void
error_func_real(error_level_t level, int num, const char* const* params);
void
error_func_fake(error_level_t level, int num, const char* const* params);
#include "function_signature.hpp"
#include "fwd.hpp"
#include "info.hpp"
#include "module_function.hpp"
//======================================================================================//
@@ -285,465 +64,6 @@ to_lower(string_t s)
//
//======================================================================================//
//
struct function_signature
{
using location_t = std::pair<unsigned long, unsigned long>;
bool m_loop = false;
bool m_info_beg = false;
bool m_info_end = false;
location_t m_row = { 0, 0 };
location_t m_col = { 0, 0 };
string_t m_return = {};
string_t m_name = {};
string_t m_params = "()";
string_t m_file = {};
mutable string_t m_signature = {};
TIMEMORY_DEFAULT_OBJECT(function_signature)
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
(void) get();
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
(void) get();
}
function_signature(string_t _ret, const string_t& _name, string_t _file,
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
bool _loop = false, bool _info_beg = false, bool _info_end = false)
: m_loop(_loop)
, m_info_beg(_info_beg)
, m_info_end(_info_end)
, m_row(std::move(_row))
, m_col(std::move(_col))
, m_return(std::move(_ret))
, m_name(tim::demangle(_name))
, m_file(std::move(_file))
{
if(m_file.find('/') != string_t::npos)
m_file = m_file.substr(m_file.find_last_of('/') + 1);
}
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
location_t _col = { 0, 0 }, bool _loop = false,
bool _info_beg = false, bool _info_end = false)
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
{
m_params = "(";
for(const auto& itr : _params)
m_params.append(itr + ", ");
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
m_params += ")";
}
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
{
return lhs.get() == rhs.get();
}
static auto get(function_signature& sig) { return sig.get(); }
string_t get() const
{
std::stringstream ss;
if(use_return_info && !m_return.empty()) ss << m_return << " ";
ss << m_name;
if(use_args_info) ss << m_params;
if(m_loop && m_info_beg)
{
if(m_info_end)
{
ss << " [{" << m_row.first << "," << m_col.first << "}-{" << m_row.second
<< "," << m_col.second << "}]";
}
else
{
ss << "[{" << m_row.first << "," << m_col.first << "}]";
}
}
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
if(use_file_info && m_file.length() > 0) ss << "]";
m_signature = ss.str();
return m_signature;
}
};
//
//======================================================================================//
//
struct module_function
{
using width_t = std::array<size_t, 3>;
using address_t = Dyninst::Address;
static constexpr size_t absolute_max_width = 80;
static auto& get_width()
{
static width_t _instance = []() {
width_t _tmp;
_tmp.fill(0);
return _tmp;
}();
return _instance;
}
TIMEMORY_DEFAULT_OBJECT(module_function)
static void reset_width() { get_width().fill(0); }
static void update_width(const module_function& rhs)
{
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module.length());
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function.length());
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
}
module_function(string_t _module, string_t _func, function_signature _sign,
procedure_t* proc)
: module(std::move(_module))
, function(std::move(_func))
, signature(std::move(_sign))
{
if(proc)
{
std::pair<address_t, address_t> _range{};
if(proc->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
}
module_function(module_t* mod, procedure_t* proc)
{
char modname[FUNCNAMELEN];
char fname[FUNCNAMELEN];
mod->getFullName(modname, FUNCNAMELEN);
proc->getName(fname, FUNCNAMELEN);
module = modname;
function = fname;
signature = get_func_file_line_info(mod, proc);
if(!proc->isInstrumentable())
{
verbprintf(0,
"Warning! module function generated for un-instrumentable "
"function: %s [%s]\n",
function.c_str(), module.c_str());
}
std::pair<address_t, address_t> _range{};
if(proc->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
friend bool operator<(const module_function& lhs, const module_function& rhs)
{
return (lhs.module == rhs.module)
? ((lhs.function == rhs.function)
? (lhs.signature.get() < rhs.signature.get())
: (lhs.function < rhs.function))
: (lhs.module < rhs.module);
}
friend bool operator==(const module_function& lhs, const module_function& rhs)
{
return std::tie(lhs.module, lhs.function, lhs.signature, lhs.address_range) ==
std::tie(rhs.module, rhs.function, rhs.signature, rhs.address_range);
}
static void write_header(std::ostream& os)
{
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
std::stringstream ss;
ss << std::setw(14) << "AddressRange"
<< " " << std::setw(w0 + 8) << std::left << "Module"
<< " " << std::setw(w1 + 8) << std::left << "Function"
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
<< "\n";
os << ss.str();
}
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
{
std::stringstream ss;
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
auto _get_str = [](const std::string& _inc) {
if(_inc.length() > absolute_max_width)
return _inc.substr(0, absolute_max_width - 3) + "...";
return _inc;
};
// clang-format off
ss << std::setw(14) << rhs.address_range << " "
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module) << " "
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function) << " "
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
// clang-format on
os << ss.str();
return os;
}
size_t address_range = 0;
string_t module = {};
string_t function = {};
function_signature signature = {};
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
_ar(cereal::make_nvp("address_range", address_range),
cereal::make_nvp("module", module), cereal::make_nvp("function", function),
cereal::make_nvp("signature", signature));
}
};
//
//======================================================================================//
//
static inline void
dump_info(std::ostream& _os, const fmodset_t& _data)
{
module_function::reset_width();
for(const auto& itr : _data)
module_function::update_width(itr);
module_function::write_header(_os);
for(const auto& itr : _data)
_os << itr << '\n';
module_function::reset_width();
}
//
template <typename ArchiveT,
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
static inline void
dump_info(ArchiveT& _ar, const fmodset_t& _data)
{
_ar(tim::cereal::make_nvp("module_functions", _data));
}
//
static inline void
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
const fmodset_t& _data, int _level, bool _fail)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
_oname += "." + _ext;
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[dump_info] Error opening '" << _oname << " for output";
verbprintf(_level, "%s\n", _msg.str().c_str());
if(_fail)
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(!debug_print && verbose_level < _level) return;
if(_ext == "txt")
{
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
dump_info(ofs, _data);
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "xml")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
output_policy::indent() = true;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "json")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
"' does not have one of recognized file extensions: txt, json, xml"));
}
}
//
static inline void
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
const string_t& _type, const strset_t& _ext)
{
for(const auto& itr : _ext)
dump_info(_type, _oname, itr, _data, _level, _fail);
}
//
static inline void
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
auto _pos = _iname.find_last_of('.');
std::string _ext = {};
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[load_info] Error opening '" << _iname << " for input";
verbprintf(_level, "%s\n", _msg.str().c_str());
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(_ext == "xml")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else if(_ext == "json")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
}
}
//
static inline void
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
{
std::vector<std::string> _exceptions{};
_exceptions.reserve(_data.size());
for(auto& itr : _data)
{
try
{
fmodset_t _tmp{};
load_info(itr.first, _inp, _tmp, _level);
// add to the existing
itr.second->insert(_tmp.begin(), _tmp.end());
// if it did not throw it was successfully loaded
_exceptions.clear();
break;
} catch(std::exception& _e)
{
_exceptions.emplace_back(_e.what());
}
}
if(!_exceptions.empty())
{
std::stringstream _msg{};
for(auto& itr : _exceptions)
{
_msg << "[omnitrace][exe] " << itr << "\n";
}
throw std::runtime_error(_msg.str());
}
}
//
//======================================================================================//
//
template <typename Tp, std::enable_if_t<!std::is_same<Tp, std::string>::value, int> = 0>
snippet_pointer_t
get_snippet(Tp arg)
@@ -962,4 +282,79 @@ omnitrace_fork_callback(thread_t* parent, thread_t* child)
}
//
//======================================================================================//
// insert_instr -- generic insert instrumentation function
//
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument, bool allow_traps)
{
module_t* module = funcToInstr->getModule();
if(!module || !traceFunc) return false;
bpvector_t<point_t*>* _points = nullptr;
auto _trace = traceFunc.get();
if(cfGraph && loopToInstrument)
{
if(traceLoc == BPatch_entry)
_points = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, loopToInstrument);
else if(traceLoc == BPatch_exit)
_points = cfGraph->findLoopInstPoints(BPatch_locLoopExit, loopToInstrument);
}
else
{
_points = funcToInstr->findPoint(traceLoc);
}
if(_points == nullptr) return false;
if(_points->empty()) return false;
/*if(loop_level_instr)
{
flow_graph_t* flow = funcToInstr->getCFG();
bpvector_t<basic_loop_t*> basicLoop;
flow->getOuterLoops(basicLoop);
for(auto litr = basicLoop.begin(); litr != basicLoop.end(); ++litr)
{
bpvector_t<point_t*>* _tmp;
if(traceLoc == BPatch_entry)
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, *litr);
else if(traceLoc == BPatch_exit)
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopExit, *litr);
if(!_tmp)
continue;
for(auto& itr : *_tmp)
_points->push_back(itr);
}
}*/
// verbprintf(0, "Instrumenting |> [ %s ]\n", name.m_name.c_str());
std::set<point_t*> _traps{};
if(!allow_traps)
{
for(auto& itr : *_points)
{
if(itr && itr->usesTrap_NP()) _traps.insert(itr);
}
}
size_t _n = 0;
for(auto& itr : *_points)
{
if(!itr || _traps.count(itr) > 0)
continue;
else if(traceLoc == BPatch_entry)
mutatee->insertSnippet(*_trace, *itr, BPatch_callBefore, BPatch_firstSnippet);
// else if(traceLoc == BPatch_exit)
// mutatee->insertSnippet(*_trace, *itr, BPatch_callAfter,
// BPatch_firstSnippet);
else
mutatee->insertSnippet(*_trace, *itr);
++_n;
}
return (_n > 0);
}
+149
Voir le fichier
@@ -0,0 +1,149 @@
# adds a ctest for executable
function(OMNITRACE_ADD_BIN_TEST)
cmake_parse_arguments(
TEST
"" # options
"NAME;TARGET;TIMEOUT;WORKING_DIRECTORY" # single value args
"ARGS;ENVIRONMENT;LABELS;PROPERTIES;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;SKIP_REGULAR_EXPRESSION;DEPENDS;COMMAND" # multiple
# value args
${ARGN})
if(NOT OMNITRACE_DYNINST_API_RT_DIR AND OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
if(OMNITRACE_BUILD_DYNINST)
set(OMNITRACE_DYNINST_API_RT_DIR
"${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT:${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI"
)
endif()
if(NOT TEST_ENVIRONMENT)
set(TEST_ENVIRONMENT
"OMNITRACE_USE_PERFETTO=ON"
"OMNITRACE_USE_TIMEMORY=ON"
"OMNITRACE_USE_SAMPLING=ON"
"OMNITRACE_TIME_OUTPUT=OFF"
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
)
endif()
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON"
"OMNITRACE_OUTPUT_PATH=omnitrace-tests-output"
"OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/")
if(TEST_COMMAND)
add_test(
NAME ${TEST_NAME}
COMMAND ${TEST_COMMAND} ${TEST_ARGS}
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
set_tests_properties(
${TEST_NAME}
PROPERTIES ENVIRONMENT
"${TEST_ENVIRONMENT}"
TIMEOUT
${TEST_TIMEOUT}
LABELS
"omnitrace-bin;${TEST_LABELS}"
PASS_REGULAR_EXPRESSION
"${TEST_PASS_REGULAR_EXPRESSION}"
FAIL_REGULAR_EXPRESSION
"${TEST_FAIL_REGULAR_EXPRESSION}"
SKIP_REGULAR_EXPRESSION
"${TEST_SKIP_REGULAR_EXPRESSION}"
${TEST_PROPERTIES})
elseif(TARGET ${TEST_TARGET})
add_test(
NAME ${TEST_NAME}
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_ARGS}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
set_tests_properties(
${TEST_NAME}
PROPERTIES ENVIRONMENT
"${TEST_ENVIRONMENT}"
TIMEOUT
${TEST_TIMEOUT}
LABELS
"omnitrace-bin;${TEST_LABELS}"
PASS_REGULAR_EXPRESSION
"${TEST_PASS_REGULAR_EXPRESSION}"
FAIL_REGULAR_EXPRESSION
"${TEST_FAIL_REGULAR_EXPRESSION}"
SKIP_REGULAR_EXPRESSION
"${TEST_SKIP_REGULAR_EXPRESSION}"
${TEST_PROPERTIES})
elseif(OMNITRACE_BUILD_TESTING)
message(FATAL_ERROR "Error! ${TEST_TARGET} does not exist")
endif()
endfunction()
omnitrace_add_bin_test(
NAME omnitrace-exe-help
TARGET omnitrace-exe
ARGS --help
LABELS omnitrace-exe
TIMEOUT 15
PASS_REGULAR_EXPRESSION
".*\\\[omnitrace\\\] Usage:.*\\\[DEBUG OPTIONS\\\].*\\\[MODE OPTIONS\\\].*\\\[LIBRARY OPTIONS\\\].*\\\[SYMBOL SELECTION OPTIONS\\\].*\\\[RUNTIME OPTIONS\\\].*\\\[GRANULARITY OPTIONS\\\].*\\\[DYNINST OPTIONS\\\].*"
)
omnitrace_add_bin_test(
NAME omnitrace-exe-simulate-ls
TARGET omnitrace-exe
ARGS --simulate --print-format json txt xml -- ls
TIMEOUT 60)
omnitrace_add_bin_test(
NAME omnitrace-exe-simulate-ls-check
DEPENDS omnitrace-exe-simulate-ls
COMMAND ls
WORKING_DIRECTORY
${PROJECT_BINARY_DIR}/omnitrace-tests-output/omnitrace-exe-simulate-ls
TIMEOUT 30
PASS_REGULAR_EXPRESSION
".*available-instr.json.*available-instr.txt.*available-instr.xml.*excluded-instr.json.*excluded-instr.txt.*excluded-instr.xml.*instrumented-instr.json.*instrumented-instr.txt.*instrumented-instr.xml.*overlapping-instr.json.*overlapping-instr.txt.*overlapping-instr.xml.*"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-help
TARGET omnitrace-avail
ARGS --help
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
".*\\\[omnitrace-avail\\\] Usage:.*\\\[CATEGORIES\\\].*\\\[VIEW OPTIONS\\\].*\\\[COLUMN OPTIONS\\\].*\\\[WIDTH OPTIONS\\\].*\\\[OUTPUT OPTIONS\\\].*"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-filter-wall-clock-available
TARGET omnitrace-avail
ARGS -r wall_clock -C --available
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
"\\\|[-]+\\\|\n\\\|[ ]+COMPONENT[ ]+\\\|\n\\\|[-]+\\\|\n\\\| (wall_clock)[ ]+\\\|\n\\\| (sampling_wall_clock)[ ]+\\\|\n\\\|[-]+\\\|"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-category-filer-omnitrace
TARGET omnitrace-avail
ARGS --categories settings::omnitrace --brief
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE|OUTPUT_PREFIX)"
FAIL_REGULAR_EXPRESSION
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-category-filer-timemory
TARGET omnitrace-avail
ARGS --categories settings::timemory --brief
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
FAIL_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE)")
+9 -181
Voir le fichier
@@ -1,186 +1,14 @@
# ------------------------------------------------------------------------------#
# ----------------------------------------------------------------------------- #
#
# omnitrace interface library
# omnitrace: contains all instrumentation functionality
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-interface-library INTERFACE)
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
target_include_directories(
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(omnitrace-interface-library SYSTEM
INTERFACE ${perfetto_DIR}/sdk)
target_compile_definitions(
omnitrace-interface-library
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
target_link_libraries(
omnitrace-interface-library
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
$<BUILD_INTERFACE:timemory::timemory-headers>
$<BUILD_INTERFACE:timemory::timemory-gotcha>
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
# ------------------------------------------------------------------------------#
# omnitrace-dl: contains minimal symbols and dlopen's omnitrace
#
# omnitrace object library
# omnitrace-user: contains symbols for user API
#
# ------------------------------------------------------------------------------#
# ----------------------------------------------------------------------------- #
add_library(omnitrace-object-library OBJECT)
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
set(library_sources
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
${perfetto_DIR}/sdk/perfetto.cc)
set(library_headers
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
${perfetto_DIR}/sdk/perfetto.h)
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
if(OMNITRACE_USE_ROCTRACER)
target_sources(
omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
endif()
if(OMNITRACE_USE_ROCM_SMI)
target_sources(omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
endif()
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
if(OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
# ------------------------------------------------------------------------------#
#
# omnitrace shared library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
set_target_properties(
omnitrace-library
PROPERTIES OUTPUT_NAME omnitrace
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
INSTALL_RPATH
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
install(
TARGETS omnitrace-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
# ------------------------------------------------------------------------------#
#
# omnitrace dl library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
add_library(omnitrace-dl-library SHARED)
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/dl.cpp)
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY})
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_dl_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_dl_library_fno_exceptions)
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_dl_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
set_target_properties(
omnitrace-dl-library
PROPERTIES OUTPUT_NAME omnitrace-dl
CXX_VISIBILITY_PRESET "protected"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-dl-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
add_subdirectory(common)
add_subdirectory(omnitrace)
add_subdirectory(omnitrace-dl)
add_subdirectory(omnitrace-user)
+22
Voir le fichier
@@ -0,0 +1,22 @@
# ------------------------------------------------------------------------------#
#
# omnitrace common headers
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-common-library INTERFACE)
add_library(omnitrace::common-library ALIAS omnitrace-common-library)
target_sources(
omnitrace-common-library
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/defines.h
${CMAKE_CURRENT_SOURCE_DIR}/delimit.hpp
${CMAKE_CURRENT_SOURCE_DIR}/environment.hpp
${CMAKE_CURRENT_SOURCE_DIR}/invoke.hpp
${CMAKE_CURRENT_SOURCE_DIR}/join.hpp)
get_filename_component(COMMON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY)
target_include_directories(omnitrace-common-library INTERFACE ${COMMON_INCLUDE_DIR})
target_compile_definitions(omnitrace-common-library
INTERFACE $<BUILD_INTERFACE:OMNITRACE_INTERNAL_BUILD>)
+36
Voir le fichier
@@ -0,0 +1,36 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
#define OMNITRACE_WEAK_API OMNITRACE_ATTRIBUTE(weak)
#define OMNITRACE_INLINE OMNITRACE_ATTRIBUTE(__always_inline__)
#if defined(__cplusplus)
# if !defined(OMNITRACE_FOLD_EXPRESSION)
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
# endif
#endif
+65
Voir le fichier
@@ -0,0 +1,65 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <string>
#include <vector>
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename ContainerT = std::vector<std::string>>
inline ContainerT
delimit(const std::string& line, const char* delimiters = "\"',;: ");
template <typename ContainerT>
inline ContainerT
delimit(const std::string& line, const char* delimiters)
{
ContainerT _result{};
size_t _beginp = 0; // position that is the beginning of the new string
size_t _delimp = 0; // position of the delimiter in the string
while(_beginp < line.length() && _delimp < line.length())
{
// find the first character (starting at _delimp) that is not a delimiter
_beginp = line.find_first_not_of(delimiters, _delimp);
// if no a character after or at _end that is not a delimiter is not found
// then we are done
if(_beginp == std::string::npos) break;
// starting at the position of the new string, find the next delimiter
_delimp = line.find_first_of(delimiters, _beginp);
std::string _tmp{};
// starting at the position of the new string, get the characters
// between this position and the next delimiter
_tmp = line.substr(_beginp, _delimp - _beginp);
// don't add empty strings
if(!_tmp.empty()) _result.emplace(_result.end(), _tmp);
}
return _result;
}
} // namespace
} // namespace common
} // namespace omnitrace
+77
Voir le fichier
@@ -0,0 +1,77 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <cstdlib>
#include <cstring>
#include <string>
#include <string_view>
namespace omnitrace
{
inline namespace common
{
namespace
{
inline std::string
get_env(const char* env_id, const char* _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::string{ env_var };
return _default;
}
inline int
get_env(const char* env_id, int _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::stoi(env_var);
return _default;
}
inline bool
get_env(const char* env_id, bool _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var)
{
if(std::string_view{ env_var }.find_first_not_of("0123456789") ==
std::string_view::npos)
return static_cast<bool>(std::stoi(env_var));
else
{
for(size_t i = 0; i < strlen(env_var); ++i)
env_var[i] = tolower(env_var[i]);
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
if(strcmp(env_var, itr) == 0) return false;
}
return true;
}
return _default;
}
} // namespace
} // namespace common
} // namespace omnitrace
+114
Voir le fichier
@@ -0,0 +1,114 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "common/defines.h"
#include "common/join.hpp"
#include <atomic>
#include <cstring>
#include <functional>
#include <string>
#if !defined(OMNITRACE_COMMON_LIBRARY_NAME)
# define OMNITRACE_COMMON_LIBRARY_NAME "common"
# error OMNITRACE_COMMON_LIBRARY_NAME must be defined
#endif
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename FuncT, typename... Args>
inline auto
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN_API;
inline int32_t&
get_guard()
{
static thread_local int32_t _v = 0;
return _v;
}
inline int64_t
get_thread_index()
{
static std::atomic<int64_t> _c{ 0 };
static thread_local auto _v = _c++;
return _v;
}
template <typename FuncT, typename... Args>
auto
invoke(const char* _name, int _verbose, FuncT&& _func, Args... _args)
{
if(_func)
{
struct decrement_guard
{
// decrement the guard as it exits the scope
~decrement_guard() { --get_guard(); }
} _unlk{};
// if _lk is ever greater than zero on the same thread, this
// means a function within the current function is calling
// our instrumentation so we ignore the call
int32_t _lk = get_guard()++;
if(_lk == 0)
{
if(_verbose > 3)
{
fflush(stderr);
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME "][%li] %s(%s)\n",
get_thread_index(), _name, join(", ", _args...).c_str());
fflush(stderr);
}
return std::invoke(std::forward<FuncT>(_func), _args...);
}
else if(_verbose > 2)
{
fflush(stderr);
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
"][%li] %s(%s) was guarded :: value = %i\n",
get_thread_index(), _name, join(", ", _args...).c_str(), _lk);
fflush(stderr);
}
}
else if(_verbose >= 0)
{
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
"][%li] %s(%s) ignored :: null function pointer\n",
get_thread_index(), _name, join(", ", _args...).c_str());
}
using return_type = decltype(std::invoke(std::forward<FuncT>(_func), _args...));
if constexpr(!std::is_void<return_type>::value) return return_type();
}
} // namespace
} // namespace common
} // namespace omnitrace
+55
Voir le fichier
@@ -0,0 +1,55 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <sstream>
#include <string>
#if !defined(OMNITRACE_FOLD_EXPRESSION)
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
#endif
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename DelimT, typename... Args>
auto
join(DelimT&& _delim, Args&&... _args)
{
std::stringstream _ss{};
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
if constexpr(std::is_same<DelimT, char>::value)
{
return _ss.str().substr(1);
}
else
{
return _ss.str().substr(std::string{ _delim }.length());
}
}
} // namespace
} // namespace common
} // namespace omnitrace
+55
Voir le fichier
@@ -0,0 +1,55 @@
# ------------------------------------------------------------------------------#
#
# omnitrace dl library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
add_library(omnitrace-dl-library SHARED)
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dl.cpp)
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY}
omnitrace::common-library)
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_dl_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_dl_library_fno_exceptions)
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_dl_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
omnitrace_target_compile_definitions(
omnitrace-dl-library PRIVATE OMNITRACE_USE_OMPT=$<BOOL:${OMNITRACE_USE_OMPT}>)
set_target_properties(
omnitrace-dl-library
PROPERTIES OUTPUT_NAME omnitrace-dl
CXX_VISIBILITY_PRESET "protected"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-dl-library
EXPORT omnitrace-dl-library-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
install(
EXPORT omnitrace-dl-library-targets
FILE omnitrace-dl-library-targets.cmake
NAMESPACE omnitrace::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
+199 -204
Voir le fichier
@@ -22,6 +22,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#define OMNITRACE_COMMON_LIBRARY_NAME "dl"
#include "common/defines.h"
#include "common/delimit.hpp"
#include "common/environment.hpp"
#include "common/invoke.hpp"
#include "common/join.hpp"
#include <atomic>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
@@ -38,15 +47,15 @@
#include <sys/stat.h>
#include <unistd.h>
#define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
#define OMNITRACE_VISIBLE __attribute__((visibility("default")))
#define OMNITRACE_HIDDEN __attribute__((visibility("internal")))
#define OMNITRACE_INLINE __attribute__((__always_inline__))
#if !defined(OMNITRACE_USE_OMPT)
# define OMNITRACE_USE_OMPT 0
#endif
#define OMNITRACE_DLSYM(VARNAME, HANDLE, FUNCNAME) \
if(HANDLE) \
{ \
*(void**) (&VARNAME) = dlsym(HANDLE, FUNCNAME); \
if(VARNAME == nullptr && _omnitrace_dl_verbose >= 0) \
if(VARNAME == nullptr && _omnitrace_dl_verbose >= _warn_verbose) \
{ \
fprintf(stderr, "[omnitrace][dl][pid=%i]> %s :: %s\n", getpid(), FUNCNAME, \
dlerror()); \
@@ -61,50 +70,45 @@
extern "C"
{
void omnitrace_init_library(void) OMNITRACE_VISIBLE;
void omnitrace_init(const char*, bool, const char*) OMNITRACE_VISIBLE;
void omnitrace_finalize(void) OMNITRACE_VISIBLE;
void omnitrace_set_env(const char* env_name, const char* env_val) OMNITRACE_VISIBLE;
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_VISIBLE;
void omnitrace_push_trace(const char* name) OMNITRACE_VISIBLE;
void omnitrace_pop_trace(const char* name) OMNITRACE_VISIBLE;
struct ompt_start_tool_result_t;
void omnitrace_init_library(void) OMNITRACE_PUBLIC_API;
void omnitrace_init(const char*, bool, const char*) OMNITRACE_PUBLIC_API;
void omnitrace_finalize(void) OMNITRACE_PUBLIC_API;
void omnitrace_set_env(const char* env_name,
const char* env_val) OMNITRACE_PUBLIC_API;
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_PUBLIC_API;
void omnitrace_push_trace(const char* name) OMNITRACE_PUBLIC_API;
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
void omnitrace_user_start_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_stop_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_start_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_stop_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_push_region_dl(const char*) OMNITRACE_HIDDEN_API;
void omnitrace_user_pop_region_dl(const char*) OMNITRACE_HIDDEN_API;
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
const char*) OMNITRACE_PUBLIC_API;
}
//--------------------------------------------------------------------------------------//
inline namespace omnitrace
namespace omnitrace
{
inline namespace dl
{
namespace
{
inline int
get_omnitrace_env();
bool
get_env(const char* env_id, bool _default);
std::string
get_env(const char* env_id, const char* _default);
int
get_env(const char* env_id, int _default);
template <typename DelimT, typename... Args>
auto
join(DelimT&& _delim, Args&&... _args)
get_omnitrace_env()
{
std::stringstream _ss{};
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
if constexpr(std::is_same<DelimT, char>::value)
{
return _ss.str().substr(1);
}
else
{
return _ss.str().substr(std::string{ _delim }.length());
}
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
}
// environment priority:
// - OMNITRACE_DL_DEBUG
// - OMNITRACE_DL_VERBOSE
@@ -114,10 +118,6 @@ int _omnitrace_dl_verbose = get_env("OMNITRACE_DL_DEBUG", false)
? 100
: get_env("OMNITRACE_DL_VERBOSE", get_omnitrace_env());
template <typename ContainerT = std::vector<std::string>>
inline ContainerT
delimit(const std::string& line, const char* delimiters = "\"',;: ");
// The docs for dlopen suggest that the combination of RTLD_LOCAL + RTLD_DEEPBIND
// (when available) helps ensure that the symbols in the instrumentation library
// libomnitrace.so will use it's own symbols... not symbols that are potentially
@@ -162,39 +162,38 @@ const char* _omnitrace_dl_dlopen_descr = "RTLD_LAZY | RTLD_LOCAL";
#endif
/// This class contains function pointers for omnitrace's instrumentation functions
struct OMNITRACE_HIDDEN indirect
struct OMNITRACE_HIDDEN_API indirect
{
explicit OMNITRACE_INLINE indirect(std::string libpath)
: m_libpath{ find_path(std::move(libpath)) }
OMNITRACE_INLINE indirect(std::string omnilib, std::string userlib)
: m_omnilib{ find_path(std::move(omnilib)) }
, m_userlib{ find_path(std::move(userlib)) }
{
if(_omnitrace_dl_verbose > 0)
{
fprintf(stderr, "[omnitrace][dl][pid=%i] libomnitrace.so resolved to '%s'\n",
getpid(), m_libpath.c_str());
getpid(), m_omnilib.c_str());
}
auto _omni_hsa_lib = m_libpath;
auto _omni_hsa_lib = m_omnilib;
const char* _hsa_lib = getenv("HSA_TOOLS_LIB");
if(_hsa_lib) _omni_hsa_lib.append(":").append(_hsa_lib);
setenv("HSA_TOOLS_LIB", _omni_hsa_lib.c_str(), 1);
open();
m_omnihandle = open(m_omnilib);
m_userhandle = open(m_userlib);
init();
}
OMNITRACE_INLINE ~indirect() { dlclose(m_libhandle); }
OMNITRACE_INLINE ~indirect() { dlclose(m_omnihandle); }
OMNITRACE_INLINE void open()
static OMNITRACE_INLINE void* open(const std::string& _lib)
{
if(m_libhandle) return;
auto* libhandle = dlopen(m_libpath.c_str(), _omnitrace_dl_dlopen_flags);
auto* libhandle = dlopen(_lib.c_str(), _omnitrace_dl_dlopen_flags);
if(libhandle)
{
m_libhandle = libhandle;
if(_omnitrace_dl_verbose > 0)
{
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: success\n",
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr);
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr);
}
}
else
@@ -203,26 +202,48 @@ struct OMNITRACE_HIDDEN indirect
{
perror("dlopen");
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: %s\n",
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr,
dlerror());
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr, dlerror());
}
}
dlerror(); // Clear any existing error
return libhandle;
}
OMNITRACE_INLINE void init()
{
if(!m_libhandle) open();
if(!m_omnihandle) m_omnihandle = open(m_omnilib);
int _warn_verbose = 0;
// Initialize all pointers
OMNITRACE_DLSYM(omnitrace_init_library_f, m_libhandle, "omnitrace_init_library");
OMNITRACE_DLSYM(omnitrace_init_f, m_libhandle, "omnitrace_init");
OMNITRACE_DLSYM(omnitrace_finalize_f, m_libhandle, "omnitrace_finalize");
OMNITRACE_DLSYM(omnitrace_set_env_f, m_libhandle, "omnitrace_set_env");
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_libhandle, "omnitrace_set_mpi");
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_libhandle, "omnitrace_push_trace");
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_libhandle, "omnitrace_pop_trace");
OMNITRACE_DLSYM(omnitrace_init_library_f, m_omnihandle, "omnitrace_init_library");
OMNITRACE_DLSYM(omnitrace_init_f, m_omnihandle, "omnitrace_init");
OMNITRACE_DLSYM(omnitrace_finalize_f, m_omnihandle, "omnitrace_finalize");
OMNITRACE_DLSYM(omnitrace_set_env_f, m_omnihandle, "omnitrace_set_env");
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_omnihandle, "omnitrace_set_mpi");
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_omnihandle, "omnitrace_push_trace");
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_omnihandle, "omnitrace_pop_trace");
OMNITRACE_DLSYM(omnitrace_push_region_f, m_omnihandle, "omnitrace_push_region");
OMNITRACE_DLSYM(omnitrace_pop_region_f, m_omnihandle, "omnitrace_pop_region");
#if OMNITRACE_USE_OMPT == 0
_warn_verbose = 5;
#endif
OMNITRACE_DLSYM(ompt_start_tool_f, m_omnihandle, "ompt_start_tool");
if(!m_userhandle) m_userhandle = open(m_userlib);
_warn_verbose = 0;
OMNITRACE_DLSYM(omnitrace_user_configure_f, m_userhandle,
"omnitrace_user_configure");
if(omnitrace_user_configure_f)
{
(*omnitrace_user_configure_f)(
&omnitrace_user_start_trace_dl, &omnitrace_user_stop_trace_dl,
&omnitrace_user_start_thread_trace_dl,
&omnitrace_user_stop_thread_trace_dl, &omnitrace_user_push_region_dl,
&omnitrace_user_pop_region_dl);
}
}
static OMNITRACE_INLINE std::string find_path(std::string&& _path)
@@ -246,196 +267,170 @@ struct OMNITRACE_HIDDEN indirect
}
public:
void (*omnitrace_init_library_f)(void) = nullptr;
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
void (*omnitrace_finalize_f)(void) = nullptr;
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
void (*omnitrace_push_trace_f)(const char*) = nullptr;
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
void (*omnitrace_init_library_f)(void) = nullptr;
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
void (*omnitrace_finalize_f)(void) = nullptr;
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
void (*omnitrace_push_trace_f)(const char*) = nullptr;
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
void (*omnitrace_push_region_f)(const char*) = nullptr;
void (*omnitrace_pop_region_f)(const char*) = nullptr;
void (*omnitrace_user_configure_f)(void (*)(void), void (*)(void), void (*)(void),
void (*)(void), void (*)(const char*),
void (*)(const char*)) = nullptr;
ompt_start_tool_result_t* (*ompt_start_tool_f)(unsigned int, const char*);
private:
void* m_libhandle = nullptr;
std::string m_libpath = {};
void* m_omnihandle = nullptr;
void* m_userhandle = nullptr;
std::string m_omnilib = {};
std::string m_userlib = {};
};
inline indirect&
get_indirect() OMNITRACE_HIDDEN;
get_indirect() OMNITRACE_HIDDEN_API;
template <typename FuncT, typename... Args>
inline void
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN;
indirect&
get_indirect()
{
static auto _v =
indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so"),
get_env("OMNITRACE_USER_LIBRARY", "libomnitrace-user.so") };
return _v;
}
auto&
get_active()
{
static bool _v = false;
return _v;
}
auto&
get_enabled()
{
static std::atomic<bool> _v{ get_env("OMNITRACE_INIT_ENABLED", true) };
return _v;
}
auto&
get_thread_enabled()
{
static thread_local bool _v = get_enabled();
return _v;
}
auto&
get_count()
{
static std::atomic<int64_t> _v{ 0 };
return _v;
}
auto&
get_thread_count()
{
static thread_local int64_t _v = 0;
return _v;
}
} // namespace
} // namespace dl
} // namespace omnitrace
//--------------------------------------------------------------------------------------//
#define OMNITRACE_DL_INVOKE(...) \
::omnitrace::common::invoke(__FUNCTION__, ::omnitrace::dl::_omnitrace_dl_verbose, \
__VA_ARGS__)
using omnitrace::get_indirect;
namespace dl = omnitrace::dl;
extern "C"
{
void omnitrace_init_library(void)
{
invoke(__FUNCTION__, get_indirect().omnitrace_init_library_f);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_library_f);
}
void omnitrace_init(const char* a, bool b, const char* c)
{
invoke(__FUNCTION__, get_indirect().omnitrace_init_f, a, b, c);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_f, a, b, c);
dl::get_active() = true;
}
void omnitrace_finalize(void)
{
invoke(__FUNCTION__, get_indirect().omnitrace_finalize_f);
dl::get_active() = false;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_finalize_f);
}
void omnitrace_push_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect().omnitrace_push_trace_f, name);
if(!dl::get_active()) return;
if(dl::get_thread_enabled())
{
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_trace_f, name);
}
else
{
++dl::get_thread_count();
}
}
void omnitrace_pop_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect().omnitrace_pop_trace_f, name);
if(!dl::get_active()) return;
if(dl::get_thread_enabled())
{
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_trace_f, name);
}
else
{
if(dl::get_thread_count()-- == 0) omnitrace_user_start_thread_trace_dl();
}
}
void omnitrace_set_env(const char* a, const char* b)
{
setenv(a, b, 0);
invoke(__FUNCTION__, get_indirect().omnitrace_set_env_f, a, b);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_env_f, a, b);
}
void omnitrace_set_mpi(bool a, bool b)
{
invoke(__FUNCTION__, get_indirect().omnitrace_set_mpi_f, a, b);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_mpi_f, a, b);
}
}
//--------------------------------------------------------------------------------------//
void omnitrace_user_start_trace_dl(void) { dl::get_enabled().store(true); }
void omnitrace_user_stop_trace_dl(void) { dl::get_enabled().store(false); }
void omnitrace_user_start_thread_trace_dl(void) { dl::get_thread_enabled() = true; }
void omnitrace_user_stop_thread_trace_dl(void) { dl::get_thread_enabled() = false; }
inline namespace omnitrace
{
inline namespace dl
{
namespace
{
template <typename ContainerT>
inline ContainerT
delimit(const std::string& line, const char* delimiters)
{
ContainerT _result{};
size_t _beginp = 0; // position that is the beginning of the new string
size_t _delimp = 0; // position of the delimiter in the string
while(_beginp < line.length() && _delimp < line.length())
void omnitrace_user_push_region_dl(const char* name)
{
// find the first character (starting at _delimp) that is not a delimiter
_beginp = line.find_first_not_of(delimiters, _delimp);
// if no a character after or at _end that is not a delimiter is not found
// then we are done
if(_beginp == std::string::npos) break;
// starting at the position of the new string, find the next delimiter
_delimp = line.find_first_of(delimiters, _beginp);
std::string _tmp{};
// starting at the position of the new string, get the characters
// between this position and the next delimiter
_tmp = line.substr(_beginp, _delimp - _beginp);
// don't add empty strings
if(!_tmp.empty()) _result.emplace(_result.end(), _tmp);
if(!dl::get_active()) return;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_region_f, name);
}
return _result;
}
std::string
get_env(const char* env_id, const char* _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::string{ env_var };
return _default;
}
int
get_env(const char* env_id, int _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::stoi(env_var);
return _default;
}
bool
get_env(const char* env_id, bool _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var)
void omnitrace_user_pop_region_dl(const char* name)
{
if(std::string{ env_var }.find_first_not_of("0123456789") == std::string::npos)
return static_cast<bool>(std::stoi(env_var));
else
{
for(size_t i = 0; i < strlen(env_var); ++i)
env_var[i] = tolower(env_var[i]);
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
if(strcmp(env_var, itr) == 0) return false;
}
return true;
if(!dl::get_active()) return;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
}
return _default;
}
int
get_omnitrace_env()
{
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
}
indirect&
get_indirect()
{
static auto _v = indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so") };
return _v;
}
int32_t&
get_guard()
{
static thread_local int32_t _v = 0;
return _v;
}
template <typename FuncT, typename... Args>
void
invoke(const char* _name, FuncT&& _func, Args... _args)
{
if(_func)
ompt_start_tool_result_t* ompt_start_tool(unsigned int omp_version,
const char* runtime_version)
{
// if _lk is ever greater than zero on the same thread, this
// means a function within the current function is calling
// our instrumentation so we ignore the call
int32_t _lk = get_guard()++;
if(_lk == 0)
{
std::invoke(std::forward<FuncT>(_func), _args...);
}
else if(_omnitrace_dl_verbose > 2)
{
fflush(stderr);
fprintf(stderr, "[omnitrace][dl] call to %s was guarded :: value = %i\n",
_name, _lk);
fflush(stderr);
}
// decrement the guard as it exits the scope
--get_guard();
}
else if(_omnitrace_dl_verbose >= 0)
{
fprintf(stderr, "[omnitrace][dl] %s\n",
join("", "null function pointer to ", _name, ". Ignoring ", _name, "(",
_args..., ")")
.c_str());
#if OMNITRACE_USE_OMPT == 0
(void) omp_version;
(void) runtime_version;
return nullptr;
#else
if(!omnitrace::common::get_env("OMNITRACE_USE_OMPT", true)) return nullptr;
return OMNITRACE_DL_INVOKE(get_indirect().ompt_start_tool_f, omp_version,
runtime_version);
#endif
}
}
} // namespace
} // namespace dl
} // namespace omnitrace
+61
Voir le fichier
@@ -0,0 +1,61 @@
# ------------------------------------------------------------------------------#
#
# omnitrace user library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_library(omnitrace-user-library SHARED)
add_library(omnitrace::omnitrace-user-library ALIAS omnitrace-user-library)
target_sources(
omnitrace-user-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/user.cpp
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h)
target_include_directories(
omnitrace-user-library PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
check_cxx_compiler_flag("-fno-exceptions" omnitrace_user_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_user_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_user_library_fno_exceptions)
target_compile_options(omnitrace-user-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_user_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-user-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
set_target_properties(
omnitrace-user-library
PROPERTIES OUTPUT_NAME omnitrace-user
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-user-library
EXPORT omnitrace-user-library-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/omnitrace
OPTIONAL)
install(
EXPORT omnitrace-user-library-targets
FILE omnitrace-user-library-targets.cmake
NAMESPACE omnitrace::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
+50
Voir le fichier
@@ -0,0 +1,50 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef OMNITRACE_USER_H_
#define OMNITRACE_USER_H_ 1
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
#if defined(__cplusplus)
extern "C"
{
#endif
extern void omnitrace_user_start_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_stop_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_start_thread_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_stop_thread_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_push_region(const char*) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_pop_region(const char*) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_configure(void (*)(void), void (*)(void), void (*)(void),
void (*)(void), void (*)(const char*),
void (*)(const char*)) OMNITRACE_PUBLIC_API;
#if defined(__cplusplus)
}
#endif
#endif // OMNITRACE_USER_H_
+84
Voir le fichier
@@ -0,0 +1,84 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#define OMNITRACE_SOURCE 1
#include "omnitrace/user.h"
#include <cstdio>
namespace
{
using void_func_t = void (*)(void);
using region_func_t = void (*)(const char*);
void_func_t _start_trace = nullptr;
void_func_t _stop_trace = nullptr;
void_func_t _start_thread_trace = nullptr;
void_func_t _stop_thread_trace = nullptr;
region_func_t _push_region = nullptr;
region_func_t _pop_region = nullptr;
} // namespace
extern "C"
{
void omnitrace_user_start_trace(void)
{
if(_start_trace) (*_start_trace)();
}
void omnitrace_user_stop_trace(void)
{
if(_stop_trace) (*_stop_trace)();
}
void omnitrace_user_start_thread_trace(void)
{
if(_start_thread_trace) (*_start_thread_trace)();
}
void omnitrace_user_stop_thread_trace(void)
{
if(_stop_thread_trace) (*_stop_thread_trace)();
}
void omnitrace_user_push_region(const char* name)
{
if(_push_region) (*_push_region)(name);
}
void omnitrace_user_pop_region(const char* name)
{
if(_pop_region) (*_pop_region)(name);
}
void omnitrace_user_configure(void (*_a)(), void (*_b)(), void (*_c)(), void (*_d)(),
void (*_e)(const char*), void (*_f)(const char*))
{
_start_trace = _a;
_stop_trace = _b;
_start_thread_trace = _c;
_stop_thread_trace = _d;
_push_region = _e;
_pop_region = _f;
}
}
+145
Voir le fichier
@@ -0,0 +1,145 @@
# ------------------------------------------------------------------------------#
#
# omnitrace interface library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-interface-library INTERFACE)
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
target_include_directories(
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(omnitrace-interface-library SYSTEM
INTERFACE ${perfetto_DIR}/sdk)
target_compile_definitions(
omnitrace-interface-library
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
target_link_libraries(
omnitrace-interface-library
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
$<BUILD_INTERFACE:timemory::timemory-headers>
$<BUILD_INTERFACE:timemory::timemory-gotcha>
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
# ------------------------------------------------------------------------------#
#
# omnitrace object library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-object-library OBJECT)
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
set(library_sources
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ompt.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/user_region.cpp
${perfetto_DIR}/sdk/perfetto.cc)
set(library_headers
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ompt.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/user_region.hpp
${perfetto_DIR}/sdk/perfetto.h)
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
if(OMNITRACE_USE_ROCTRACER)
target_sources(
omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
endif()
if(OMNITRACE_USE_ROCM_SMI)
target_sources(omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
endif()
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
if(OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
# ------------------------------------------------------------------------------#
#
# omnitrace shared library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
set_target_properties(
omnitrace-library
PROPERTIES OUTPUT_NAME omnitrace
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
INSTALL_RPATH
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
install(
TARGETS omnitrace-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
@@ -51,6 +51,12 @@ extern "C"
/// stops an instrumentation region
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
/// starts an instrumentation region (user-defined)
void omnitrace_push_region(const char* name) OMNITRACE_PUBLIC_API;
/// stops an instrumentation region (user-defined)
void omnitrace_pop_region(const char* name) OMNITRACE_PUBLIC_API;
// these are the real implementations for internal calling convention
void omnitrace_init_library_hidden(void) OMNITRACE_HIDDEN_API;
void omnitrace_init_hidden(const char*, bool, const char*) OMNITRACE_HIDDEN_API;
@@ -60,4 +66,6 @@ extern "C"
void omnitrace_set_mpi_hidden(bool use, bool attached) OMNITRACE_HIDDEN_API;
void omnitrace_push_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_pop_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_push_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_pop_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
}
@@ -68,6 +68,7 @@ using functor_t = std::function<void(Tp...)>;
using default_functor_t = functor_t<const char*>;
struct omnitrace;
struct user_region;
struct backtrace;
struct backtrace_wall_clock
{};
@@ -126,6 +127,8 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_
TIMEMORY_SET_COMPONENT_API(omnitrace::component::omnitrace, project::omnitrace,
category::dynamic_instrumentation, os::supports_linux)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::user_region, project::omnitrace,
os::supports_linux)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::roctracer, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux,
category::external)
@@ -154,6 +157,8 @@ TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_temp, project::omn
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::omnitrace, OMNITRACE_COMPONENT,
"omnitrace", "omnitrace_component")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::user_region, OMNITRACE_USER_REGION,
"user_region", "omnitrace_user_region")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
"roctracer", "omnitrace_roctracer")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
@@ -173,6 +178,15 @@ TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
OMNITRACE_SAMPLING_GPU_TEMP, "sampling_gpu_temp", "")
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::omnitrace, "omnitrace",
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
"Used by gotcha wrappers")
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::user_region, "user_region",
"Invokes instrumentation functions 'omnitrace_user_push_region' and "
"'omnitrace_user_pop_region'",
"Used by OMPT")
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
"High-precision ROCm API and kernel tracing", "")
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
@@ -43,8 +43,3 @@ private:
};
} // namespace component
} // namespace omnitrace
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::omnitrace, "omnitrace",
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
"Used by gotcha wrappers")
+56
Voir le fichier
@@ -0,0 +1,56 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "library/defines.hpp"
#include "library/timemory.hpp"
namespace omnitrace
{
namespace component
{
// timemory component which calls omnitrace functions
// (used in gotcha wrappers)
struct user_region : comp::base<user_region, void>
{
static std::string label() { return "user_region"; }
void start();
void stop();
void set_prefix(const char*);
private:
const char* m_prefix = nullptr;
};
} // namespace component
} // namespace omnitrace
TIMEMORY_COMPONENT_ALIAS(omnitrace_user_region, omnitrace::component::user_region)
#if !defined(OMNITRACE_EXTERN_COMPONENTS) || \
(defined(OMNITRACE_EXTERN_COMPONENTS) && OMNITRACE_EXTERN_COMPONENTS > 0)
# include <timemory/operations.hpp>
TIMEMORY_DECLARE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
#endif
@@ -171,6 +171,9 @@ get_use_critical_trace();
bool
get_use_kokkosp();
bool
get_use_ompt();
bool
get_timeline_sampling();
@@ -245,6 +248,9 @@ get_critical_trace_per_row();
State&
get_state();
/// returns old state
State set_state(State);
std::unique_ptr<main_bundle_t>&
get_main_bundle();
@@ -30,6 +30,9 @@
#include <timemory/utility/utility.hpp>
#include <cstdio>
#include <cstring>
#include <string_view>
#include <utility>
namespace omnitrace
{
@@ -47,8 +50,32 @@ get_debug_pid();
bool
get_critical_trace_debug();
} // namespace config
namespace debug
{
namespace
{
template <typename T, size_t... Idx>
auto get_chars(std::index_sequence<Idx...>)
{
static const char _v[sizeof...(Idx) + 1] = { T::get()[Idx]..., '\0' };
return _v;
}
template <typename T>
auto
get_chars()
{
return get_chars<T>(typename T::sequence{});
}
} // namespace
} // namespace debug
} // namespace omnitrace
#define OMNITRACE_VAR_NAME_COMBINE(X, Y) X##Y
#define OMNITRACE_LINESTR TIMEMORY_STRINGIZE(__LINE__)
#define OMNITRACE_VARIABLE(LABEL) OMNITRACE_VAR_NAME_COMBINE(_omni_var_, LABEL)
#if defined(TIMEMORY_USE_MPI)
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::dmp::rank())
#elif defined(TIMEMORY_USE_MPI_HEADERS)
@@ -59,6 +86,26 @@ get_critical_trace_debug();
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::process::get_id())
#endif
#define OMNITRACE_FUNCTION \
std::string{ __FUNCTION__ } \
.substr(0, std::string_view{ __FUNCTION__ }.find("_hidden")) \
.c_str()
#define OMNITRACE_CT_FUNCTION(VAR, STR) \
static constexpr auto OMNITRACE_VARIABLE(__LINE__) = std::string_view{ STR }; \
VAR = OMNITRACE_CT_FUNCTION_IMPL(OMNITRACE_VARIABLE(__LINE__));
#define OMNITRACE_CT_FUNCTION_IMPL(STR) \
[]() { \
struct wrapper \
{ \
static constexpr const char* get() { return STR.data(); } \
using sequence = \
std::make_index_sequence<std::min(STR.find("_hidden"), STR.length())>; \
}; \
return ::omnitrace::debug::get_chars<wrapper>(); \
}();
#define OMNITRACE_CONDITIONAL_PRINT(COND, ...) \
if((COND) && ::omnitrace::config::get_debug_tid() && \
::omnitrace::config::get_debug_pid()) \
@@ -89,7 +136,7 @@ get_critical_trace_debug();
fflush(stderr); \
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
fprintf(stderr, "[omnitrace][%i][%li][%s] ", OMNITRACE_PROCESS_IDENTIFIER, \
tim::threading::get_id(), __FUNCTION__); \
tim::threading::get_id(), OMNITRACE_FUNCTION); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
@@ -100,7 +147,7 @@ get_critical_trace_debug();
{ \
fflush(stderr); \
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
fprintf(stderr, "[omnitrace][%s] ", __FUNCTION__); \
fprintf(stderr, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
@@ -110,7 +157,8 @@ get_critical_trace_debug();
{ \
char _msg_buffer[2048]; \
snprintf(_msg_buffer, 2048, "[omnitrace][%i][%li][%s] ", \
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), __FUNCTION__); \
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), \
OMNITRACE_FUNCTION); \
auto len = strlen(_msg_buffer); \
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
throw std::runtime_error(_msg_buffer); \
@@ -120,12 +168,20 @@ get_critical_trace_debug();
if(COND) \
{ \
char _msg_buffer[2048]; \
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", __FUNCTION__); \
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
auto len = strlen(_msg_buffer); \
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
throw std::runtime_error(_msg_buffer); \
}
#define OMNITRACE_CI_THROW(COND, ...) \
OMNITRACE_CONDITIONAL_THROW(::omnitrace::get_is_continuous_integration() && (COND), \
__VA_ARGS__)
#define OMNITRACE_CI_BASIC_THROW(COND, ...) \
OMNITRACE_CONDITIONAL_BASIC_THROW( \
::omnitrace::get_is_continuous_integration() && (COND), __VA_ARGS__)
#define OMNITRACE_STRINGIZE(...) #__VA_ARGS__
#define OMNITRACE_ESC(...) __VA_ARGS__
@@ -36,12 +36,14 @@
// clang-format on
#define TIMEMORY_USER_COMPONENT_ENUM \
OMNITRACE_COMPONENT_idx, OMNITRACE_ROCTRACER_idx, OMNITRACE_SAMPLING_WALL_CLOCK_idx, \
OMNITRACE_SAMPLING_CPU_CLOCK_idx, OMNITRACE_SAMPLING_PERCENT_idx, \
OMNITRACE_SAMPLING_GPU_POWER_idx, OMNITRACE_SAMPLING_GPU_TEMP_idx, \
OMNITRACE_SAMPLING_GPU_BUSY_idx, OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
OMNITRACE_COMPONENT_idx, OMNITRACE_USER_REGION_idx, OMNITRACE_ROCTRACER_idx, \
OMNITRACE_SAMPLING_WALL_CLOCK_idx, OMNITRACE_SAMPLING_CPU_CLOCK_idx, \
OMNITRACE_SAMPLING_PERCENT_idx, OMNITRACE_SAMPLING_GPU_POWER_idx, \
OMNITRACE_SAMPLING_GPU_TEMP_idx, OMNITRACE_SAMPLING_GPU_BUSY_idx, \
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
#define OMNITRACE_COMPONENT OMNITRACE_COMPONENT_idx
#define OMNITRACE_USER_REGION OMNITRACE_USER_REGION_idx
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
+35
Voir le fichier
@@ -0,0 +1,35 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
namespace omnitrace
{
namespace ompt
{
void
setup();
void
shutdown();
} // namespace ompt
} // namespace omnitrace
@@ -33,6 +33,7 @@
# define PERFETTO_CATEGORIES \
perfetto::Category("host").SetDescription("Host-side function tracing"), \
perfetto::Category("device").SetDescription("Device-side function tracing"), \
perfetto::Category("user").SetDescription("User-defined regions"), \
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
perfetto::Category("sampling") \
.SetDescription("Metrics derived from sampling"), \
@@ -46,6 +47,7 @@
# define PERFETTO_CATEGORIES \
perfetto::Category("host").SetDescription("Host-side function tracing"), \
perfetto::Category("device").SetDescription("Device-side function tracing"), \
perfetto::Category("user").SetDescription("User-defined regions"), \
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
perfetto::Category("sampling") \
.SetDescription("Metrics derived from sampling"), \
+191 -46
Voir le fichier
@@ -32,6 +32,7 @@
#include "library/debug.hpp"
#include "library/defines.hpp"
#include "library/gpu.hpp"
#include "library/ompt.hpp"
#include "library/ptl.hpp"
#include "library/sampling.hpp"
#include "library/thread_data.hpp"
@@ -46,10 +47,22 @@ using namespace omnitrace;
//======================================================================================//
using library_functors = omnitrace::component::functors<omnitrace::api::omnitrace>;
namespace
{
struct omni_regions
{};
struct user_regions
{};
} // namespace
TIMEMORY_DEFINE_NAME_TRAIT("cpu_instrumentation", library_functors);
TIMEMORY_INVOKE_PREINIT(library_functors)
using omni_functors = omnitrace::component::functors<omni_regions>;
using user_functors = omnitrace::component::functors<user_regions>;
// TIMEMORY_DEFINE_NAME_TRAIT("host", omni_functors);
// TIMEMORY_DEFINE_NAME_TRAIT("user", user_functors);
TIMEMORY_INVOKE_PREINIT(omni_functors)
TIMEMORY_INVOKE_PREINIT(user_functors)
//======================================================================================//
@@ -159,6 +172,9 @@ pop_count()
}
auto _debug_push = tim::get_env("OMNITRACE_DEBUG_PUSH", false) && !get_debug_env();
auto _debug_pop = tim::get_env("OMNITRACE_DEBUG_POP", false) && !get_debug_env();
auto _debug_user =
tim::get_env("OMNITRACE_DEBUG_USER_REGIONS", false) && !get_debug_env();
} // namespace
//======================================================================================//
@@ -172,11 +188,11 @@ omnitrace_push_trace_hidden(const char* name)
if(get_state() == State::Finalized)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug_push, "%s(%s) called during finalization\n", __FUNCTION__, name);
_debug_push, "omnitrace_push_trace(%s) called during finalization\n", name);
return;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "%s(%s)\n", __FUNCTION__, name);
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_trace(%s)\n", name);
// the expectation here is that if the state is not active then the call
// to omnitrace_init_tooling_hidden will activate all the appropriate
@@ -184,12 +200,13 @@ omnitrace_push_trace_hidden(const char* name)
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
{
static auto _debug = get_debug_env() || get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug, "%s :: not active. state = %s\n",
name, std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_push_trace(%s) ignored :: not active. state = %s\n", name,
std::to_string(get_state()).c_str());
return;
}
OMNITRACE_DEBUG_F("%s\n", name);
OMNITRACE_DEBUG("omnitrace_push_trace(%s)\n", name);
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
static thread_local size_t _sample_idx = 0;
@@ -197,7 +214,7 @@ omnitrace_push_trace_hidden(const char* name)
auto _enabled = (_sample_idx++ % _sample_rate == 0);
_interval->emplace_back(_enabled);
if(_enabled) library_functors::start(name);
if(_enabled) omni_functors::start(name);
if(get_use_critical_trace())
{
uint64_t _cid = 0;
@@ -222,15 +239,17 @@ omnitrace_pop_trace_hidden(const char* name)
{
++pop_count();
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_pop, "omnitrace_pop_trace(%s)\n", name);
// only execute when active
if(get_state() == State::Active)
{
OMNITRACE_DEBUG_F("%s\n", name);
OMNITRACE_DEBUG("omnitrace_pop_trace(%s)\n", name);
auto& _interval_data = get_interval_data();
if(!_interval_data->empty())
{
if(_interval_data->back()) library_functors::stop(name);
if(_interval_data->back()) omni_functors::stop(name);
_interval_data->pop_back();
}
@@ -255,9 +274,64 @@ omnitrace_pop_trace_hidden(const char* name)
else
{
static auto _debug = get_debug_env();
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug, "[%s] %s ignored :: state = %s\n",
__FUNCTION__, name,
std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_pop_trace(%s) ignored :: state = %s\n", name,
std::to_string(get_state()).c_str());
}
}
//======================================================================================//
///
///
///
//======================================================================================//
extern "C" void
omnitrace_push_region_hidden(const char* name)
{
// unconditionally return if finalized
if(get_state() == State::Finalized)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug_user, "omnitrace_push_region(%s) called during finalization\n", name);
return;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_region(%s)\n", name);
// the expectation here is that if the state is not active then the call
// to omnitrace_init_tooling_hidden will activate all the appropriate
// tooling one time and as it exits set it to active and return true.
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
{
static auto _debug = get_debug_env() || get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_push_region(%s) ignored :: not active. state = %s\n", name,
std::to_string(get_state()).c_str());
return;
}
OMNITRACE_DEBUG("omnitrace_push_region(%s)\n", name);
user_functors::start(name);
}
//======================================================================================//
extern "C" void
omnitrace_pop_region_hidden(const char* name)
{
// only execute when active
if(get_state() == State::Active)
{
OMNITRACE_DEBUG("omnitrace_pop_region(%s)\n", name);
user_functors::stop(name);
}
else
{
static auto _debug = get_debug_env();
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_pop_region(%s) ignored :: state = %s\n", name,
std::to_string(get_state()).c_str());
}
}
@@ -271,7 +345,7 @@ extern "C" void
omnitrace_set_env_hidden(const char* env_name, const char* env_val)
{
// just search env to avoid initializing the settings
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
"[%s] Setting env: %s=%s\n", __FUNCTION__, env_name,
env_val);
@@ -279,9 +353,10 @@ omnitrace_set_env_hidden(const char* env_name, const char* env_val)
OMNITRACE_CONDITIONAL_THROW(
get_state() >= State::Init &&
(config::get_is_continuous_integration() || get_debug_env()),
"%s(\"%s\", \"%s\") called after omnitrace was initialized. state = %s",
__FUNCTION__, env_name, env_val, std::to_string(get_state()).c_str());
(config::get_is_continuous_integration() || get_debug_init()),
"omnitrace_set_env(\"%s\", \"%s\") called after omnitrace was initialized. state "
"= %s",
env_name, env_val, std::to_string(get_state()).c_str());
}
//======================================================================================//
@@ -300,7 +375,7 @@ extern "C" void
omnitrace_set_mpi_hidden(bool use, bool attached)
{
// just search env to avoid initializing the settings
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
"[%s] use: %s, attached: %s\n", __FUNCTION__,
(use) ? "y" : "n", (attached) ? "y" : "n");
@@ -319,9 +394,10 @@ omnitrace_set_mpi_hidden(bool use, bool attached)
OMNITRACE_CONDITIONAL_THROW(
get_state() >= State::Init &&
(config::get_is_continuous_integration() || get_debug_env()),
"%s(use=%s, attached=%s) called after omnitrace was initialized. state = %s",
__FUNCTION__, std::to_string(use).c_str(), std::to_string(attached).c_str(),
(config::get_is_continuous_integration() || get_debug_init()),
"omnitrace_set_mpi(use=%s, attached=%s) called after omnitrace was initialized. "
"state = %s",
std::to_string(use).c_str(), std::to_string(attached).c_str(),
std::to_string(get_state()).c_str());
_start_gotcha_callback();
@@ -335,23 +411,37 @@ omnitrace_init_library_hidden()
auto _tid = threading::get_id();
(void) _tid;
auto _mode = get_mode();
auto _debug_init = get_debug_init();
static bool _once = false;
auto _mode = get_mode();
auto _debug_init = get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
std::to_string(get_state()).c_str());
OMNITRACE_CI_THROW(get_state() != State::PreInit, "State is not PreInit :: %s",
std::to_string(get_state()).c_str());
if(get_state() != State::PreInit || get_state() == State::Init || _once) return;
_once = true;
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s. Setting to %s...\n",
std::to_string(get_state()).c_str(),
std::to_string(State::Init).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
"glibc's backtrace() occurs...\n");
{
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
"glibc's backtrace() occurs...\n");
std::stringstream _ss{};
tim::print_backtrace<64>(_ss);
(void) _ss;
}
get_state() = State::Init;
set_state(State::Init);
OMNITRACE_CI_THROW(get_state() != State::Init,
"set_state(State::Init) failed. state is %s",
std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "Configuring settings...\n");
@@ -395,8 +485,9 @@ omnitrace_init_library_hidden()
if(get_use_kokkosp())
{
auto _force = 0;
if(tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY") == "libtimemory.so")
auto _force = 0;
auto _current_kokkosp_lib = tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY");
if(std::regex_search(_current_kokkosp_lib, std::regex{ "libtimemory\\." }))
_force = 1;
tim::set_env("KOKKOS_PROFILE_LIBRARY", "libomnitrace.so", _force);
}
@@ -537,8 +628,12 @@ omnitrace_init_tooling_hidden()
return true;
}();
static thread_local auto _dtor = scope::destructor{ []() {
if(get_use_sampling()) sampling::shutdown();
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
if(get_state() != State::Finalized)
{
if(get_use_sampling()) sampling::shutdown();
if(thread_data<omnitrace_thread_bundle_t>::instance())
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
}
} };
(void) _thread_setup;
(void) _dtor;
@@ -555,7 +650,7 @@ omnitrace_init_tooling_hidden()
(void) _v;
};
// functors for starting and stopping timemory
// functors for starting and stopping timemory omni functors
auto _push_timemory = [](const char* name) {
auto& _data = get_instrumentation_bundles();
// this generates a hash for the raw string array
@@ -566,11 +661,6 @@ omnitrace_init_tooling_hidden()
_bundle->start();
};
auto _push_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
};
auto _pop_timemory = [](const char* name) {
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
auto& _data = get_instrumentation_bundles();
@@ -593,14 +683,33 @@ omnitrace_init_tooling_hidden()
}
};
// functors for starting and stopping perfetto omni functors
auto _push_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
};
auto _pop_perfetto = [](const char*) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_END("host", _ts);
};
// functors for starting and stopping perfetto user functors
auto _push_user_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("user", nullptr, _ts, [name](perfetto::EventContext& _ctx) {
_ctx.event()->set_name(name);
});
};
auto _pop_user_perfetto = [](const char*) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_END("user", _ts);
};
if(get_use_perfetto() && get_use_timemory())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_perfetto(name);
@@ -611,20 +720,44 @@ omnitrace_init_tooling_hidden()
_pop_timemory(name);
_pop_perfetto(name);
});
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_user_perfetto(name);
_push_timemory(name);
},
[=](const char* name) {
_pop_timemory(name);
_pop_user_perfetto(name);
});
}
else if(get_use_perfetto())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_perfetto(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_perfetto(name); });
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_user_perfetto(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_user_perfetto(name); });
}
else if(get_use_timemory())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_timemory(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_timemory(name); });
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_timemory(name);
@@ -633,6 +766,8 @@ omnitrace_init_tooling_hidden()
[=](const char* name) { _pop_timemory(name); });
}
ompt::setup();
if(get_use_perfetto() && !is_system_backend())
{
#if defined(CUSTOM_DATA_SOURCE)
@@ -676,9 +811,16 @@ omnitrace_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _a
(void) pop_count();
get_finalization_functions().emplace_back([_argv0]() {
// if main hasn't been popped yet, pop it
OMNITRACE_BASIC_PRINT("Running omnitrace_pop_trace(%s)...\n", _argv0);
omnitrace_pop_trace_hidden(_argv0);
OMNITRACE_CI_THROW(get_state() != State::Active,
"Finalizer function for popping main invoked in non-active "
"state :: state = %s\n",
std::to_string(get_state()).c_str());
if(get_state() == State::Active)
{
// if main hasn't been popped yet, pop it
OMNITRACE_BASIC_VERBOSE(2, "Running omnitrace_pop_trace(%s)...\n", _argv0);
omnitrace_pop_trace_hidden(_argv0);
}
});
std::atexit([]() {
@@ -740,9 +882,10 @@ omnitrace_finalize_hidden(void)
}
}
get_state() = State::Finalized;
set_state(State::Finalized);
library_functors::configure([](const char*) {}, [](const char*) {});
omni_functors::configure([](const char*) {}, [](const char*) {});
user_functors::configure([](const char*) {}, [](const char*) {});
pthread_gotcha::push_enable_sampling_on_child_threads(false);
pthread_gotcha::set_sampling_on_all_future_threads(false);
@@ -785,6 +928,8 @@ omnitrace_finalize_hidden(void)
}
}
ompt::shutdown();
OMNITRACE_DEBUG_F("Stopping and destroying instrumentation bundles...\n");
for(auto& itr : instrumentation_bundles::instances())
{
+12
Voir le fichier
@@ -34,6 +34,18 @@ omnitrace_pop_trace(const char* _name)
omnitrace_pop_trace_hidden(_name);
}
extern "C" void
omnitrace_push_region(const char* _name)
{
omnitrace_push_region_hidden(_name);
}
extern "C" void
omnitrace_pop_region(const char* _name)
{
omnitrace_pop_region_hidden(_name);
}
extern "C" void
omnitrace_init_library(void)
{
@@ -231,7 +231,7 @@ backtrace::get_thread_cpu_timestamp() const
void
backtrace::sample(int signum)
{
if(get_state() != State::Active)
if(signum != -1 && get_state() != State::Active)
{
OMNITRACE_CONDITIONAL_PRINT(
get_debug_sampling(),
@@ -341,7 +341,6 @@ backtrace::configure(bool _setup, int64_t _tid)
OMNITRACE_DEBUG("Configuring sampler for thread %lu...\n", _tid);
sampler_running_instances::construct(true);
backtrace_init_instances::construct();
sampling::sampler_instances::construct("omnitrace", _tid, *_signal_types);
_sampler->set_signals(*_signal_types);
_sampler->set_flags(SA_RESTART);
@@ -363,6 +362,7 @@ backtrace::configure(bool _setup, int64_t _tid)
_sampler->get_rate(units::sec));
// (void) sampling::sampler_t::get_samplers(_tid);
backtrace_init_instances::construct();
get_backtrace_init(_tid)->sample();
_sampler->configure(false);
_sampler->start();
@@ -617,6 +617,8 @@ backtrace::post_process(int64_t _tid)
auto* _bt = ditr->get<backtrace>();
if(_bt->m_ts < _last_wall_ts) continue;
double _elapsed_wc = (_bt->m_ts - _last_wall_ts).count();
double _elapsed_cc = (_bt->m_thr_cpu_ts - _last_cpu_ts);
@@ -86,8 +86,7 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***)
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s(int*, char***)\n",
__FUNCTION__, _data.tool_id.c_str());
if(get_state() == ::omnitrace::State::DelayedInit)
get_state() = ::omnitrace::State::PreInit;
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
omnitrace_push_trace_hidden(_data.tool_id.c_str());
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
@@ -102,8 +101,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***, in
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(),
"[%s] %s(int*, char***, int, int*)\n", __FUNCTION__,
_data.tool_id.c_str());
if(get_state() == ::omnitrace::State::DelayedInit)
get_state() = ::omnitrace::State::PreInit;
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
omnitrace_push_trace_hidden(_data.tool_id.c_str());
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
@@ -140,6 +140,8 @@ pthread_gotcha::wrapper::operator()() const
{
_tid = threading::get_id();
threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid).c_str());
// initialize thread-local statics
(void) tim::get_unw_backtrace<12, 1, false>();
{
std::unique_lock<std::mutex> _lk{ bundles_mutex };
if(comp::roctracer::is_setup())
@@ -86,7 +86,7 @@ check_error(rsmi_status_t ec)
}
std::atomic<State>&
get_rocm_smi_state()
get_state()
{
static std::atomic<State> _v{ State::PreInit };
return _v;
@@ -151,7 +151,7 @@ config()
void
sample()
{
if(get_rocm_smi_state() != State::Active) return;
if(rocm_smi::get_state() != State::Active) return;
for(auto itr : data::device_list)
{
@@ -168,63 +168,9 @@ sample()
void
set_state(State _v)
{
get_rocm_smi_state().store(_v);
rocm_smi::get_state().store(_v);
}
/*
void
data::poll(std::atomic<State>* _state, nsec_t _interval, promise_t* _ready)
{
threading::set_thread_name("omni.rocm_smi");
// notify thread started
if(_ready) _ready->set_value();
std::vector<std::unique_ptr<bundle_t>*> _bundle_data{};
_bundle_data.resize(device_count, nullptr);
for(size_t i = 0; i < device_count; ++i)
{
if(device_list.count(i) > 0)
{
_bundle_data.at(i) = &sampler_instances::instances().at(i);
if(!*_bundle_data.at(i)) *_bundle_data.at(i) = std::make_unique<bundle_t>();
}
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(
get_verbose() > 0 || get_debug(),
"Polling rocm-smi for %zu device(s) at an interval of %f seconds...\n",
device_list.size(),
std::chrono::duration_cast<std::chrono::duration<double>>(_interval).count());
get_initial().resize(device_count);
for(auto itr : device_list)
get_initial().at(itr).sample(itr);
auto _now = std::chrono::steady_clock::now();
while(_state && _state->load() != State::Finalized && get_state() != State::Finalized)
{
std::this_thread::sleep_until(_now);
if(_state->load() != State::Active) continue;
for(auto itr : device_list)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(),
"Polling rocm-smi for device %u...\n", itr);
auto& _data = *_bundle_data.at(itr);
if(!_data) continue;
_data->emplace_back(data{ itr });
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), " %s\n",
TIMEMORY_JOIN("", _data->back()).c_str());
}
while(_now < std::chrono::steady_clock::now())
_now += _interval;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), "Polling rocm-smi completed...\n");
if(polling_finished) polling_finished->set_value();
}
*/
std::vector<data>&
data::get_initial()
{
@@ -236,7 +182,7 @@ bool
data::setup()
{
perfetto_counter_track<data>::init();
set_state(State::PreInit);
rocm_smi::set_state(State::PreInit);
return true;
}
@@ -244,7 +190,7 @@ bool
data::shutdown()
{
OMNITRACE_DEBUG("Shutting down rocm-smi...\n");
set_state(State::Finalized);
rocm_smi::set_state(State::Finalized);
return true;
}
+52
Voir le fichier
@@ -0,0 +1,52 @@
// MIT License
//
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "library/components/user_region.hpp"
#include "library/api.hpp"
#include "library/components/fwd.hpp"
namespace omnitrace
{
namespace component
{
void
user_region::start()
{
if(m_prefix) omnitrace_push_region_hidden(m_prefix);
}
void
user_region::stop()
{
if(m_prefix) omnitrace_pop_region_hidden(m_prefix);
}
void
user_region::set_prefix(const char* _prefix)
{
m_prefix = _prefix;
}
} // namespace component
} // namespace omnitrace
TIMEMORY_INITIALIZE_STORAGE(omnitrace::component::user_region)
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
@@ -150,6 +150,12 @@ configure_settings()
"Enable support for Kokkos Tools", false, "kokkos",
"backend");
#if defined(TIMEMORY_USE_OMPT)
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_OMPT",
"Enable support for OpenMP-Tools", true, "openmp", "ompt",
"backend");
#endif
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_INSTRUMENTATION_INTERVAL",
"Instrumentation only takes measurements once every N "
"function calls (not statistical)",
@@ -736,6 +742,17 @@ get_use_kokkosp()
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
}
bool
get_use_ompt()
{
#if defined(TIMEMORY_USE_OMPT)
static auto _v = get_config()->find("OMNITRACE_USE_OMPT");
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
#else
return false;
#endif
}
bool
get_critical_trace_debug()
{
@@ -956,6 +973,20 @@ get_state()
return _v;
}
State
set_state(State _n)
{
auto _o = get_state();
OMNITRACE_CONDITIONAL_PRINT_F(get_debug_init(), "Setting state :: %s -> %s\n",
std::to_string(_o).c_str(), std::to_string(_n).c_str());
// state should always be increased, not decreased
OMNITRACE_CI_BASIC_THROW(_n < _o,
"State is being assigned to a lesser value :: %s -> %s",
std::to_string(_o).c_str(), std::to_string(_n).c_str());
get_state() = _n;
return _o;
}
std::atomic<uint64_t>&
get_cpu_cid()
{
@@ -22,10 +22,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// used by Kokkos decls
#if !defined(TIMEMORY_LIBRARY_SOURCE)
# define TIMEMORY_LIBRARY_SOURCE 1
#endif
#include "library/defines.hpp"
#define TIMEMORY_KOKKOSP_POSTFIX OMNITRACE_PUBLIC_API
#include "library/components/omnitrace.hpp"
#include "library/config.hpp"
+114
Voir le fichier
@@ -0,0 +1,114 @@
// MIT License
//
// Copyright (c) 2020, The Regents of the University of California,
// through Lawrence Berkeley National Laboratory (subject to receipt of any
// required approvals from the U.S. Dept. of Energy). All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "library/defines.hpp"
#include <timemory/defines.h>
#if defined(TIMEMORY_USE_OMPT)
# include "library/components/fwd.hpp"
# include "library/components/user_region.hpp"
# include "library/config.hpp"
# include "library/debug.hpp"
# include <timemory/components/ompt.hpp>
# include <timemory/components/ompt/extern.hpp>
# include <timemory/timemory.hpp>
# include <memory>
using api_t = TIMEMORY_API;
using ompt_handle_t = tim::component::ompt_handle<api_t>;
using ompt_context_t = tim::openmp::context_handler<api_t>;
using ompt_toolset_t = typename ompt_handle_t::toolset_type;
using ompt_bundle_t = tim::component_tuple<ompt_handle_t>;
extern "C"
{
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
const char*) OMNITRACE_PUBLIC_API;
}
namespace omnitrace
{
namespace ompt
{
namespace
{
std::unique_ptr<ompt_bundle_t> f_bundle = {};
bool _init_toolset_off = (trait::runtime_enabled<ompt_toolset_t>::set(false), true);
} // namespace
void
setup()
{
OMNITRACE_VERBOSE(1, "Setting up OMPT...\n");
trait::runtime_enabled<ompt_toolset_t>::set(config::get_use_ompt());
comp::user_ompt_bundle::global_init();
comp::user_ompt_bundle::reset();
// provide environment variable for enabling/disabling
if(config::get_use_ompt())
{
tim::auto_lock_t lk{ tim::type_mutex<ompt_handle_t>() };
comp::user_ompt_bundle::configure<omnitrace::component::user_region>();
f_bundle =
std::make_unique<ompt_bundle_t>("ompt", quirk::config<quirk::auto_start>{});
}
}
void
shutdown()
{
OMNITRACE_VERBOSE(1, "Shutting down OMPT...\n");
if(f_bundle)
{
f_bundle->stop();
ompt_context_t::cleanup();
trait::runtime_enabled<ompt_toolset_t>::set(false);
}
f_bundle.reset();
}
} // namespace ompt
} // namespace omnitrace
// include the ompt_start_tool definition
# include <timemory/components/ompt/start_tool.hpp>
#else
namespace omnitrace
{
namespace ompt
{
void
setup()
{}
void
shutdown()
{}
} // namespace ompt
} // namespace omnitrace
#endif

Certains fichiers ne sont pas affichés car ce diff contient trop de modifications Voir plus