omnitrace-dl-library (#25)

* timemory submodule update

* Visibility, setting categories, and task-group protection

- OMNITRACE_VISIBILITY instead of TIMEMORY_VISIBILITY
- increased task group data-race protection
- add omnitrace categories to settings

* set component_apis type-trait

* omnitrace-dl-library implementation

- this library dlopen + dlsym's libomnitrace
- significantly reduces the instrumentation time

* omnitrace-avail categories

- suppress AVAILABLE column when --available

* omnitrace-exe update

- uses omnitrace-dl
- adds --print-excluded option
- removes --jump option
- comments out --stubs option
- removes --stdlib option
- support for C++ STL functions not in libstdc++
- tweak the --print-* outputs
- significantly refactors instrument_module and instrument_entity
- removes unused c_stdlib_module_constraint
- removes unused c_stdlib_function_constraint
- decreases get_whole_function_names() coverage

* library.cpp updates

- OMNITRACE_DEBUG -> OMNITRACE_DEBUG_F
- omnitrace_finalize sets state earlier
- omnitrace_finalize clears push/pop functors
- increased tasking shutdown safety

* - fix critical-trace thread hierarchy
- signal handler calls omnitrace_finalize
- get_cpu_cid_stack supports parent tid
- interval data reserves
- omnitrace-avail serialization support for module_functions
- omnitrace --simulate option
- omnitrace --print-format option
- omnitrace --load-instr option
- omnitrace runtime-inst doesn't oneTimeCode
- updated regex
- expand get_whole_function_names()
- Test Install CI update

* fixes to last commit

- expand get_whole_function_names()
- ignore sig c modules
- kill process in signal handler

* Remove RTLD_DEEPBIND + more

- removed use of RTLD_DEEPBIND
  - causes dyninst segfaults
- fixed signal handling
- updated timemory submodule

* Build/link static timemory libraries

* omnitrace --{module,function}-restrict option

- Added restrict regex options
- Reworked handling of regex options
- Reworked reporting of module/function skipping
- Handle -o w/o file specified

* timemory-avail

- category views
- backtrace::sample checks state

* get_debug_sampling()

[ROCm/rocprofiler-systems commit: 145a6ae06f]
This commit is contained in:
Jonathan R. Madsen
2022-02-23 06:59:32 -06:00
committed by GitHub
orang tua b99b153030
melakukan 8b058902a2
23 mengubah file dengan 2107 tambahan dan 793 penghapusan
@@ -30,7 +30,7 @@ target_link_libraries(
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
$<BUILD_INTERFACE:timemory::timemory-headers>
$<BUILD_INTERFACE:timemory::timemory-gotcha>
$<BUILD_INTERFACE:timemory::timemory-cxx-shared>
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
# ------------------------------------------------------------------------------#
@@ -137,3 +137,31 @@ install(
TARGETS omnitrace-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
# ------------------------------------------------------------------------------#
#
# omnitrace dl library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-dl-library SHARED)
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
target_compile_definitions(omnitrace-dl-library PRIVATE TIMEMORY_USE_VISIBILITY=0)
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/dl.cpp)
target_link_libraries(omnitrace-dl-library
PRIVATE $<BUILD_INTERFACE:timemory::timemory-headers>)
set_target_properties(
omnitrace-dl-library
PROPERTIES OUTPUT_NAME omnitrace-dl
CXX_VISIBILITY_PRESET "hidden"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-dl-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
@@ -30,27 +30,27 @@
extern "C"
{
/// handles configuration logic
void omnitrace_init_library(void) TIMEMORY_VISIBILITY("default");
void omnitrace_init_library(void) OMNITRACE_VISIBILITY("default");
/// starts gotcha wrappers
void omnitrace_init(const char*, bool, const char*) TIMEMORY_VISIBILITY("default");
void omnitrace_init(const char*, bool, const char*) OMNITRACE_VISIBILITY("default");
/// shuts down all tooling and generates output
void omnitrace_finalize(void) TIMEMORY_VISIBILITY("default");
void omnitrace_finalize(void) OMNITRACE_VISIBILITY("default");
/// sets an environment variable
void omnitrace_set_env(const char* env_name, const char* env_val)
TIMEMORY_VISIBILITY("default");
OMNITRACE_VISIBILITY("default");
/// sets whether MPI should be used
void omnitrace_set_mpi(bool use, bool attached) TIMEMORY_VISIBILITY("default");
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_VISIBILITY("default");
/// starts an instrumentation region
void omnitrace_push_trace(const char* name) TIMEMORY_VISIBILITY("default");
void omnitrace_push_trace(const char* name) OMNITRACE_VISIBILITY("default");
/// stops an instrumentation region
void omnitrace_pop_trace(const char* name) TIMEMORY_VISIBILITY("default");
void omnitrace_pop_trace(const char* name) OMNITRACE_VISIBILITY("default");
/// used by omnitrace-critical-trace
bool omnitrace_init_tooling() TIMEMORY_VISIBILITY("hidden");
bool omnitrace_init_tooling() OMNITRACE_VISIBILITY("hidden");
}
@@ -24,12 +24,16 @@
#include "library/defines.hpp"
#include <timemory/api.hpp>
#include <timemory/api/macros.hpp>
#include <timemory/components/data_tracker/types.hpp>
#include <timemory/components/macros.hpp>
#include <timemory/components/user_bundle/types.hpp>
#include <timemory/enum.h>
#include <timemory/mpl/concepts.hpp>
TIMEMORY_DEFINE_NS_API(project, omnitrace)
TIMEMORY_DECLARE_COMPONENT(roctracer)
namespace omnitrace
@@ -92,6 +96,34 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_
false_type)
#endif
TIMEMORY_SET_COMPONENT_API(omnitrace::component::omnitrace, project::omnitrace,
category::dynamic_instrumentation, os::supports_linux)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::roctracer, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux,
category::external)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_wall_clock, project::omnitrace,
category::timing, os::supports_unix, category::sampling,
category::interrupt_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_cpu_clock, project::omnitrace,
category::timing, os::supports_unix, category::sampling,
category::interrupt_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_percent, project::omnitrace,
category::timing, os::supports_unix, category::sampling,
category::interrupt_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_busy, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux,
category::sampling, category::thread_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_memory, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux, category::memory,
category::sampling, category::thread_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_power, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux, category::power,
category::sampling, category::thread_sampling)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_temp, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux,
category::temperature, category::sampling,
category::thread_sampling)
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::omnitrace, OMNITRACE_COMPONENT,
"omnitrace", "omnitrace_component")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
@@ -37,13 +37,14 @@ struct pthread_gotcha : tim::component::base<pthread_gotcha, void>
using routine_t = void* (*) (void*);
using promise_t = std::promise<void>;
wrapper(routine_t _routine, void* _arg, bool, promise_t*);
wrapper(routine_t _routine, void* _arg, bool, int64_t, promise_t*);
void* operator()() const;
static void* wrap(void* _arg);
private:
bool m_enable_sampling = false;
int64_t m_parent_tid = 0;
routine_t m_routine = nullptr;
void* m_arg = nullptr;
promise_t* m_promise = nullptr;
@@ -31,9 +31,9 @@
#include "library/defines.hpp"
#include "library/state.hpp"
#include "library/timemory.hpp"
#include "timemory/macros/language.hpp"
#include <timemory/backends/threading.hpp>
#include <timemory/macros/language.hpp>
#include <string>
#include <string_view>
@@ -129,6 +129,9 @@ get_debug_finalize();
bool
get_debug();
bool
get_debug_sampling();
bool
get_debug_tid();
@@ -252,5 +255,5 @@ std::atomic<uint64_t>&
get_cpu_cid();
std::unique_ptr<std::vector<uint64_t>>&
get_cpu_cid_stack(int64_t _tid = threading::get_id());
get_cpu_cid_stack(int64_t _tid = threading::get_id(), int64_t _parent = 0);
} // namespace omnitrace
@@ -50,3 +50,8 @@
#define OMNITRACE_SAMPLING_GPU_TEMP OMNITRACE_SAMPLING_GPU_TEMP_idx
#define OMNITRACE_SAMPLING_GPU_BUSY OMNITRACE_SAMPLING_GPU_BUSY_idx
#define OMNITRACE_SAMPLING_GPU_MEMORY_USAGE OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx
#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")
@@ -0,0 +1,325 @@
// 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 <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/environment/types.hpp>
#include <timemory/macros/attributes.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/variadic/macros.hpp>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <dlfcn.h>
#include <gnu/libc-version.h>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <sys/stat.h>
#define OMNITRACE_VISIBLE __attribute__((visibility("default")))
#define OMNITRACE_HIDDEN __attribute__((visibility("internal")))
#define OMNITRACE_INLINE __attribute__((__always_inline__))
#define OMNITRACE_DLSYM(VARNAME, HANDLE, FUNCNAME) \
if(HANDLE) \
{ \
*(void**) (&VARNAME) = dlsym(HANDLE, FUNCNAME); \
if(VARNAME == nullptr && _omnitrace_dl_verbose >= 0) \
{ \
fprintf(stderr, "[omnitrace][dl][pid=%i]> %s :: %s\n", process::get_id(), \
FUNCNAME, dlerror()); \
} \
}
namespace process = tim::process;
//--------------------------------------------------------------------------------------//
//
// omnitrace symbols
//
//--------------------------------------------------------------------------------------//
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;
}
//--------------------------------------------------------------------------------------//
namespace
{
inline int
get_omnitrace_env();
// environment priority:
// - OMNITRACE_DL_DEBUG
// - OMNITRACE_DL_VERBOSE
// - OMNITRACE_DEBUG
// - OMNITRACE_VERBOSE
int _omnitrace_dl_verbose =
tim::get_env<bool>("OMNITRACE_DL_DEBUG", false, false)
? 100
: tim::get_env<int>("OMNITRACE_DL_VERBOSE", get_omnitrace_env(), false);
// 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
// instrumented. However, this only applies to the symbols in libomnitrace.so,
// which is NOT self-contained, i.e. symbols in timemory and the libs it links to
// (such as libpapi.so) are not protected by the deep-bind option. Additionally,
// it should be noted that DynInst does *NOT* add instrumentation by manipulating the
// dynamic linker (otherwise it would only be limited to shared libs) -- it manipulates
// the instructions in the binary so that a call to a function such as "main" actually
// calls "main_dyninst", which executes the instrumentation snippets around the actual
// "main" (this is the reason you need the dyninstAPI_RT library).
//
// UPDATE:
// Use of RTLD_DEEPBIND has been removed because it causes the dyninst
// ProcControlAPI to segfault within pthread_cond_wait on certain executables.
//
// Here are the docs on the dlopen options used:
//
// RTLD_LAZY
// Perform lazy binding. Only resolve symbols as the code that references them is
// executed. If the symbol is never referenced, then it is never resolved. (Lazy
// binding is only performed for function references; references to variables are
// always immediately bound when the library is loaded.)
//
// RTLD_LOCAL
// This is the converse of RTLD_GLOBAL, and the default if neither flag is specified.
// Symbols defined in this library are not made available to resolve references in
// subsequently loaded libraries.
//
// RTLD_DEEPBIND (since glibc 2.3.4)
// Place the lookup scope of the symbols in this library ahead of the global scope.
// This means that a self-contained library will use its own symbols in preference to
// global symbols with the same name contained in libraries that have already been
// loaded. This flag is not specified in POSIX.1-2001.
//
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4
auto _omnitrace_dl_dlopen_flags = RTLD_LAZY | RTLD_LOCAL;
const char* _omnitrace_dl_dlopen_descr = "RTLD_LAZY | RTLD_LOCAL";
#else
auto _omnitrace_dl_dlopen_flags = RTLD_LAZY | RTLD_LOCAL;
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
{
explicit OMNITRACE_INLINE indirect(std::string libpath)
: m_libpath{ find_path(std::move(libpath)) }
{
if(_omnitrace_dl_verbose > 0)
{
fprintf(stderr, "[omnitrace][dl][pid=%i] libomnitrace.so resolved to '%s'\n",
process::get_id(), m_libpath.c_str());
}
tim::set_env("HSA_TOOLS_LIB", m_libpath, 0);
open();
init();
}
OMNITRACE_INLINE ~indirect() { dlclose(m_libhandle); }
OMNITRACE_INLINE void open()
{
if(m_libhandle) return;
auto* libhandle = dlopen(m_libpath.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",
process::get_id(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr);
}
}
else
{
if(_omnitrace_dl_verbose >= 0)
{
perror("dlopen");
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: %s\n",
process::get_id(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr,
dlerror());
}
}
dlerror(); // Clear any existing error
}
OMNITRACE_INLINE void init()
{
if(!m_libhandle) open();
// 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");
}
static OMNITRACE_INLINE std::string find_path(std::string&& _path)
{
auto _paths = tim::delimit(
TIMEMORY_JOIN(":", tim::get_env<std::string>("OMNITRACE_PATH", ""),
tim::get_env<std::string>("LD_LIBRARY_PATH", ""),
tim::get_env<std::string>("LIBRARY_PATH", "")),
":");
auto file_exists = [](const std::string& name) {
struct stat buffer;
return (stat(name.c_str(), &buffer) == 0);
};
for(auto&& itr : _paths)
{
auto _f = TIMEMORY_JOIN('/', itr, _path);
if(file_exists(_f)) return _f;
}
return _path;
}
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;
private:
void* m_libhandle = nullptr;
std::string m_libpath = {};
};
inline std::unique_ptr<indirect>&
get_indirect() OMNITRACE_HIDDEN;
template <typename FuncT, typename... Args>
inline void
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN;
} // namespace
//--------------------------------------------------------------------------------------//
extern "C"
{
void omnitrace_init_library(void)
{
invoke(__FUNCTION__, 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);
}
void omnitrace_finalize(void)
{
invoke(__FUNCTION__, get_indirect()->omnitrace_finalize_f);
}
void omnitrace_push_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect()->omnitrace_push_trace_f, name);
}
void omnitrace_pop_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect()->omnitrace_pop_trace_f, name);
}
void omnitrace_set_env(const char* a, const char* b)
{
tim::set_env(a, b, 0);
invoke(__FUNCTION__, 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);
}
}
//--------------------------------------------------------------------------------------//
namespace
{
int
get_omnitrace_env()
{
auto&& _debug = tim::get_env<bool>("OMNITRACE_DEBUG", false, false);
return tim::get_env<int>("OMNITRACE_VERBOSE", (_debug) ? 100 : 0, false);
}
std::unique_ptr<indirect>&
get_indirect()
{
static std::unique_ptr<indirect> _v = std::make_unique<indirect>(
tim::get_env<std::string>("OMNITRACE_LIBRARY", "libomnitrace.so"));
return _v;
}
template <typename FuncT, typename... Args>
void
invoke(const char* _name, FuncT&& _func, Args... _args)
{
if(!get_indirect())
{
// allow -2 verbosity to avoid throwing exception
if(_omnitrace_dl_verbose >= -1)
throw std::runtime_error(
"[omnitrace][dl] nullptr to struct holding dlsym function");
return;
}
if(_func)
{
std::invoke(std::forward<FuncT>(_func), _args...);
}
else if(_omnitrace_dl_verbose >= 0)
{
fprintf(stderr, "[omnitrace][dl] %s\n",
TIMEMORY_JOIN("", "null function pointer to ", _name, ". Ignoring ",
_name, "(", _args..., ")")
.c_str());
}
}
} // namespace
@@ -28,11 +28,11 @@
#include "library/debug.hpp"
#include "library/defines.hpp"
#include "library/gpu.hpp"
#include "library/ptl.hpp"
#include "library/sampling.hpp"
#include "library/thread_data.hpp"
#include "library/thread_sampler.hpp"
#include "library/timemory.hpp"
#include "timemory/mpl/type_traits.hpp"
#include <mutex>
#include <string_view>
@@ -44,7 +44,11 @@ namespace
std::vector<bool>&
get_interval_data()
{
static thread_local auto _v = std::vector<bool>{};
static thread_local auto _v = []() {
auto _tmp = std::vector<bool>{};
_tmp.reserve(max_supported_threads);
return _tmp;
}();
return _v;
}
@@ -86,10 +90,9 @@ is_system_backend()
}
auto&
get_instrumentation_bundles()
get_instrumentation_bundles(int64_t _tid = threading::get_id())
{
static thread_local auto& _v =
instrumentation_bundles::instances().at(threading::get_id());
static thread_local auto& _v = instrumentation_bundles::instances().at(_tid);
return _v;
}
@@ -120,10 +123,41 @@ using Phase = critical_trace::Phase;
/// \brief the "start" function for an instrumentation region
///
//======================================================================================//
namespace
{
auto&
push_count()
{
static thread_local uint16_t _v = 0;
return _v;
}
auto&
pop_count()
{
static thread_local uint16_t _v = 0;
return _v;
}
struct reentry_guard
{
reentry_guard(uint16_t& _v)
: m_v{ _v }
{
++m_v;
}
~reentry_guard() { --m_v; }
uint16_t& m_v;
operator bool() const { return (m_v <= 1); }
};
} // namespace
extern "C" void
omnitrace_push_trace(const char* name)
{
reentry_guard _lk{ push_count() };
if(!_lk) return;
// return if not active
if(get_state() == State::Finalized) return;
@@ -135,12 +169,14 @@ omnitrace_push_trace(const char* name)
return;
}
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
OMNITRACE_DEBUG_F("%s\n", name);
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
static thread_local size_t _sample_idx = 0;
auto& _interval = get_interval_data();
auto _enabled = (_sample_idx++ % _sample_rate == 0);
get_interval_data().emplace_back(_enabled);
_interval.emplace_back(_enabled);
if(_enabled) get_functors().first(name);
if(get_use_critical_trace())
{
@@ -168,9 +204,17 @@ omnitrace_push_trace(const char* name)
extern "C" void
omnitrace_pop_trace(const char* name)
{
// the same thread should not be pushing AND popping
if(push_count() > 0) return;
reentry_guard _lk{ pop_count() };
// return if reentry
if(!_lk) return;
// only execute when active
if(get_state() == State::Active)
{
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
OMNITRACE_DEBUG_F("%s\n", name);
auto& _interval_data = get_interval_data();
if(!_interval_data.empty())
{
@@ -382,9 +426,8 @@ omnitrace_init_tooling()
!get_use_rocm_smi())
{
get_state() = State::Finalized;
OMNITRACE_DEBUG("[%s] Both perfetto and timemory are disabled. Setting the state "
"to finalized\n",
__FUNCTION__);
OMNITRACE_DEBUG_F("Both perfetto and timemory are disabled. Setting the state "
"to finalized\n");
return false;
}
@@ -487,6 +530,7 @@ omnitrace_init_tooling()
};
static auto _pop_timemory = [](const char* name) {
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
auto& _data = get_instrumentation_bundles();
if(_data.bundles.empty())
{
@@ -494,10 +538,17 @@ omnitrace_init_tooling()
"omnitrace_pop_trace", name);
return;
}
_data.bundles.back()->stop();
_data.allocator.destroy(_data.bundles.back());
_data.allocator.deallocate(_data.bundles.back(), 1);
_data.bundles.pop_back();
for(size_t i = _data.bundles.size(); i > 0; --i)
{
auto*& _v = _data.bundles.at(i - 1);
if(_v->get_hash() == _hash)
{
_v->stop();
_data.allocator.destroy(_v);
_data.allocator.deallocate(_v, 1);
_data.bundles.erase(_data.bundles.begin() + (i - 1));
}
}
};
static auto _pop_perfetto = [](const char*) {
@@ -597,11 +648,32 @@ omnitrace_finalize(void)
// return if not active
if(get_state() != State::Active)
{
OMNITRACE_DEBUG_F("State = %s. Finalization skipped\n",
std::to_string(get_state()).c_str());
OMNITRACE_BASIC_DEBUG_F("State = %s. Finalization skipped\n",
std::to_string(get_state()).c_str());
return;
}
get_state() = State::Finalized;
get_functors().first = [](const char*) {};
get_functors().second = [](const char*) {};
if(get_use_timemory())
{
auto& _data = get_instrumentation_bundles();
if(!_data.bundles.empty())
{
for(size_t i = _data.bundles.size(); i > 0; --i)
{
auto*& _v = _data.bundles.at(i - 1);
_v->stop();
_data.allocator.destroy(_v);
_data.allocator.deallocate(_v, 1);
}
_data.bundles.clear();
}
}
pthread_gotcha::enable_sampling_on_child_threads() = false;
auto _debug_init = get_debug_finalize();
@@ -611,24 +683,22 @@ omnitrace_finalize(void)
if(_debug_init) config::set_setting_value("OMNITRACE_DEBUG", _debug_value);
} };
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
OMNITRACE_DEBUG_F("\n");
auto& _thread_bundle = thread_data<omnitrace_thread_bundle_t>::instance();
if(_thread_bundle) _thread_bundle->stop();
if(dmp::rank() == 0 && get_verbose() >= 0) fprintf(stderr, "\n");
if(get_verbose_env() > 0) config::print_settings();
get_state() = State::Finalized;
if(get_verbose() > 0 || get_debug()) config::print_settings();
if(get_use_sampling())
{
OMNITRACE_DEBUG("[%s] Shutting down sampling...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Shutting down sampling...\n");
sampling::shutdown();
sampling::block_signals();
}
OMNITRACE_DEBUG("[%s] Stopping gotcha bundle...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Stopping gotcha bundle...\n");
// stop the gotcha bundle
if(get_gotcha_bundle())
{
@@ -639,13 +709,13 @@ omnitrace_finalize(void)
pthread_gotcha::shutdown();
thread_sampler::shutdown();
OMNITRACE_DEBUG("[%s] Shutting down roctracer...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Shutting down roctracer...\n");
// ensure that threads running roctracer callbacks shutdown
comp::roctracer::shutdown();
if(dmp::rank() == 0) fprintf(stderr, "\n");
OMNITRACE_DEBUG("[%s] Stopping main bundle...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Stopping main bundle...\n");
// stop the main bundle and report the high-level metrics
if(get_main_bundle())
{
@@ -659,18 +729,18 @@ omnitrace_finalize(void)
int _threadpool_verbose = (get_debug()) ? 4 : -1;
tasking::get_roctracer_thread_pool().set_verbose(_threadpool_verbose);
tasking::get_critical_trace_thread_pool().set_verbose(_threadpool_verbose);
if(get_use_critical_trace())
tasking::get_critical_trace_thread_pool().set_verbose(_threadpool_verbose);
// join extra thread(s) used by roctracer
OMNITRACE_DEBUG("[%s] waiting for all roctracer tasks to complete...\n",
__FUNCTION__);
OMNITRACE_DEBUG_F("waiting for all roctracer tasks to complete...\n");
tasking::get_roctracer_task_group().join();
// print out thread-data if they are not still running
// if they are still running (e.g. thread-pool still alive), the
// thread-specific data will be wrong if try to stop them from
// the main thread.
OMNITRACE_DEBUG("[%s] Destroying thread bundle data...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Destroying thread bundle data...\n");
for(auto& itr : thread_data<omnitrace_thread_bundle_t>::instances())
{
if(itr && itr->get<comp::wall_clock>() &&
@@ -684,8 +754,7 @@ omnitrace_finalize(void)
}
// ensure that all the MT instances are flushed
OMNITRACE_DEBUG("[%s] Stopping and destroying instrumentation bundles...\n",
__FUNCTION__);
OMNITRACE_DEBUG_F("Stopping and destroying instrumentation bundles...\n");
for(auto& itr : instrumentation_bundles::instances())
{
while(!itr.bundles.empty())
@@ -701,8 +770,7 @@ omnitrace_finalize(void)
// ensure that all the MT instances are flushed
if(get_use_sampling())
{
OMNITRACE_DEBUG("[%s] Post-processing the sampling backtraces...\n",
__FUNCTION__);
OMNITRACE_DEBUG_F("Post-processing the sampling backtraces...\n");
for(size_t i = 0; i < max_supported_threads; ++i)
{
sampling::backtrace::post_process(i);
@@ -712,7 +780,7 @@ omnitrace_finalize(void)
if(get_use_critical_trace() || (get_use_rocm_smi() && get_use_roctracer()))
{
OMNITRACE_DEBUG("[%s] Generating the critical trace...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Generating the critical trace...\n");
// increase the thread-pool size
tasking::get_critical_trace_thread_pool().initialize_threadpool(
get_critical_trace_num_threads());
@@ -739,18 +807,12 @@ omnitrace_finalize(void)
if(get_use_critical_trace())
{
OMNITRACE_DEBUG("[%s] Generating the critical trace...\n", __FUNCTION__);
// increase the thread-pool size
tasking::get_critical_trace_thread_pool().initialize_threadpool(
get_critical_trace_num_threads());
// make sure outstanding hash tasks completed before compute
OMNITRACE_PRINT("[%s] waiting for all critical trace tasks to complete...\n",
__FUNCTION__);
OMNITRACE_PRINT_F("waiting for all critical trace tasks to complete...\n");
tasking::get_critical_trace_task_group().join();
// launch compute task
OMNITRACE_PRINT("[%s] launching critical trace compute task...\n", __FUNCTION__);
OMNITRACE_PRINT_F("launching critical trace compute task...\n");
critical_trace::compute();
}
@@ -767,11 +829,10 @@ omnitrace_finalize(void)
perfetto::TrackEvent::Flush();
auto& tracing_session = get_trace_session();
OMNITRACE_DEBUG("[%s] Stopping the blocking perfetto trace sessions...\n",
__FUNCTION__);
OMNITRACE_DEBUG_F("Stopping the blocking perfetto trace sessions...\n");
tracing_session->StopBlocking();
OMNITRACE_DEBUG("[%s] Getting the trace data...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Getting the trace data...\n");
std::vector<char> trace_data{ tracing_session->ReadTraceBlocking() };
if(trace_data.empty())
@@ -808,18 +869,31 @@ omnitrace_finalize(void)
// these should be destroyed before timemory is finalized, especially the
// roctracer thread-pool
OMNITRACE_DEBUG("[%s] Destroying the thread pools...\n", __FUNCTION__);
tasking::get_roctracer_thread_pool().destroy_threadpool();
tasking::get_critical_trace_thread_pool().destroy_threadpool();
OMNITRACE_DEBUG_F("Destroying the roctracer thread pool...\n");
{
std::unique_lock<std::mutex> _lk{ tasking::get_roctracer_mutex() };
tasking::get_roctracer_task_group().join();
tasking::get_roctracer_task_group().clear();
tasking::get_roctracer_task_group().set_pool(nullptr);
tasking::get_roctracer_thread_pool().destroy_threadpool();
}
if(get_use_sampling())
static_cast<tim::tsettings<bool>*>(
tim::settings::instance()->find("OMNITRACE_DEBUG")->second.get())
->set(false);
OMNITRACE_DEBUG_F("Destroying the critical trace thread pool...\n");
{
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex() };
tasking::get_critical_trace_task_group().join();
tasking::get_critical_trace_task_group().clear();
tasking::get_critical_trace_task_group().set_pool(nullptr);
tasking::get_critical_trace_thread_pool().destroy_threadpool();
}
OMNITRACE_DEBUG("[%s] Finalizing timemory...\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Finalizing timemory...\n");
tim::timemory_finalize();
OMNITRACE_DEBUG("[%s] Finalizing timemory... Done\n", __FUNCTION__);
OMNITRACE_DEBUG_F("Disabling signal handling...\n");
tim::disable_signal_detection();
OMNITRACE_DEBUG_F("Finalized\n");
if(_perfetto_output_error)
{
@@ -231,8 +231,16 @@ backtrace::get_thread_cpu_timestamp() const
void
backtrace::sample(int signum)
{
static bool _debug = tim::get_env<bool>("OMNITRACE_DEBUG_SAMPLING", get_debug());
if(_debug)
if(get_state() != State::Active)
{
OMNITRACE_CONDITIONAL_PRINT(
get_debug_sampling(),
"request to sample (signal %i) ignored because omnitrace is not active\n",
signum);
return;
}
if(get_debug_sampling())
{
static auto _timestamp_str = [](const auto& _tp) {
char _repr[64];
@@ -269,7 +277,7 @@ backtrace::sample(int signum)
if(strlen(*itr) == 0) break;
}
std::reverse(m_data.begin(), itr);
if(!get_debug())
if(!get_debug_sampling())
{
bool _ignore = false;
for(auto& itr : m_data)
@@ -317,6 +325,7 @@ backtrace::configure(bool _setup, int64_t _tid)
if(_setup && !_sampler && !_is_running)
{
(void) get_debug_sampling(); // make sure query in sampler does not allocate
assert(_tid == threading::get_id());
sampling::block_signals(*_signal_types);
if constexpr(tim::trait::is_available<hw_counters>::value)
@@ -424,7 +433,7 @@ backtrace::post_process(int64_t _tid)
auto _use_label = [](const std::string& _lbl, bool _check_internal) -> short {
// debugging feature
static bool _keep_internal =
tim::get_env<bool>("OMNITRACE_SAMPLING_KEEP_INTERNAL", get_debug());
tim::get_env<bool>("OMNITRACE_SAMPLING_KEEP_INTERNAL", get_debug_sampling());
const auto _npos = std::string::npos;
if(_keep_internal) return 1;
if(_lbl.find("omnitrace_init_tooling") != _npos) return -1;
@@ -450,8 +459,8 @@ backtrace::post_process(int64_t _tid)
// "_dyninst", i.e. "main" will show up as "main_dyninst" in the backtrace.
auto _patch_label = [](std::string _lbl) -> std::string {
// debugging feature
static bool _keep_suffix =
tim::get_env<bool>("OMNITRACE_SAMPLING_KEEP_DYNINST_SUFFIX", get_debug());
static bool _keep_suffix = tim::get_env<bool>(
"OMNITRACE_SAMPLING_KEEP_DYNINST_SUFFIX", get_debug_sampling());
if(_keep_suffix) return _lbl;
const std::string _dyninst{ "_dyninst" };
auto _pos = _lbl.find(_dyninst);
@@ -570,7 +579,7 @@ backtrace::post_process(int64_t _tid)
if(_data.empty()) return;
OMNITRACE_CONDITIONAL_PRINT(
get_verbose() >= 0 || get_debug(),
get_verbose() >= 0 || get_debug_sampling(),
"Post-processing %zu sampling entries for thread %lu...\n", _data.size(), _tid);
std::sort(_data.begin(), _data.end(),
@@ -25,10 +25,10 @@
#include "library/components/omnitrace.hpp"
#include "library/config.hpp"
#include "library/debug.hpp"
#include "timemory/backends/process.hpp"
#include <thread>
#include <timemory/backends/mpi.hpp>
#include <timemory/backends/process.hpp>
namespace omnitrace
{
@@ -27,10 +27,11 @@
#include "library/debug.hpp"
#include "library/sampling.hpp"
#include <ostream>
#include <timemory/backends/threading.hpp>
#include <timemory/sampling/allocator.hpp>
#include <timemory/utility/types.hpp>
#include <ostream>
#include <pthread.h>
namespace omnitrace
@@ -85,8 +86,9 @@ stop_bundle(bundle_t& _bundle, int64_t _tid)
} // namespace
pthread_gotcha::wrapper::wrapper(routine_t _routine, void* _arg, bool _enable_sampling,
promise_t* _p)
int64_t _parent, promise_t* _p)
: m_enable_sampling{ _enable_sampling }
, m_parent_tid{ _parent }
, m_routine{ _routine }
, m_arg{ _arg }
, m_promise{ _p }
@@ -117,6 +119,8 @@ pthread_gotcha::wrapper::operator()() const
}
} };
if(_active) get_cpu_cid_stack(threading::get_id(), m_parent_tid);
if(m_enable_sampling && _enable_sampling && _active)
{
_tid = threading::get_id();
@@ -197,11 +201,16 @@ pthread_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr,
{
bundle_t _bundle{ "pthread_create" };
auto _enable_sampling = enable_sampling_on_child_threads();
auto _active = (get_state() == omnitrace::State::Active);
int64_t _tid = (_active) ? threading::get_id() : 0;
// ensure that cpu cid stack exists on the parent thread if active
if(_active) get_cpu_cid_stack();
if(!get_use_sampling() || !_enable_sampling)
{
// if(!get_use_sampling()) start_bundle(_bundle);
auto* _obj = new wrapper(start_routine, arg, _enable_sampling, nullptr);
auto* _obj = new wrapper(start_routine, arg, _enable_sampling, _tid, nullptr);
// create the thread
auto _ret =
pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_obj));
@@ -219,7 +228,7 @@ pthread_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr,
// promise set by thread when signal handler is configured
auto _promise = std::promise<void>{};
auto _fut = _promise.get_future();
auto* _wrap = new wrapper(start_routine, arg, _enable_sampling, &_promise);
auto* _wrap = new wrapper(start_routine, arg, _enable_sampling, _tid, &_promise);
// create the thread
auto _ret = pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_wrap));
@@ -215,8 +215,8 @@ TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(roctracer_data, true, double)
extern "C"
{
bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count,
const char* const* failed_tool_names) TIMEMORY_VISIBILITY("default");
void OnUnload() TIMEMORY_VISIBILITY("default");
const char* const* failed_tool_names) OMNITRACE_VISIBILITY("default");
void OnUnload() OMNITRACE_VISIBILITY("default");
bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count,
const char* const* failed_tool_names)
@@ -185,14 +185,15 @@ hsa_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
std::unique_lock<std::mutex> _lk{ tasking::get_roctracer_mutex() };
auto _begin_ns = begin_timestamp;
auto _end_ns = end_timestamp;
tasking::get_roctracer_task_group().exec(
[_name, _begin_ns, _end_ns]() {
roctracer_hsa_bundle_t _bundle{ _name, _scope };
_bundle.start()
.store(std::plus<double>{},
static_cast<double>(_end_ns - _begin_ns))
.stop();
});
if(tasking::get_roctracer_task_group().pool())
tasking::get_roctracer_task_group().exec(
[_name, _begin_ns, _end_ns]() {
roctracer_hsa_bundle_t _bundle{ _name, _scope };
_bundle.start()
.store(std::plus<double>{},
static_cast<double>(_end_ns - _begin_ns))
.stop();
});
}
// timemory is disabled in this callback because collecting data in this
// thread causes strange segmentation faults
@@ -251,7 +252,8 @@ hsa_activity_callback(uint32_t op, activity_record_t* record, void* arg)
};
std::unique_lock<std::mutex> _lk{ tasking::get_roctracer_mutex() };
tasking::get_roctracer_task_group().exec(_func);
if(tasking::get_roctracer_task_group().pool())
tasking::get_roctracer_task_group().exec(_func);
// timemory is disabled in this callback because collecting data in this thread
// causes strange segmentation faults
@@ -21,6 +21,7 @@
// SOFTWARE.
#include "library/config.hpp"
#include "library/api.hpp"
#include "library/debug.hpp"
#include "library/defines.hpp"
#include "library/thread_data.hpp"
@@ -29,16 +30,21 @@
#include <timemory/backends/mpi.hpp>
#include <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/sampling/allocator.hpp>
#include <timemory/settings.hpp>
#include <timemory/settings/types.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/declaration.hpp>
#include <timemory/utility/signals.hpp>
#include <array>
#include <csignal>
#include <cstdint>
#include <cstdlib>
#include <numeric>
#include <ostream>
#include <string>
#include <unistd.h>
namespace omnitrace
{
@@ -69,7 +75,8 @@ get_setting_name(std::string _v)
{ \
auto _ret = _config->insert<TYPE, TYPE>( \
ENV_NAME, get_setting_name(ENV_NAME), DESCRIPTION, INITIAL_VALUE, \
std::set<std::string>{ "custom", "omnitrace", __VA_ARGS__ }); \
std::set<std::string>{ "custom", "omnitrace", "omnitrace-library", \
__VA_ARGS__ }); \
if(!_ret.second) \
OMNITRACE_PRINT("Warning! Duplicate setting: %s / %s\n", \
get_setting_name(ENV_NAME).c_str(), ENV_NAME); \
@@ -261,6 +268,24 @@ configure_settings()
_config->get_memory_units() = "MB";
_config->get_papi_events() = "PAPI_TOT_CYC, PAPI_TOT_INS";
// settings native to timemory but critically and/or extensively used by omnitrace
auto _add_omnitrace_category = [](auto itr) {
if(itr != _config->end())
{
auto _categories = itr->second->get_categories();
_categories.emplace("omnitrace");
_categories.emplace("omnitrace-library");
itr->second->set_categories(_categories);
}
};
_add_omnitrace_category(_config->find("OMNITRACE_CONFIG_FILE"));
_add_omnitrace_category(_config->find("OMNITRACE_DEBUG"));
_add_omnitrace_category(_config->find("OMNITRACE_VERBOSE"));
_add_omnitrace_category(_config->find("OMNITRACE_TIME_OUTPUT"));
_add_omnitrace_category(_config->find("OMNITRACE_OUTPUT_PREFIX"));
_add_omnitrace_category(_config->find("OMNITRACE_OUTPUT_PATH"));
#if defined(TIMEMORY_USE_PAPI)
int _paranoid = 2;
{
@@ -287,6 +312,10 @@ configure_settings()
tim::trait::runtime_enabled<comp::cpu_roofline_sp_flops>::set(false);
_config->get_papi_events() = "";
}
else
{
_add_omnitrace_category(_config->find("OMNITRACE_PAPI_EVENTS"));
}
#else
_config->get_papi_quiet() = true;
#endif
@@ -330,6 +359,30 @@ configure_settings()
if(tim::mpi::is_initialized()) settings::default_process_suffix() = tim::mpi::rank();
#endif
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_verbose_env() > 0, "configuration complete\n");
if(_config->get_enable_signal_handler())
{
using signal_settings = tim::signal_settings;
using sys_signal = tim::sys_signal;
tim::disable_signal_detection();
auto _exit_action = [](int nsig) {
tim::sampling::block_signals({ SIGPROF, SIGALRM },
tim::sampling::sigmask_scope::process);
OMNITRACE_BASIC_PRINT(
"Finalizing afer signal %i :: %s\n", nsig,
signal_settings::str(static_cast<sys_signal>(nsig)).c_str());
if(get_state() == State::Active) omnitrace_finalize();
kill(process::get_id(), nsig);
};
signal_settings::set_exit_action(_exit_action);
tim::set_env("SIGNAL_ENABLE_INTERRUPT", "1", 0);
signal_settings::check_environment();
auto default_signals = signal_settings::get_default();
for(const auto& itr : default_signals)
signal_settings::enable(itr);
auto enabled_signals = signal_settings::get_enabled();
tim::enable_signal_detection(enabled_signals);
}
}
void
@@ -575,6 +628,13 @@ get_debug()
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
}
bool
get_debug_sampling()
{
static bool _v = tim::get_env<bool>("OMNITRACE_DEBUG_SAMPLING", get_debug_env());
return (_v || get_debug());
}
int
get_verbose_env()
{
@@ -896,19 +956,24 @@ get_cpu_cid()
}
std::unique_ptr<std::vector<uint64_t>>&
get_cpu_cid_stack(int64_t _tid)
get_cpu_cid_stack(int64_t _tid, int64_t _parent)
{
struct omnitrace_cpu_cid_stack
{};
using thread_data_t = thread_data<std::vector<uint64_t>, omnitrace_cpu_cid_stack>;
static auto& _v = thread_data_t::instances();
static thread_local auto _v_check = [_tid]() {
thread_data_t::construct((_tid > 0) ? *thread_data_t::instances().at(0)
: std::vector<uint64_t>{});
static auto& _v = thread_data_t::instances();
static thread_local auto _v_copy = [_tid, _parent]() {
auto _parent_tid = _parent;
// if tid != parent and there is not a valid pointer for the provided parent
// thread id set it to zero since that will always be valid
if(_tid != _parent_tid && !_v.at(_parent_tid)) _parent_tid = 0;
// copy over the thread ids from the parent if tid != parent
thread_data_t::construct((_tid != _parent_tid) ? *(_v.at(_parent_tid))
: std::vector<uint64_t>{});
return true;
}();
return _v.at(_tid);
(void) _v_check;
(void) _v_copy;
}
namespace
@@ -508,10 +508,9 @@ get(int64_t _tid)
void
add_hash_id(const hash_ids& _labels)
{
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex(),
std::defer_lock };
if(!_lk.owns_lock()) _lk.lock();
tasking::get_critical_trace_task_group().run([_labels]() {
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex() };
if(!tasking::get_critical_trace_task_group().pool()) return;
tasking::get_critical_trace_task_group().exec([_labels]() {
static std::mutex _mtx{};
_mtx.lock();
for(auto itr : _labels)
@@ -539,9 +538,8 @@ void
update(int64_t _tid)
{
if(!get_use_critical_trace() && !get_use_rocm_smi()) return;
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex(),
std::defer_lock };
if(!_lk.owns_lock()) _lk.lock();
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex() };
if(!tasking::get_critical_trace_task_group().pool()) return;
call_chain _data{};
std::swap(_data, *critical_trace::get(_tid));
tasking::get_critical_trace_task_group().exec(update_critical_path, _data, _tid);
@@ -551,6 +549,8 @@ void
compute(int64_t _tid)
{
update(_tid);
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex() };
if(!tasking::get_critical_trace_task_group().pool()) return;
tasking::get_critical_trace_task_group().exec(compute_critical_trace);
}
@@ -824,8 +824,10 @@ get_entries(int64_t _ts, const std::function<bool(const entry&)>& _eval)
}
*_targ = _v;
};
std::unique_lock<std::mutex> _lk{ tasking::get_critical_trace_mutex() };
size_t _n = 0;
std::vector<std::pair<std::string, entry>> _v{};
if(!tasking::get_critical_trace_task_group().pool()) return _v;
tasking::get_critical_trace_task_group().exec(_func, &_v, &_n);
tasking::get_critical_trace_task_group().join();
OMNITRACE_DEBUG("critical_trace::%s :: found %zu out of %zu entries at %li...\n",
@@ -28,7 +28,7 @@
# if !defined(TIMEMORY_USE_HIP)
# define TIMEMORY_USE_HIP 1
# endif
# include "timemory/components/hip/backends.hpp"
# include <timemory/components/hip/backends.hpp>
#endif
namespace omnitrace