diff --git a/cmake/BuildSettings.cmake b/cmake/BuildSettings.cmake index e386d2bb41..e7d1a06aa1 100644 --- a/cmake/BuildSettings.cmake +++ b/cmake/BuildSettings.cmake @@ -83,7 +83,7 @@ add_flag_if_avail( "-Wno-attributes" "-Wno-missing-field-initializers") if(OMNITRACE_BUILD_DEBUG) - add_flag_if_avail("-g3" "-gdwarf-3" "-fno-omit-frame-pointer") + add_flag_if_avail("-g3" "-fno-omit-frame-pointer") endif() if(WIN32) @@ -103,7 +103,7 @@ omnitrace_add_interface_library( "Attempts to set best flags for more expressive profiling information in debug or optimized binaries" ) -add_target_flag_if_avail(omnitrace-compile-debuginfo "-g" "-fno-omit-frame-pointer" +add_target_flag_if_avail(omnitrace-compile-debuginfo "-g3" "-fno-omit-frame-pointer" "-fno-optimize-sibling-calls") if(CMAKE_CUDA_COMPILER_IS_NVIDIA) diff --git a/cmake/Packages.cmake b/cmake/Packages.cmake index b6c6d7a7b3..9d7276640e 100644 --- a/cmake/Packages.cmake +++ b/cmake/Packages.cmake @@ -526,8 +526,7 @@ if(OMNITRACE_BUILD_STACK_PROTECTOR) endif() if(OMNITRACE_BUILD_DEBUG) - add_target_flag_if_avail(omnitrace-timemory-config "-fno-omit-frame-pointer" "-g" - "-gdwarf-3") + add_target_flag_if_avail(omnitrace-timemory-config "-fno-omit-frame-pointer" "-g3") endif() set(TIMEMORY_EXTERNAL_INTERFACE_LIBRARY diff --git a/cmake/Perfetto.cmake b/cmake/Perfetto.cmake index 65ff5b57f7..d81c14ac2a 100644 --- a/cmake/Perfetto.cmake +++ b/cmake/Perfetto.cmake @@ -178,7 +178,7 @@ target_sources( target_link_libraries( omnitrace-perfetto-library PRIVATE omnitrace::omnitrace-threading omnitrace::omnitrace-static-libgcc - omnitrace::omnitrace-static-libstdcxx) + omnitrace::omnitrace-static-libstdcxx omnitrace::omnitrace-compile-options) set_target_properties( omnitrace-perfetto-library PROPERTIES OUTPUT_NAME perfetto diff --git a/cmake/Templates/modulefile.in b/cmake/Templates/modulefile.in index 8bed058ec1..5f138333d3 100644 --- a/cmake/Templates/modulefile.in +++ b/cmake/Templates/modulefile.in @@ -15,7 +15,6 @@ prepend-path LD_LIBRARY_PATH "${ROOT}/@CMAKE_INSTALL_LIBDIR@" prepend-path PYTHONPATH "${ROOT}/@CMAKE_INSTALL_PYTHONDIR@" setenv @PROJECT_NAME@_DIR "${ROOT}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME@" -@OMNITRACE_HSA_ENV@setenv HSA_TOOLS_LIB "${ROOT}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" -@OMNITRACE_HSA_ENV@setenv HSA_TOOLS_REPORT_LOAD_FAILURE 1 -@OMNITRACE_ROCP_ENV@setenv ROCP_TOOL_LIB "${ROOT}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" -@OMNITRACE_ROCP_ENV@setenv ROCP_HSA_INTERCEPT 1 +# @OMNITRACE_HSA_ENV@setenv HSA_TOOLS_LIB "${ROOT}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" +# @OMNITRACE_HSA_ENV@setenv HSA_TOOLS_REPORT_LOAD_FAILURE 1 +# @OMNITRACE_ROCP_ENV@setenv ROCP_TOOL_LIB "${ROOT}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" diff --git a/cmake/Templates/setup-env.sh.in b/cmake/Templates/setup-env.sh.in index 6c7b96fca7..a234e0551a 100644 --- a/cmake/Templates/setup-env.sh.in +++ b/cmake/Templates/setup-env.sh.in @@ -23,12 +23,10 @@ export CMAKE_PREFIX_PATH export @PROJECT_NAME@_DIR # ROCm environment variables -@OMNITRACE_HSA_ENV@HSA_TOOLS_LIB="${BASEDIR}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" -@OMNITRACE_HSA_ENV@HSA_TOOLS_REPORT_LOAD_FAILURE=1 -@OMNITRACE_ROCP_ENV@ROCP_TOOL_LIB="${BASEDIR}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" -@OMNITRACE_ROCP_ENV@ROCP_HSA_INTERCEPT=1 +# @OMNITRACE_HSA_ENV@HSA_TOOLS_LIB="${BASEDIR}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace-dl@CMAKE_SHARED_LIBRARY_SUFFIX@" +# @OMNITRACE_HSA_ENV@HSA_TOOLS_REPORT_LOAD_FAILURE=1 +# @OMNITRACE_ROCP_ENV@ROCP_TOOL_LIB="${BASEDIR}/@CMAKE_INSTALL_LIBDIR@/@CMAKE_SHARED_LIBRARY_PREFIX@omnitrace@CMAKE_SHARED_LIBRARY_SUFFIX@" -@OMNITRACE_HSA_ENV@export HSA_TOOLS_LIB -@OMNITRACE_HSA_ENV@export HSA_TOOLS_REPORT_LOAD_FAILURE -@OMNITRACE_ROCP_ENV@export ROCP_TOOL_LIB -@OMNITRACE_ROCP_ENV@export ROCP_HSA_INTERCEPT +# @OMNITRACE_HSA_ENV@export HSA_TOOLS_LIB +# @OMNITRACE_HSA_ENV@export HSA_TOOLS_REPORT_LOAD_FAILURE +# @OMNITRACE_ROCP_ENV@export ROCP_TOOL_LIB diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 055d140f45..73676ebc80 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -18,7 +18,7 @@ set(CMAKE_CXX_CLANG_TIDY) set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME examples) if(OMNITRACE_BUILD_DEBUG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -gdwarf-3 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fno-omit-frame-pointer") endif() option(BUILD_SHARED_LIBS "Build dynamic libraries" ON) diff --git a/examples/mpi/mpi.cpp b/examples/mpi/mpi.cpp index 68e6d821fa..a51787da63 100644 --- a/examples/mpi/mpi.cpp +++ b/examples/mpi/mpi.cpp @@ -100,14 +100,16 @@ all2all(int _rank, MPI_Comm _comm) values_sent[i] = get_dist(_mt); if(_rank == 0) - printf("[%s][%s][%i] values sent (# = %zu) :: %s.\n", _name.c_str(), __FUNCTION__, - _rank, values_sent.size(), get_values_str(values_sent).c_str()); + printf("[%s][%s][%2i] values sent (# = %zu) :: %s.\n", _name.c_str(), + __FUNCTION__, _rank, values_sent.size(), + get_values_str(values_sent).c_str()); MPI_Alltoall(&values_sent[_rank], 1, _dtype, &values_recv[_rank], 1, _dtype, _comm); if(_rank == 0) - printf("[%s][%s][%i] values recv (# = %zu) :: %s.\n", _name.c_str(), __FUNCTION__, - _rank, values_sent.size(), get_values_str(values_recv).c_str()); + printf("[%s][%s][%2i] values recv (# = %zu) :: %s.\n", _name.c_str(), + __FUNCTION__, _rank, values_sent.size(), + get_values_str(values_recv).c_str()); } template @@ -126,9 +128,10 @@ send_recv(int _rank, MPI_Comm _comm) for(size_t i = 0; i < N; ++i) values_sent[i] = get_dist(_mt); - if(_rank == 0) - printf("[%s][%s][%i] values sent (# = %zu) :: %s.\n", _name.c_str(), __FUNCTION__, - _rank, values_sent.size(), get_values_str(values_sent).c_str()); + if(_rank == 0 || _rank == _size - 1) + printf("[%s][%s][%2i] values sent (# = %zu) :: %s.\n", _name.c_str(), + __FUNCTION__, _rank, values_sent.size(), + get_values_str(values_sent).c_str()); for(int i = 0; i < _size; ++i) { @@ -144,9 +147,10 @@ send_recv(int _rank, MPI_Comm _comm) } } - if(_rank == 0) - printf("[%s][%s][%i] values recv (# = %zu) :: %s.\n", _name.c_str(), __FUNCTION__, - _rank, values_sent.size(), get_values_str(values_recv).c_str()); + if(_rank == 0 || _rank == _size - 1) + printf("[%s][%s][%2i] values recv (# = %zu) :: %s.\n", _name.c_str(), + __FUNCTION__, _rank, values_sent.size(), + get_values_str(values_recv).c_str()); } void @@ -158,8 +162,8 @@ run(MPI_Comm _comm, int nitr) MPI_Comm_rank(_comm, &_rank); MPI_Comm_size(_comm, &_size); - printf("[%s][%i][%s] running %i iterations on %i ranks... \n", _name.c_str(), _rank, - __FUNCTION__, nitr, _size); + printf("[%s][%s][%2i] running %i iterations on %i ranks... \n", _name.c_str(), + __FUNCTION__, _rank, nitr, _size); MPI_Barrier(_comm); for(int i = 0; i < nitr; ++i) @@ -176,8 +180,8 @@ run(MPI_Comm _comm, int nitr) } MPI_Barrier(_comm); - printf("[%s][%i][%s] running %i iterations on %i ranks... Done\n", _name.c_str(), - _rank, __FUNCTION__, nitr, _size); + printf("[%s][%s][%2i] running %i iterations on %i ranks... Done\n", _name.c_str(), + __FUNCTION__, _rank, nitr, _size); } void @@ -223,7 +227,7 @@ run_main(int argc, char** argv) int size = 1; int nitr = 1; - if(argc > 1) nitr = atoi(argv[2]); + if(argc > 1) nitr = atoi(argv[1]); MPI_Comm_size(MPI_COMM_WORLD, &size); @@ -233,7 +237,7 @@ run_main(int argc, char** argv) printf("[%s] Number of iterations: %i\n", _name.c_str(), nitr); - printf("[%s][%i] running with MPI_COMM_WORLD...\n", _name.c_str(), getpid()); + printf("[%s][%2i] running with MPI_COMM_WORLD...\n", _name.c_str(), getpid()); run(MPI_COMM_WORLD, nitr); print_info(MPI_COMM_WORLD, true, "MPI_COMM_WORLD"); @@ -241,16 +245,16 @@ run_main(int argc, char** argv) if(size > 1) { MPI_Comm dup; - printf("[%s][%i] Duplicating MPI_COMM_WORLD...\n", _name.c_str(), getpid()); + printf("[%s][%2i] Duplicating MPI_COMM_WORLD...\n", _name.c_str(), getpid()); MPI_Comm_dup(MPI_COMM_WORLD, &dup); - printf("[%s][%i] running with duplicated comm of MPI_COMM_WORLD...\n", + printf("[%s][%2i] running with duplicated comm of MPI_COMM_WORLD...\n", _name.c_str(), getpid()); run(dup, nitr); MPI_Comm_rank(dup, &rank); if(rank == 0) printf("[%s]\n", _name.c_str()); - printf("[%s][%i] RANK = %i on duplicated MPI_COMM_WORLD...\n", _name.c_str(), + printf("[%s][%2i] RANK = %i on duplicated MPI_COMM_WORLD...\n", _name.c_str(), getpid(), rank); if(size > 3) @@ -259,8 +263,9 @@ run_main(int argc, char** argv) for(int i = 0; i < size; ++i) { auto _idx = i % 3; - printf("[%s][%i] Splitting duplicated MPI_COMM_WORLD %i (rank = %i)...\n", - _name.c_str(), getpid(), _idx, rank); + printf( + "[%s][%2i] Splitting duplicated MPI_COMM_WORLD %i (rank = %i)...\n", + _name.c_str(), getpid(), _idx, rank); MPI_Comm* comm = &comms.at(_idx); MPI_Comm_split(dup, _idx, rank, comm); } @@ -273,7 +278,7 @@ run_main(int argc, char** argv) auto _idx = i % 3; int _rank = 0; MPI_Comm_rank(comms.at(_idx), &_rank); - printf("[%s][%i] Running on split communicator %i (rank = %i)...\n", + printf("[%s][%2i] Running on split communicator %i (rank = %i)...\n", _name.c_str(), getpid(), _idx, _rank); run(comms.at(_idx), nitr); } @@ -315,15 +320,19 @@ run_main(int argc, char** argv) print_info(dup, false); } - printf("[%s][%i of %i] %s... Done", _name.c_str(), rank, size, __FUNCTION__); + printf("[%s][%i of %i] %s... Done\n", _name.c_str(), rank, size, __FUNCTION__); } int main(int argc, char** argv) { std::this_thread::sleep_for(std::chrono::seconds{ 2 }); - int _mpi_thread_provided; - MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &_mpi_thread_provided); + int _mpi_thread_requested = MPI_THREAD_SERIALIZED; + int _mpi_thread_provided = 0; + MPI_Init_thread(&argc, &argv, _mpi_thread_requested, &_mpi_thread_provided); + + if(_mpi_thread_provided != _mpi_thread_requested) + throw std::runtime_error("Error! requested thread mode != provided thread mode"); auto _prom = std::promise{}; auto _fut = _prom.get_future(); diff --git a/examples/rccl/CMakeLists.txt b/examples/rccl/CMakeLists.txt index 275b16012b..226b42aa8d 100644 --- a/examples/rccl/CMakeLists.txt +++ b/examples/rccl/CMakeLists.txt @@ -20,7 +20,7 @@ if(hip_FOUND AND rccl_FOUND) # After the following call, the CMake targets defined by googletest and Catch2 will be # available to the rest of the build - fetchcontent_makeavailable(rccl-tests) + fetchcontent_populate(rccl-tests) get_filename_component(rccl_ROOT_DIR "${rccl_INCLUDE_DIR}" DIRECTORY) diff --git a/external/timemory b/external/timemory index 45fdc98ed9..59ac91b591 160000 --- a/external/timemory +++ b/external/timemory @@ -1 +1 @@ -Subproject commit 45fdc98ed93d6d699ba246cb39ff27c392aa8e00 +Subproject commit 59ac91b591468ec29a0a59fe79e4cf05b768e871 diff --git a/scripts/build-release.sh b/scripts/build-release.sh index 33a84fc8a0..0939d2b240 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -8,7 +8,7 @@ : ${NJOBS:=12} : ${DISTRO:=""} : ${LTO:="OFF"} -: ${STRIP:="ON"} +: ${STRIP:="OFF"} : ${LIBGCC:="ON"} : ${LIBSTDCXX:="ON"} : ${MAX_THREADS:=2048} diff --git a/source/bin/omnitrace-avail/get_availability.hpp b/source/bin/omnitrace-avail/get_availability.hpp index 1a923ae622..8ebb24da3d 100644 --- a/source/bin/omnitrace-avail/get_availability.hpp +++ b/source/bin/omnitrace-avail/get_availability.hpp @@ -182,29 +182,8 @@ get_availability::get_info() } string_t categories = get_categories(category_types{}); - -#if 0 - auto _remove_typelist = [](std::string _tmp) { - if(_tmp.empty()) return _tmp; - auto _key = std::string{ "type_list" }; - auto _idx = _tmp.find(_key); - if(_idx == std::string::npos) return _tmp; - _idx = _tmp.find('<', _idx); - _tmp = _tmp.substr(_idx + 1); - _idx = _tmp.find_last_of('>'); - _tmp = _tmp.substr(0, _idx); - if(_tmp.empty()) return _tmp; - // strip trailing whitespaces - while((_idx = _tmp.find_last_of(' ')) == _tmp.length() - 1) - _tmp = _tmp.substr(0, _idx); - return _tmp; - }; - auto apis = _remove_typelist(demangle>()); - if(!apis.empty()) description += ". APIs: " + apis; -#endif - - description = _replace(_replace(description, ". .", "."), "..", "."); - data_type = _replace(_cleanup(data_type, "::__1"), "> >", ">>"); + description = _replace(_replace(description, ". .", "."), "..", "."); + data_type = _replace(_cleanup(data_type, "::__1"), "> >", ">>"); return info_type{ name, is_available, str_vec_t{ data_type, enum_type, id_type, ids_str, label, description, categories } }; diff --git a/source/bin/omnitrace-critical-trace/critical-trace.cpp b/source/bin/omnitrace-critical-trace/critical-trace.cpp index 46e69d0b70..2d2a0b94e2 100644 --- a/source/bin/omnitrace-critical-trace/critical-trace.cpp +++ b/source/bin/omnitrace-critical-trace/critical-trace.cpp @@ -227,7 +227,7 @@ save_call_graph(const std::string& _fname, const std::string& _label, _perf.stop(); if(_msg) { - OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).substr(4).c_str()); + OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).c_str()); } } @@ -281,7 +281,7 @@ save_critical_trace(const std::string& _fname, const std::string& _label, _perf.stop(); if(_msg) { - OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).substr(4).c_str()); + OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).c_str()); } } @@ -311,7 +311,7 @@ save_call_chain_text(const std::string& _fname, const call_chain& _call_chain, _perf.stop(); if(_msg) { - OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).substr(4).c_str()); + OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).c_str()); } } @@ -365,7 +365,7 @@ save_call_chain_json(const std::string& _fname, const std::string& _label, _perf.stop(); if(_msg) { - OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).substr(4).c_str()); + OMNITRACE_CT_DEBUG("%s\n", JOIN("", _perf).c_str()); } } @@ -847,7 +847,9 @@ compute_critical_trace() auto _report_perf = [](auto& _perf, const char* _func, const std::string& _label) { _perf.stop().rekey(_label); - OMNITRACE_BASIC_PRINT("[%s] %s\n", _func, JOIN("", _perf).substr(5).c_str()); + auto _str = JOIN("", _perf); + if(_str.length() > 5) _str = _str.substr(5); + OMNITRACE_BASIC_PRINT("[%s] %s\n", _func, _str.c_str()); OMNITRACE_BASIC_PRINT("\n"); _perf.reset().start(); }; diff --git a/source/bin/omnitrace/info.hpp b/source/bin/omnitrace/info.hpp index f25c2e8517..2b24223a0f 100644 --- a/source/bin/omnitrace/info.hpp +++ b/source/bin/omnitrace/info.hpp @@ -170,7 +170,7 @@ load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int auto _pos = _iname.find_last_of('.'); std::string _ext = {}; - if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length()); + if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1); auto _handle_error = [&]() { std::stringstream _msg{}; diff --git a/source/bin/omnitrace/omnitrace.cpp b/source/bin/omnitrace/omnitrace.cpp index fedc4f6880..22e0fbf5bc 100644 --- a/source/bin/omnitrace/omnitrace.cpp +++ b/source/bin/omnitrace/omnitrace.cpp @@ -212,7 +212,8 @@ main(int argc, char** argv) stderr, "These were the last %i log entries from omnitrace. You can control the " "number of log entries via the '--log ' option or OMNITRACE_LOG_COUNT " - "env variable.\n"); + "env variable.\n", + num_log_entries); if(log_ofs) log_ofs->close(); log_ofs.reset(); diff --git a/source/lib/common/setup.hpp b/source/lib/common/setup.hpp index 8b7dd7860d..fe40466b30 100644 --- a/source/lib/common/setup.hpp +++ b/source/lib/common/setup.hpp @@ -166,7 +166,8 @@ setup_environ(int _verbose, const std::string& _search_paths = {}, .c_str(), 0); setenv("OMNITRACE_ROCPROFILER_LIBRARY", - common::join('/', getenv(itr), "rocprofiler/lib/librocprofiler64.so") + common::join('/', getenv(itr), ROCPROFILER_METRICS_DIR, + "librocprofiler64.so") .c_str(), 0); break; diff --git a/source/lib/omnitrace-dl/CMakeLists.txt b/source/lib/omnitrace-dl/CMakeLists.txt index 6c332abd94..45b7d407ff 100644 --- a/source/lib/omnitrace-dl/CMakeLists.txt +++ b/source/lib/omnitrace-dl/CMakeLists.txt @@ -10,11 +10,15 @@ set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) set(CMAKE_CXX_VISIBILITY_PRESET "internal") set(CMAKE_POSITION_INDEPENDENT_CODE ON) +find_package(Threads REQUIRED) + 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 - ${CMAKE_CURRENT_SOURCE_DIR}/dl.hpp) +target_sources( + omnitrace-dl-library + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dl.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) target_include_directories( omnitrace-dl-library PUBLIC $ @@ -24,10 +28,11 @@ target_include_directories( target_link_libraries( omnitrace-dl-library PUBLIC $ $ - $) + $ + $) add_target_cxx_flag_if_avail(omnitrace-dl-library "-ftls-model=global-dynamic") -add_target_cxx_flag_if_avail(omnitrace-dl-library "-g") +add_target_cxx_flag_if_avail(omnitrace-dl-library "-g3") set_target_properties( omnitrace-dl-library diff --git a/source/lib/omnitrace-dl/dl.cpp b/source/lib/omnitrace-dl/dl.cpp index d684f60b8e..23fb06abc9 100644 --- a/source/lib/omnitrace-dl/dl.cpp +++ b/source/lib/omnitrace-dl/dl.cpp @@ -95,6 +95,14 @@ get_omnitrace_dl_env() : get_env("OMNITRACE_DL_VERBOSE", get_omnitrace_env()); } +inline bool +get_omnitrace_preload() +{ + auto&& _preload = get_env("OMNITRACE_PRELOAD", false); + auto&& _preload_libs = get_env("LD_PRELOAD", std::string{}); + return (_preload || _preload_libs.find("libomnitrace-dl.so") != std::string::npos); +} + // environment priority: // - OMNITRACE_DL_DEBUG // - OMNITRACE_DL_VERBOSE @@ -216,6 +224,7 @@ struct OMNITRACE_HIDDEN_API indirect int _info_verbose = 2; // Initialize all pointers OMNITRACE_DLSYM(omnitrace_init_library_f, m_omnihandle, "omnitrace_init_library"); + OMNITRACE_DLSYM(omnitrace_init_tooling_f, m_omnihandle, "omnitrace_init_tooling"); 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"); @@ -280,6 +289,11 @@ struct OMNITRACE_HIDDEN_API indirect OMNITRACE_DLSYM(hsa_on_unload_f, m_omnihandle, "OnUnload"); #endif +#if OMNITRACE_USE_ROCPROFILER > 0 + OMNITRACE_DLSYM(rocp_on_load_tool_prop_f, m_omnihandle, "OnLoadToolProp"); + OMNITRACE_DLSYM(rocp_on_unload_tool_f, m_omnihandle, "OnUnloadTool"); +#endif + #if OMNITRACE_USE_OMPT == 0 _warn_verbose = 5; #else @@ -311,6 +325,7 @@ struct OMNITRACE_HIDDEN_API indirect public: // omnitrace functions void (*omnitrace_init_library_f)(void) = nullptr; + void (*omnitrace_init_tooling_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; @@ -364,11 +379,21 @@ public: void (*hsa_on_unload_f)() = nullptr; #endif + // ROCP functions +#if OMNITRACE_USE_ROCPROFILER > 0 + void (*rocp_on_load_tool_prop_f)(rocprofiler_settings* settings) = nullptr; + void (*rocp_on_unload_tool_f)() = nullptr; +#endif + // OpenMP functions #if defined(OMNITRACE_USE_OMPT) && OMNITRACE_USE_OMPT > 0 ompt_start_tool_result_t* (*ompt_start_tool_f)(unsigned int, const char*); #endif + auto get_omni_library() const { return m_omnilib; } + auto get_user_library() const { return m_userlib; } + auto get_dl_library() const { return m_dllib; } + private: void* m_omnihandle = nullptr; void* m_userhandle = nullptr; @@ -483,6 +508,11 @@ extern "C" OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_library_f); } + void omnitrace_init_tooling(void) + { + OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_tooling_f); + } + void omnitrace_init(const char* a, bool b, const char* c) { if(dl::get_inited() && dl::get_finied()) @@ -837,6 +867,24 @@ extern "C" void OnUnload() { return OMNITRACE_DL_INVOKE(get_indirect().hsa_on_unload_f); } #endif + //----------------------------------------------------------------------------------// + // + // ROCP + // + //----------------------------------------------------------------------------------// + +#if OMNITRACE_USE_ROCTRACER > 0 + void OnLoadToolProp(rocprofiler_settings* settings) + { + return OMNITRACE_DL_INVOKE(get_indirect().rocp_on_load_tool_prop_f, settings); + } + + void OnUnloadTool() + { + return OMNITRACE_DL_INVOKE(get_indirect().rocp_on_unload_tool_f); + } +#endif + //----------------------------------------------------------------------------------// // // OMPT @@ -852,3 +900,40 @@ extern "C" } #endif } + +namespace omnitrace +{ +inline namespace dl +{ +namespace +{ +bool +omnitrace_preload() OMNITRACE_HIDDEN_API; + +bool +omnitrace_preload() +{ + auto _preloaded = get_omnitrace_preload(); + auto _enabled = get_env("OMNITRACE_ENABLED", true); + + static bool _once = false; + if(_once) return _preloaded; + _once = true; + + if(_preloaded && _enabled) + { + OMNITRACE_DL_LOG(0, "[%s] invoking %s(%s)\n", __FUNCTION__, "omnitrace_init", + ::omnitrace::join(::omnitrace::QuoteStrings{}, ", ", "sampling", + false, "main") + .c_str()); + omnitrace_init("sampling", false, "omnitrace"); + omnitrace_init_tooling(); + } + + return _preloaded; +} + +bool _handle_preload = omnitrace::dl::omnitrace_preload(); +} // namespace +} // namespace dl +} // namespace omnitrace diff --git a/source/lib/omnitrace-dl/dl.hpp b/source/lib/omnitrace-dl/dl.hpp index e8e3677877..373a94b4fa 100644 --- a/source/lib/omnitrace-dl/dl.hpp +++ b/source/lib/omnitrace-dl/dl.hpp @@ -57,6 +57,10 @@ # define OMNITRACE_USE_ROCTRACER 0 #endif +#if !defined(OMNITRACE_USE_ROCPROFILER) +# define OMNITRACE_USE_ROCPROFILER 0 +#endif + //--------------------------------------------------------------------------------------// // // omnitrace symbols @@ -66,6 +70,7 @@ extern "C" { void omnitrace_init_library(void) OMNITRACE_PUBLIC_API; + void omnitrace_init_tooling(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, @@ -156,6 +161,13 @@ extern "C" const char* const* failed_tool_names) OMNITRACE_PUBLIC_API; void OnUnload() OMNITRACE_PUBLIC_API; # endif + +# if OMNITRACE_USE_ROCPROFILER > 0 + // ROCP + struct rocprofiler_settings; + void OnLoadToolProp(rocprofiler_settings* settings) OMNITRACE_PUBLIC_API; + void OnUnloadTool() OMNITRACE_PUBLIC_API; +# endif #endif } diff --git a/source/lib/omnitrace-dl/main.c b/source/lib/omnitrace-dl/main.c new file mode 100644 index 0000000000..0ded1bfb18 --- /dev/null +++ b/source/lib/omnitrace-dl/main.c @@ -0,0 +1,115 @@ +// 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 _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +extern void +omnitrace_finalize(void); + +extern void +omnitrace_push_trace(const char* name); + +extern void +omnitrace_pop_trace(const char* name); + +// extern void +// omnitrace_update_env(char*** envp); + +extern void +omnitrace_init_tooling(void); + +extern void +omnitrace_init(const char*, bool, const char*); + +// Trampoline for the real main() +static int (*main_real)(int, char**, char**); + +int +omnitrace_main(int argc, char** argv, char** envp) +{ + // prevent re-entry + static int _reentry = 0; + if(_reentry > 0) return -1; + _reentry = 1; + + // set the relevant environment variables + // omnitrace_update_env(&envp); + + const char* mode = getenv("OMNITRACE_MODE"); + omnitrace_init(mode ? mode : "sampling", false, argv[0]); + omnitrace_init_tooling(); + omnitrace_push_trace("main(int argc, char** argv)"); + + int ret = main_real(argc, argv, envp); + + omnitrace_pop_trace("main(int argc, char** argv)"); + omnitrace_finalize(); + + return ret; +} + +typedef int +(*omnitrace_libc_start_main)(int (*)(int, char**, char**), int, char**, + int (*)(int, char**, char**), void (*)(void), + void (*)(void), void*); + +int +__libc_start_main(int (*_main)(int, char**, char**), int _argc, char** _argv, + int (*_init)(int, char**, char**), void (*_fini)(void), + void (*_rtld_fini)(void), void* _stack_end) +{ + // prevent re-entry + static int _reentry = 0; + if(_reentry > 0) return -1; + _reentry = 1; + + // get the address of this function + void* _this_func = __builtin_return_address(0); + + // Save the real main function address + main_real = _main; + + // Find the real __libc_start_main() + omnitrace_libc_start_main user_main = dlsym(RTLD_NEXT, "__libc_start_main"); + + if(user_main && user_main != _this_func) + { + //if(strcmp(_argv[0], "mpirun") == 0) + // return user_main(_main, _argc, _argv, _init, _fini, _rtld_fini, + // _stack_end); + //else + // call omnitrace main function wrapper + return user_main(omnitrace_main, _argc, _argv, _init, _fini, _rtld_fini, _stack_end); + } + else + { + fputs("Error! omnitrace could not find __libc_start_main!", stderr); + return -1; + } +} diff --git a/source/lib/omnitrace/api.cpp b/source/lib/omnitrace/api.cpp index 1a436d8eab..014cf599c0 100644 --- a/source/lib/omnitrace/api.cpp +++ b/source/lib/omnitrace/api.cpp @@ -72,6 +72,12 @@ omnitrace_init_library(void) omnitrace_init_library_hidden(); } +extern "C" void +omnitrace_init_tooling(void) +{ + omnitrace_init_tooling_hidden(); +} + extern "C" void omnitrace_init(const char* _mode, bool _rewrite, const char* _arg0) { diff --git a/source/lib/omnitrace/api.hpp b/source/lib/omnitrace/api.hpp index dc29a050b5..22ed38d683 100644 --- a/source/lib/omnitrace/api.hpp +++ b/source/lib/omnitrace/api.hpp @@ -34,6 +34,9 @@ extern "C" /// handles configuration logic void omnitrace_init_library(void) OMNITRACE_PUBLIC_API; + /// handles configuration logic + void omnitrace_init_tooling(void) OMNITRACE_PUBLIC_API; + /// starts gotcha wrappers void omnitrace_init(const char*, bool, const char*) OMNITRACE_PUBLIC_API; diff --git a/source/lib/omnitrace/library.cpp b/source/lib/omnitrace/library.cpp index c3f682fe20..b8e3536e9a 100644 --- a/source/lib/omnitrace/library.cpp +++ b/source/lib/omnitrace/library.cpp @@ -48,8 +48,10 @@ #include "library/tracing.hpp" #include +#include #include #include +#include #include #include @@ -62,6 +64,21 @@ using namespace omnitrace; //======================================================================================// +namespace omnitrace +{ +namespace perfetto +{ +// declare this here bc it has a tendency to cause namespace ambiguities +void +setup(); + +void +start(); +} // namespace perfetto +} // namespace omnitrace + +//======================================================================================// + namespace { auto @@ -78,6 +95,9 @@ ensure_finalization(bool _static_init = false) if(!get_env("OMNITRACE_COLORIZED_LOG", true)) tim::log::colorized() = false; + (void) tim::manager::instance(); + (void) tim::settings::shared_instance(); + if(!_static_init) { OMNITRACE_DEBUG_F("\n"); @@ -167,12 +187,14 @@ omnitrace_set_env_hidden(const char* env_name, const char* env_val) tim::set_env(env_name, env_val, 0); - OMNITRACE_CONDITIONAL_THROW( - _success && get_state() >= State::Init && - (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()); + if(_success && get_state() >= State::Init) + { + OMNITRACE_WARNING_F( + 0, + "omnitrace_set_env(\"%s\", \"%s\") called after omnitrace was initialized. " + "state = %s. This environment variable will have no effect\n", + env_name, env_val, std::to_string(get_state()).c_str()); + } } //======================================================================================// @@ -184,7 +206,15 @@ omnitrace_set_env_hidden(const char* env_name, const char* env_val) namespace { bool _set_mpi_called = false; -std::function _preinit_callback = []() {}; +std::function _preinit_callback = []() { get_preinit_bundle()->start(); }; + +void +omnitrace_preinit_hidden() +{ + // run once and discard + _preinit_callback(); + _preinit_callback = []() {}; +} } // namespace extern "C" void @@ -215,15 +245,18 @@ omnitrace_set_mpi_hidden(bool use, bool attached) trait::runtime_enabled::set(false); } - OMNITRACE_CONDITIONAL_THROW( - get_state() >= State::Init && - (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()); + if(get_state() >= State::Init) + { + OMNITRACE_WARNING_F( + 0, + "omnitrace_set_mpi(use=%s, attached=%s) called after omnitrace was " + "initialized. state = %s. MPI support may not be properly initialized. Use " + "OMNITRACE_USE_MPIP=ON and OMNITRACE_USE_PID=ON to ensure full support\n", + std::to_string(use).c_str(), std::to_string(attached).c_str(), + std::to_string(get_state()).c_str()); + } - _preinit_callback(); + omnitrace_preinit_hidden(); } //======================================================================================// @@ -351,21 +384,29 @@ omnitrace_init_tooling_hidden() sampling::unblock_signals(); } get_main_bundle()->start(); + OMNITRACE_DEBUG_F("State: %s -> State::Active\n", + std::to_string(get_state()).c_str()); set_state(State::Active); // set to active as very last operation } }; OMNITRACE_SCOPED_SAMPLING_ON_CHILD_THREADS(false); + // perfetto initialization + if(get_use_perfetto()) + { + OMNITRACE_VERBOSE_F(1, "Setting up Perfetto...\n"); + omnitrace::perfetto::setup(); + } + + // ideally these have already been started + omnitrace_preinit_hidden(); + // start these gotchas once settings have been initialized get_init_bundle()->start(); if(get_use_sampling()) sampling::block_signals(); - if(get_use_critical_trace()) - { - // initialize the thread pool - (void) tasking::critical_trace::get_task_group(); - } + tasking::setup(); if(get_use_timemory()) { @@ -396,56 +437,6 @@ omnitrace_init_tooling_hidden() } } - perfetto::TracingInitArgs args{}; - perfetto::TraceConfig cfg{}; - perfetto::protos::gen::TrackEventConfig track_event_cfg{}; - - // perfetto initialization - if(get_use_perfetto()) - { - // environment settings - auto shmem_size_hint = get_perfetto_shmem_size_hint(); - auto buffer_size = get_perfetto_buffer_size(); - - auto _policy = - get_perfetto_fill_policy() == "discard" - ? perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_DISCARD - : perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_RING_BUFFER; - auto* buffer_config = cfg.add_buffers(); - buffer_config->set_size_kb(buffer_size); - buffer_config->set_fill_policy(_policy); - - std::set _available_categories = {}; - std::set _disabled_categories = {}; - for(auto itr : { OMNITRACE_PERFETTO_CATEGORIES }) - _available_categories.emplace(itr.name); - auto _enabled_categories = config::get_perfetto_categories(); - for(const auto& itr : _available_categories) - { - if(!_enabled_categories.empty() && _enabled_categories.count(itr) == 0) - _disabled_categories.emplace(itr); - } - - for(const auto& itr : _disabled_categories) - { - OMNITRACE_VERBOSE_F(1, "Disabling perfetto track event category: %s\n", - itr.c_str()); - track_event_cfg.add_disabled_categories(itr); - } - - auto* ds_cfg = cfg.add_data_sources()->mutable_config(); - ds_cfg->set_name("track_event"); // this MUST be track_event - ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString()); - - args.shmem_size_hint_kb = shmem_size_hint; - - if(get_backend() != "inprocess") args.backends |= perfetto::kSystemBackend; - if(get_backend() != "system") args.backends |= perfetto::kInProcessBackend; - - perfetto::Tracing::Initialize(args); - perfetto::TrackEvent::Register(); - } - if(get_use_ompt()) { OMNITRACE_VERBOSE_F(1, "Setting up OMPT...\n"); @@ -460,24 +451,7 @@ omnitrace_init_tooling_hidden() if(get_use_perfetto() && !is_system_backend()) { -#if defined(CUSTOM_DATA_SOURCE) - // Add the following: - perfetto::DataSourceDescriptor dsd{}; - dsd.set_name("com.example.custom_data_source"); - CustomDataSource::Register(dsd); - auto* ds_cfg = cfg.add_data_sources()->mutable_config(); - ds_cfg->set_name("com.example.custom_data_source"); - CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs()); - packet->set_for_testing()->set_str("Hello world!"); - PRINT_HERE("%s", "Trace"); - }); -#endif - auto& tracing_session = tracing::get_trace_session(); - tracing_session = perfetto::Tracing::NewTrace(); - tracing_session->Setup(cfg); - tracing_session->StartBlocking(); + omnitrace::perfetto::start(); } // if static objects are destroyed in the inverse order of when they are @@ -521,13 +495,20 @@ omnitrace_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _a (void) tracing::push_count(); (void) tracing::pop_count(); - OMNITRACE_CONDITIONAL_THROW( - get_state() >= State::Init && - (config::get_is_continuous_integration() || get_debug_init()), - "omnitrace_init(mode=%s, is_binary_rewrite=%s, argv0=%s) called after omnitrace " - "was initialized. state = %s", - _mode, std::to_string(_is_binary_rewrite).c_str(), _argv0, - std::to_string(get_state()).c_str()); + if(get_state() >= State::Init) + { + if(std::string_view{ _mode } != "trace" && std::string_view{ _mode } != "Trace") + { + OMNITRACE_WARNING_F( + 0, + "omnitrace_init(mode=%s, is_binary_rewrite=%s, argv0=%s) " + "called after omnitrace was initialized. state = %s. Mode-based settings " + "(via -M passed to omnitrace exe) may not be properly " + "configured.\n", + _mode, std::to_string(_is_binary_rewrite).c_str(), _argv0, + std::to_string(get_state()).c_str()); + } + } tracing::get_finalization_functions().emplace_back([_argv0]() { OMNITRACE_CI_THROW(get_state() != State::Active, @@ -555,13 +536,9 @@ omnitrace_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _a tim::set_env("OMNITRACE_MODE", _mode, 0); config::is_binary_rewrite() = _is_binary_rewrite; - if(!_set_mpi_called) + if(_set_mpi_called) { - _preinit_callback = []() { get_preinit_bundle()->start(); }; - } - else - { - get_preinit_bundle()->start(); + omnitrace_preinit_hidden(); } } @@ -586,6 +563,9 @@ omnitrace_finalize_hidden(void) if(get_verbose() >= 0 || get_debug()) fprintf(stderr, "\n"); OMNITRACE_VERBOSE_F(0, "finalizing...\n"); + + sampling::block_samples(); + thread_info::set_stop(comp::wall_clock::record()); tim::sampling::block_signals(get_sampling_signals(), @@ -779,10 +759,6 @@ omnitrace_finalize_hidden(void) if(get_use_critical_trace() || (get_use_rocm_smi() && get_use_roctracer())) { OMNITRACE_VERBOSE_F(1, "Generating the critical trace...\n"); - // (potentially) increase the thread-pool size since application - // shouldn't be using threads during finalization - tasking::initialize_threadpool(std::min( - { std::thread::hardware_concurrency(), get_thread_pool_size(), 8 })); for(size_t i = 0; i < max_supported_threads; ++i) { @@ -790,7 +766,10 @@ omnitrace_finalize_hidden(void) thread_data; if(critical_trace_hash_data::instances().at(i)) + { + OMNITRACE_DEBUG_F("Copying the hash id data for thread %zu...\n", i); critical_trace::add_hash_id(*critical_trace_hash_data::instances().at(i)); + } } for(size_t i = 0; i < max_supported_threads; ++i) @@ -798,7 +777,11 @@ omnitrace_finalize_hidden(void) using critical_trace_chain_data = thread_data; if(critical_trace_chain_data::instances().at(i)) + { + OMNITRACE_DEBUG_F( + "Updating the critical trace call-chains for thread %zu...\n", i); critical_trace::update(i); // launch update task + } } OMNITRACE_VERBOSE_F(1, "Waiting on critical trace updates...\n"); @@ -813,9 +796,6 @@ omnitrace_finalize_hidden(void) if(get_use_critical_trace()) { - // make sure outstanding hash tasks completed before compute - tasking::join(); - // launch compute task OMNITRACE_VERBOSE_F(1, "launching critical trace compute task...\n"); critical_trace::compute(); @@ -837,7 +817,7 @@ omnitrace_finalize_hidden(void) bool _perfetto_output_error = false; if(get_use_perfetto() && !is_system_backend()) { - auto& tracing_session = tracing::get_trace_session(); + auto& tracing_session = tracing::get_perfetto_session(); OMNITRACE_CI_THROW(tracing_session == nullptr, "Null pointer to the tracing session"); @@ -845,7 +825,7 @@ omnitrace_finalize_hidden(void) OMNITRACE_VERBOSE_F(0, "Finalizing perfetto...\n"); // Make sure the last event is closed for this example. - perfetto::TrackEvent::Flush(); + ::perfetto::TrackEvent::Flush(); tracing_session->FlushBlocking(); OMNITRACE_VERBOSE_F(3, "Stopping the blocking perfetto trace session...\n"); @@ -934,9 +914,18 @@ omnitrace_finalize_hidden(void) tim::cereal::make_nvp("memory_maps", _maps)); }); + auto _manager = tim::manager::instance(); + if(_manager) _manager->set_write_metadata(-1); + OMNITRACE_VERBOSE_F(1, "Finalizing timemory...\n"); tim::timemory_finalize(); + if(_manager) + { + _manager->write_metadata(settings::get_global_output_prefix(), "omnitrace", + settings::default_process_suffix()); + } + if(_perfetto_output_error) { OMNITRACE_THROW("Error opening perfetto output file: %s", @@ -965,4 +954,6 @@ namespace // this might call finalization before perfetto ends the tracing session // but static variable in omnitrace_init_tooling_hidden is more likely auto _ensure_finalization = ensure_finalization(true); +auto _manager = tim::manager::instance(); +auto _settings = tim::settings::shared_instance(); } // namespace diff --git a/source/lib/omnitrace/library/categories.hpp b/source/lib/omnitrace/library/categories.hpp index cc590479fc..e6ea803461 100644 --- a/source/lib/omnitrace/library/categories.hpp +++ b/source/lib/omnitrace/library/categories.hpp @@ -156,7 +156,7 @@ using name = perfetto_category; OMNITRACE_PERFETTO_CATEGORY(category::thread_hardware_counter), \ OMNITRACE_PERFETTO_CATEGORY(category::kernel_hardware_counter), \ OMNITRACE_PERFETTO_CATEGORY(category::numa), \ - perfetto::Category("timemory").SetDescription("Events from the timemory API") + ::perfetto::Category("timemory").SetDescription("Events from the timemory API") #if defined(TIMEMORY_USE_PERFETTO) # define TIMEMORY_PERFETTO_CATEGORIES OMNITRACE_PERFETTO_CATEGORIES diff --git a/source/lib/omnitrace/library/components/backtrace.cpp b/source/lib/omnitrace/library/components/backtrace.cpp index c9e67833dd..d55e2ba9c8 100644 --- a/source/lib/omnitrace/library/components/backtrace.cpp +++ b/source/lib/omnitrace/library/components/backtrace.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include "library/common.hpp" #include "library/components/ensure_storage.hpp" #include "library/components/fwd.hpp" #include "library/config.hpp" @@ -72,40 +73,25 @@ namespace omnitrace { namespace component { -std::vector +std::vector backtrace::get() const { - std::vector _v = {}; + std::vector _v = {}; if(size() == 0) return _v; - _v.reserve(m_data.size()); - for(const auto& itr : m_data.call_stack) + { - if(!itr) continue; - -#if defined(OMNITRACE_CI) && OMNITRACE_CI > 0 - std::string _name = {}; - _name.reserve(1024); - const char* _addr = _name.data(); - _name = itr->get_name(m_data.context, _name); - - OMNITRACE_CONDITIONAL_PRINT( - _name.data() != _addr, - "[backtrace::get()] processing unw_get_proc_name_from_ip for '%s' " - "caused a reallocation. Before=%p, After=%p\n", - _name.c_str(), _addr, _name.data()); -#else - auto _name = itr->get_name(m_data.context); -#endif - - if(!_name.empty()) _v.emplace_back(_name); + static auto _cache = cache_type{}; + auto_lock_t _lk{ type_mutex() }; + _v = m_data.get(&_cache, true); } + // put the bottom of the call-stack on top std::reverse(_v.begin(), _v.end()); // auto _known_excludes = std::set{ "funlockfile", "killpg", "__restore_rt" }; // remove some known functions which are by-products of interrupts - while(!_v.empty() && _known_excludes.find(_v.back()) != _known_excludes.end()) + while(!_v.empty() && _known_excludes.find(_v.back().name) != _known_excludes.end()) _v.pop_back(); return _v; @@ -124,7 +110,7 @@ backtrace::description() } std::vector -backtrace::filter_and_patch(const std::vector& _data) +backtrace::filter_and_patch(const std::vector& _data) { // check whether the call-stack entry should be used. -1 means break, 0 means continue auto _use_label = [](std::string_view _lbl) -> short { @@ -160,7 +146,7 @@ backtrace::filter_and_patch(const std::vector& _data) auto _ret = std::vector{}; for(const auto& itr : _data) { - auto _name = tim::demangle(_patch_label(itr)); + auto _name = tim::demangle(_patch_label(itr.name)); auto _use = _use_label(_name); if(_use == -1) break; if(_use == 0) continue; diff --git a/source/lib/omnitrace/library/components/backtrace.hpp b/source/lib/omnitrace/library/components/backtrace.hpp index 45f8ff2a8b..0f18a8bc8e 100644 --- a/source/lib/omnitrace/library/components/backtrace.hpp +++ b/source/lib/omnitrace/library/components/backtrace.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,8 @@ struct backtrace static constexpr size_t stack_depth = OMNITRACE_MAX_UNWIND_DEPTH; using data_t = tim::unwind::stack; + using cache_type = typename data_t::cache_type; + using entry_type = tim::unwind::processed_entry; using clock_type = std::chrono::steady_clock; using value_type = void; using system_clock = std::chrono::system_clock; @@ -67,15 +70,15 @@ struct backtrace backtrace& operator=(const backtrace&) = default; backtrace& operator=(backtrace&&) noexcept = default; - static std::vector filter_and_patch(const std::vector&); + static std::vector filter_and_patch(const std::vector&); static void start(); static void stop(); - void sample(int = -1); - bool empty() const; - size_t size() const; - std::vector get() const; + void sample(int = -1); + bool empty() const; + size_t size() const; + std::vector get() const; private: data_t m_data = {}; diff --git a/source/lib/omnitrace/library/components/backtrace_metrics.cpp b/source/lib/omnitrace/library/components/backtrace_metrics.cpp index 4d917293aa..634e55198a 100644 --- a/source/lib/omnitrace/library/components/backtrace_metrics.cpp +++ b/source/lib/omnitrace/library/components/backtrace_metrics.cpp @@ -162,6 +162,12 @@ backtrace_metrics::sample(int) { assert(get_papi_vector(_tid).get() != nullptr); m_hw_counter = get_papi_vector(_tid)->record(); + // const auto& _cfg = get_papi_vector(_tid)->get_config(); + // std::cerr << "Config: "; + // for(size_t i = 0; i < _cfg->size; ++i) + // std::cerr << "[" << _cfg->labels.at(i) << "|" << _cfg->event_names.at(i) + // << "|" << _cfg->event_codes.at(i) << "]"; + // std::cerr << "\n"; } } } @@ -188,7 +194,8 @@ backtrace_metrics::configure(bool _setup, int64_t _tid) { using common_type_t = typename hw_counters::common_type; get_papi_vector(_tid)->start(); - *get_papi_labels(_tid) = comp::papi_common::get_events(); + *get_papi_labels(_tid) = + comp::papi_common::get_config()->labels; } } } diff --git a/source/lib/omnitrace/library/components/comm_data.hpp b/source/lib/omnitrace/library/components/comm_data.hpp index 7763d784d6..9cfc572080 100644 --- a/source/lib/omnitrace/library/components/comm_data.hpp +++ b/source/lib/omnitrace/library/components/comm_data.hpp @@ -216,19 +216,19 @@ private: return _t; } - static auto&& add(const gotcha_data& _data, data_type value) + static auto add(const gotcha_data& _data, data_type value) { tracker_t _t{ std::string_view{ _data.tool_id.c_str() } }; return add(_t, value); } - static auto&& add(std::string&& _name, data_type value) + static auto add(std::string&& _name, data_type value) { tracker_t _t{ _name }; return add(_t, value); } - static auto&& add(std::string_view _name, data_type value) + static auto add(std::string_view _name, data_type value) { tracker_t _t{ _name }; return add(_t, value); diff --git a/source/lib/omnitrace/library/components/exit_gotcha.hpp b/source/lib/omnitrace/library/components/exit_gotcha.hpp index a531adf881..685b018fb9 100644 --- a/source/lib/omnitrace/library/components/exit_gotcha.hpp +++ b/source/lib/omnitrace/library/components/exit_gotcha.hpp @@ -38,6 +38,8 @@ namespace component { struct exit_gotcha : tim::component::base { + static constexpr size_t gotcha_capacity = 3; + using gotcha_data = tim::component::gotcha_data; using exit_func_t = void (*)(int); using abort_func_t = void (*)(); @@ -61,5 +63,6 @@ struct exit_gotcha : tim::component::base }; } // namespace component -using exit_gotcha_t = tim::component::gotcha<3, std::tuple<>, component::exit_gotcha>; +using exit_gotcha_t = tim::component::gotcha, component::exit_gotcha>; } // namespace omnitrace diff --git a/source/lib/omnitrace/library/components/fork_gotcha.hpp b/source/lib/omnitrace/library/components/fork_gotcha.hpp index 7cdcc8f70f..2051b868af 100644 --- a/source/lib/omnitrace/library/components/fork_gotcha.hpp +++ b/source/lib/omnitrace/library/components/fork_gotcha.hpp @@ -33,6 +33,8 @@ namespace component // this is used to wrap fork() struct fork_gotcha : comp::base { + static constexpr size_t gotcha_capacity = 1; + using gotcha_data_t = comp::gotcha_data; TIMEMORY_DEFAULT_OBJECT(fork_gotcha) @@ -56,5 +58,6 @@ struct fork_gotcha : comp::base } // namespace component using fork_gotcha_t = - comp::gotcha<4, tim::component_tuple, project::omnitrace>; + comp::gotcha, project::omnitrace>; } // namespace omnitrace diff --git a/source/lib/omnitrace/library/components/mpi_gotcha.cpp b/source/lib/omnitrace/library/components/mpi_gotcha.cpp index 07b00227b9..2deb204715 100644 --- a/source/lib/omnitrace/library/components/mpi_gotcha.cpp +++ b/source/lib/omnitrace/library/components/mpi_gotcha.cpp @@ -138,6 +138,16 @@ auto reject_bindings = strset_t{}; void mpi_gotcha::configure() { + // don't emit warnings for missing MPI functions unless debug or verbosity >= 3 + if(get_verbose_env() < 3 && !get_debug_env()) + { + for(size_t i = 0; i < mpi_gotcha_t::capacity(); ++i) + { + auto* itr = mpi_gotcha_t::at(i); + if(itr) itr->verbose = -1; + } + } + mpi_gotcha_t::get_initializer() = []() { mpi_gotcha_t::template configure<0, int, int*, char***>("MPI_Init"); mpi_gotcha_t::template configure<1, int, int*, char***, int, int*>( @@ -280,6 +290,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval) { OMNITRACE_BASIC_DEBUG_F("%s() returned %i\n", _data.tool_id.c_str(), (int) _retval); + if(!settings::use_output_suffix()) settings::use_output_suffix() = true; + if(_retval == tim::mpi::success_v && _data.tool_id.find("MPI_Init") == 0) { omnitrace_mpi_set_attr(); diff --git a/source/lib/omnitrace/library/components/pthread_create_gotcha.cpp b/source/lib/omnitrace/library/components/pthread_create_gotcha.cpp index 24bdc3cdf8..b0c8829eae 100644 --- a/source/lib/omnitrace/library/components/pthread_create_gotcha.cpp +++ b/source/lib/omnitrace/library/components/pthread_create_gotcha.cpp @@ -40,6 +40,7 @@ #include #include +#include namespace omnitrace { @@ -132,13 +133,14 @@ stop_bundle(bundle_t& _bundle, int64_t _tid, Args&&... _args) //--------------------------------------------------------------------------------------// pthread_create_gotcha::wrapper::wrapper(routine_t _routine, void* _arg, - bool _enable_sampling, int64_t _parent, - promise_t* _p) + bool _enable_sampling, bool _offset, + int64_t _parent, promise_t _p) : m_enable_sampling{ _enable_sampling } +, m_offset{ _offset } , m_parent_tid{ _parent } , m_routine{ _routine } , m_arg{ _arg } -, m_promise{ _p } +, m_promise{ std::move(_p) } {} void* @@ -188,10 +190,10 @@ pthread_create_gotcha::wrapper::operator()() const auto _active = (get_state() == ::omnitrace::State::Active && bundles != nullptr && bundles_mutex != nullptr); - if(_active && !_coverage) + const auto& _info = thread_info::init(m_offset); + if(_active && !_coverage && !m_offset) { - const auto& _tid_index = thread_info::init(); - _tid = _tid_index->index_data->sequent_value; + _tid = _info->index_data->sequent_value; threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid).c_str()); if(!thread_bundle_data_t::instances().at(_tid)) { @@ -217,10 +219,6 @@ pthread_create_gotcha::wrapper::operator()() const sampling::unblock_signals(); } } - else - { - thread_info::init(true); - } // notify the wrapper that all internal work is completed if(m_promise) m_promise->set_value(); @@ -292,7 +290,8 @@ pthread_create_gotcha::shutdown() bundles->clear(); OMNITRACE_BASIC_VERBOSE( - 2 && _ndangling > 0, + 1, + // 2 && _ndangling > 0, "[pthread_create_gotcha::shutdown] cleaned up %lu dangling bundles\n", _ndangling); } @@ -300,6 +299,8 @@ pthread_create_gotcha::shutdown() void pthread_create_gotcha::shutdown(int64_t _tid) { + if(_tid == 0) shutdown(); + if(is_shutdown && *is_shutdown) return; if(!bundles_mutex || !bundles) return; @@ -323,23 +324,51 @@ pthread_create_gotcha::set_data(wrappee_t _v) // pthread_create int pthread_create_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr, - void* (*start_routine)(void*), void* arg) const + void* (*func)(void*), void* arg) const { - auto _disabled = (get_thread_state() == ThreadState::Disabled); - auto _enabled = (get_thread_state() == ThreadState::Enabled); - auto _bundle = std::optional{}; + auto _tid = utility::get_thread_index(); + auto _thr_state = get_thread_state(); + auto _glob_state = get_state(); + auto _mode = get_mode(); + auto _disabled = (_thr_state == ThreadState::Disabled); + auto _enabled = (_thr_state == ThreadState::Enabled); + auto _bundle = std::optional{}; + auto _sample_child = sampling_enabled_on_child_threads(); + auto _active = (_glob_state == ::omnitrace::State::Active && !_disabled); + const auto& _info = thread_info::init(!_active || !_sample_child || _disabled); OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal); - auto _active = (get_state() == ::omnitrace::State::Active && !_disabled); - auto _coverage = (get_mode() == Mode::Coverage); - auto _use_sampling = get_use_sampling(); - auto _sample_child = sampling_enabled_on_child_threads(); - auto _tid = utility::get_thread_index(); - auto _use_bundle = (_active && !_coverage); - const auto& _info = thread_info::init(!_active || !_sample_child || _disabled); - auto _enable_sampling = - (!_disabled && _enabled && _sample_child && _use_sampling && !_info->is_offset); + auto _coverage = (_mode == Mode::Coverage); + auto _use_sampling = get_use_sampling(); + auto _offset = (!_enabled || !_active || _info->is_offset); + auto _use_bundle = (_active && !_coverage && !_offset); + auto _enable_sampling = + (_use_sampling && _sample_child && _active && !_coverage && !_offset); + + static bool debug_threading_get_id = + get_env(TIMEMORY_SETTINGS_PREFIX "DEBUG_THREADING_GET_ID", false); + + auto _verbose = (debug_threading_get_id) ? 0 : 3; + OMNITRACE_VERBOSE( + _verbose, + "Creating new thread :: global_state=%s, thread_state=%s, mode=%s, active=%s, " + "coverage=%s, use_sampling=%s, sample_children=%s, tid=%li, use_bundle=%s, " + "enable_sampling=%s, thread_info=(%s)...\n", + std::to_string(_glob_state).c_str(), std::to_string(_thr_state).c_str(), + std::to_string(_mode).c_str(), std::to_string(_active).c_str(), + std::to_string(_coverage).c_str(), std::to_string(_use_sampling).c_str(), + std::to_string(_sample_child).c_str(), _tid, std::to_string(_use_bundle).c_str(), + std::to_string(_enable_sampling).c_str(), JOIN("", *_info).c_str()); + + if(debug_threading_get_id) + { + timemory_print_demangled_backtrace<8>(std::cerr, std::string{}, + std::string{ "threading::get_id() [id=" } + + std::to_string(_tid) + + std::string{ "]" }, + std::string{ " " }, false); + } if(_active && !_disabled && !_info->is_offset) { @@ -348,13 +377,16 @@ pthread_create_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr, } // ensure that cpu cid stack exists on the parent thread if active - if(_active && !_coverage) get_cpu_cid_stack(); + if(_active && !_coverage) + { + OMNITRACE_DEBUG("blocking signals...\n"); + get_cpu_cid_stack(); + } set_thread_state(ThreadState::Disabled); auto _blocked = get_sampling_signals(); - auto _promise = std::promise{}; - auto _fut = _promise.get_future(); - auto* _wrap = new wrapper(start_routine, arg, _enable_sampling, _tid, &_promise); + auto _promise = (_active) ? std::make_shared>() : promise_t{}; + auto* _wrap = new wrapper(func, arg, _enable_sampling, _offset, _tid, _promise); set_thread_state(ThreadState::Internal); // block the signals in entire process @@ -367,15 +399,18 @@ pthread_create_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr, if(_use_bundle) { _bundle = bundle_t{ "pthread_create" }; - start_bundle(*_bundle, audit::incoming{}, thread, attr, start_routine, arg); + start_bundle(*_bundle, audit::incoming{}, thread, attr, func, arg); } // create the thread auto _ret = (*m_wrappee)(thread, attr, &wrapper::wrap, static_cast(_wrap)); // wait for thread to set promise - OMNITRACE_DEBUG("waiting for child to signal it is setup...\n"); - _fut.wait(); + if(_promise) + { + OMNITRACE_DEBUG("waiting for child to signal it is setup...\n"); + _promise->get_future().wait_for(std::chrono::milliseconds{ 500 }); + } if(_use_bundle) stop_bundle(*_bundle, threading::get_id(), audit::outgoing{}, _ret); diff --git a/source/lib/omnitrace/library/components/pthread_create_gotcha.hpp b/source/lib/omnitrace/library/components/pthread_create_gotcha.hpp index 459f834767..05703cde59 100644 --- a/source/lib/omnitrace/library/components/pthread_create_gotcha.hpp +++ b/source/lib/omnitrace/library/components/pthread_create_gotcha.hpp @@ -36,24 +36,26 @@ namespace component { struct pthread_create_gotcha : tim::component::base { + static constexpr size_t gotcha_capacity = 1; + using routine_t = void* (*) (void*); using wrappee_t = int (*)(pthread_t*, const pthread_attr_t*, routine_t, void*); + using promise_t = std::shared_ptr>; struct wrapper { - using promise_t = std::promise; - - wrapper(routine_t _routine, void* _arg, bool, int64_t, promise_t*); + wrapper(routine_t _routine, void* _arg, bool, 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; + bool m_enable_sampling = false; + bool m_offset = false; + int64_t m_parent_tid = 0; + routine_t m_routine = nullptr; + void* m_arg = nullptr; + promise_t m_promise = {}; }; TIMEMORY_DEFAULT_OBJECT(pthread_create_gotcha) @@ -77,6 +79,7 @@ private: }; using pthread_create_gotcha_t = - tim::component::gotcha<2, std::tuple<>, pthread_create_gotcha>; + tim::component::gotcha, + pthread_create_gotcha>; } // namespace component } // namespace omnitrace diff --git a/source/lib/omnitrace/library/components/roctracer.cpp b/source/lib/omnitrace/library/components/roctracer.cpp index a5a26f61d2..77726c255b 100644 --- a/source/lib/omnitrace/library/components/roctracer.cpp +++ b/source/lib/omnitrace/library/components/roctracer.cpp @@ -169,6 +169,10 @@ roctracer::setup() for(auto& itr : roctracer_setup_routines()) itr.second(); + // make sure all async callbacks are allocated + for(size_t i = 0; i < max_supported_threads; ++i) + hip_exec_activity_callbacks(i); + OMNITRACE_VERBOSE_F(1, "roctracer is setup\n"); } diff --git a/source/lib/omnitrace/library/config.cpp b/source/lib/omnitrace/library/config.cpp index 742f8d9dbf..cdca176cf5 100644 --- a/source/lib/omnitrace/library/config.cpp +++ b/source/lib/omnitrace/library/config.cpp @@ -235,7 +235,7 @@ configure_settings(bool _init) OMNITRACE_HIP_VERSION_PATCH); #endif - static auto _config = settings::shared_instance(); + auto _config = settings::shared_instance(); // if using timemory, default to perfetto being off auto _default_perfetto_v = @@ -338,7 +338,7 @@ configure_settings(bool _init) OMNITRACE_CONFIG_SETTING( double, "OMNITRACE_SAMPLING_FREQ", - "Number of software interrupts per second when OMNITTRACE_USE_SAMPLING=ON", 10.0, + "Number of software interrupts per second when OMNITTRACE_USE_SAMPLING=ON", 300.0, "sampling", "process_sampling"); OMNITRACE_CONFIG_SETTING(double, "OMNITRACE_SAMPLING_CPUTIME_FREQ", @@ -452,12 +452,12 @@ configure_settings(bool _init) OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_TRACE_THREAD_RW_LOCKS", "Enable tracing calls to pthread_rwlock_* functions. May " "cause deadlocks with ROCm-enabled OpenMPI.", - true, "backend", "parallelism", "gotcha", "advanced"); + false, "backend", "parallelism", "gotcha", "advanced"); OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_TRACE_THREAD_SPIN_LOCKS", "Enable tracing calls to pthread_spin_* functions. May " "cause deadlocks with MPI distributions.", - true, "backend", "parallelism", "gotcha", "advanced"); + false, "backend", "parallelism", "gotcha", "advanced"); OMNITRACE_CONFIG_SETTING( bool, "OMNITRACE_SAMPLING_KEEP_INTERNAL", @@ -600,7 +600,7 @@ configure_settings(bool _init) _config->get_papi_events() = "PAPI_TOT_CYC"; // settings native to timemory but critically and/or extensively used by omnitrace - auto _add_omnitrace_category = [](auto itr) { + auto _add_omnitrace_category = [&_config](auto itr) { if(itr != _config->end()) { auto _categories = itr->second->get_categories(); @@ -617,7 +617,7 @@ configure_settings(bool _init) _add_omnitrace_category(_config->find("OMNITRACE_OUTPUT_PREFIX")); _add_omnitrace_category(_config->find("OMNITRACE_OUTPUT_PATH")); - auto _add_advanced_category = [](const std::string& _name) { + auto _add_advanced_category = [&_config](const std::string& _name) { auto itr = _config->find(_name); if(itr != _config->end()) { @@ -690,7 +690,7 @@ configure_settings(bool _init) OMNITRACE_BASIC_VERBOSE(0, "In order to enable PAPI support, run 'echo N | sudo tee " "/proc/sys/kernel/perf_event_paranoid' where N is < 2\n"); - tim::trait::runtime_enabled::set(false); + tim::trait::runtime_enabled>::set(false); tim::trait::runtime_enabled::set(false); tim::trait::runtime_enabled::set(false); tim::trait::runtime_enabled::set(false); @@ -1500,7 +1500,7 @@ get_use_pid() bool& get_use_mpip() { - static bool _v = tim::get_env("OMNITRACE_USE_MPIP", false, false); + static bool _v = tim::get_env("OMNITRACE_USE_MPIP", true, false); return _v; } diff --git a/source/lib/omnitrace/library/critical_trace.cpp b/source/lib/omnitrace/library/critical_trace.cpp index f0ea480a15..fbb929ddee 100644 --- a/source/lib/omnitrace/library/critical_trace.cpp +++ b/source/lib/omnitrace/library/critical_trace.cpp @@ -62,6 +62,7 @@ using call_graph_preorder_itr_t = typename call_graph_t::pre_order_iterator; hash_ids complete_hash_ids{}; call_chain complete_call_chain{}; std::mutex complete_call_mutex{}; +std::mutex tasking_mutex{}; void update_critical_path(call_chain _chain, int64_t _tid); @@ -549,6 +550,7 @@ add_hash_id(const hash_ids& _labels) { OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal); if(!tasking::critical_trace::get_task_group().pool()) return; + std::unique_lock _lk{ tasking_mutex }; tasking::critical_trace::get_task_group().exec([_labels]() { static std::mutex _mtx{}; _mtx.lock(); @@ -579,7 +581,8 @@ update(int64_t _tid) if(!get_use_critical_trace() && !get_use_rocm_smi()) return; OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal); if(!tasking::critical_trace::get_task_group().pool()) return; - call_chain _data{}; + std::unique_lock _lk{ tasking_mutex }; + call_chain _data{}; std::swap(_data, *critical_trace::get(_tid)); tasking::critical_trace::get_task_group().exec(update_critical_path, _data, _tid); } @@ -590,6 +593,7 @@ compute(int64_t _tid) update(_tid); OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal); if(!tasking::critical_trace::get_task_group().pool()) return; + std::unique_lock _lk{ tasking_mutex }; tasking::critical_trace::get_task_group().exec(compute_critical_trace); } @@ -867,6 +871,7 @@ get_entries(int64_t _ts, const std::function& _eval) size_t _n = 0; std::vector> _v{}; if(!tasking::critical_trace::get_task_group().pool()) return _v; + std::unique_lock _lk{ tasking_mutex }; tasking::critical_trace::get_task_group().exec(_func, &_v, &_n); tasking::critical_trace::get_task_group().join(); OMNITRACE_DEBUG("critical_trace::%s :: found %zu out of %zu entries at %li...\n", diff --git a/source/lib/omnitrace/library/debug.cpp b/source/lib/omnitrace/library/debug.cpp index 9af50b877f..32c426fa92 100644 --- a/source/lib/omnitrace/library/debug.cpp +++ b/source/lib/omnitrace/library/debug.cpp @@ -24,10 +24,37 @@ #include "library/runtime.hpp" #include "library/state.hpp" +#include +#include + namespace omnitrace { namespace debug { +namespace +{ +struct source_location_history +{ + std::array data = {}; + size_t size = 0; +}; + +auto& +get_source_location_history() +{ + static thread_local auto _v = source_location_history{}; + return _v; +} +} // namespace + +void +set_source_location(source_location&& _v) +{ + auto& _hist = get_source_location_history(); + auto _idx = _hist.size++; + _hist.data.at(_idx % _hist.data.size()) = _v; +} + lock::lock() : m_lk{ tim::type_mutex(), std::defer_lock } { @@ -46,5 +73,16 @@ lock::~lock() pop_thread_state(); } } + +FILE* +get_file() +{ + static FILE* _v = []() { + auto&& _fname = tim::get_env("OMNITRACE_LOG_FILE", ""); + tim::log::colorized() = _fname.empty(); + return (_fname.empty()) ? stderr : tim::filepath::fopen(_fname, "w"); + }(); + return _v; +} } // namespace debug } // namespace omnitrace diff --git a/source/lib/omnitrace/library/debug.hpp b/source/lib/omnitrace/library/debug.hpp index 27c9186b20..c005dca91e 100644 --- a/source/lib/omnitrace/library/debug.hpp +++ b/source/lib/omnitrace/library/debug.hpp @@ -71,14 +71,27 @@ get_critical_trace_debug() OMNITRACE_HOT; namespace debug { +struct source_location +{ + std::string_view function = {}; + std::string_view file = {}; + int line = 0; +}; +// +void +set_source_location(source_location&&); +// +FILE* +get_file(); +// inline void flush() { fprintf(stdout, "%s", ::tim::log::color::end()); fflush(stdout); std::cout << ::tim::log::color::end() << std::flush; - fprintf(stderr, "%s", ::tim::log::color::end()); - fflush(stderr); + fprintf(::omnitrace::debug::get_file(), "%s", ::tim::log::color::end()); + fflush(::omnitrace::debug::get_file()); std::cerr << ::tim::log::color::end() << std::flush; } // @@ -135,6 +148,16 @@ get_chars(T&& _c, std::index_sequence) # define OMNITRACE_DEBUG_THREAD_IDENTIFIER ::tim::threading::get_id() #endif +#if !defined(OMNITRACE_SOURCE_LOCATION) +# define OMNITRACE_SOURCE_LOCATION \ + ::omnitrace::debug::source_location { __PRETTY_FUNCTION__, __FILE__, __LINE__ } +#endif + +#if !defined(OMNITRACE_RECORD_SOURCE_LOCATION) +# define OMNITRACE_RECORD_SOURCE_LOCATION \ + ::omnitrace::debug::set_source_location(OMNITRACE_SOURCE_LOCATION) +#endif + #if defined(__clang__) || (__GNUC__ < 9) # define OMNITRACE_FUNCTION \ std::string{ __FUNCTION__ } \ @@ -164,7 +187,7 @@ get_chars(T&& _c, std::index_sequence) //--------------------------------------------------------------------------------------// #define OMNITRACE_FPRINTF_STDERR_COLOR(COLOR) \ - fprintf(stderr, "%s", ::tim::log::color::COLOR()) + fprintf(::omnitrace::debug::get_file(), "%s", ::tim::log::color::COLOR()) //--------------------------------------------------------------------------------------// @@ -175,10 +198,10 @@ get_chars(T&& _c, std::index_sequence) ::omnitrace::debug::flush(); \ ::omnitrace::debug::lock _lk{}; \ OMNITRACE_FPRINTF_STDERR_COLOR(info); \ - fprintf(stderr, "[omnitrace][%i][%li]%s", OMNITRACE_DEBUG_PROCESS_IDENTIFIER, \ - OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \ + OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ } @@ -189,9 +212,9 @@ get_chars(T&& _c, std::index_sequence) ::omnitrace::debug::flush(); \ ::omnitrace::debug::lock _lk{}; \ OMNITRACE_FPRINTF_STDERR_COLOR(info); \ - fprintf(stderr, "[omnitrace]%s", \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace]%s", \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ } @@ -202,11 +225,11 @@ get_chars(T&& _c, std::index_sequence) ::omnitrace::debug::flush(); \ ::omnitrace::debug::lock _lk{}; \ OMNITRACE_FPRINTF_STDERR_COLOR(info); \ - fprintf(stderr, "[omnitrace][%i][%li][%s]%s", \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \ OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ OMNITRACE_FUNCTION, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ } @@ -217,9 +240,66 @@ get_chars(T&& _c, std::index_sequence) ::omnitrace::debug::flush(); \ ::omnitrace::debug::lock _lk{}; \ OMNITRACE_FPRINTF_STDERR_COLOR(info); \ - fprintf(stderr, "[omnitrace][%s]%s", OMNITRACE_FUNCTION, \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%s]%s", OMNITRACE_FUNCTION, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ + ::omnitrace::debug::flush(); \ + } + +//--------------------------------------------------------------------------------------// + +#define OMNITRACE_CONDITIONAL_WARN(COND, ...) \ + if((COND) && ::omnitrace::config::get_debug_tid() && \ + ::omnitrace::config::get_debug_pid()) \ + { \ + ::omnitrace::debug::flush(); \ + ::omnitrace::debug::lock _lk{}; \ + OMNITRACE_FPRINTF_STDERR_COLOR(warning); \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \ + OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ + ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ + ::omnitrace::debug::flush(); \ + } + +#define OMNITRACE_CONDITIONAL_BASIC_WARN(COND, ...) \ + if((COND) && ::omnitrace::config::get_debug_tid() && \ + ::omnitrace::config::get_debug_pid()) \ + { \ + ::omnitrace::debug::flush(); \ + ::omnitrace::debug::lock _lk{}; \ + OMNITRACE_FPRINTF_STDERR_COLOR(warning); \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace]%s", \ + ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ + ::omnitrace::debug::flush(); \ + } + +#define OMNITRACE_CONDITIONAL_WARN_F(COND, ...) \ + if((COND) && ::omnitrace::config::get_debug_tid() && \ + ::omnitrace::config::get_debug_pid()) \ + { \ + ::omnitrace::debug::flush(); \ + ::omnitrace::debug::lock _lk{}; \ + OMNITRACE_FPRINTF_STDERR_COLOR(warning); \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \ + OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ + OMNITRACE_FUNCTION, \ + ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ + ::omnitrace::debug::flush(); \ + } + +#define OMNITRACE_CONDITIONAL_BASIC_WARN_F(COND, ...) \ + if((COND) && ::omnitrace::config::get_debug_tid() && \ + ::omnitrace::config::get_debug_pid()) \ + { \ + ::omnitrace::debug::flush(); \ + ::omnitrace::debug::lock _lk{}; \ + OMNITRACE_FPRINTF_STDERR_COLOR(warning); \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%s]%s", OMNITRACE_FUNCTION, \ + ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ } @@ -267,10 +347,10 @@ get_chars(T&& _c, std::index_sequence) { \ ::omnitrace::debug::flush(); \ OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \ - fprintf(stderr, "[omnitrace][%i][%li]%s", OMNITRACE_DEBUG_PROCESS_IDENTIFIER, \ - OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \ + OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ ::omnitrace::set_state(::omnitrace::State::Finalized); \ ::tim::disable_signal_detection(); \ @@ -283,9 +363,9 @@ get_chars(T&& _c, std::index_sequence) { \ ::omnitrace::debug::flush(); \ OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \ - fprintf(stderr, "[omnitrace]%s", \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace]%s", \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ ::omnitrace::set_state(::omnitrace::State::Finalized); \ ::tim::disable_signal_detection(); \ @@ -298,11 +378,11 @@ get_chars(T&& _c, std::index_sequence) { \ ::omnitrace::debug::flush(); \ OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \ - fprintf(stderr, "[omnitrace][%i][%li][%s]%s", \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \ OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \ OMNITRACE_FUNCTION, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ ::omnitrace::set_state(::omnitrace::State::Finalized); \ ::tim::disable_signal_detection(); \ @@ -315,9 +395,9 @@ get_chars(T&& _c, std::index_sequence) { \ ::omnitrace::debug::flush(); \ OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \ - fprintf(stderr, "[omnitrace][%s]%s", OMNITRACE_FUNCTION, \ + fprintf(::omnitrace::debug::get_file(), "[omnitrace][%s]%s", OMNITRACE_FUNCTION, \ ::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \ ::omnitrace::debug::flush(); \ ::omnitrace::set_state(::omnitrace::State::Finalized); \ ::tim::disable_signal_detection(); \ @@ -427,6 +507,30 @@ get_chars(T&& _c, std::index_sequence) (::omnitrace::get_verbose_env() >= LEVEL), \ __VA_ARGS__) +//--------------------------------------------------------------------------------------// +// +// Warning macros +// +//--------------------------------------------------------------------------------------// + +#define OMNITRACE_WARNING(LEVEL, ...) \ + OMNITRACE_CONDITIONAL_WARN( \ + ::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__) + +#define OMNITRACE_BASIC_WARNING(LEVEL, ...) \ + OMNITRACE_CONDITIONAL_BASIC_WARN(::omnitrace::get_debug_env() || \ + (::omnitrace::get_verbose_env() >= LEVEL), \ + __VA_ARGS__) + +#define OMNITRACE_WARNING_F(LEVEL, ...) \ + OMNITRACE_CONDITIONAL_WARN_F( \ + ::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__) + +#define OMNITRACE_BASIC_WARNING_F(LEVEL, ...) \ + OMNITRACE_CONDITIONAL_BASIC_WARN_F(::omnitrace::get_debug_env() || \ + (::omnitrace::get_verbose_env() >= LEVEL), \ + __VA_ARGS__) + //--------------------------------------------------------------------------------------// // // Basic print macros (basic means it will not provide PID/RANK or TID) and will not diff --git a/source/lib/omnitrace/library/perfetto.cpp b/source/lib/omnitrace/library/perfetto.cpp index 0649d0c793..f941727c1f 100644 --- a/source/lib/omnitrace/library/perfetto.cpp +++ b/source/lib/omnitrace/library/perfetto.cpp @@ -21,6 +21,88 @@ // SOFTWARE. #include "library/perfetto.hpp" +#include "library/config.hpp" +#include "library/tracing.hpp" + +namespace omnitrace +{ +namespace perfetto +{ +void +setup() +{ + auto args = ::perfetto::TracingInitArgs{}; + auto track_event_cfg = ::perfetto::protos::gen::TrackEventConfig{}; + auto& cfg = tracing::get_perfetto_config(); + + // environment settings + auto shmem_size_hint = get_perfetto_shmem_size_hint(); + auto buffer_size = get_perfetto_buffer_size(); + + auto _policy = + get_perfetto_fill_policy() == "discard" + ? ::perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_DISCARD + : ::perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_RING_BUFFER; + auto* buffer_config = cfg.add_buffers(); + buffer_config->set_size_kb(buffer_size); + buffer_config->set_fill_policy(_policy); + + std::set _available_categories = {}; + std::set _disabled_categories = {}; + for(auto itr : { OMNITRACE_PERFETTO_CATEGORIES }) + _available_categories.emplace(itr.name); + auto _enabled_categories = config::get_perfetto_categories(); + for(const auto& itr : _available_categories) + { + if(!_enabled_categories.empty() && _enabled_categories.count(itr) == 0) + _disabled_categories.emplace(itr); + } + + for(const auto& itr : _disabled_categories) + { + OMNITRACE_VERBOSE_F(1, "Disabling perfetto track event category: %s\n", + itr.c_str()); + track_event_cfg.add_disabled_categories(itr); + } + + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name("track_event"); // this MUST be track_event + ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString()); + + args.shmem_size_hint_kb = shmem_size_hint; + + if(get_backend() != "inprocess") args.backends |= ::perfetto::kSystemBackend; + if(get_backend() != "system") args.backends |= ::perfetto::kInProcessBackend; + + ::perfetto::Tracing::Initialize(args); + ::perfetto::TrackEvent::Register(); +} + +void +start() +{ +#if defined(CUSTOM_DATA_SOURCE) + // Add the following: + ::perfetto::DataSourceDescriptor dsd{}; + dsd.set_name("com.example.custom_data_source"); + CustomDataSource::Register(dsd); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name("com.example.custom_data_source"); + CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(::perfetto::TrackEvent::GetTraceTimeNs()); + packet->set_for_testing()->set_str("Hello world!"); + PRINT_HERE("%s", "Trace"); + }); +#endif + auto& cfg = tracing::get_perfetto_config(); + auto& tracing_session = tracing::get_perfetto_session(); + tracing_session = ::perfetto::Tracing::NewTrace(); + tracing_session->Setup(cfg); + tracing_session->StartBlocking(); +} +} // namespace perfetto +} // namespace omnitrace PERFETTO_TRACK_EVENT_STATIC_STORAGE(); diff --git a/source/lib/omnitrace/library/process_sampler.cpp b/source/lib/omnitrace/library/process_sampler.cpp index 9fc941e93d..efbfffcb5d 100644 --- a/source/lib/omnitrace/library/process_sampler.cpp +++ b/source/lib/omnitrace/library/process_sampler.cpp @@ -106,8 +106,7 @@ sampler::poll(std::atomic* _state, nsec_t _interval, promise_t* _ready) itr->sample(); get_sampler_is_sampling().store(false); if(_has_duration && _now >= _end) break; - while(_now < std::chrono::steady_clock::now()) - _now += _interval; + _now = std::chrono::steady_clock::now() + _interval; } // ensure this is always false @@ -167,16 +166,13 @@ sampler::setup() auto _freq = get_process_sampling_freq(); uint64_t _msec_freq = (1.0 / _freq) * 1.0e3; - promise_t _prom{}; - auto _fut = _prom.get_future(); polling_finished = std::make_unique(); OMNITRACE_SCOPED_SAMPLING_ON_CHILD_THREADS(false); set_state(State::PreInit); get_thread() = std::make_unique(&poll, &get_sampler_state(), - msec_t{ _msec_freq }, &_prom); - _fut.wait(); + msec_t{ _msec_freq }, nullptr); set_state(State::Active); } diff --git a/source/lib/omnitrace/library/ptl.cpp b/source/lib/omnitrace/library/ptl.cpp index b33eb1dc37..04f4cc7de4 100644 --- a/source/lib/omnitrace/library/ptl.cpp +++ b/source/lib/omnitrace/library/ptl.cpp @@ -123,7 +123,10 @@ get_thread_pool_state() void setup() -{} +{ + OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal); + (void) get_thread_pool(); +} void join() diff --git a/source/lib/omnitrace/library/rocm.cpp b/source/lib/omnitrace/library/rocm.cpp index c960ef96fc..90c55d7bb8 100644 --- a/source/lib/omnitrace/library/rocm.cpp +++ b/source/lib/omnitrace/library/rocm.cpp @@ -163,6 +163,9 @@ extern "C" bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, const char* const* failed_tool_names) { + tim::consume_parameters(table, runtime_version, failed_tool_count, + failed_tool_names); + OMNITRACE_BASIC_VERBOSE_F(2 || rocm::on_load_trace, "Loading...\n"); OMNITRACE_SCOPED_SAMPLING_ON_CHILD_THREADS(false); @@ -172,9 +175,6 @@ extern "C" roctracer_is_init() = true; OMNITRACE_BASIC_VERBOSE_F(1 || rocm::on_load_trace, "Loading ROCm tooling...\n"); - tim::consume_parameters(table, runtime_version, failed_tool_count, - failed_tool_names); - if(!config::settings_are_configured() && get_state() < State::Active) omnitrace_init_tooling_hidden(); @@ -326,9 +326,6 @@ extern "C" void OnUnload() { OMNITRACE_BASIC_VERBOSE_F(2 || rocm::on_load_trace, "Unloading...\n"); - rocm_smi::set_state(State::Finalized); - comp::roctracer::shutdown(); - comp::rocprofiler::shutdown(); omnitrace_finalize_hidden(); OMNITRACE_BASIC_VERBOSE_F(2 || rocm::on_load_trace, "Unloading... Done\n"); } diff --git a/source/lib/omnitrace/library/rocm/hsa_rsrc_factory.cpp b/source/lib/omnitrace/library/rocm/hsa_rsrc_factory.cpp index 223b49166c..004585d28e 100644 --- a/source/lib/omnitrace/library/rocm/hsa_rsrc_factory.cpp +++ b/source/lib/omnitrace/library/rocm/hsa_rsrc_factory.cpp @@ -536,7 +536,7 @@ HsaRsrcFactory::GetCpuAgentInfo(uint32_t idx, const AgentInfo** agent_info) // // @return bool true if successful, false otherwise // -bool +bool // NOLINTNEXTLINE(readability-convert-member-functions-to-static) HsaRsrcFactory::CreateQueue(const AgentInfo* agent_info, uint32_t num_pkts, hsa_queue_t** queue) { @@ -550,7 +550,7 @@ HsaRsrcFactory::CreateQueue(const AgentInfo* agent_info, uint32_t num_pkts, // @param value Initial value of signal object // @param signal Output parameter updated with handle of signal object // @return bool true if successful, false otherwise -bool +bool // NOLINTNEXTLINE(readability-convert-member-functions-to-static) HsaRsrcFactory::CreateSignal(uint32_t value, hsa_signal_t* signal) { hsa_status_t status; @@ -563,7 +563,7 @@ HsaRsrcFactory::CreateSignal(uint32_t value, hsa_signal_t* signal) // @param agent_info Agent from whose memory region to allocate // @param size Size of memory in terms of bytes // @return uint8_t* Pointer to buffer, null if allocation fails. -uint8_t* +uint8_t* // NOLINTNEXTLINE(readability-convert-member-functions-to-static) HsaRsrcFactory::AllocateLocalMemory(const AgentInfo* agent_info, size_t size) { hsa_status_t status = HSA_STATUS_ERROR; @@ -647,7 +647,7 @@ HsaRsrcFactory::AllocateCmdMemory(const AgentInfo* agent_info, size_t size) void HsaRsrcFactory::SignalWait(const hsa_signal_t& signal) const { - while(1) + while(true) { const hsa_signal_value_t signal_value = hsa_api_.hsa_signal_wait_scacquire( signal, HSA_SIGNAL_CONDITION_LT, 1, timeout_, HSA_WAIT_STATE_BLOCKED); @@ -714,7 +714,7 @@ HsaRsrcFactory::FreeMemory(void* ptr) // @param code_desc Handle of finalized Code Descriptor that could // be used to submit for execution // @return bool true if successful, false otherwise -bool +bool // NOLINTNEXTLINE(readability-convert-member-functions-to-static) HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path, const char* kernel_name, hsa_executable_t* executable, hsa_executable_symbol_t* code_desc) diff --git a/source/lib/omnitrace/library/runtime.cpp b/source/lib/omnitrace/library/runtime.cpp index 1c1db9b1f9..62c5239db8 100644 --- a/source/lib/omnitrace/library/runtime.cpp +++ b/source/lib/omnitrace/library/runtime.cpp @@ -26,6 +26,7 @@ #include "library/debug.hpp" #include "library/defines.hpp" #include "library/thread_data.hpp" +#include "library/thread_info.hpp" #include "library/utility.hpp" #include @@ -65,9 +66,18 @@ get_sampling_on_child_threads_history(int64_t _idx = utility::get_thread_index() bool& sampling_on_child_threads() { - static thread_local bool _v = get_sampling_on_child_threads_history().empty() - ? false - : get_sampling_on_child_threads_history().back(); + static const auto& _thr_info = thread_info::get(); + // if the thread is offset, disable by default + // if the global state is not active or the thread state is not enabled, disable by + // default if there is no history, disable by default (first thread) otherwise, + // inherit the last state + static thread_local bool _v = + (_thr_info) ? !_thr_info->is_offset + : (get_state() != State::Active || get_thread_state() != ThreadState::Enabled) + ? false + : (get_sampling_on_child_threads_history().empty() + ? false + : get_sampling_on_child_threads_history().back()); return _v; } } // namespace diff --git a/source/lib/omnitrace/library/sampling.cpp b/source/lib/omnitrace/library/sampling.cpp index 0218cfda90..265ae7bed4 100644 --- a/source/lib/omnitrace/library/sampling.cpp +++ b/source/lib/omnitrace/library/sampling.cpp @@ -136,7 +136,8 @@ get_signal_names(Tp&& _v) _sig_names += std::get<0>(tim::signal_settings::get_info( static_cast(itr))) + " "; - return _sig_names.substr(0, _sig_names.length() - 1); + return (_sig_names.empty()) ? _sig_names + : _sig_names.substr(0, _sig_names.length() - 1); } unique_ptr_t& @@ -418,6 +419,18 @@ shutdown() return configure(false); } +void +block_samples() +{ + trait::runtime_enabled::set(false); +} + +void +unblock_samples() +{ + trait::runtime_enabled::set(true); +} + void block_signals(std::set _signals) { diff --git a/source/lib/omnitrace/library/sampling.hpp b/source/lib/omnitrace/library/sampling.hpp index 3ad938330a..d726e00077 100644 --- a/source/lib/omnitrace/library/sampling.hpp +++ b/source/lib/omnitrace/library/sampling.hpp @@ -66,12 +66,17 @@ setup(); std::set shutdown(); +void +block_samples(); + +void +unblock_samples(); + void block_signals(std::set = {}); void unblock_signals(std::set = {}); void post_process(); - } // namespace sampling } // namespace omnitrace diff --git a/source/lib/omnitrace/library/thread_info.cpp b/source/lib/omnitrace/library/thread_info.cpp index e53cffc5e9..7d6bd14f5c 100644 --- a/source/lib/omnitrace/library/thread_info.cpp +++ b/source/lib/omnitrace/library/thread_info.cpp @@ -47,9 +47,9 @@ get_index_data(int64_t _tid) } auto -init_index_data(bool _offset = false) +init_index_data(int64_t _tid, bool _offset = false) { - auto& itr = get_index_data(utility::get_thread_index()); + auto& itr = get_index_data(_tid); if(!itr) { threading::offset_this_id(_offset); @@ -76,20 +76,20 @@ const auto unknown_thread = std::optional{}; const std::optional& thread_info::init(bool _offset) { - auto& _instances = thread_info_data_t::instances(); - auto _tid = utility::get_thread_index(); - auto _init = [&] { + static thread_local bool _once = false; + auto& _instances = thread_info_data_t::instances(); + auto _tid = utility::get_thread_index(); + + if(!_once && (_once = true)) + { threading::offset_this_id(_offset); - std::optional& _info = _instances.at(_tid); - _info = thread_info{}; - _info->is_offset = threading::offset_this_id(); - _info->index_data = init_index_data(_info->is_offset); + auto& _info = _instances.at(_tid); + _info = thread_info{}; + _info->is_offset = threading::offset_this_id(); + _info->index_data = init_index_data(_tid, _info->is_offset); _info->lifetime.first = tim::get_clock_real_now(); if(_info->is_offset) set_thread_state(ThreadState::Disabled); - }; - - static thread_local std::once_flag _once{}; - std::call_once(_once, _init); + } return _instances.at(_tid); } diff --git a/source/lib/omnitrace/library/tracing.cpp b/source/lib/omnitrace/library/tracing.cpp index 193be872a7..d254b02c65 100644 --- a/source/lib/omnitrace/library/tracing.cpp +++ b/source/lib/omnitrace/library/tracing.cpp @@ -27,11 +27,18 @@ namespace omnitrace { namespace tracing { -std::unique_ptr& -get_trace_session() +perfetto::TraceConfig& +get_perfetto_config() { - static auto _session = std::unique_ptr{}; - return _session; + static auto _v = ::perfetto::TraceConfig{}; + return _v; +} + +std::unique_ptr& +get_perfetto_session() +{ + static auto _v = std::unique_ptr{}; + return _v; } std::vector>& diff --git a/source/lib/omnitrace/library/tracing.hpp b/source/lib/omnitrace/library/tracing.hpp index c9773d1e42..40587c7acb 100644 --- a/source/lib/omnitrace/library/tracing.hpp +++ b/source/lib/omnitrace/library/tracing.hpp @@ -43,8 +43,11 @@ namespace tracing { using interval_data_instances = thread_data>; +perfetto::TraceConfig& +get_perfetto_config(); + std::unique_ptr& -get_trace_session(); +get_perfetto_session(); std::vector>& get_finalization_functions(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1d1b066b66..e87c5e9067 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -115,13 +115,13 @@ set(_attach_environment "OMNITRACE_USE_TIMEMORY=ON" "OMNITRACE_USE_SAMPLING=OFF" "OMNITRACE_USE_PROCESS_SAMPLING=ON" - "OMNITRACE_USE_CRITICAL_TRACE=ON" + "OMNITRACE_USE_CRITICAL_TRACE=OFF" "OMNITRACE_USE_OMPT=ON" "OMNITRACE_USE_KOKKOSP=ON" "OMNITRACE_TIME_OUTPUT=OFF" "OMNITRACE_USE_PID=OFF" "OMNITRACE_TIMEMORY_COMPONENTS=wall_clock,trip_count" - "${_test_openmp_env}" + "OMP_NUM_THREADS=${NUM_PROCS_REAL}" "${_test_library_path}") set(_rccl_environment @@ -213,7 +213,7 @@ function(OMNITRACE_WRITE_TEST_CONFIG _FILE _ENV) OMNITRACE_CI = ON OMNITRACE_VERBOSE = 1 OMNITRACE_DL_VERBOSE = 1 -OMNITRACE_SAMPLING_FREQ = 50 +OMNITRACE_SAMPLING_FREQ = 300 OMNITRACE_SAMPLING_DELAY = 0.05 OMNITRACE_SAMPLING_CPUS = 0-${NUM_SAMPLING_PROCS} OMNITRACE_SAMPLING_GPUS = $env:HIP_VISIBLE_DEVICES