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
This commit is contained in:
Jonathan R. Madsen
2022-03-07 20:40:48 -06:00
committed by GitHub
parent 2acaa7aa9f
commit d80752bc69
106 changed files with 9180 additions and 1947 deletions
+9 -181
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
@@ -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
View File
@@ -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)
@@ -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
View File
@@ -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
View File
@@ -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")
@@ -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
@@ -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"), \
@@ -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())
{
@@ -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;
}
@@ -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
View File
@@ -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