rocm-smi and KokkosTools support (#23)
* renamed omnitrace_thread_data to thread_data
* initial implementation
* Numerous fixes and updates
- Updated timemory submodule
- Updated perfetto submodule (pulls in fixes for TRACE_EVENT)
- pthread_gotcha only after omnitrace_init_tooling
- omnitrace banner
- config settings for rocm-smi freq and devices
- critical_trace::get_entries
- OMNITRACE_BASIC_PRINT
- rocm_smi perfetto category
- redirect roctracer warnings for ROCm 4.5.0
- property specializations for rocm-smi components
- units fixes data_tracker types
- roctracer entries for pthread_create and start_thread
- omnitrace-avail defaults to settings, not components
- settings have conforming names
- settings warn about duplicates
- ptl named threads
- decreased max freq for sampler SIGALRM
- rocm-smi names thread
- rocm-smi avoids call to hipGetDeviceCount
- name roctracer activity callback threads
- fixed binary rewrite test output names
* Update lulesh example
- supports non-UVM GPU
* Lulesh tweaks + formatting
* KokkosP + Mode + Roctracer sampling deadlock fix
- kokkosp support
- omnitrace_init_library
- config::print_settings()
- config::get_mode()
- omnitrace::Mode
- omnitrace-avail improvements (removes settings)
- handle get_verbose() < 0
- disable dyninst InstrStackFrames by default
- handle perf_event_paranoid > 1 by disabling PAPI
- SIGALRM max freq to 5.0
- Name threads
- rocm-smi handles get_use_perfetto() and get_use_timemory()
- HSA_ENABLE_INTERRUPT=0 when roctracer + sampling (fixes deadlock)
* Tests, API renaming, roctracer
- disable renaming of thread 0
- verbprintf_bare
- enable dyninst merge tramp
- tweaked some omnitrace exe verbose levels
- reworked roctracer::setup and roctracer::shutdown
- rocm_smi::data::poll checks get_state()
- omnitrace_trace_finalize -> omnitrace_finalize
- omnitrace_trace_init -> omnitrace_init
- omnitrace_trace_set_env -> omnitrace_set_env
- omnitrace_trace_set_mpi -> omnitrace_set_mpi
- sampling mode does not disable timemory
- disable roctracer before shutting down rocm-smi
- lulesh tests w/ and w/o kokkosp
- lulesh tests for perfetto only
- with --dynamic-callsites --traps --allow-overlapping
- lulesh tests for timemory only
- with --stdlib --dynamic-callsites --traps --allow-overlapping
* Update timemory submodule
- fix for TIMEMORY_PROPERTY_SPECIALIZATION
* get_verbose() handling + timemory submodule update
- Findroctracer.cmake uses find_package(hsakmt)
* Stability fixes + rework roctracer + perfetto
- reworked roctracer start up
- critical_trace perfetto basic values
- perfetto sampling category
- sampler checks signals
- peak_rss in sampling
- pthread_gotcha::shutdown()
- rocm_smi::device_count()
- HSA_TOOLS_LIB is set
- HSA_ENABLE_INTERRUPT in omnitrace exe
- omnitrace exe verbosity level changes
- Avoid instrumenting Impl ns in Kokkos
- gpu::device_count prefers rocm_smi instead of hip
- ptl blocks signals
- fixed pthread_gotcha roctracer_data values
- removed runtime-instrument-sampling tests
- timemory submodule update
* cmake formatting
* timemory + roctracer updates
- fix timemory issue with papi_common
- fix timemory issue with units
- define roctracer::is_setup()
* Miscellaneous tweaks
- Disable sampling during runtime instrument
- Fixed warnings about dynamic callsites
- Fixed backtrace output when timemory disabled
- Test tweaks
* cmake-format
* omnitrace_target_compile_definitions
* timemory submodule update
* config, omnitrace, State, mpi_gotcha updates
- use OMNITRACE_THROW instead of direct throw
- is_attached()
- is_binary_rewrite()
- get_is_continuous_integration()
- get_debug_init()
- get_debug_finalize()
- max_thread_bookmarks default to 1
- State::Init
- app_thread oneTimeCode
- runtime instrumentation uses waitpid
- fixed init_names
- include main in MPI runs
- fixed sampling setup when disabled
- reworked mpi_gotcha
- disabled critical trace in transpose test
* cmake-format
* handle rocm_smi::device_count() exception
* CI timeouts
* Re-enable runtime-instrument + sampling
[ROCm/rocprofiler-systems commit: 39f17ae8b8]
This commit is contained in:
کامیت شده توسط
GitHub
والد
b4a82711d1
کامیت
4ae26e2d08
@@ -29,6 +29,12 @@ parse:
|
||||
RUN_ARGS: '*'
|
||||
ENVIRONMENT: '*'
|
||||
LABELS: '*'
|
||||
PROPERTIES: '*'
|
||||
omnitrace_target_compile_definitions:
|
||||
kwargs:
|
||||
PUBLIC: '*'
|
||||
PRIVATE: '*'
|
||||
INTERFACE: '*'
|
||||
override_spec: {}
|
||||
vartags: []
|
||||
proptags: []
|
||||
|
||||
+18
-1
@@ -9,6 +9,8 @@ on:
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
ELFUTILS_DOWNLOAD_VERSION: 0.183
|
||||
OMNITRACE_DEBUG_FINALIZE: ON
|
||||
OMNITRACE_VERBOSE: 1
|
||||
|
||||
jobs:
|
||||
ubuntu-focal:
|
||||
@@ -22,6 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Packages
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libtbb-dev libboost-{atomic,system,thread,date-time,filesystem,timer}-dev ${{ matrix.compiler }} ${{ matrix.mpi }} &&
|
||||
@@ -36,6 +39,7 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=/opt/omnitrace/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure CMake
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
cmake --version &&
|
||||
if [ -z "${{ matrix.mpi }}" ]; then USE_MPI=OFF; else USE_MPI=ON; fi &&
|
||||
@@ -102,6 +106,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Packages
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip ${{ matrix.compiler }} ${{ matrix.mpi }} &&
|
||||
@@ -116,6 +121,7 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=/opt/omnitrace/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure CMake
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
cmake --version &&
|
||||
if [ -z "${{ matrix.mpi }}" ]; then USE_MPI=OFF; else USE_MPI=ON; fi &&
|
||||
@@ -181,6 +187,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Packages
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} &&
|
||||
@@ -196,6 +203,7 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=/opt/omnitrace/lib:/opt/dyninst/lib:/opt/elfutils/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install ElfUtils
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
pushd external &&
|
||||
wget https://sourceware.org/elfutils/ftp/${ELFUTILS_DOWNLOAD_VERSION}/elfutils-${ELFUTILS_DOWNLOAD_VERSION}.tar.bz2 &&
|
||||
@@ -208,6 +216,7 @@ jobs:
|
||||
rm -rf elfutils*
|
||||
|
||||
- name: Install Dyninst
|
||||
timeout-minutes: 20
|
||||
run:
|
||||
cmake --version &&
|
||||
git submodule update --init external/dyninst &&
|
||||
@@ -222,6 +231,7 @@ jobs:
|
||||
rm -rf build
|
||||
|
||||
- name: Configure CMake
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
cmake --version &&
|
||||
cmake -B ${{ github.workspace }}/build
|
||||
@@ -284,6 +294,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Packages
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip ${{ matrix.compiler }} &&
|
||||
@@ -299,6 +310,7 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=/opt/omnitrace/lib:/opt/dyninst/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Dyninst
|
||||
timeout-minutes: 20
|
||||
run:
|
||||
cmake --version &&
|
||||
git submodule update --init external/dyninst &&
|
||||
@@ -318,6 +330,7 @@ jobs:
|
||||
rm -rf build
|
||||
|
||||
- name: Configure CMake
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
cmake --version &&
|
||||
cmake -B ${{ github.workspace }}/build
|
||||
@@ -382,6 +395,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Packages
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid &&
|
||||
sudo apt-get update &&
|
||||
@@ -389,7 +403,7 @@ jobs:
|
||||
sudo wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | sudo apt-key add - &&
|
||||
echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/${{ matrix.rocm_version }}/ ubuntu main" | sudo tee /etc/apt/sources.list.d/rocm.list &&
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} libudev-dev libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
|
||||
sudo python3 -m pip install --upgrade pip &&
|
||||
python3 -m pip install 'cmake==3.16.3'
|
||||
|
||||
@@ -402,6 +416,7 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH=/opt/omnitrace/lib:/opt/dyninst/lib:/opt/elfutils/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install ElfUtils
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
pushd external &&
|
||||
wget https://sourceware.org/elfutils/ftp/${ELFUTILS_DOWNLOAD_VERSION}/elfutils-${ELFUTILS_DOWNLOAD_VERSION}.tar.bz2 &&
|
||||
@@ -414,6 +429,7 @@ jobs:
|
||||
rm -rf elfutils*
|
||||
|
||||
- name: Install Dyninst
|
||||
timeout-minutes: 20
|
||||
run:
|
||||
cmake --version &&
|
||||
git submodule update --init external/dyninst &&
|
||||
@@ -428,6 +444,7 @@ jobs:
|
||||
rm -rf build
|
||||
|
||||
- name: Configure CMake
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
cmake --version &&
|
||||
cmake -B ${{ github.workspace }}/build
|
||||
|
||||
@@ -69,6 +69,9 @@ omnitrace_add_option(OMNITRACE_USE_MPI "Enable MPI support" OFF)
|
||||
omnitrace_add_option(OMNITRACE_USE_HIP "Enable HIP support" ON)
|
||||
omnitrace_add_option(OMNITRACE_USE_ROCTRACER "Enable roctracer support"
|
||||
${OMNITRACE_USE_HIP})
|
||||
omnitrace_add_option(
|
||||
OMNITRACE_USE_ROCM_SMI "Enable rocm-smi support for power/temp/etc. sampling"
|
||||
${OMNITRACE_USE_HIP})
|
||||
omnitrace_add_option(OMNITRACE_USE_MPI_HEADERS
|
||||
"Enable wrapping MPI functions w/o enabling MPI dependency" OFF)
|
||||
omnitrace_add_option(OMNITRACE_BUILD_DYNINST "Build dyninst from submodule" OFF)
|
||||
@@ -139,7 +142,12 @@ if(OMNITRACE_BUILD_HIDDEN_VISIBILITY)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_LTO)
|
||||
omnitrace_save_variables(LTO VARIABLES CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
endif()
|
||||
|
||||
@@ -153,10 +161,12 @@ set(library_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
|
||||
@@ -185,6 +195,9 @@ set(library_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
|
||||
${perfetto_DIR}/sdk/perfetto.h)
|
||||
|
||||
@@ -193,11 +206,13 @@ add_library(omnitrace-library SHARED ${library_sources} ${library_headers})
|
||||
if(OMNITRACE_USE_ROCTRACER)
|
||||
target_sources(
|
||||
omnitrace-library
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp)
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_USE_ROCM_SMI)
|
||||
target_sources(omnitrace-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
|
||||
endif()
|
||||
|
||||
target_include_directories(omnitrace-library SYSTEM PRIVATE ${perfetto_DIR}/sdk)
|
||||
@@ -214,6 +229,7 @@ target_link_libraries(
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
|
||||
$<BUILD_INTERFACE:timemory::timemory-headers>
|
||||
@@ -285,6 +301,11 @@ set_target_properties(
|
||||
"\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/timemory/libunwind:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/dyninst-tpls/lib"
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES "^(DEBUG|Debug)")
|
||||
string(REPLACE " " ";" _FLAGS "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
target_compile_options(omnitrace-exe PRIVATE ${_FLAGS})
|
||||
endif()
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-exe
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
@@ -320,6 +341,10 @@ install(
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_BUILD_LTO)
|
||||
omnitrace_restore_variables(LTO VARIABLES CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
@@ -457,6 +457,9 @@ endfunction()
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
function(OMNITRACE_TARGET_COMPILE_DEFINITIONS _TARG _VIS)
|
||||
foreach(_DEF ${ARGN})
|
||||
if(NOT "${_DEF}" MATCHES "[A-Za-z_]+=.*" AND "${_DEF}" MATCHES "^OMNITRACE_")
|
||||
set(_DEF "${_DEF}=1")
|
||||
endif()
|
||||
target_compile_definitions(${_TARG} ${_VIS} $<$<COMPILE_LANGUAGE:CXX>:${_DEF}>)
|
||||
if(CMAKE_CUDA_COMPILER_IS_NVIDIA)
|
||||
target_compile_definitions(${_TARG} ${_VIS}
|
||||
|
||||
@@ -42,7 +42,8 @@ find_program(OMNITRACE_CLANG_FORMAT_EXE NAMES clang-format-11 clang-format-mp-11
|
||||
|
||||
if(OMNITRACE_CLANG_FORMAT_EXE)
|
||||
file(GLOB_RECURSE sources ${PROJECT_SOURCE_DIR}/src/*.cpp)
|
||||
file(GLOB_RECURSE headers ${PROJECT_SOURCE_DIR}/include/*.hpp)
|
||||
file(GLOB_RECURSE headers ${PROJECT_SOURCE_DIR}/include/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/*.hpp.in)
|
||||
file(GLOB_RECURSE examples ${PROJECT_SOURCE_DIR}/examples/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/examples/*.hpp)
|
||||
file(GLOB_RECURSE external ${PROJECT_SOURCE_DIR}/examples/lulesh/external/*.cpp
|
||||
|
||||
@@ -9,7 +9,7 @@ include(FindPackageHandleStandardArgs)
|
||||
find_path(
|
||||
MPI_HEADERS_INCLUDE_DIR
|
||||
NAMES mpi.h
|
||||
PATH_SUFFIXES include include/mpich include/openmpi mpich openmpi
|
||||
PATH_SUFFIXES include/openmpi openmpi include include/mpich mpich
|
||||
HINTS ${MPI_ROOT_DIR}
|
||||
PATHS ${MPI_ROOT_DIR})
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying file
|
||||
# Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
# set(_ROCM_PATHS $ENV{ROCM_HOME} /opt/rocm)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_path(
|
||||
rocm-smi_ROOT_DIR
|
||||
NAMES include/rocm_smi/rocm_smi.h
|
||||
HINTS ${_ROCM_PATHS}
|
||||
PATHS ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES rocm_smi)
|
||||
|
||||
mark_as_advanced(rocm-smi_ROOT_DIR)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_path(
|
||||
rocm-smi_INCLUDE_DIR
|
||||
NAMES rocm_smi/rocm_smi.h
|
||||
HINTS ${rocm-smi_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATHS ${rocm-smi_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES rocm_smi/include rocm_smi)
|
||||
|
||||
mark_as_advanced(rocm-smi_INCLUDE_DIR)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_library(
|
||||
rocm-smi_LIBRARY
|
||||
NAMES rocm_smi64 rocm_smi
|
||||
HINTS ${rocm-smi_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATHS ${rocm-smi_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES rocm_smi/lib rocm_smi/lib64 lib lib64)
|
||||
|
||||
if(rocm-smi_LIBRARY)
|
||||
get_filename_component(rocm-smi_LIBRARY_DIR "${rocm-smi_LIBRARY}" PATH CACHE)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(rocm-smi_LIBRARY)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_package_handle_standard_args(rocm-smi DEFAULT_MSG rocm-smi_ROOT_DIR
|
||||
rocm-smi_INCLUDE_DIR rocm-smi_LIBRARY)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
if(rocm-smi_FOUND)
|
||||
add_library(rocm-smi::rocm-smi INTERFACE IMPORTED)
|
||||
add_library(rocm-smi::roctx INTERFACE IMPORTED)
|
||||
set(rocm-smi_INCLUDE_DIRS ${rocm-smi_INCLUDE_DIR})
|
||||
set(rocm-smi_LIBRARIES ${rocm-smi_LIBRARY})
|
||||
set(rocm-smi_LIBRARY_DIRS ${rocm-smi_LIBRARY_DIR})
|
||||
|
||||
target_include_directories(rocm-smi::rocm-smi INTERFACE ${rocm-smi_INCLUDE_DIR})
|
||||
target_link_libraries(rocm-smi::rocm-smi INTERFACE ${rocm-smi_LIBRARY})
|
||||
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
unset(_ROCM_PATHS)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
@@ -61,18 +61,25 @@ find_library(
|
||||
PATHS ${roctracer_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES lib lib64)
|
||||
|
||||
find_library(
|
||||
roctracer_hsakmt_LIBRARY
|
||||
NAMES hsakmt
|
||||
HINTS ${roctracer_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATHS ${roctracer_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES lib lib64)
|
||||
find_package(hsakmt)
|
||||
if(hsakmt_FOUND)
|
||||
set(roctracer_hsakmt_LIBRARY
|
||||
hsakmt::hsakmt
|
||||
CACHE STRING "Imported hsakmt target")
|
||||
else()
|
||||
find_library(
|
||||
roctracer_hsakmt_LIBRARY
|
||||
NAMES hsakmt
|
||||
HINTS ${roctracer_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATHS ${roctracer_ROOT_DIR} ${_ROCM_PATHS}
|
||||
PATH_SUFFIXES lib lib64)
|
||||
endif()
|
||||
|
||||
if(roctracer_LIBRARY)
|
||||
get_filename_component(roctracer_LIBRARY_DIR "${roctracer_LIBRARY}" PATH CACHE)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(roctracer_LIBRARY roctracer_roctx_LIBRARY)
|
||||
mark_as_advanced(roctracer_LIBRARY roctracer_roctx_LIBRARY roctracer_hsakmt_LIBRARY)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ omnitrace_add_interface_library(
|
||||
omnitrace_add_interface_library(omnitrace-hip "Provides flags and libraries for HIP")
|
||||
omnitrace_add_interface_library(omnitrace-roctracer
|
||||
"Provides flags and libraries for roctracer")
|
||||
omnitrace_add_interface_library(omnitrace-rocm-smi
|
||||
"Provides flags and libraries for rocm-smi")
|
||||
omnitrace_add_interface_library(omnitrace-mpi "Provides MPI or MPI headers")
|
||||
omnitrace_add_interface_library(omnitrace-ptl "Enables PTL support (tasking)")
|
||||
|
||||
@@ -60,7 +62,7 @@ endif()
|
||||
if(OMNITRACE_USE_HIP)
|
||||
list(APPEND CMAKE_PREFIX_PATH /opt/rocm)
|
||||
find_package(hip ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
target_compile_definitions(omnitrace-hip INTERFACE OMNITRACE_USE_HIP)
|
||||
omnitrace_target_compile_definitions(omnitrace-hip INTERFACE OMNITRACE_USE_HIP)
|
||||
target_link_libraries(omnitrace-hip INTERFACE hip::host)
|
||||
endif()
|
||||
|
||||
@@ -73,12 +75,28 @@ endif()
|
||||
if(OMNITRACE_USE_ROCTRACER)
|
||||
list(APPEND CMAKE_PREFIX_PATH /opt/rocm)
|
||||
find_package(roctracer ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
target_compile_definitions(omnitrace-roctracer INTERFACE OMNITRACE_USE_ROCTRACER)
|
||||
omnitrace_target_compile_definitions(omnitrace-roctracer
|
||||
INTERFACE OMNITRACE_USE_ROCTRACER)
|
||||
target_link_libraries(omnitrace-roctracer INTERFACE roctracer::roctracer
|
||||
omnitrace::omnitrace-hip)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${roctracer_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# rocm-smmi
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_ROCM_SMI)
|
||||
list(APPEND CMAKE_PREFIX_PATH /opt/rocm)
|
||||
find_package(rocm-smi ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
omnitrace_target_compile_definitions(omnitrace-rocm-smi
|
||||
INTERFACE OMNITRACE_USE_ROCM_SMI)
|
||||
target_link_libraries(omnitrace-rocm-smi INTERFACE rocm-smi::rocm-smi)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${rocm-smi_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# MPI
|
||||
@@ -90,8 +108,8 @@ if(OMNITRACE_USE_MPI)
|
||||
target_link_libraries(omnitrace-mpi INTERFACE MPI::MPI_C MPI::MPI_CXX)
|
||||
elseif(OMNITRACE_USE_MPI_HEADERS)
|
||||
find_package(MPI-Headers ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
target_compile_definitions(omnitrace-mpi INTERFACE TIMEMORY_USE_MPI_HEADERS
|
||||
OMNITRACE_USE_MPI_HEADERS)
|
||||
omnitrace_target_compile_definitions(
|
||||
omnitrace-mpi INTERFACE TIMEMORY_USE_MPI_HEADERS OMNITRACE_USE_MPI_HEADERS)
|
||||
target_link_libraries(omnitrace-mpi INTERFACE MPI::MPI_HEADERS)
|
||||
endif()
|
||||
|
||||
@@ -143,7 +161,7 @@ if(OMNITRACE_BUILD_DYNINST)
|
||||
)
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
target_compile_definitions(
|
||||
omnitrace_target_compile_definitions(
|
||||
omnitrace-dyninst
|
||||
INTERFACE
|
||||
DYNINST_API_RT="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}:$<TARGET_FILE_DIR:Dyninst::dyninstAPI_RT>:${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:Dyninst::dyninstAPI_RT>:$<TARGET_FILE:Dyninst::dyninstAPI_RT>"
|
||||
@@ -163,7 +181,7 @@ else()
|
||||
PATH_SUFFIXES lib)
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
target_compile_definitions(
|
||||
omnitrace_target_compile_definitions(
|
||||
omnitrace-dyninst INTERFACE DYNINST_API_RT="${OMNITRACE_DYNINST_API_RT}")
|
||||
endif()
|
||||
|
||||
@@ -214,7 +232,7 @@ else()
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
target_compile_definitions(
|
||||
omnitrace_target_compile_definitions(
|
||||
omnitrace-dyninst INTERFACE DYNINST_API_RT="${OMNITRACE_DYNINST_API_RT}")
|
||||
endif()
|
||||
|
||||
@@ -253,7 +271,8 @@ else()
|
||||
target_include_directories(
|
||||
omnitrace-dyninst SYSTEM INTERFACE ${TBB_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}
|
||||
${DYNINST_HEADER_DIR})
|
||||
target_compile_definitions(omnitrace-dyninst INTERFACE omnitrace_USE_DYNINST)
|
||||
omnitrace_target_compile_definitions(omnitrace-dyninst
|
||||
INTERFACE OMNITRACE_USE_DYNINST)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -4,7 +4,16 @@ project(lulesh LANGUAGES C CXX)
|
||||
|
||||
list(INSERT CMAKE_MODULE_PATH 0 ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
||||
|
||||
add_subdirectory(external)
|
||||
option(LULESH_BUILD_KOKKOS "Build Kokkos from submodule" ON)
|
||||
if(LULESH_BUILD_KOKKOS)
|
||||
add_subdirectory(external)
|
||||
if(LULESH_USE_CUDA OR LULESH_USE_HIP)
|
||||
kokkos_compilation(PROJECT)
|
||||
endif()
|
||||
else()
|
||||
find_package(Kokkos REQUIRED COMPONENTS separable_compilation)
|
||||
kokkos_compilation(PROJECT)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
@@ -14,7 +23,9 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
CACHE STRING "CMake build type" FORCE)
|
||||
endif()
|
||||
|
||||
if(DEFINED OMNITRACE_USE_MPI)
|
||||
if(DEFINED OMNITRACE_USE_MPI
|
||||
AND NOT LULESH_USE_CUDA
|
||||
AND NOT LULESH_USE_HIP)
|
||||
option(LULESH_USE_MPI "Enable MPI" ${OMNITRACE_USE_MPI})
|
||||
else()
|
||||
option(LULESH_USE_MPI "Enable MPI" OFF)
|
||||
|
||||
+16
-11
@@ -1,22 +1,27 @@
|
||||
# include(Utilities)
|
||||
|
||||
option(LULESH_USE_CUDA "Enable Kokkos CUDA backend for lulesh" OFF)
|
||||
option(LULESH_USE_HIP "Enable Kokkos HIP backend for lulesh" OFF)
|
||||
|
||||
set(Kokkos_ENABLE_SERIAL
|
||||
ON
|
||||
CACHE BOOL "Enable Serial")
|
||||
set(Kokkos_ENABLE_OPENMP
|
||||
ON
|
||||
CACHE BOOL "Enable OpenMP")
|
||||
if(USE_CUDA)
|
||||
|
||||
if(LULESH_USE_CUDA)
|
||||
set(Kokkos_ENABLE_CUDA
|
||||
ON
|
||||
CACHE BOOL "Enable CUDA")
|
||||
set(Kokkos_ENABLE_CUDA_UVM
|
||||
ON
|
||||
CACHE BOOL "Enable CUDA UVM")
|
||||
CACHE BOOL "Enable CUDA" FORCE)
|
||||
set(Kokkos_ENABLE_CUDA_LAMBDA
|
||||
ON
|
||||
CACHE BOOL "Enable CUDA UVM")
|
||||
set(Kokkos_ENABLE_CUDA_CONSTEXPR
|
||||
CACHE BOOL "Enable CUDA lambda support" FORCE)
|
||||
elseif(LULESH_USE_HIP)
|
||||
set(Kokkos_ENABLE_HIP
|
||||
ON
|
||||
CACHE BOOL "Enable CUDA UVM")
|
||||
CACHE BOOL "Enable HIP" FORCE)
|
||||
else()
|
||||
set(Kokkos_ENABLE_OPENMP
|
||||
ON
|
||||
CACHE BOOL "Enable OpenMP")
|
||||
endif()
|
||||
|
||||
checkout_git_submodule(
|
||||
|
||||
+1
-1
Submodule projects/rocprofiler-systems/examples/lulesh/external/kokkos updated: 56468253ef...698a67731a
@@ -9,8 +9,8 @@
|
||||
/* Comm Routines */
|
||||
|
||||
# define ALLOW_UNPACKED_PLANE false
|
||||
# define ALLOW_UNPACKED_ROW false
|
||||
# define ALLOW_UNPACKED_COL false
|
||||
# define ALLOW_UNPACKED_ROW false
|
||||
# define ALLOW_UNPACKED_COL false
|
||||
|
||||
/*
|
||||
There are coherence issues for packing and unpacking message
|
||||
@@ -59,8 +59,7 @@ void
|
||||
CommRecv(Domain& domain, int msgType, Index_t xferFields, Index_t dx, Index_t dy,
|
||||
Index_t dz, bool doRecv, bool planeOnly)
|
||||
{
|
||||
if(domain.numRanks() == 1)
|
||||
return;
|
||||
if(domain.numRanks() == 1) return;
|
||||
|
||||
/* post recieve buffers for all incoming messages */
|
||||
int myRank;
|
||||
@@ -366,8 +365,7 @@ void
|
||||
CommSend(Domain& domain, int msgType, Index_t xferFields, Domain_member* fieldData,
|
||||
Index_t dx, Index_t dy, Index_t dz, bool doSend, bool planeOnly)
|
||||
{
|
||||
if(domain.numRanks() == 1)
|
||||
return;
|
||||
if(domain.numRanks() == 1) return;
|
||||
|
||||
/* post recieve buffers for all incoming messages */
|
||||
int myRank;
|
||||
@@ -926,8 +924,7 @@ CommSend(Domain& domain, int msgType, Index_t xferFields, Domain_member* fieldDa
|
||||
void
|
||||
CommSBN(Domain& domain, int xferFields, Domain_member* fieldData)
|
||||
{
|
||||
if(domain.numRanks() == 1)
|
||||
return;
|
||||
if(domain.numRanks() == 1) return;
|
||||
|
||||
/* summation order should be from smallest value to largest */
|
||||
/* or we could try out kahan summation! */
|
||||
@@ -1405,8 +1402,7 @@ CommSBN(Domain& domain, int xferFields, Domain_member* fieldData)
|
||||
void
|
||||
CommSyncPosVel(Domain& domain)
|
||||
{
|
||||
if(domain.numRanks() == 1)
|
||||
return;
|
||||
if(domain.numRanks() == 1) return;
|
||||
|
||||
int myRank;
|
||||
bool doRecv = false;
|
||||
@@ -1893,8 +1889,7 @@ CommSyncPosVel(Domain& domain)
|
||||
void
|
||||
CommMonoQ(Domain& domain)
|
||||
{
|
||||
if(domain.numRanks() == 1)
|
||||
return;
|
||||
if(domain.numRanks() == 1) return;
|
||||
|
||||
int myRank;
|
||||
Index_t xferFields = 3; /* delv_xi, delv_eta, delv_zeta */
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
#if USE_MPI
|
||||
# include <mpi.h>
|
||||
#endif
|
||||
#if _OPENMP
|
||||
# include <omp.h>
|
||||
#endif
|
||||
#include "lulesh.h"
|
||||
#include <cstdlib>
|
||||
#include <limits.h>
|
||||
@@ -13,12 +10,12 @@
|
||||
#include <string.h>
|
||||
|
||||
static KOKKOS_INLINE_FUNCTION Real_t
|
||||
CalcElemVolume(const Real_t x0, const Real_t x1, const Real_t x2, const Real_t x3,
|
||||
const Real_t x4, const Real_t x5, const Real_t x6, const Real_t x7,
|
||||
const Real_t y0, const Real_t y1, const Real_t y2, const Real_t y3,
|
||||
const Real_t y4, const Real_t y5, const Real_t y6, const Real_t y7,
|
||||
const Real_t z0, const Real_t z1, const Real_t z2, const Real_t z3,
|
||||
const Real_t z4, const Real_t z5, const Real_t z6, const Real_t z7)
|
||||
CalcElemVolume(const Real_t x0, const Real_t x1, const Real_t x2, const Real_t x3,
|
||||
const Real_t x4, const Real_t x5, const Real_t x6, const Real_t x7,
|
||||
const Real_t y0, const Real_t y1, const Real_t y2, const Real_t y3,
|
||||
const Real_t y4, const Real_t y5, const Real_t y6, const Real_t y7,
|
||||
const Real_t z0, const Real_t z1, const Real_t z2, const Real_t z3,
|
||||
const Real_t z4, const Real_t z5, const Real_t z6, const Real_t z7)
|
||||
{
|
||||
Real_t twelveth = Real_t(1.0) / Real_t(12.0);
|
||||
|
||||
@@ -122,15 +119,15 @@ Domain::Domain(Int_t numRanks, Index_t colLoc, Index_t rowLoc, Index_t planeLoc,
|
||||
, m_dvovmax(Real_t(0.1))
|
||||
, m_refdens(Real_t(1.0))
|
||||
,
|
||||
//
|
||||
// set pointers to (potentially) "new'd" arrays to null to
|
||||
// simplify deallocation.
|
||||
//
|
||||
m_regNumList(0)
|
||||
, m_nodeElemStart(0)
|
||||
, m_nodeElemCornerList(0)
|
||||
, m_regElemSize(0)
|
||||
, m_regElemlist(0)
|
||||
//
|
||||
// set pointers to (potentially) "new'd" arrays to null to
|
||||
// simplify deallocation.
|
||||
//
|
||||
m_regNumList(0)
|
||||
// m_nodeElemStart(0),
|
||||
// m_nodeElemCornerList(0),
|
||||
// m_regElemSize(0),
|
||||
// m_regElemlist(0)
|
||||
#if USE_MPI
|
||||
, commDataSend(0)
|
||||
, commDataRecv(0)
|
||||
@@ -171,48 +168,27 @@ Domain::Domain(Int_t numRanks, Index_t colLoc, Index_t rowLoc, Index_t planeLoc,
|
||||
SetupCommBuffers(edgeNodes);
|
||||
|
||||
// Basic Field Initialization
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
e(i) = Real_t(0.0);
|
||||
p(i) = Real_t(0.0);
|
||||
q(i) = Real_t(0.0);
|
||||
ss(i) = Real_t(0.0);
|
||||
}
|
||||
Kokkos::deep_copy(m_e, 0.0);
|
||||
Kokkos::deep_copy(m_p, 0.0);
|
||||
Kokkos::deep_copy(m_q, 0.0);
|
||||
Kokkos::deep_copy(m_ss, 0.0);
|
||||
|
||||
// Note - v initializes to 1.0, not 0.0!
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
v(i) = Real_t(1.0);
|
||||
}
|
||||
Kokkos::deep_copy(m_v, 1.0);
|
||||
|
||||
for(Index_t i = 0; i < numNode(); ++i)
|
||||
{
|
||||
xd(i) = Real_t(0.0);
|
||||
yd(i) = Real_t(0.0);
|
||||
zd(i) = Real_t(0.0);
|
||||
}
|
||||
Kokkos::deep_copy(m_xd, 0.0);
|
||||
Kokkos::deep_copy(m_yd, 0.0);
|
||||
Kokkos::deep_copy(m_zd, 0.0);
|
||||
|
||||
for(Index_t i = 0; i < numNode(); ++i)
|
||||
{
|
||||
xdd(i) = Real_t(0.0);
|
||||
ydd(i) = Real_t(0.0);
|
||||
zdd(i) = Real_t(0.0);
|
||||
}
|
||||
Kokkos::deep_copy(m_xdd, 0.0);
|
||||
Kokkos::deep_copy(m_ydd, 0.0);
|
||||
Kokkos::deep_copy(m_zdd, 0.0);
|
||||
|
||||
for(Index_t i = 0; i < numNode(); ++i)
|
||||
{
|
||||
nodalMass(i) = Real_t(0.0);
|
||||
}
|
||||
Kokkos::deep_copy(m_nodalMass, 0.0);
|
||||
|
||||
BuildMesh(nx, edgeNodes, edgeElems);
|
||||
|
||||
#if _OPENMP
|
||||
SetupThreadSupportStructures();
|
||||
#else
|
||||
// These arrays are not used if we're not threaded
|
||||
m_nodeElemStart = NULL;
|
||||
m_nodeElemCornerList = NULL;
|
||||
#endif
|
||||
|
||||
// Setup region index sets. For now, these are constant sized
|
||||
// throughout the run, but could be changed every cycle to
|
||||
@@ -247,30 +223,46 @@ Domain::Domain(Int_t numRanks, Index_t colLoc, Index_t rowLoc, Index_t planeLoc,
|
||||
time() = Real_t(0.);
|
||||
cycle() = Int_t(0);
|
||||
|
||||
// With C++17 requirement we could just run this on the device
|
||||
// without creating temporary host copies
|
||||
auto h_nodelist = Kokkos::create_mirror_view(m_nodelist);
|
||||
auto h_x = Kokkos::create_mirror_view(m_x);
|
||||
auto h_y = Kokkos::create_mirror_view(m_y);
|
||||
auto h_z = Kokkos::create_mirror_view(m_z);
|
||||
auto h_volo = Kokkos::create_mirror_view(m_volo);
|
||||
auto h_elemMass = Kokkos::create_mirror_view(m_elemMass);
|
||||
auto h_nodalMass = Kokkos::create_mirror_view(m_nodalMass);
|
||||
Kokkos::deep_copy(h_nodelist, m_nodelist);
|
||||
Kokkos::deep_copy(h_x, m_x);
|
||||
Kokkos::deep_copy(h_y, m_y);
|
||||
Kokkos::deep_copy(h_z, m_z);
|
||||
// initialize field data
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
Real_t x_local[8], y_local[8], z_local[8];
|
||||
Index_t* elemToNode = nodelist(i);
|
||||
Real_t x_local[8], y_local[8], z_local[8];
|
||||
for(Index_t lnode = 0; lnode < 8; ++lnode)
|
||||
{
|
||||
Index_t gnode = elemToNode[lnode];
|
||||
x_local[lnode] = x(gnode);
|
||||
y_local[lnode] = y(gnode);
|
||||
z_local[lnode] = z(gnode);
|
||||
Index_t gnode = h_nodelist(i, lnode);
|
||||
x_local[lnode] = h_x(gnode);
|
||||
y_local[lnode] = h_y(gnode);
|
||||
z_local[lnode] = h_z(gnode);
|
||||
}
|
||||
|
||||
// volume calculations
|
||||
Real_t volume = CalcElemVolume(x_local, y_local, z_local);
|
||||
volo(i) = volume;
|
||||
elemMass(i) = volume;
|
||||
h_volo(i) = volume;
|
||||
h_elemMass(i) = volume;
|
||||
for(Index_t j = 0; j < 8; ++j)
|
||||
{
|
||||
Index_t idx = elemToNode[j];
|
||||
nodalMass(idx) += volume / Real_t(8.0);
|
||||
Index_t idx = h_nodelist(i, j);
|
||||
h_nodalMass(idx) += volume / Real_t(8.0);
|
||||
}
|
||||
}
|
||||
|
||||
Kokkos::deep_copy(m_volo, h_volo);
|
||||
Kokkos::deep_copy(m_elemMass, h_elemMass);
|
||||
Kokkos::deep_copy(m_nodalMass, h_nodalMass);
|
||||
|
||||
// deposit initial energy
|
||||
// An energy of 3.948746e+7 is correct for a problem with
|
||||
// 45 zones along a side - we need to scale it
|
||||
@@ -281,10 +273,11 @@ Domain::Domain(Int_t numRanks, Index_t colLoc, Index_t rowLoc, Index_t planeLoc,
|
||||
{
|
||||
// Dump into the first zone (which we know is in the corner)
|
||||
// of the domain that sits at the origin
|
||||
e(0) = einit;
|
||||
Kokkos::deep_copy(Kokkos::subview(m_e, 0), einit);
|
||||
// e(0) = einit;
|
||||
}
|
||||
// set initial deltatime base on analytic CFL calculation
|
||||
deltatime() = (Real_t(.5) * cbrt(volo(0))) / sqrt(Real_t(2.0) * einit);
|
||||
deltatime() = (Real_t(.5) * cbrt(h_volo(0))) / sqrt(Real_t(2.0) * einit);
|
||||
|
||||
} // End constructor
|
||||
|
||||
@@ -315,6 +308,10 @@ Domain::BuildMesh(Int_t nx, Int_t edgeNodes, Int_t edgeElems)
|
||||
{
|
||||
Index_t meshEdgeElems = m_tp * nx;
|
||||
|
||||
auto h_x = Kokkos::create_mirror_view(m_x);
|
||||
auto h_y = Kokkos::create_mirror_view(m_y);
|
||||
auto h_z = Kokkos::create_mirror_view(m_z);
|
||||
|
||||
// initialize nodal coordinates
|
||||
Index_t nidx = 0;
|
||||
Real_t tz = Real_t(1.125) * Real_t(m_planeLoc * nx) / Real_t(meshEdgeElems);
|
||||
@@ -326,9 +323,9 @@ Domain::BuildMesh(Int_t nx, Int_t edgeNodes, Int_t edgeElems)
|
||||
Real_t tx = Real_t(1.125) * Real_t(m_colLoc * nx) / Real_t(meshEdgeElems);
|
||||
for(Index_t col = 0; col < edgeNodes; ++col)
|
||||
{
|
||||
x(nidx) = tx;
|
||||
y(nidx) = ty;
|
||||
z(nidx) = tz;
|
||||
h_x(nidx) = tx;
|
||||
h_y(nidx) = ty;
|
||||
h_z(nidx) = tz;
|
||||
++nidx;
|
||||
// tx += ds ; // may accumulate roundoff...
|
||||
tx = Real_t(1.125) * Real_t(m_colLoc * nx + col + 1) /
|
||||
@@ -341,6 +338,11 @@ Domain::BuildMesh(Int_t nx, Int_t edgeNodes, Int_t edgeElems)
|
||||
tz = Real_t(1.125) * Real_t(m_planeLoc * nx + plane + 1) / Real_t(meshEdgeElems);
|
||||
}
|
||||
|
||||
Kokkos::deep_copy(m_x, h_x);
|
||||
Kokkos::deep_copy(m_y, h_y);
|
||||
Kokkos::deep_copy(m_z, h_z);
|
||||
|
||||
auto h_nodelist = Kokkos::create_mirror_view(m_nodelist);
|
||||
// embed hexehedral elements in nodal point lattice
|
||||
Index_t zidx = 0;
|
||||
nidx = 0;
|
||||
@@ -350,15 +352,14 @@ Domain::BuildMesh(Int_t nx, Int_t edgeNodes, Int_t edgeElems)
|
||||
{
|
||||
for(Index_t col = 0; col < edgeElems; ++col)
|
||||
{
|
||||
Index_t* localNode = nodelist(zidx);
|
||||
localNode[0] = nidx;
|
||||
localNode[1] = nidx + 1;
|
||||
localNode[2] = nidx + edgeNodes + 1;
|
||||
localNode[3] = nidx + edgeNodes;
|
||||
localNode[4] = nidx + edgeNodes * edgeNodes;
|
||||
localNode[5] = nidx + edgeNodes * edgeNodes + 1;
|
||||
localNode[6] = nidx + edgeNodes * edgeNodes + edgeNodes + 1;
|
||||
localNode[7] = nidx + edgeNodes * edgeNodes + edgeNodes;
|
||||
h_nodelist(zidx, 0) = nidx;
|
||||
h_nodelist(zidx, 1) = nidx + 1;
|
||||
h_nodelist(zidx, 2) = nidx + edgeNodes + 1;
|
||||
h_nodelist(zidx, 3) = nidx + edgeNodes;
|
||||
h_nodelist(zidx, 4) = nidx + edgeNodes * edgeNodes;
|
||||
h_nodelist(zidx, 5) = nidx + edgeNodes * edgeNodes + 1;
|
||||
h_nodelist(zidx, 6) = nidx + edgeNodes * edgeNodes + edgeNodes + 1;
|
||||
h_nodelist(zidx, 7) = nidx + edgeNodes * edgeNodes + edgeNodes;
|
||||
++zidx;
|
||||
++nidx;
|
||||
}
|
||||
@@ -366,6 +367,7 @@ Domain::BuildMesh(Int_t nx, Int_t edgeNodes, Int_t edgeElems)
|
||||
}
|
||||
nidx += edgeNodes;
|
||||
}
|
||||
Kokkos::deep_copy(m_nodelist, h_nodelist);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -373,32 +375,31 @@ void
|
||||
Domain::SetupThreadSupportStructures()
|
||||
{
|
||||
// set up node-centered indexing of elements
|
||||
Index_t* nodeElemCount = Allocate<Index_t>(numNode());
|
||||
|
||||
for(Index_t i = 0; i < numNode(); ++i)
|
||||
{
|
||||
nodeElemCount[i] = 0;
|
||||
}
|
||||
Kokkos::View<Index_t*, Kokkos::HostSpace> nodeElemCount("nodeElemCount", numNode());
|
||||
auto h_nodelist = Kokkos::create_mirror_view(m_nodelist);
|
||||
Kokkos::deep_copy(h_nodelist, m_nodelist);
|
||||
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
Index_t* nl = nodelist(i);
|
||||
for(Index_t j = 0; j < 8; ++j)
|
||||
{
|
||||
++(nodeElemCount[nl[j]]);
|
||||
++(nodeElemCount[h_nodelist(i, j)]);
|
||||
}
|
||||
}
|
||||
|
||||
m_nodeElemStart = Allocate<Index_t>(numNode() + 1);
|
||||
m_nodeElemStart = Kokkos::View<Index_t*>("m_nodeElemStart", numNode() + 1);
|
||||
auto h_nodeElemStart = Kokkos::create_mirror_view(m_nodeElemStart);
|
||||
|
||||
m_nodeElemStart[0] = 0;
|
||||
h_nodeElemStart[0] = 0;
|
||||
|
||||
for(Index_t i = 1; i <= numNode(); ++i)
|
||||
{
|
||||
m_nodeElemStart[i] = m_nodeElemStart[i - 1] + nodeElemCount[i - 1];
|
||||
h_nodeElemStart[i] = h_nodeElemStart[i - 1] + nodeElemCount[i - 1];
|
||||
}
|
||||
|
||||
m_nodeElemCornerList = Allocate<Index_t>(m_nodeElemStart[numNode()]);
|
||||
m_nodeElemCornerList =
|
||||
Kokkos::View<Index_t*>("nodeElemCornerList", h_nodeElemStart[numNode()]);
|
||||
auto h_nodeElemCornerList = Kokkos::create_mirror_view(m_nodeElemCornerList);
|
||||
|
||||
for(Index_t i = 0; i < numNode(); ++i)
|
||||
{
|
||||
@@ -407,21 +408,20 @@ Domain::SetupThreadSupportStructures()
|
||||
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
Index_t* nl = nodelist(i);
|
||||
for(Index_t j = 0; j < 8; ++j)
|
||||
{
|
||||
Index_t m = nl[j];
|
||||
Index_t m = h_nodelist(i, j);
|
||||
Index_t k = i * 8 + j;
|
||||
Index_t offset = m_nodeElemStart[m] + nodeElemCount[m];
|
||||
m_nodeElemCornerList[offset] = k;
|
||||
Index_t offset = h_nodeElemStart[m] + nodeElemCount[m];
|
||||
h_nodeElemCornerList[offset] = k;
|
||||
++(nodeElemCount[m]);
|
||||
}
|
||||
}
|
||||
|
||||
Index_t clSize = m_nodeElemStart[numNode()];
|
||||
Index_t clSize = h_nodeElemStart[numNode()];
|
||||
for(Index_t i = 0; i < clSize; ++i)
|
||||
{
|
||||
Index_t clv = m_nodeElemCornerList[i];
|
||||
Index_t clv = h_nodeElemCornerList[i];
|
||||
if((clv < 0) || (clv > numElem() * 8))
|
||||
{
|
||||
fprintf(
|
||||
@@ -434,8 +434,8 @@ Domain::SetupThreadSupportStructures()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Release<Index_t>(&nodeElemCount);
|
||||
Kokkos::deep_copy(m_nodeElemCornerList, h_nodeElemCornerList);
|
||||
Kokkos::deep_copy(m_nodeElemStart, h_nodeElemStart);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -486,12 +486,9 @@ Domain::SetupCommBuffers(Int_t edgeNodes)
|
||||
#endif
|
||||
|
||||
// Boundary nodesets
|
||||
if(m_colLoc == 0)
|
||||
m_symmX.resize(edgeNodes * edgeNodes);
|
||||
if(m_rowLoc == 0)
|
||||
m_symmY.resize(edgeNodes * edgeNodes);
|
||||
if(m_planeLoc == 0)
|
||||
m_symmZ.resize(edgeNodes * edgeNodes);
|
||||
if(m_colLoc == 0) Kokkos::resize(m_symmX, edgeNodes * edgeNodes);
|
||||
if(m_rowLoc == 0) Kokkos::resize(m_symmY, edgeNodes * edgeNodes);
|
||||
if(m_planeLoc == 0) Kokkos::resize(m_symmZ, edgeNodes * edgeNodes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -506,9 +503,14 @@ Domain::CreateRegionIndexSets(Int_t nr, Int_t balance)
|
||||
srand(0);
|
||||
Index_t myRank = 0;
|
||||
#endif
|
||||
this->numReg() = nr;
|
||||
m_regElemSize = Allocate<Index_t>(numReg());
|
||||
m_regElemlist = Allocate<Index_t*>(numReg());
|
||||
this->numReg() = nr;
|
||||
m_regElemSize = Allocate<Index_t>(numReg());
|
||||
auto row_map = Kokkos::View<Index_t*>("regElemlist::row_map", numReg() + 1);
|
||||
auto h_row_map = Kokkos::create_mirror_view(row_map);
|
||||
auto entries = Kokkos::View<Index_t*>("regElemlist::entries", numElem());
|
||||
m_regElemlist = t_regElemlist(entries, row_map);
|
||||
auto h_regElemlist = typename t_regElemlist::HostMirror(
|
||||
Kokkos::create_mirror_view(m_regElemlist.entries), h_row_map);
|
||||
Index_t nextIndex = 0;
|
||||
// if we only have one region just fill it
|
||||
// Fill out the regNumList with material numbers, which are always
|
||||
@@ -525,14 +527,14 @@ Domain::CreateRegionIndexSets(Int_t nr, Int_t balance)
|
||||
// If we have more than one region distribute the elements.
|
||||
else
|
||||
{
|
||||
Int_t regionNum;
|
||||
Int_t regionVar;
|
||||
Int_t lastReg = -1;
|
||||
Int_t binSize;
|
||||
Index_t elements;
|
||||
Index_t runto = 0;
|
||||
Int_t costDenominator = 0;
|
||||
Int_t* regBinEnd = Allocate<Int_t>(numReg());
|
||||
Int_t regionNum;
|
||||
Int_t regionVar;
|
||||
Int_t lastReg = -1;
|
||||
Int_t binSize;
|
||||
Index_t elements;
|
||||
Index_t runto = 0;
|
||||
Int_t costDenominator = 0;
|
||||
Kokkos::View<Int_t*, Kokkos::HostSpace> regBinEnd("regBinEnd", numReg());
|
||||
// Determine the relative weights of all the regions. This is based off the -b
|
||||
// flag. Balance is the value passed into b.
|
||||
for(Index_t i = 0; i < numReg(); ++i)
|
||||
@@ -612,23 +614,28 @@ Domain::CreateRegionIndexSets(Int_t nr, Int_t balance)
|
||||
// Second, allocate each region index set
|
||||
for(Index_t i = 0; i < numReg(); ++i)
|
||||
{
|
||||
m_regElemlist[i] = Allocate<Int_t>(regElemSize(i));
|
||||
h_row_map(i + 1) = regElemSize(i);
|
||||
regElemSize(i) = 0;
|
||||
}
|
||||
// Third, fill index sets
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
Index_t r = regNumList(i) - 1; // region index == regnum-1
|
||||
Index_t regndx = regElemSize(r)++; // Note increment
|
||||
regElemlist(r, regndx) = i;
|
||||
Index_t r = regNumList(i) - 1; // region index == regnum-1
|
||||
Index_t regndx = regElemSize(r)++; // Note increment
|
||||
h_regElemlist.entries(h_row_map(r) + regndx) = i;
|
||||
}
|
||||
Kokkos::deep_copy(m_regElemlist.entries, h_regElemlist.entries);
|
||||
Kokkos::deep_copy(row_map, h_row_map);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
void
|
||||
Domain::SetupSymmetryPlanes(Int_t edgeNodes)
|
||||
{
|
||||
Index_t nidx = 0;
|
||||
Index_t nidx = 0;
|
||||
auto h_symmZ = Kokkos::create_mirror_view(m_symmZ);
|
||||
auto h_symmY = Kokkos::create_mirror_view(m_symmY);
|
||||
auto h_symmX = Kokkos::create_mirror_view(m_symmX);
|
||||
for(Index_t i = 0; i < edgeNodes; ++i)
|
||||
{
|
||||
Index_t planeInc = i * edgeNodes * edgeNodes;
|
||||
@@ -637,55 +644,72 @@ Domain::SetupSymmetryPlanes(Int_t edgeNodes)
|
||||
{
|
||||
if(m_planeLoc == 0)
|
||||
{
|
||||
m_symmZ[nidx] = rowInc + j;
|
||||
h_symmZ[nidx] = rowInc + j;
|
||||
}
|
||||
if(m_rowLoc == 0)
|
||||
{
|
||||
m_symmY[nidx] = planeInc + j;
|
||||
h_symmY[nidx] = planeInc + j;
|
||||
}
|
||||
if(m_colLoc == 0)
|
||||
{
|
||||
m_symmX[nidx] = planeInc + j * edgeNodes;
|
||||
h_symmX[nidx] = planeInc + j * edgeNodes;
|
||||
}
|
||||
++nidx;
|
||||
}
|
||||
}
|
||||
Kokkos::deep_copy(m_symmZ, h_symmZ);
|
||||
Kokkos::deep_copy(m_symmY, h_symmY);
|
||||
Kokkos::deep_copy(m_symmX, h_symmX);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
void
|
||||
Domain::SetupElementConnectivities(Int_t edgeElems)
|
||||
{
|
||||
lxim(0) = 0;
|
||||
// With C++17 we wouldn't need to do this and could run this on the GPU
|
||||
// using class lambdas
|
||||
auto h_lxim = Kokkos::create_mirror_view(m_lxim);
|
||||
auto h_lxip = Kokkos::create_mirror_view(m_lxip);
|
||||
h_lxim(0) = 0;
|
||||
for(Index_t i = 1; i < numElem(); ++i)
|
||||
{
|
||||
lxim(i) = i - 1;
|
||||
lxip(i - 1) = i;
|
||||
h_lxim(i) = i - 1;
|
||||
h_lxip(i - 1) = i;
|
||||
}
|
||||
lxip(numElem() - 1) = numElem() - 1;
|
||||
h_lxip(numElem() - 1) = numElem() - 1;
|
||||
Kokkos::deep_copy(m_lxim, h_lxim);
|
||||
Kokkos::deep_copy(m_lxip, h_lxip);
|
||||
|
||||
auto h_letam = Kokkos::create_mirror_view(m_letam);
|
||||
auto h_letap = Kokkos::create_mirror_view(m_letap);
|
||||
for(Index_t i = 0; i < edgeElems; ++i)
|
||||
{
|
||||
letam(i) = i;
|
||||
letap(numElem() - edgeElems + i) = numElem() - edgeElems + i;
|
||||
h_letam(i) = i;
|
||||
h_letap(numElem() - edgeElems + i) = numElem() - edgeElems + i;
|
||||
}
|
||||
for(Index_t i = edgeElems; i < numElem(); ++i)
|
||||
{
|
||||
letam(i) = i - edgeElems;
|
||||
letap(i - edgeElems) = i;
|
||||
h_letam(i) = i - edgeElems;
|
||||
h_letap(i - edgeElems) = i;
|
||||
}
|
||||
Kokkos::deep_copy(m_letam, h_letam);
|
||||
Kokkos::deep_copy(m_letap, h_letap);
|
||||
|
||||
auto h_lzetam = Kokkos::create_mirror_view(m_lzetam);
|
||||
auto h_lzetap = Kokkos::create_mirror_view(m_lzetap);
|
||||
for(Index_t i = 0; i < edgeElems * edgeElems; ++i)
|
||||
{
|
||||
lzetam(i) = i;
|
||||
lzetap(numElem() - edgeElems * edgeElems + i) =
|
||||
h_lzetam(i) = i;
|
||||
h_lzetap(numElem() - edgeElems * edgeElems + i) =
|
||||
numElem() - edgeElems * edgeElems + i;
|
||||
}
|
||||
for(Index_t i = edgeElems * edgeElems; i < numElem(); ++i)
|
||||
{
|
||||
lzetam(i) = i - edgeElems * edgeElems;
|
||||
lzetap(i - edgeElems * edgeElems) = i;
|
||||
h_lzetam(i) = i - edgeElems * edgeElems;
|
||||
h_lzetap(i - edgeElems * edgeElems) = i;
|
||||
}
|
||||
Kokkos::deep_copy(m_lzetam, h_lzetam);
|
||||
Kokkos::deep_copy(m_lzetap, h_lzetap);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
@@ -693,11 +717,24 @@ void
|
||||
Domain::SetupBoundaryConditions(Int_t edgeElems)
|
||||
{
|
||||
Index_t ghostIdx[6]; // offsets to ghost locations
|
||||
auto h_elemBC = Kokkos::create_mirror_view(m_elemBC);
|
||||
auto h_lzetam = Kokkos::create_mirror_view(m_lzetam);
|
||||
auto h_lzetap = Kokkos::create_mirror_view(m_lzetap);
|
||||
auto h_letam = Kokkos::create_mirror_view(m_letam);
|
||||
auto h_letap = Kokkos::create_mirror_view(m_letap);
|
||||
auto h_lxim = Kokkos::create_mirror_view(m_lxim);
|
||||
auto h_lxip = Kokkos::create_mirror_view(m_lxip);
|
||||
Kokkos::deep_copy(h_lzetam, m_lzetam);
|
||||
Kokkos::deep_copy(h_lzetap, m_lzetap);
|
||||
Kokkos::deep_copy(h_letam, m_letam);
|
||||
Kokkos::deep_copy(h_letap, m_letap);
|
||||
Kokkos::deep_copy(h_lxim, m_lxim);
|
||||
Kokkos::deep_copy(h_lxip, m_lxip);
|
||||
|
||||
// set up boundary condition information
|
||||
for(Index_t i = 0; i < numElem(); ++i)
|
||||
{
|
||||
elemBC(i) = Int_t(0);
|
||||
h_elemBC(i) = Int_t(0);
|
||||
}
|
||||
|
||||
for(Index_t i = 0; i < 6; ++i)
|
||||
@@ -750,67 +787,75 @@ Domain::SetupBoundaryConditions(Int_t edgeElems)
|
||||
{
|
||||
if(m_planeLoc == 0)
|
||||
{
|
||||
elemBC(rowInc + j) |= ZETA_M_SYMM;
|
||||
h_elemBC(rowInc + j) |= ZETA_M_SYMM;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(rowInc + j) |= ZETA_M_COMM;
|
||||
lzetam(rowInc + j) = ghostIdx[0] + rowInc + j;
|
||||
h_elemBC(rowInc + j) |= ZETA_M_COMM;
|
||||
h_lzetam(rowInc + j) = ghostIdx[0] + rowInc + j;
|
||||
}
|
||||
|
||||
if(m_planeLoc == m_tp - 1)
|
||||
{
|
||||
elemBC(rowInc + j + numElem() - edgeElems * edgeElems) |= ZETA_P_FREE;
|
||||
h_elemBC(rowInc + j + numElem() - edgeElems * edgeElems) |= ZETA_P_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(rowInc + j + numElem() - edgeElems * edgeElems) |= ZETA_P_COMM;
|
||||
lzetap(rowInc + j + numElem() - edgeElems * edgeElems) =
|
||||
h_elemBC(rowInc + j + numElem() - edgeElems * edgeElems) |= ZETA_P_COMM;
|
||||
h_lzetap(rowInc + j + numElem() - edgeElems * edgeElems) =
|
||||
ghostIdx[1] + rowInc + j;
|
||||
}
|
||||
|
||||
if(m_rowLoc == 0)
|
||||
{
|
||||
elemBC(planeInc + j) |= ETA_M_SYMM;
|
||||
h_elemBC(planeInc + j) |= ETA_M_SYMM;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(planeInc + j) |= ETA_M_COMM;
|
||||
letam(planeInc + j) = ghostIdx[2] + rowInc + j;
|
||||
h_elemBC(planeInc + j) |= ETA_M_COMM;
|
||||
h_letam(planeInc + j) = ghostIdx[2] + rowInc + j;
|
||||
}
|
||||
|
||||
if(m_rowLoc == m_tp - 1)
|
||||
{
|
||||
elemBC(planeInc + j + edgeElems * edgeElems - edgeElems) |= ETA_P_FREE;
|
||||
h_elemBC(planeInc + j + edgeElems * edgeElems - edgeElems) |= ETA_P_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(planeInc + j + edgeElems * edgeElems - edgeElems) |= ETA_P_COMM;
|
||||
letap(planeInc + j + edgeElems * edgeElems - edgeElems) =
|
||||
h_elemBC(planeInc + j + edgeElems * edgeElems - edgeElems) |= ETA_P_COMM;
|
||||
h_letap(planeInc + j + edgeElems * edgeElems - edgeElems) =
|
||||
ghostIdx[3] + rowInc + j;
|
||||
}
|
||||
|
||||
if(m_colLoc == 0)
|
||||
{
|
||||
elemBC(planeInc + j * edgeElems) |= XI_M_SYMM;
|
||||
h_elemBC(planeInc + j * edgeElems) |= XI_M_SYMM;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(planeInc + j * edgeElems) |= XI_M_COMM;
|
||||
lxim(planeInc + j * edgeElems) = ghostIdx[4] + rowInc + j;
|
||||
h_elemBC(planeInc + j * edgeElems) |= XI_M_COMM;
|
||||
h_lxim(planeInc + j * edgeElems) = ghostIdx[4] + rowInc + j;
|
||||
}
|
||||
|
||||
if(m_colLoc == m_tp - 1)
|
||||
{
|
||||
elemBC(planeInc + j * edgeElems + edgeElems - 1) |= XI_P_FREE;
|
||||
h_elemBC(planeInc + j * edgeElems + edgeElems - 1) |= XI_P_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
elemBC(planeInc + j * edgeElems + edgeElems - 1) |= XI_P_COMM;
|
||||
lxip(planeInc + j * edgeElems + edgeElems - 1) = ghostIdx[5] + rowInc + j;
|
||||
h_elemBC(planeInc + j * edgeElems + edgeElems - 1) |= XI_P_COMM;
|
||||
h_lxip(planeInc + j * edgeElems + edgeElems - 1) =
|
||||
ghostIdx[5] + rowInc + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
Kokkos::deep_copy(m_elemBC, h_elemBC);
|
||||
Kokkos::deep_copy(m_lzetam, h_lzetam);
|
||||
Kokkos::deep_copy(m_lzetap, h_lzetap);
|
||||
Kokkos::deep_copy(m_letam, h_letam);
|
||||
Kokkos::deep_copy(m_letap, h_letap);
|
||||
Kokkos::deep_copy(m_lxim, h_lxim);
|
||||
Kokkos::deep_copy(m_lxip, h_lxip);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -15,8 +15,7 @@ StrToInt(const char* token, int* retVal)
|
||||
char* endptr;
|
||||
const int decimal_base = 10;
|
||||
|
||||
if(token == NULL)
|
||||
return 0;
|
||||
if(token == NULL) return 0;
|
||||
|
||||
c = token;
|
||||
*retVal = (int) strtol(c, &endptr, decimal_base);
|
||||
@@ -229,11 +228,13 @@ VerifyAndWriteFinalOutput(Real_t elapsed_time, Domain& locDom, Int_t nx, Int_t n
|
||||
((elapsed_time * 1e6) / locDom.cycle()) / (nx * nx * nx * numRanks);
|
||||
|
||||
Index_t ElemId = 0;
|
||||
auto h_e = Kokkos::create_mirror_view(locDom.e_view());
|
||||
Kokkos::deep_copy(h_e, locDom.e_view());
|
||||
printf("Run completed: \n");
|
||||
printf(" Problem size = %i \n", nx);
|
||||
printf(" MPI tasks = %i \n", numRanks);
|
||||
printf(" Iteration count = %i \n", locDom.cycle());
|
||||
printf(" Final Origin Energy = %12.6e \n", locDom.e(ElemId));
|
||||
printf(" Final Origin Energy = %12.6e \n", h_e(ElemId));
|
||||
|
||||
Real_t MaxAbsDiff = Real_t(0.0);
|
||||
Real_t TotalAbsDiff = Real_t(0.0);
|
||||
@@ -243,16 +244,14 @@ VerifyAndWriteFinalOutput(Real_t elapsed_time, Domain& locDom, Int_t nx, Int_t n
|
||||
{
|
||||
for(Index_t k = j + 1; k < nx; ++k)
|
||||
{
|
||||
Real_t AbsDiff = FABS(locDom.e(j * nx + k) - locDom.e(k * nx + j));
|
||||
Real_t AbsDiff = FABS(h_e(j * nx + k) - h_e(k * nx + j));
|
||||
TotalAbsDiff += AbsDiff;
|
||||
|
||||
if(MaxAbsDiff < AbsDiff)
|
||||
MaxAbsDiff = AbsDiff;
|
||||
if(MaxAbsDiff < AbsDiff) MaxAbsDiff = AbsDiff;
|
||||
|
||||
Real_t RelDiff = AbsDiff / locDom.e(k * nx + j);
|
||||
Real_t RelDiff = AbsDiff / h_e(k * nx + j);
|
||||
|
||||
if(MaxRelDiff < RelDiff)
|
||||
MaxRelDiff = RelDiff;
|
||||
if(MaxRelDiff < RelDiff) MaxRelDiff = RelDiff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -403,8 +403,7 @@ static void
|
||||
LULESH_PMPIO_Close(void* file, void* udata)
|
||||
{
|
||||
DBfile* db = (DBfile*) file;
|
||||
if(db)
|
||||
DBClose(db);
|
||||
if(db) DBClose(db);
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
project(omnitrace-transpose LANGUAGES CXX)
|
||||
|
||||
find_program(HIPCC_EXECUTABLE NAMES hipcc)
|
||||
mark_as_advanced(HIPCC_EXECUTABLE)
|
||||
|
||||
if(NOT HIPCC_EXECUTABLE)
|
||||
message(AUTHOR_WARNING "hipcc could not be found. Cannot build transpose target")
|
||||
|
||||
+1
-1
Submodule projects/rocprofiler-systems/external/perfetto updated: dd1f2f378f...0551922853
+1
-1
Submodule projects/rocprofiler-systems/external/timemory updated: ccc83e80c6...110b907b35
@@ -55,8 +55,6 @@ add_critical_trace(int64_t _tid, size_t _cpu_cid, size_t _gpu_cid, size_t _paren
|
||||
int64_t _ts_beg, int64_t _ts_val, size_t _hash, uint16_t _depth,
|
||||
uint16_t _prio = 0)
|
||||
{
|
||||
if(!get_use_critical_trace()) return;
|
||||
|
||||
// clang-format off
|
||||
// these are used to create unique type mutexes
|
||||
struct critical_insert {};
|
||||
|
||||
@@ -29,12 +29,25 @@
|
||||
// forward decl of the API
|
||||
extern "C"
|
||||
{
|
||||
/// handles configuration logic
|
||||
void omnitrace_init_library(void) TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// starts gotcha wrappers
|
||||
void omnitrace_init(const char*, bool, const char*) TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// shuts down all tooling and generates output
|
||||
void omnitrace_finalize(void) TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// sets an environment variable
|
||||
void omnitrace_set_env(const char* env_name, const char* env_val)
|
||||
TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// sets whether MPI should be used
|
||||
void omnitrace_set_mpi(bool use, bool attached) TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// starts an instrumentation region
|
||||
void omnitrace_push_trace(const char* name) TIMEMORY_VISIBILITY("default");
|
||||
|
||||
/// stops an instrumentation region
|
||||
void omnitrace_pop_trace(const char* name) TIMEMORY_VISIBILITY("default");
|
||||
void omnitrace_trace_init(const char*, bool, const char*)
|
||||
TIMEMORY_VISIBILITY("default");
|
||||
void omnitrace_trace_finalize(void) TIMEMORY_VISIBILITY("default");
|
||||
void omnitrace_trace_set_env(const char* env_name, const char* env_val)
|
||||
TIMEMORY_VISIBILITY("default");
|
||||
void omnitrace_trace_set_mpi(bool use, bool attached) TIMEMORY_VISIBILITY("default");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
TIMEMORY_DEFINE_NS_API(api, omnitrace)
|
||||
TIMEMORY_DEFINE_NS_API(api, sampling)
|
||||
TIMEMORY_DEFINE_NS_API(api, rocm_smi)
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
|
||||
@@ -91,6 +91,7 @@ struct backtrace
|
||||
private:
|
||||
int64_t m_tid = 0;
|
||||
int64_t m_thr_cpu_ts = 0;
|
||||
int64_t m_mem_peak = 0;
|
||||
size_t m_size = 0;
|
||||
time_point_type m_ts = {};
|
||||
data_t m_data = {};
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <timemory/components/macros.hpp>
|
||||
#include <timemory/components/user_bundle/types.hpp>
|
||||
#include <timemory/enum.h>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
|
||||
TIMEMORY_DECLARE_COMPONENT(roctracer)
|
||||
|
||||
@@ -46,9 +47,21 @@ struct backtrace_cpu_clock
|
||||
{};
|
||||
struct backtrace_fraction
|
||||
{};
|
||||
struct backtrace_gpu_busy
|
||||
{};
|
||||
struct backtrace_gpu_temp
|
||||
{};
|
||||
struct backtrace_gpu_power
|
||||
{};
|
||||
struct backtrace_gpu_memory
|
||||
{};
|
||||
using sampling_wall_clock = data_tracker<double, backtrace_wall_clock>;
|
||||
using sampling_cpu_clock = data_tracker<double, backtrace_cpu_clock>;
|
||||
using sampling_percent = data_tracker<double, backtrace_fraction>;
|
||||
using sampling_gpu_busy = data_tracker<double, backtrace_gpu_busy>;
|
||||
using sampling_gpu_temp = data_tracker<double, backtrace_gpu_temp>;
|
||||
using sampling_gpu_power = data_tracker<double, backtrace_gpu_power>;
|
||||
using sampling_gpu_memory = data_tracker<double, backtrace_gpu_memory>;
|
||||
using roctracer = tim::component::roctracer;
|
||||
} // namespace component
|
||||
} // namespace omnitrace
|
||||
@@ -59,7 +72,7 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, component::roctracer, false_type)
|
||||
|
||||
#if !defined(TIMEMORY_USE_LIBUNWIND)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::api::sampling, false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::sampling::backtrace, false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::backtrace, false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_wall_clock,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_cpu_clock,
|
||||
@@ -68,6 +81,17 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_perc
|
||||
false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_USE_LIBUNWIND) || !defined(OMNITRACE_USE_ROCM_SMI)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_busy,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_temp,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_power,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_memory,
|
||||
false_type)
|
||||
#endif
|
||||
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::omnitrace, OMNITRACE_COMPONENT,
|
||||
"omnitrace", "omnitrace_component")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
|
||||
@@ -78,38 +102,87 @@ TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_cpu_clock,
|
||||
OMNITRACE_SAMPLING_CPU_CLOCK, "sampling_cpu_clock", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_percent,
|
||||
OMNITRACE_SAMPLING_PERCENT, "sampling_percent", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_busy,
|
||||
OMNITRACE_SAMPLING_GPU_BUSY, "sampling_gpu_busy",
|
||||
"sampling_gpu_util")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_memory,
|
||||
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE,
|
||||
"sampling_gpu_memory_usage", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
|
||||
OMNITRACE_SAMPLING_GPU_POWER, "sampling_gpu_power", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
|
||||
OMNITRACE_SAMPLING_GPU_TEMP, "sampling_gpu_temp", "")
|
||||
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
|
||||
"High-precision ROCm API and kernel tracing", "")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
|
||||
"sampling_wall_clock", "Wall-clock timing",
|
||||
"derived from statistical sampling")
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_cpu_clock,
|
||||
"sampling_cpu_clock", "CPU-clock timing",
|
||||
"derived from statistical sampling")
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_percent,
|
||||
"sampling_percent",
|
||||
"Fraction of wall-clock time spent in functions",
|
||||
"derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
|
||||
"High-precision ROCm API and kernel tracing", "")
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_busy,
|
||||
"sampling_gpu_busy",
|
||||
"GPU Utilization (% busy) via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_memory,
|
||||
"sampling_gpu_memory_usage",
|
||||
"GPU Memory Usage via ROCm-SMI", "Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
|
||||
"sampling_gpu_power", "GPU Power Usage via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
|
||||
"sampling_gpu_temp", "GPU Temperature via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
|
||||
// statistics type
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_wall_clock, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_cpu_clock, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_busy, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_temp, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_power, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_memory, double)
|
||||
|
||||
// enable timing units
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_timing_category,
|
||||
omnitrace::component::sampling_wall_clock, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_timing_units,
|
||||
omnitrace::component::sampling_wall_clock, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_timing_category,
|
||||
omnitrace::component::sampling_cpu_clock, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_timing_units,
|
||||
omnitrace::component::sampling_cpu_clock, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_timing_category, omnitrace::component::sampling_percent,
|
||||
true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_timing_units,
|
||||
omnitrace::component::sampling_wall_clock, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_timing_units,
|
||||
omnitrace::component::sampling_cpu_clock, true_type)
|
||||
|
||||
// enable percent units
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_percent_units,
|
||||
omnitrace::component::sampling_gpu_busy, true_type)
|
||||
|
||||
// enable memory units
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_memory_category,
|
||||
omnitrace::component::sampling_gpu_memory, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(uses_memory_units,
|
||||
omnitrace::component::sampling_gpu_memory, true_type)
|
||||
|
||||
// reporting categories (sum)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_sum, omnitrace::component::sampling_gpu_busy,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_sum, omnitrace::component::sampling_gpu_temp,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_sum, omnitrace::component::sampling_gpu_power,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_sum, omnitrace::component::sampling_gpu_memory,
|
||||
false_type)
|
||||
|
||||
// reporting categories (mean)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_mean, omnitrace::component::sampling_percent,
|
||||
false_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_units, omnitrace::component::sampling_percent,
|
||||
false_type)
|
||||
|
||||
// reporting categories (stats)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(report_statistics, omnitrace::component::sampling_percent,
|
||||
false_type)
|
||||
|
||||
@@ -56,6 +56,7 @@ struct pthread_gotcha : tim::component::base<pthread_gotcha, void>
|
||||
|
||||
// generate the gotcha wrappers
|
||||
static void configure();
|
||||
static void shutdown();
|
||||
|
||||
// threads can set this to avoid starting sampling on child threads
|
||||
static bool& enable_sampling_on_child_threads();
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2018 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
|
||||
// with 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the names of Advanced Micro Devices, Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this Software without specific prior written permission.
|
||||
//
|
||||
// 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
|
||||
// CONTRIBUTORS 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 WITH
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "library/common.hpp"
|
||||
#include "library/components/fwd.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <future>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ratio>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace rocm_smi
|
||||
{
|
||||
void
|
||||
setup();
|
||||
|
||||
void
|
||||
shutdown();
|
||||
|
||||
uint32_t
|
||||
device_count();
|
||||
|
||||
struct data
|
||||
{
|
||||
using msec_t = std::chrono::milliseconds;
|
||||
using usec_t = std::chrono::microseconds;
|
||||
using nsec_t = std::chrono::nanoseconds;
|
||||
using promise_t = std::promise<void>;
|
||||
|
||||
using timestamp_t = int64_t;
|
||||
using power_t = uint64_t;
|
||||
using busy_perc_t = uint32_t;
|
||||
using mem_usage_t = uint64_t;
|
||||
using temp_t = int64_t;
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(data)
|
||||
|
||||
explicit data(uint32_t _dev_id);
|
||||
|
||||
void sample(uint32_t _dev_id);
|
||||
void print(std::ostream& _os) const;
|
||||
|
||||
template <typename Tp = nsec_t,
|
||||
std::enable_if_t<!std::is_same_v<std::decay_t<Tp>, nsec_t>, int> = 0>
|
||||
static void poll(std::atomic<State>* _state, Tp&& _interval, promise_t*);
|
||||
|
||||
static void set_state(State);
|
||||
static void poll(std::atomic<State>* _state, nsec_t _interval, promise_t*);
|
||||
static void post_process(uint32_t _dev_id);
|
||||
|
||||
uint32_t m_dev_id = std::numeric_limits<uint32_t>::max();
|
||||
timestamp_t m_ts = 0;
|
||||
busy_perc_t m_busy_perc = 0;
|
||||
temp_t m_temp = 0;
|
||||
power_t m_power = 0;
|
||||
mem_usage_t m_mem_usage = 0;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& _os, const data& _v)
|
||||
{
|
||||
_v.print(_os);
|
||||
return _os;
|
||||
}
|
||||
|
||||
private:
|
||||
friend void omnitrace::rocm_smi::setup();
|
||||
friend void omnitrace::rocm_smi::shutdown();
|
||||
|
||||
static size_t device_count;
|
||||
static std::set<uint32_t> device_list;
|
||||
static std::unique_ptr<promise_t> polling_finished;
|
||||
static std::vector<data>& get_initial();
|
||||
static std::unique_ptr<std::thread>& get_thread();
|
||||
static bool setup();
|
||||
static bool shutdown();
|
||||
};
|
||||
|
||||
template <
|
||||
typename Tp,
|
||||
std::enable_if_t<!std::is_same_v<std::decay_t<Tp>, std::chrono::nanoseconds>, int>>
|
||||
void
|
||||
data::poll(std::atomic<State>* _state, Tp&& _interval, promise_t* _prom)
|
||||
{
|
||||
poll(_state, std::chrono::duration_cast<nsec_t>(_interval), _prom);
|
||||
}
|
||||
|
||||
using bundle_t = std::deque<data>;
|
||||
using sampler_instances = thread_data<bundle_t, api::rocm_smi>;
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCM_SMI)
|
||||
inline void
|
||||
setup()
|
||||
{}
|
||||
|
||||
inline void
|
||||
shutdown()
|
||||
{}
|
||||
|
||||
inline void data::post_process(uint32_t) {}
|
||||
#endif
|
||||
} // namespace rocm_smi
|
||||
} // namespace omnitrace
|
||||
|
||||
#if defined(OMNITRACE_USE_ROCM_SMI)
|
||||
# if !defined(OMNITRACE_EXTERN_COMPONENTS) || \
|
||||
(defined(OMNITRACE_EXTERN_COMPONENTS) && OMNITRACE_EXTERN_COMPONENTS > 0)
|
||||
|
||||
# include <timemory/components/base.hpp>
|
||||
# include <timemory/components/data_tracker/components.hpp>
|
||||
# include <timemory/operations.hpp>
|
||||
|
||||
TIMEMORY_DECLARE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_busy>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_DECLARE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_temp>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_DECLARE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_power>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_DECLARE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_memory>), true,
|
||||
double)
|
||||
|
||||
# endif
|
||||
#endif
|
||||
@@ -52,26 +52,42 @@ struct roctracer
|
||||
|
||||
static void preinit();
|
||||
static void global_init() { setup(); }
|
||||
static void global_finalize() { tear_down(); }
|
||||
static void global_finalize() { shutdown(); }
|
||||
|
||||
static bool is_setup();
|
||||
static void setup();
|
||||
static void tear_down();
|
||||
static void shutdown();
|
||||
static void add_setup(const std::string&, std::function<void()>&&);
|
||||
static void add_tear_down(const std::string&, std::function<void()>&&);
|
||||
static void add_shutdown(const std::string&, std::function<void()>&&);
|
||||
static void remove_setup(const std::string&);
|
||||
static void remove_tear_down(const std::string&);
|
||||
static void remove_shutdown(const std::string&);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void set_prefix(const char* _v) { m_prefix = _v; }
|
||||
|
||||
private:
|
||||
const char* m_prefix = nullptr;
|
||||
};
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCTRACER)
|
||||
inline void
|
||||
roctracer::setup()
|
||||
{}
|
||||
|
||||
inline void
|
||||
roctracer::shutdown()
|
||||
{}
|
||||
|
||||
inline bool
|
||||
roctracer::is_setup()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // namespace component
|
||||
} // namespace tim
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCTRACER)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, component::roctracer_data, false_type)
|
||||
#endif
|
||||
|
||||
TIMEMORY_SET_COMPONENT_API(component::roctracer_data, project::timemory, category::timing,
|
||||
os::supports_unix)
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(is_timing_category, component::roctracer_data, true_type)
|
||||
|
||||
@@ -90,5 +90,5 @@ roctracer_functions_t&
|
||||
roctracer_setup_routines();
|
||||
|
||||
roctracer_functions_t&
|
||||
roctracer_tear_down_routines();
|
||||
roctracer_shutdown_routines();
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "library/defines.hpp"
|
||||
#include "library/state.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
#include "timemory/macros/language.hpp"
|
||||
|
||||
#include <timemory/backends/threading.hpp>
|
||||
|
||||
@@ -43,10 +44,9 @@ namespace omnitrace
|
||||
// bundle of components around omnitrace_init and omnitrace_finalize
|
||||
using main_bundle_t =
|
||||
tim::lightweight_tuple<comp::wall_clock, comp::peak_rss, comp::cpu_clock,
|
||||
comp::cpu_util, comp::roctracer>;
|
||||
comp::cpu_util, pthread_gotcha_t>;
|
||||
|
||||
using gotcha_bundle_t =
|
||||
tim::lightweight_tuple<fork_gotcha_t, mpi_gotcha_t, pthread_gotcha_t>;
|
||||
using gotcha_bundle_t = tim::lightweight_tuple<fork_gotcha_t, mpi_gotcha_t>;
|
||||
|
||||
// bundle of components used in instrumentation
|
||||
using instrumentation_bundle_t =
|
||||
@@ -69,26 +69,63 @@ using omnitrace_thread_bundle_t =
|
||||
//
|
||||
// Initialization routines
|
||||
//
|
||||
inline namespace config
|
||||
{
|
||||
void
|
||||
configure_settings() TIMEMORY_VISIBILITY("default");
|
||||
configure_settings();
|
||||
|
||||
void
|
||||
print_config_settings(
|
||||
print_banner(std::ostream& _os = std::cout);
|
||||
|
||||
void
|
||||
print_settings(
|
||||
std::ostream& _os,
|
||||
std::function<bool(const std::string_view&, const std::set<std::string>&)>&& _filter);
|
||||
|
||||
void
|
||||
print_settings();
|
||||
|
||||
std::string&
|
||||
get_exe_name();
|
||||
|
||||
template <typename Tp>
|
||||
bool
|
||||
set_setting_value(const std::string& _name, Tp&& _v)
|
||||
{
|
||||
auto _instance = tim::settings::shared_instance();
|
||||
auto _setting = _instance->find(_name);
|
||||
if(_setting == _instance->end()) return false;
|
||||
if(!_setting->second) return false;
|
||||
return _setting->second->set(std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
//
|
||||
// User-configurable settings
|
||||
//
|
||||
std::string
|
||||
get_config_file();
|
||||
|
||||
Mode
|
||||
get_mode();
|
||||
|
||||
bool&
|
||||
is_attached();
|
||||
|
||||
bool&
|
||||
is_binary_rewrite();
|
||||
|
||||
bool
|
||||
get_is_continuous_integration();
|
||||
|
||||
bool
|
||||
get_debug_env();
|
||||
|
||||
bool
|
||||
get_debug_init();
|
||||
|
||||
bool
|
||||
get_debug_finalize();
|
||||
|
||||
bool
|
||||
get_debug();
|
||||
|
||||
@@ -113,6 +150,9 @@ get_use_timemory();
|
||||
bool&
|
||||
get_use_roctracer();
|
||||
|
||||
bool&
|
||||
get_use_rocm_smi();
|
||||
|
||||
bool&
|
||||
get_use_sampling();
|
||||
|
||||
@@ -125,6 +165,9 @@ get_use_mpip();
|
||||
bool&
|
||||
get_use_critical_trace();
|
||||
|
||||
bool
|
||||
get_use_kokkosp();
|
||||
|
||||
bool
|
||||
get_timeline_sampling();
|
||||
|
||||
@@ -167,8 +210,9 @@ get_trace_hsa_api_types();
|
||||
std::string&
|
||||
get_backend();
|
||||
|
||||
// make this visible so omnitrace-avail can call it
|
||||
std::string&
|
||||
get_perfetto_output_filename();
|
||||
get_perfetto_output_filename() TIMEMORY_VISIBILITY("default");
|
||||
|
||||
int64_t
|
||||
get_critical_trace_count();
|
||||
@@ -182,8 +226,15 @@ get_sampling_freq();
|
||||
double&
|
||||
get_sampling_delay();
|
||||
|
||||
double&
|
||||
get_rocm_smi_freq();
|
||||
|
||||
std::string
|
||||
get_rocm_smi_devices();
|
||||
|
||||
int64_t
|
||||
get_critical_trace_per_row();
|
||||
} // namespace config
|
||||
|
||||
//
|
||||
// Runtime configuration data
|
||||
|
||||
@@ -175,7 +175,7 @@ struct call_chain : private std::vector<entry>
|
||||
}
|
||||
|
||||
template <Device DevT>
|
||||
void generate_perfetto(std::set<entry>& _used) const;
|
||||
void generate_perfetto(std::set<entry>& _used, bool _basic = false) const;
|
||||
|
||||
template <bool BoolV = true, typename FuncT>
|
||||
bool query(FuncT&&) const;
|
||||
@@ -201,6 +201,11 @@ update(int64_t _tid = threading::get_id());
|
||||
void
|
||||
compute(int64_t _tid = threading::get_id());
|
||||
|
||||
std::vector<std::pair<std::string, entry>>
|
||||
get_entries(
|
||||
int64_t _ts,
|
||||
const std::function<bool(const entry&)>& _eval = [](const entry&) { return true; });
|
||||
|
||||
struct id
|
||||
{};
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace config
|
||||
{
|
||||
bool
|
||||
get_debug();
|
||||
|
||||
@@ -44,6 +46,7 @@ get_debug_pid();
|
||||
|
||||
bool
|
||||
get_critical_trace_debug();
|
||||
} // namespace config
|
||||
} // namespace omnitrace
|
||||
|
||||
#if defined(TIMEMORY_USE_MPI)
|
||||
@@ -80,8 +83,58 @@ get_critical_trace_debug();
|
||||
fflush(stderr); \
|
||||
}
|
||||
|
||||
#if defined(TIMEMORY_USE_MPI)
|
||||
# define OMNITRACE_CONDITIONAL_THROW(COND, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[2048]; \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace][%i][%li] ", \
|
||||
static_cast<int>(tim::dmp::rank()), tim::threading::get_id()); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
|
||||
throw std::runtime_error(_msg_buffer); \
|
||||
}
|
||||
#else
|
||||
# define OMNITRACE_CONDITIONAL_THROW(COND, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[2048]; \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace][%i][%li] ", \
|
||||
static_cast<int>(tim::process::get_id()), \
|
||||
tim::threading::get_id()); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
|
||||
throw std::runtime_error(_msg_buffer); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_THROW(COND, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[2048]; \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace] " __VA_ARGS__); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
|
||||
throw std::runtime_error(_msg_buffer); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_DEBUG(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT(::omnitrace::get_debug(), __VA_ARGS__)
|
||||
#define OMNITRACE_PRINT(...) OMNITRACE_CONDITIONAL_PRINT(true, __VA_ARGS__)
|
||||
#define OMNITRACE_CT_DEBUG(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT(::omnitrace::get_critical_trace_debug(), __VA_ARGS__)
|
||||
#define OMNITRACE_BASIC_PRINT(...) OMNITRACE_CONDITIONAL_BASIC_PRINT(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_THROW(...) OMNITRACE_CONDITIONAL_THROW(true, __VA_ARGS__)
|
||||
#define OMNITRACE_BASIC_THROW(...) OMNITRACE_CONDITIONAL_BASIC_THROW(true, __VA_ARGS__)
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
inline std::string
|
||||
to_string(bool _v)
|
||||
{
|
||||
return (_v) ? "true" : "false";
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
@@ -36,11 +36,17 @@
|
||||
// clang-format on
|
||||
|
||||
#define TIMEMORY_USER_COMPONENT_ENUM \
|
||||
OMNITRACE_SAMPLING_WALL_CLOCK_idx, OMNITRACE_SAMPLING_CPU_CLOCK_idx, \
|
||||
OMNITRACE_SAMPLING_PERCENT_idx, OMNITRACE_COMPONENT_idx, OMNITRACE_ROCTRACER_idx,
|
||||
OMNITRACE_COMPONENT_idx, OMNITRACE_ROCTRACER_idx, OMNITRACE_SAMPLING_WALL_CLOCK_idx, \
|
||||
OMNITRACE_SAMPLING_CPU_CLOCK_idx, OMNITRACE_SAMPLING_PERCENT_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_POWER_idx, OMNITRACE_SAMPLING_GPU_TEMP_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_BUSY_idx, OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
|
||||
|
||||
#define OMNITRACE_COMPONENT OMNITRACE_COMPONENT_idx
|
||||
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
|
||||
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_PERCENT OMNITRACE_SAMPLING_PERCENT_idx
|
||||
#define OMNITRACE_COMPONENT OMNITRACE_COMPONENT_idx
|
||||
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
|
||||
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_PERCENT OMNITRACE_SAMPLING_PERCENT_idx
|
||||
#define OMNITRACE_SAMPLING_GPU_POWER OMNITRACE_SAMPLING_GPU_POWER_idx
|
||||
#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
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
# define PERFETTO_CATEGORIES \
|
||||
perfetto::Category("host").SetDescription("Host-side function tracing"), \
|
||||
perfetto::Category("device").SetDescription("Device-side function tracing"), \
|
||||
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
|
||||
perfetto::Category("sampling") \
|
||||
.SetDescription("Metrics derived from sampling"), \
|
||||
perfetto::Category("host-critical-trace") \
|
||||
.SetDescription("Host-side critical traces"), \
|
||||
perfetto::Category("device-critical-trace") \
|
||||
@@ -41,6 +44,9 @@
|
||||
# define PERFETTO_CATEGORIES \
|
||||
perfetto::Category("host").SetDescription("Host-side function tracing"), \
|
||||
perfetto::Category("device").SetDescription("Device-side function tracing"), \
|
||||
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
|
||||
perfetto::Category("sampling") \
|
||||
.SetDescription("Metrics derived from sampling"), \
|
||||
perfetto::Category("host-critical-trace") \
|
||||
.SetDescription("Host-side critical traces"), \
|
||||
perfetto::Category("device-critical-trace") \
|
||||
@@ -87,4 +93,44 @@ public:
|
||||
|
||||
PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
|
||||
#endif
|
||||
|
||||
template <typename Tp>
|
||||
struct perfetto_counter_track
|
||||
{
|
||||
using track_map_t = std::map<uint32_t, std::vector<perfetto::CounterTrack>>;
|
||||
using name_map_t = std::map<uint32_t, std::vector<std::string>>;
|
||||
using data_t = std::pair<name_map_t, track_map_t>;
|
||||
|
||||
static auto init() { (void) get_data(); }
|
||||
|
||||
static auto exists(size_t _idx, int64_t _n = -1)
|
||||
{
|
||||
bool _v = get_data().second.count(_idx) != 0;
|
||||
if(_n < 0 || !_v) return _v;
|
||||
return static_cast<size_t>(_n) < get_data().second.at(_idx).size();
|
||||
}
|
||||
|
||||
static size_t size(size_t _idx)
|
||||
{
|
||||
bool _v = get_data().second.count(_idx) != 0;
|
||||
if(!_v) return 0;
|
||||
return get_data().second.at(_idx).size();
|
||||
}
|
||||
|
||||
static auto emplace(size_t _idx, const std::string& _v, const char* _units)
|
||||
{
|
||||
get_data().first[_idx].emplace_back(_v);
|
||||
get_data().second[_idx].emplace_back(get_data().first[_idx].back().c_str(),
|
||||
_units);
|
||||
}
|
||||
|
||||
static auto& at(size_t _idx, size_t _n) { return get_data().second.at(_idx).at(_n); }
|
||||
|
||||
private:
|
||||
static data_t& get_data()
|
||||
{
|
||||
static auto* _v = new data_t{};
|
||||
return *_v;
|
||||
}
|
||||
};
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace config
|
||||
{
|
||||
bool
|
||||
get_debug();
|
||||
|
||||
int
|
||||
get_verbose();
|
||||
} // namespace config
|
||||
|
||||
struct redirect
|
||||
{
|
||||
redirect(std::ostream& _os, std::string _expected)
|
||||
: m_os{ _os }
|
||||
, m_expected{ std::move(_expected) }
|
||||
{
|
||||
if(!get_debug())
|
||||
{
|
||||
// save stream buffer
|
||||
m_strm_buffer = m_os.rdbuf();
|
||||
// redirect to stringstream
|
||||
_os.rdbuf(m_buffer.rdbuf());
|
||||
}
|
||||
}
|
||||
|
||||
~redirect()
|
||||
{
|
||||
if(!m_strm_buffer) return;
|
||||
// restore stream buffer
|
||||
m_os.rdbuf(m_strm_buffer);
|
||||
auto _v = m_buffer.str();
|
||||
_v = replace(m_buffer.str(), '\n');
|
||||
auto _expect = replace(m_expected, '\n');
|
||||
if(_v != _expect)
|
||||
{
|
||||
if(get_verbose() > 0)
|
||||
std::cerr << "[omnitrace::redirect] Expected:\n[omnitrace::redirect] "
|
||||
<< _expect
|
||||
<< "\n[omnitrace::redirect] Found:\n[omnitrace::redirect] "
|
||||
<< _v << "\n";
|
||||
if(get_verbose() <= 0 || (&m_os != &std::cerr && &m_os != &std::cout))
|
||||
m_os << m_buffer.str() << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Tp>
|
||||
static std::string replace(std::string _v, Tp _c, const std::string& _s = " ")
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
auto _pos = _v.find(_c);
|
||||
if(_pos == std::string::npos) break;
|
||||
_v = _v.replace(_pos, 1, _s);
|
||||
}
|
||||
return _v;
|
||||
}
|
||||
|
||||
std::ostream& m_os;
|
||||
std::string m_expected = {};
|
||||
std::stringstream m_buffer{};
|
||||
std::streambuf* m_strm_buffer = nullptr;
|
||||
};
|
||||
} // namespace omnitrace
|
||||
@@ -46,6 +46,10 @@ using component::backtrace_cpu_clock; // NOLINT
|
||||
using component::backtrace_fraction; // NOLINT
|
||||
using component::backtrace_wall_clock; // NOLINT
|
||||
using component::sampling_cpu_clock;
|
||||
using component::sampling_gpu_busy;
|
||||
using component::sampling_gpu_memory;
|
||||
using component::sampling_gpu_power;
|
||||
using component::sampling_gpu_temp;
|
||||
using component::sampling_percent;
|
||||
using component::sampling_wall_clock;
|
||||
|
||||
@@ -64,7 +68,7 @@ void unblock_signals(std::set<int> = {});
|
||||
|
||||
using bundle_t = tim::lightweight_tuple<backtrace>;
|
||||
using sampler_t = tim::sampling::sampler<bundle_t, tim::sampling::dynamic>;
|
||||
using sampler_instances = omnitrace_thread_data<sampler_t, api::sampling>;
|
||||
using sampler_instances = thread_data<sampler_t, api::sampling>;
|
||||
|
||||
std::unique_ptr<sampler_t>&
|
||||
get_sampler(int64_t _tid = threading::get_id());
|
||||
@@ -76,7 +80,7 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(prevent_reentry, omnitrace::sampling::sampler_t,
|
||||
std::true_type)
|
||||
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(check_signals, omnitrace::sampling::sampler_t,
|
||||
std::false_type)
|
||||
std::true_type)
|
||||
|
||||
TIMEMORY_DEFINE_CONCRETE_TRAIT(buffer_size, omnitrace::sampling::sampler_t,
|
||||
TIMEMORY_ESC(std::integral_constant<size_t, 256>))
|
||||
|
||||
@@ -31,7 +31,25 @@ enum class State : unsigned short
|
||||
{
|
||||
DelayedInit = 0,
|
||||
PreInit,
|
||||
Init,
|
||||
Active,
|
||||
Finalized
|
||||
};
|
||||
|
||||
enum class Mode : unsigned short
|
||||
{
|
||||
Trace = 0,
|
||||
Sampling
|
||||
};
|
||||
} // namespace omnitrace
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
std::string
|
||||
to_string(omnitrace::State _v);
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::Mode _v);
|
||||
} // namespace std
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace omnitrace
|
||||
static constexpr size_t max_supported_threads = OMNITRACE_MAX_THREADS;
|
||||
|
||||
template <typename Tp, typename Tag = void, size_t MaxThreads = max_supported_threads>
|
||||
struct omnitrace_thread_data
|
||||
struct thread_data
|
||||
{
|
||||
using instance_array_t = std::array<std::unique_ptr<Tp>, MaxThreads>;
|
||||
using construct_on_init = std::true_type;
|
||||
@@ -58,7 +58,7 @@ struct omnitrace_thread_data
|
||||
template <typename Tp, typename Tag, size_t MaxThreads>
|
||||
template <typename... Args>
|
||||
void
|
||||
omnitrace_thread_data<Tp, Tag, MaxThreads>::construct(Args&&... _args)
|
||||
thread_data<Tp, Tag, MaxThreads>::construct(Args&&... _args)
|
||||
{
|
||||
// construct outside of lambda to prevent data-race
|
||||
static auto& _instances = instances();
|
||||
@@ -72,14 +72,14 @@ omnitrace_thread_data<Tp, Tag, MaxThreads>::construct(Args&&... _args)
|
||||
|
||||
template <typename Tp, typename Tag, size_t MaxThreads>
|
||||
std::unique_ptr<Tp>&
|
||||
omnitrace_thread_data<Tp, Tag, MaxThreads>::instance()
|
||||
thread_data<Tp, Tag, MaxThreads>::instance()
|
||||
{
|
||||
return instances().at(threading::get_id());
|
||||
}
|
||||
|
||||
template <typename Tp, typename Tag, size_t MaxThreads>
|
||||
typename omnitrace_thread_data<Tp, Tag, MaxThreads>::instance_array_t&
|
||||
omnitrace_thread_data<Tp, Tag, MaxThreads>::instances()
|
||||
typename thread_data<Tp, Tag, MaxThreads>::instance_array_t&
|
||||
thread_data<Tp, Tag, MaxThreads>::instances()
|
||||
{
|
||||
static auto _v = instance_array_t{};
|
||||
return _v;
|
||||
@@ -88,7 +88,7 @@ omnitrace_thread_data<Tp, Tag, MaxThreads>::instances()
|
||||
template <typename Tp, typename Tag, size_t MaxThreads>
|
||||
template <typename... Args>
|
||||
std::unique_ptr<Tp>&
|
||||
omnitrace_thread_data<Tp, Tag, MaxThreads>::instance(construct_on_init, Args&&... _args)
|
||||
thread_data<Tp, Tag, MaxThreads>::instance(construct_on_init, Args&&... _args)
|
||||
{
|
||||
construct(std::forward<Args>(_args)...);
|
||||
return instances().at(threading::get_id());
|
||||
@@ -96,8 +96,8 @@ omnitrace_thread_data<Tp, Tag, MaxThreads>::instance(construct_on_init, Args&&..
|
||||
|
||||
template <typename Tp, typename Tag, size_t MaxThreads>
|
||||
template <typename... Args>
|
||||
typename omnitrace_thread_data<Tp, Tag, MaxThreads>::instance_array_t&
|
||||
omnitrace_thread_data<Tp, Tag, MaxThreads>::instances(construct_on_init, Args&&... _args)
|
||||
typename thread_data<Tp, Tag, MaxThreads>::instance_array_t&
|
||||
thread_data<Tp, Tag, MaxThreads>::instances(construct_on_init, Args&&... _args)
|
||||
{
|
||||
static auto _v = [&]() {
|
||||
auto _internal = instance_array_t{};
|
||||
|
||||
@@ -160,6 +160,10 @@ static regexvec_t file_exclude = {};
|
||||
if(verbose_level >= LEVEL) fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
|
||||
fflush(stdout);
|
||||
|
||||
#define verbprintf_bare(LEVEL, ...) \
|
||||
if(verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
|
||||
fflush(stdout);
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
template <typename... T>
|
||||
@@ -477,7 +481,7 @@ dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail
|
||||
{
|
||||
verbprintf(_level, "Dumping '%s'... ", _oname.c_str());
|
||||
dump_info(ofs, _data);
|
||||
verbprintf(_level, "Done\n");
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -597,7 +601,7 @@ omnitrace_get_address_space(patch_pointer_t& _bpatch, int _cmdc, char** _cmdv,
|
||||
_name.c_str());
|
||||
throw std::runtime_error("Failed to open binary");
|
||||
}
|
||||
verbprintf(1, "Done\n");
|
||||
verbprintf_bare(1, "Done\n");
|
||||
}
|
||||
else if(_pid >= 0)
|
||||
{
|
||||
@@ -611,7 +615,7 @@ omnitrace_get_address_space(patch_pointer_t& _bpatch, int _cmdc, char** _cmdv,
|
||||
(int) _pid);
|
||||
throw std::runtime_error("Failed to attach to process");
|
||||
}
|
||||
verbprintf(1, "Done\n");
|
||||
verbprintf_bare(1, "Done\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -630,7 +634,7 @@ omnitrace_get_address_space(patch_pointer_t& _bpatch, int _cmdc, char** _cmdv,
|
||||
ss.str().c_str());
|
||||
throw std::runtime_error("Failed to create process");
|
||||
}
|
||||
verbprintf(1, "Done\n");
|
||||
verbprintf_bare(1, "Done\n");
|
||||
}
|
||||
|
||||
return mutatee;
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "avail.hpp"
|
||||
|
||||
#include "library/api.hpp"
|
||||
#include "library/components/backtrace.hpp"
|
||||
#include "library/components/fork_gotcha.hpp"
|
||||
#include "library/components/mpi_gotcha.hpp"
|
||||
#include "library/components/omnitrace.hpp"
|
||||
#include "library/components/pthread_gotcha.hpp"
|
||||
#include "library/components/roctracer.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
|
||||
#include <timemory/components.hpp>
|
||||
#include <timemory/components/definition.hpp>
|
||||
@@ -249,8 +249,6 @@ enum
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
omnitrace::configure_settings();
|
||||
|
||||
array_t<bool, 6> options = { false, false, false, false, false, false };
|
||||
array_t<string_t, 6> fields = {};
|
||||
array_t<bool, 6> use_mark = {};
|
||||
@@ -436,7 +434,7 @@ main(int argc, char** argv)
|
||||
_parser_set_if_exists(include_hw_counters, "hw-counters");
|
||||
|
||||
if(!include_components && !include_settings && !include_hw_counters)
|
||||
include_components = true;
|
||||
include_settings = true;
|
||||
|
||||
if(markdown || include_hw_counters) padding = 6;
|
||||
|
||||
@@ -457,6 +455,8 @@ main(int argc, char** argv)
|
||||
|
||||
if(!os) os = &std::cout;
|
||||
|
||||
omnitrace_init_library();
|
||||
|
||||
if(include_components) write_component_info(*os, options, use_mark, fields);
|
||||
|
||||
dump_log();
|
||||
@@ -699,39 +699,49 @@ write_settings_info(std::ostream& os, const array_t<bool, N>& opts,
|
||||
using width_type = array_t<int64_t, size>;
|
||||
using width_bool = array_t<bool, size>;
|
||||
|
||||
array_type _setting_output;
|
||||
unique_set _settings_exclude = { "OMNITRACE_ENVIRONMENT",
|
||||
"OMNITRACE_COMMAND_LINE",
|
||||
"cereal_class_version",
|
||||
"settings",
|
||||
"OMNITRACE_CUDA_EVENT_BATCH_SIZE",
|
||||
"OMNITRACE_CUPTI_ACTIVITY_KINDS",
|
||||
"OMNITRACE_CUPTI_ACTIVITY_LEVEL",
|
||||
"OMNITRACE_CUPTI_DEVICE",
|
||||
"OMNITRACE_CUPTI_EVENTS",
|
||||
"OMNITRACE_CUPTI_METRICS",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_NUM_COLLECT",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_PERIOD",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_PER_LINE",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_REGION_TOTALS",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_SERIALIZED",
|
||||
"OMNITRACE_CUPTI_PCSAMPLING_STALL_REASONS" };
|
||||
|
||||
cereal::SettingsTextArchive settings_archive{ _setting_output, _settings_exclude };
|
||||
settings::serialize_settings(settings_archive);
|
||||
|
||||
width_type _widths = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
width_bool _wusing = {
|
||||
true, !force_brief, opts[0], opts[1], opts[1], opts[1], opts[2]
|
||||
};
|
||||
width_bool _mark = { false, false, false, true, true, true, false };
|
||||
|
||||
// this settings has delayed initialization. make sure it is generated
|
||||
(void) omnitrace::config::get_perfetto_output_filename();
|
||||
|
||||
array_type _setting_output;
|
||||
unique_set _settings_exclude = { "OMNITRACE_ENVIRONMENT", "OMNITRACE_COMMAND_LINE",
|
||||
"cereal_class_version", "settings" };
|
||||
|
||||
#if !defined(TIMEMORY_USE_CRAYPAT)
|
||||
_settings_exclude.emplace("OMNITRACE_CRAYPAT");
|
||||
#endif
|
||||
|
||||
cereal::SettingsTextArchive settings_archive{ _setting_output, _settings_exclude };
|
||||
settings::serialize_settings(settings_archive);
|
||||
|
||||
// exclude some timemory settings which are not relevant to omnitrace
|
||||
// exact matches, e.g. OMNITRACE_BANNER
|
||||
std::string _settings_rexclude_exact =
|
||||
"^OMNITRACE_(BANNER|DESTRUCTOR_REPORT|COMPONENTS|(GLOBAL|MPIP|NCCLP|OMPT|"
|
||||
"PROFILER|TRACE)_COMPONENTS|PYTHON_EXE|PAPI_ATTACH|PLOT_OUTPUT|SEPARATOR_FREQ|"
|
||||
"STACK_CLEARING|TARGET_PID|THROTTLE_(COUNT|VALUE)|(AUTO|FLAMEGRAPH)_OUTPUT|"
|
||||
"(ENABLE|DISABLE)_ALL_SIGNALS|ALLOW_SIGNAL_HANDLER|CTEST_NOTES)$";
|
||||
// leading matches, e.g. OMNITRACE_MPI_[A-Z_]+
|
||||
std::string _settings_rexclude_begin =
|
||||
"^OMNITRACE_(ERT|DART|MPI|UPCXX|ROOFLINE|CUDA|NVTX|CUPTI)_[A-Z_]+$";
|
||||
|
||||
// lambda for deciding which settings we want to restrict displaying
|
||||
auto&& _remove_conditions = [&_settings_exclude, &_settings_rexclude_exact,
|
||||
&_settings_rexclude_begin](const auto& itr) {
|
||||
auto&& _v = itr.find("environ")->second;
|
||||
bool _a = _settings_exclude.find(_v) != _settings_exclude.end();
|
||||
bool _b = std::regex_match(_v, std::regex(_settings_rexclude_exact));
|
||||
bool _c = std::regex_match(_v, std::regex(_settings_rexclude_begin));
|
||||
return (_a || _b || _c);
|
||||
};
|
||||
|
||||
_setting_output.erase(std::remove_if(_setting_output.begin(), _setting_output.end(),
|
||||
[&_settings_exclude](const auto& itr) {
|
||||
return _settings_exclude.find(
|
||||
itr.find("environ")->second) !=
|
||||
_settings_exclude.end();
|
||||
}),
|
||||
_remove_conditions),
|
||||
_setting_output.end());
|
||||
|
||||
if(alphabetical)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "library.hpp"
|
||||
#include "library/components/fork_gotcha.hpp"
|
||||
#include "library/components/mpi_gotcha.hpp"
|
||||
#include "library/components/rocm_smi.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/critical_trace.hpp"
|
||||
#include "library/debug.hpp"
|
||||
@@ -31,6 +32,7 @@
|
||||
#include "library/sampling.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
#include "timemory/mpl/type_traits.hpp"
|
||||
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
@@ -58,8 +60,15 @@ ensure_finalization(bool _static_init = false)
|
||||
else
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env(), "[%s]\n", __FUNCTION__);
|
||||
// This environment variable forces the ROCR-Runtime to use polling to wait
|
||||
// for signals rather than interrupts. We set this variable to avoid issues with
|
||||
// rocm/roctracer hanging when interrupted by the sampler
|
||||
//
|
||||
// see:
|
||||
// https://github.com/ROCm-Developer-Tools/roctracer/issues/22#issuecomment-572814465
|
||||
tim::set_env("HSA_ENABLE_INTERRUPT", "0", 0);
|
||||
}
|
||||
return scope::destructor{ []() { omnitrace_trace_finalize(); } };
|
||||
return scope::destructor{ []() { omnitrace_finalize(); } };
|
||||
}
|
||||
|
||||
auto&
|
||||
@@ -105,40 +114,271 @@ using Device = critical_trace::Device;
|
||||
using Phase = critical_trace::Phase;
|
||||
|
||||
bool
|
||||
omnitrace_init_tooling()
|
||||
{
|
||||
static bool _once = false;
|
||||
if(get_state() != State::PreInit || _once) return false;
|
||||
_once = true;
|
||||
omnitrace_init_tooling();
|
||||
} // namespace
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
/// \fn void omnitrace_push_trace(const char* name)
|
||||
/// \brief the "start" function for an instrumentation region
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_trace(const char* name)
|
||||
{
|
||||
// return if not active
|
||||
if(get_state() == State::Finalized) return;
|
||||
|
||||
if(get_state() != State::Active && !omnitrace_init_tooling())
|
||||
{
|
||||
static auto _debug = get_debug_env();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug, "[%s] %s :: not active and perfetto not initialized\n", __FUNCTION__,
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
|
||||
|
||||
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
|
||||
static thread_local size_t _sample_idx = 0;
|
||||
auto _enabled = (_sample_idx++ % _sample_rate == 0);
|
||||
get_interval_data().emplace_back(_enabled);
|
||||
if(_enabled) get_functors().first(name);
|
||||
if(get_use_critical_trace())
|
||||
{
|
||||
auto _ts = comp::wall_clock::record();
|
||||
auto _cid = get_cpu_cid()++;
|
||||
uint16_t _depth = (get_cpu_cid_stack()->empty())
|
||||
? get_cpu_cid_stack(0)->size()
|
||||
: get_cpu_cid_stack()->size() - 1;
|
||||
auto _parent_cid = (get_cpu_cid_stack()->empty()) ? get_cpu_cid_stack(0)->back()
|
||||
: get_cpu_cid_stack()->back();
|
||||
get_cpu_cid_parents().emplace(_cid, std::make_tuple(_parent_cid, _depth));
|
||||
add_critical_trace<Device::CPU, Phase::BEGIN>(
|
||||
threading::get_id(), _cid, 0, _parent_cid, _ts, 0,
|
||||
critical_trace::add_hash_id(name), _depth);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
/// \fn void omnitrace_pop_trace(const char* name)
|
||||
/// \brief the "stop" function for an instrumentation region
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_trace(const char* name)
|
||||
{
|
||||
if(get_state() == State::Active)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
|
||||
auto& _interval_data = get_interval_data();
|
||||
if(!_interval_data.empty())
|
||||
{
|
||||
if(_interval_data.back()) get_functors().second(name);
|
||||
_interval_data.pop_back();
|
||||
}
|
||||
if(get_use_critical_trace())
|
||||
{
|
||||
if(get_cpu_cid_stack() && !get_cpu_cid_stack()->empty())
|
||||
{
|
||||
auto _cid = get_cpu_cid_stack()->back();
|
||||
if(get_cpu_cid_parents().find(_cid) != get_cpu_cid_parents().end())
|
||||
{
|
||||
uint64_t _parent_cid = 0;
|
||||
uint16_t _depth = 0;
|
||||
auto _ts = comp::wall_clock::record();
|
||||
std::tie(_parent_cid, _depth) = get_cpu_cid_parents().at(_cid);
|
||||
add_critical_trace<Device::CPU, Phase::END>(
|
||||
threading::get_id(), _cid, 0, _parent_cid, _ts, _ts,
|
||||
critical_trace::add_hash_id(name), _depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static auto _debug = get_debug_env();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug, "[%s] %s ignored :: not active\n",
|
||||
__FUNCTION__, name);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
/// \fn void omnitrace_set_env(const char* name, const char* env_val)
|
||||
/// \brief Sets an initial environment variable
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_set_env(const char* env_name, const char* env_val)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
|
||||
"[%s] Setting env: %s=%s\n", __FUNCTION__, env_name,
|
||||
env_val);
|
||||
|
||||
tim::set_env(env_name, env_val, 0);
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() >= State::Init &&
|
||||
(config::get_is_continuous_integration() || get_debug_env()),
|
||||
"%s(\"%s\", \"%s\") called after omnitrace was initialized. state = %s",
|
||||
__FUNCTION__, env_name, env_val, std::to_string(get_state()).c_str());
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
/// \fn void omnitrace_set_mpi(bool use, bool attached)
|
||||
/// \brief Configures whether MPI support should be activated
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
namespace
|
||||
{
|
||||
bool _set_mpi_called = false;
|
||||
std::function<void()> _start_gotcha_callback = []() {};
|
||||
} // namespace
|
||||
|
||||
extern "C" void
|
||||
omnitrace_set_mpi(bool use, bool attached)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
|
||||
"[%s] use: %s, attached: %s\n", __FUNCTION__,
|
||||
(use) ? "y" : "n", (attached) ? "y" : "n");
|
||||
|
||||
_set_mpi_called = true;
|
||||
config::is_attached() = attached;
|
||||
|
||||
if(use && !attached &&
|
||||
(get_state() == State::PreInit || get_state() == State::DelayedInit))
|
||||
{
|
||||
tim::set_env("OMNITRACE_USE_PID", "ON", 1);
|
||||
}
|
||||
else if(!use)
|
||||
{
|
||||
trait::runtime_enabled<mpi_gotcha_t>::set(false);
|
||||
}
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() >= State::Init &&
|
||||
(config::get_is_continuous_integration() || get_debug_env()),
|
||||
"%s(use=%s, attached=%s) called after omnitrace was initialized. state = %s",
|
||||
__FUNCTION__, std::to_string(use).c_str(), std::to_string(attached).c_str(),
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
_start_gotcha_callback();
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_init_library()
|
||||
{
|
||||
auto _tid = threading::get_id();
|
||||
(void) _tid;
|
||||
|
||||
auto _mode = tim::get_env<std::string>("OMNITRACE_MODE", "");
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(true, "Instrumentation mode: %s\n", _mode.c_str());
|
||||
auto _mode = get_mode();
|
||||
|
||||
get_state() = State::Init;
|
||||
|
||||
// configure the settings
|
||||
configure_settings();
|
||||
|
||||
if(gpu::device_count() == 0)
|
||||
auto _debug_init = get_debug_init();
|
||||
auto _debug_value = get_debug();
|
||||
if(_debug_init) config::set_setting_value("OMNITRACE_DEBUG", true);
|
||||
scope::destructor _debug_dtor{ [_debug_value, _debug_init]() {
|
||||
if(_debug_init) config::set_setting_value("OMNITRACE_DEBUG", _debug_value);
|
||||
} };
|
||||
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
// below will effectively do:
|
||||
// get_cpu_cid_stack(0)->emplace_back(-1);
|
||||
// plus query some env variables
|
||||
add_critical_trace<Device::CPU, Phase::NONE>(0, -1, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
if(gpu::device_count() == 0 && get_state() != State::Active)
|
||||
{
|
||||
OMNITRACE_DEBUG("No HIP devices were found: disabling roctracer...\n");
|
||||
OMNITRACE_DEBUG(
|
||||
"No HIP devices were found: disabling roctracer and rocm_smi...\n");
|
||||
get_use_roctracer() = false;
|
||||
get_use_rocm_smi() = false;
|
||||
}
|
||||
|
||||
if(_mode == "sampling")
|
||||
if(_mode == Mode::Sampling)
|
||||
{
|
||||
OMNITRACE_PRINT(
|
||||
"Disabling perfetto, timemory, and critical trace in %s mode...\n",
|
||||
_mode.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0,
|
||||
"Disabling critical trace in %s mode...\n",
|
||||
std::to_string(_mode).c_str());
|
||||
get_use_sampling() = true;
|
||||
get_use_timemory() = false;
|
||||
get_use_perfetto() = false;
|
||||
get_use_roctracer() = false;
|
||||
get_use_critical_trace() = false;
|
||||
}
|
||||
|
||||
tim::trait::runtime_enabled<comp::roctracer>::set(get_use_roctracer());
|
||||
tim::trait::runtime_enabled<comp::roctracer_data>::set(get_use_roctracer());
|
||||
|
||||
if(get_instrumentation_interval() < 1) get_instrumentation_interval() = 1;
|
||||
get_interval_data().reserve(512);
|
||||
|
||||
if(get_use_kokkosp())
|
||||
{
|
||||
auto _force = 0;
|
||||
if(tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY") == "libtimemory.so")
|
||||
_force = 1;
|
||||
tim::set_env("KOKKOS_PROFILE_LIBRARY", "libomnitrace.so", _force);
|
||||
}
|
||||
|
||||
#if defined(OMNITRACE_USE_ROCTRACER)
|
||||
tim::set_env("HSA_TOOLS_LIB", "libomnitrace.so", 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
namespace
|
||||
{
|
||||
bool
|
||||
omnitrace_init_tooling()
|
||||
{
|
||||
static bool _once = false;
|
||||
if(get_state() != State::PreInit || get_state() == State::Init || _once) return false;
|
||||
_once = true;
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() == State::Init,
|
||||
"%s called after omnitrace_init_library() was explicitly called", __FUNCTION__);
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_verbose_env() >= 0,
|
||||
"Instrumentation mode: %s\n",
|
||||
std::to_string(config::get_mode()).c_str());
|
||||
|
||||
if(get_verbose_env() >= 0) print_banner();
|
||||
|
||||
omnitrace_init_library();
|
||||
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
auto _dtor = scope::destructor{ []() {
|
||||
// if roctracer is not enabled, we cannot rely on OnLoad(...) via HSA tools
|
||||
// to setup rocm-smi
|
||||
if constexpr(!trait::is_available<comp::roctracer>::value)
|
||||
{
|
||||
try
|
||||
{
|
||||
rocm_smi::setup();
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_PRINT("Exception: %s\n", _e.what());
|
||||
}
|
||||
}
|
||||
|
||||
if(get_use_sampling())
|
||||
{
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
@@ -146,6 +386,8 @@ omnitrace_init_tooling()
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = true;
|
||||
sampling::unblock_signals();
|
||||
}
|
||||
get_main_bundle()->start();
|
||||
get_state()= State::Active; // set to active as very last operation
|
||||
} };
|
||||
|
||||
if(get_use_sampling())
|
||||
@@ -154,9 +396,8 @@ omnitrace_init_tooling()
|
||||
sampling::block_signals();
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
if(!get_use_timemory() && !get_use_perfetto() && !get_use_sampling())
|
||||
if(!get_use_timemory() && !get_use_perfetto() && !get_use_sampling() &&
|
||||
!get_use_rocm_smi())
|
||||
{
|
||||
get_state() = State::Finalized;
|
||||
OMNITRACE_DEBUG("[%s] Both perfetto and timemory are disabled. Setting the state "
|
||||
@@ -165,16 +406,6 @@ omnitrace_init_tooling()
|
||||
return false;
|
||||
}
|
||||
|
||||
// below will effectively do:
|
||||
// get_cpu_cid_stack(0)->emplace_back(-1);
|
||||
// plus query some env variables
|
||||
add_critical_trace<Device::CPU, Phase::NONE>(0, -1, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
tim::trait::runtime_enabled<comp::roctracer>::set(get_use_roctracer());
|
||||
|
||||
if(get_instrumentation_interval() < 1) get_instrumentation_interval() = 1;
|
||||
get_interval_data().reserve(512);
|
||||
|
||||
if(get_use_timemory())
|
||||
{
|
||||
comp::user_global_bundle::global_init();
|
||||
@@ -204,17 +435,6 @@ omnitrace_init_tooling()
|
||||
}
|
||||
}
|
||||
|
||||
auto& _main_bundle = get_main_bundle();
|
||||
_main_bundle->start();
|
||||
|
||||
#if defined(OMNITRACE_USE_ROCTRACER)
|
||||
if(get_use_roctracer())
|
||||
{
|
||||
assert(_main_bundle->get<comp::roctracer>() != nullptr);
|
||||
assert(_main_bundle->get<comp::roctracer>()->get_is_running());
|
||||
}
|
||||
#endif
|
||||
|
||||
perfetto::TracingInitArgs args{};
|
||||
perfetto::TraceConfig cfg{};
|
||||
perfetto::protos::gen::TrackEventConfig track_event_cfg{};
|
||||
@@ -248,17 +468,20 @@ omnitrace_init_tooling()
|
||||
|
||||
auto _exe = get_exe_name();
|
||||
static auto _thread_init = [_exe]() {
|
||||
omnitrace_thread_data<omnitrace_thread_bundle_t>::construct(
|
||||
TIMEMORY_JOIN("", _exe, "/thread-", threading::get_id()),
|
||||
quirk::config<quirk::auto_start>{});
|
||||
if(get_use_sampling())
|
||||
{
|
||||
static thread_local auto _once = std::once_flag{};
|
||||
std::call_once(_once, sampling::setup);
|
||||
}
|
||||
static thread_local auto _thread_setup = [_exe]() {
|
||||
if(threading::get_id() > 0)
|
||||
threading::set_thread_name(
|
||||
TIMEMORY_JOIN(" ", "Thread", threading::get_id()).c_str());
|
||||
thread_data<omnitrace_thread_bundle_t>::construct(
|
||||
TIMEMORY_JOIN("", _exe, "/thread-", threading::get_id()),
|
||||
quirk::config<quirk::auto_start>{});
|
||||
if(get_use_sampling()) sampling::setup();
|
||||
};
|
||||
static thread_local auto _once = std::once_flag{};
|
||||
std::call_once(_once, _thread_setup);
|
||||
static thread_local auto _dtor = scope::destructor{ []() {
|
||||
if(get_use_sampling()) sampling::shutdown();
|
||||
omnitrace_thread_data<omnitrace_thread_bundle_t>::instance()->stop();
|
||||
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
|
||||
} };
|
||||
(void) _dtor;
|
||||
};
|
||||
@@ -318,58 +541,6 @@ omnitrace_init_tooling()
|
||||
get_functors().second = _pop_timemory;
|
||||
}
|
||||
|
||||
if(dmp::rank() == 0)
|
||||
{
|
||||
static std::set<tim::string_view_t> _sample_options = {
|
||||
"OMNITRACE_SAMPLING_FREQ", "OMNITRACE_SAMPLING_DELAY",
|
||||
"OMNITRACE_FLAT_SAMPLING", "OMNITRACE_TIMELINE_SAMPLING",
|
||||
"OMNITRACE_FLAT_SAMPLING", "OMNITRACE_TIMELINE_SAMPLING",
|
||||
};
|
||||
static std::set<tim::string_view_t> _perfetto_options = {
|
||||
"OMNITRACE_OUTPUT_FILE",
|
||||
"OMNITRACE_BACKEND",
|
||||
"OMNITRACE_SHMEM_SIZE_HINT_KB",
|
||||
"OMNITRACE_BUFFER_SIZE_KB",
|
||||
};
|
||||
static std::set<tim::string_view_t> _timemory_options = {
|
||||
"OMNITRACE_ROCTRACER_FLAT_PROFILE", "OMNITRACE_ROCTRACER_TIMELINE_PROFILE"
|
||||
};
|
||||
// generic filter for filtering relevant options
|
||||
auto _is_omnitrace_option = [](const auto& _v, const auto& _c) {
|
||||
if(!get_use_roctracer() && _v.find("OMNITRACE_ROCTRACER_") == 0) return false;
|
||||
if(!get_use_critical_trace() && _v.find("OMNITRACE_CRITICAL_TRACE_") == 0)
|
||||
return false;
|
||||
if(!get_use_perfetto() && _perfetto_options.count(_v) > 0) return false;
|
||||
if(!get_use_timemory() && _timemory_options.count(_v) > 0) return false;
|
||||
if(!get_use_sampling() && _sample_options.count(_v) > 0) return false;
|
||||
const auto npos = std::string::npos;
|
||||
if(_v.find("WIDTH") != npos || _v.find("SEPARATOR_FREQ") != npos ||
|
||||
_v.find("AUTO_OUTPUT") != npos || _v.find("DART_OUTPUT") != npos ||
|
||||
_v.find("FILE_OUTPUT") != npos || _v.find("PLOT_OUTPUT") != npos ||
|
||||
_v.find("FLAMEGRAPH_OUTPUT") != npos)
|
||||
return false;
|
||||
if(!_c.empty())
|
||||
{
|
||||
if(_c.find("omnitrace") != _c.end()) return true;
|
||||
if(_c.find("debugging") != _c.end() && _v.find("DEBUG") != npos)
|
||||
return true;
|
||||
if(_c.find("config") != _c.end()) return true;
|
||||
if(_c.find("dart") != _c.end()) return false;
|
||||
if(_c.find("io") != _c.end() && _v.find("_OUTPUT") != npos) return true;
|
||||
if(_c.find("format") != _c.end()) return true;
|
||||
return false;
|
||||
}
|
||||
return (_v.find("OMNITRACE_") == 0);
|
||||
};
|
||||
|
||||
if(tim::settings::verbose() > 0)
|
||||
tim::print_env(std::cerr, [_is_omnitrace_option](const std::string& _v) {
|
||||
return _is_omnitrace_option(_v, std::set<std::string>{});
|
||||
});
|
||||
|
||||
print_config_settings(std::cerr, _is_omnitrace_option);
|
||||
}
|
||||
|
||||
if(get_use_perfetto() && !is_system_backend())
|
||||
{
|
||||
#if defined(CUSTOM_DATA_SOURCE)
|
||||
@@ -392,126 +563,78 @@ omnitrace_init_tooling()
|
||||
tracing_session->StartBlocking();
|
||||
}
|
||||
|
||||
get_state() = State::Active;
|
||||
|
||||
// if static objects are destroyed in the inverse order of when they are
|
||||
// created this should ensure that finalization is called before perfetto
|
||||
// ends the tracing session
|
||||
static auto _ensure_finalization = ensure_finalization();
|
||||
|
||||
if(dmp::rank() == 0) puts("");
|
||||
if(dmp::rank() == 0 && get_verbose() >= 0) fprintf(stderr, "\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_trace(const char* name)
|
||||
omnitrace_init(const char* _mode, bool _is_binary_rewrite, const char* _argv0)
|
||||
{
|
||||
// return if not active
|
||||
if(get_state() == State::Finalized) return;
|
||||
// always the first
|
||||
std::atexit(&omnitrace_finalize);
|
||||
|
||||
if(get_state() != State::Active && !omnitrace_init_tooling())
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_debug_env() || get_verbose_env() > 2,
|
||||
"[%s] mode: %s | is binary rewrite: %s | command: %s\n", __FUNCTION__, _mode,
|
||||
(_is_binary_rewrite) ? "y" : "n", _argv0);
|
||||
|
||||
tim::set_env("OMNITRACE_MODE", _mode, 0);
|
||||
config::is_binary_rewrite() = _is_binary_rewrite;
|
||||
|
||||
if(!_set_mpi_called)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] %s :: not active and perfetto not initialized\n",
|
||||
__FUNCTION__, name);
|
||||
return;
|
||||
_start_gotcha_callback = []() { get_gotcha_bundle()->start(); };
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
|
||||
}
|
||||
|
||||
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
|
||||
static thread_local size_t _sample_idx = 0;
|
||||
auto _enabled = (_sample_idx++ % _sample_rate == 0);
|
||||
get_interval_data().emplace_back(_enabled);
|
||||
if(_enabled) get_functors().first(name);
|
||||
if(get_use_critical_trace())
|
||||
{
|
||||
auto _ts = comp::wall_clock::record();
|
||||
auto _cid = get_cpu_cid()++;
|
||||
uint16_t _depth = (get_cpu_cid_stack()->empty())
|
||||
? get_cpu_cid_stack(0)->size()
|
||||
: get_cpu_cid_stack()->size() - 1;
|
||||
auto _parent_cid = (get_cpu_cid_stack()->empty()) ? get_cpu_cid_stack(0)->back()
|
||||
: get_cpu_cid_stack()->back();
|
||||
get_cpu_cid_parents().emplace(_cid, std::make_tuple(_parent_cid, _depth));
|
||||
add_critical_trace<Device::CPU, Phase::BEGIN>(
|
||||
threading::get_id(), _cid, 0, _parent_cid, _ts, 0,
|
||||
critical_trace::add_hash_id(name), _depth);
|
||||
get_gotcha_bundle()->start();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_trace(const char* name)
|
||||
{
|
||||
if(get_state() == State::Active)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] %s\n", __FUNCTION__, name);
|
||||
auto& _interval_data = get_interval_data();
|
||||
if(!_interval_data.empty())
|
||||
{
|
||||
if(_interval_data.back()) get_functors().second(name);
|
||||
_interval_data.pop_back();
|
||||
}
|
||||
if(get_use_critical_trace())
|
||||
{
|
||||
if(get_cpu_cid_stack() && !get_cpu_cid_stack()->empty())
|
||||
{
|
||||
auto _cid = get_cpu_cid_stack()->back();
|
||||
if(get_cpu_cid_parents().find(_cid) != get_cpu_cid_parents().end())
|
||||
{
|
||||
uint64_t _parent_cid = 0;
|
||||
uint16_t _depth = 0;
|
||||
auto _ts = comp::wall_clock::record();
|
||||
std::tie(_parent_cid, _depth) = get_cpu_cid_parents().at(_cid);
|
||||
add_critical_trace<Device::CPU, Phase::END>(
|
||||
threading::get_id(), _cid, 0, _parent_cid, _ts, _ts,
|
||||
critical_trace::add_hash_id(name), _depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] %s :: not active\n", __FUNCTION__, name);
|
||||
}
|
||||
}
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_trace_init(const char* _info, bool _b, const char* _extra)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s | %s | %s\n",
|
||||
__FUNCTION__, _info, (_b) ? "y" : "n", _extra);
|
||||
auto& _gotcha_bundle = get_gotcha_bundle();
|
||||
(void) _gotcha_bundle;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_trace_finalize(void)
|
||||
omnitrace_finalize(void)
|
||||
{
|
||||
// return if not active
|
||||
if(get_state() != State::Active) return;
|
||||
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
|
||||
auto _debug_init = get_debug_finalize();
|
||||
auto _debug_value = get_debug();
|
||||
if(_debug_init) config::set_setting_value("OMNITRACE_DEBUG", true);
|
||||
scope::destructor _debug_dtor{ [_debug_value, _debug_init]() {
|
||||
if(_debug_init) config::set_setting_value("OMNITRACE_DEBUG", _debug_value);
|
||||
} };
|
||||
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
if(dmp::rank() == 0) puts("");
|
||||
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_use_sampling())
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] Shutting down sampling...\n", __FUNCTION__);
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
sampling::shutdown();
|
||||
sampling::block_signals();
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("[%s] Stopping gotcha bundle...\n", __FUNCTION__);
|
||||
|
||||
// stop the gotcha bundle
|
||||
if(get_gotcha_bundle())
|
||||
{
|
||||
@@ -519,11 +642,19 @@ omnitrace_trace_finalize(void)
|
||||
get_gotcha_bundle().reset();
|
||||
}
|
||||
|
||||
#if defined(OMNITRACE_USE_ROCTRACER)
|
||||
pthread_gotcha::shutdown();
|
||||
|
||||
if(get_use_rocm_smi())
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] Shutting down rocm-smi sampling...\n", __FUNCTION__);
|
||||
rocm_smi::shutdown();
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("[%s] Shutting down roctracer...\n", __FUNCTION__);
|
||||
// ensure that threads running roctracer callbacks shutdown
|
||||
if(get_use_roctracer()) comp::roctracer::tear_down();
|
||||
#endif
|
||||
comp::roctracer::shutdown();
|
||||
|
||||
if(dmp::rank() == 0) fprintf(stderr, "\n");
|
||||
|
||||
OMNITRACE_DEBUG("[%s] Stopping main bundle...\n", __FUNCTION__);
|
||||
// stop the main bundle and report the high-level metrics
|
||||
@@ -551,7 +682,7 @@ omnitrace_trace_finalize(void)
|
||||
// thread-specific data will be wrong if try to stop them from
|
||||
// the main thread.
|
||||
OMNITRACE_DEBUG("[%s] Destroying thread bundle data...\n", __FUNCTION__);
|
||||
for(auto& itr : omnitrace_thread_data<omnitrace_thread_bundle_t>::instances())
|
||||
for(auto& itr : thread_data<omnitrace_thread_bundle_t>::instances())
|
||||
{
|
||||
if(itr && itr->get<comp::wall_clock>() &&
|
||||
!itr->get<comp::wall_clock>()->get_is_running())
|
||||
@@ -559,7 +690,7 @@ omnitrace_trace_finalize(void)
|
||||
std::string _msg = JOIN("", *itr);
|
||||
auto _pos = _msg.find(">>> ");
|
||||
if(_pos != std::string::npos) _msg = _msg.substr(_pos + 5);
|
||||
OMNITRACE_PRINT("%s\n", _msg.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0, "%s\n", _msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +721,7 @@ omnitrace_trace_finalize(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(get_use_critical_trace())
|
||||
if(get_use_critical_trace() || (get_use_rocm_smi() && get_use_roctracer()))
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] Generating the critical trace...\n", __FUNCTION__);
|
||||
// increase the thread-pool size
|
||||
@@ -600,7 +731,7 @@ omnitrace_trace_finalize(void)
|
||||
for(size_t i = 0; i < max_supported_threads; ++i)
|
||||
{
|
||||
using critical_trace_hash_data =
|
||||
omnitrace_thread_data<critical_trace::hash_ids, critical_trace::id>;
|
||||
thread_data<critical_trace::hash_ids, critical_trace::id>;
|
||||
|
||||
if(critical_trace_hash_data::instances().at(i))
|
||||
critical_trace::add_hash_id(*critical_trace_hash_data::instances().at(i));
|
||||
@@ -608,12 +739,34 @@ omnitrace_trace_finalize(void)
|
||||
|
||||
for(size_t i = 0; i < max_supported_threads; ++i)
|
||||
{
|
||||
using critical_trace_chain_data =
|
||||
omnitrace_thread_data<critical_trace::call_chain>;
|
||||
using critical_trace_chain_data = thread_data<critical_trace::call_chain>;
|
||||
|
||||
if(critical_trace_chain_data::instances().at(i))
|
||||
critical_trace::update(i); // launch update task
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that all the MT instances are flushed
|
||||
if(get_use_rocm_smi())
|
||||
{
|
||||
size_t _ndevice = gpu::device_count();
|
||||
OMNITRACE_CONDITIONAL_PRINT(
|
||||
get_debug() || get_verbose() > 0,
|
||||
"[%s] Post-processing rocm-smi samples for %zu devices...\n", __FUNCTION__,
|
||||
_ndevice);
|
||||
for(size_t i = 0; i < _ndevice; ++i)
|
||||
{
|
||||
rocm_smi::data::post_process(i);
|
||||
rocm_smi::sampler_instances::instances().at(i).reset();
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
@@ -630,7 +783,10 @@ omnitrace_trace_finalize(void)
|
||||
bool _perfetto_output_error = false;
|
||||
if(get_use_perfetto() && !is_system_backend())
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] Flushing perfetto...\n", __FUNCTION__);
|
||||
if(get_verbose() >= 0) fprintf(stderr, "\n");
|
||||
if(get_verbose() >= 0 || get_debug())
|
||||
fprintf(stderr, "[%s]|%i> Flushing perfetto...\n", __FUNCTION__, dmp::rank());
|
||||
|
||||
// Make sure the last event is closed for this example.
|
||||
perfetto::TrackEvent::Flush();
|
||||
|
||||
@@ -650,14 +806,12 @@ omnitrace_trace_finalize(void)
|
||||
return;
|
||||
}
|
||||
// Write the trace into a file.
|
||||
fprintf(stderr,
|
||||
"[%s]> Outputting '%s'. Trace data: %lu B (%.2f KB / %.2f MB / %.2f "
|
||||
"GB)... ",
|
||||
__FUNCTION__, get_perfetto_output_filename().c_str(),
|
||||
(unsigned long) trace_data.size(),
|
||||
static_cast<double>(trace_data.size()) / units::KB,
|
||||
static_cast<double>(trace_data.size()) / units::MB,
|
||||
static_cast<double>(trace_data.size()) / units::GB);
|
||||
if(get_verbose() >= 0)
|
||||
fprintf(stderr, "[%s]|%i> Outputting '%s' (%.2f KB / %.2f MB / %.2f GB)... ",
|
||||
__FUNCTION__, dmp::rank(), get_perfetto_output_filename().c_str(),
|
||||
static_cast<double>(trace_data.size()) / units::KB,
|
||||
static_cast<double>(trace_data.size()) / units::MB,
|
||||
static_cast<double>(trace_data.size()) / units::GB);
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, get_perfetto_output_filename(),
|
||||
std::ios::out | std::ios::binary))
|
||||
@@ -669,10 +823,11 @@ omnitrace_trace_finalize(void)
|
||||
else
|
||||
{
|
||||
// Write the trace into a file.
|
||||
fprintf(stderr, "Done\n");
|
||||
if(get_verbose() >= 0) fprintf(stderr, "Done\n");
|
||||
ofs.write(&trace_data[0], trace_data.size());
|
||||
}
|
||||
ofs.close();
|
||||
if(get_verbose() >= 0) fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
// these should be destroyed before timemory is finalized, especially the
|
||||
@@ -691,33 +846,14 @@ omnitrace_trace_finalize(void)
|
||||
OMNITRACE_DEBUG("[%s] Finalizing timemory... Done\n", __FUNCTION__);
|
||||
|
||||
if(_perfetto_output_error)
|
||||
throw std::runtime_error("Unable to create perfetto output file");
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_trace_set_env(const char* env_name, const char* env_val)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env(), "[%s] Setting env: %s=%s\n",
|
||||
__FUNCTION__, env_name, env_val);
|
||||
|
||||
tim::set_env(env_name, env_val, 0);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_trace_set_mpi(bool use, bool attached)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env(), "[%s] use: %s, attached: %s\n",
|
||||
__FUNCTION__, (use) ? "y" : "n", (attached) ? "y" : "n");
|
||||
if(use && !attached &&
|
||||
(get_state() == State::PreInit || get_state() == State::DelayedInit))
|
||||
{
|
||||
tim::set_env("OMNITRACE_USE_PID", "ON", 1);
|
||||
get_state() = State::DelayedInit;
|
||||
OMNITRACE_THROW("Error opening perfetto output file: %s",
|
||||
get_perfetto_output_filename().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
namespace
|
||||
{
|
||||
// if static objects are destroyed randomly (relatively uncommon behavior)
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/fwd.hpp"
|
||||
#include "library/components/rocm_smi.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/perfetto.hpp"
|
||||
#include "library/ptl.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
|
||||
@@ -44,6 +46,7 @@
|
||||
#include <timemory/sampling/allocator.hpp>
|
||||
#include <timemory/sampling/sampler.hpp>
|
||||
#include <timemory/storage.hpp>
|
||||
#include <timemory/units.hpp>
|
||||
#include <timemory/utility/backtrace.hpp>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
#include <timemory/utility/types.hpp>
|
||||
@@ -99,10 +102,10 @@ namespace omnitrace
|
||||
namespace component
|
||||
{
|
||||
using hw_counters = typename backtrace::hw_counters;
|
||||
using signal_type_instances = omnitrace_thread_data<std::set<int>, api::sampling>;
|
||||
using backtrace_init_instances = omnitrace_thread_data<backtrace, api::sampling>;
|
||||
using sampler_running_instances = omnitrace_thread_data<bool, api::sampling>;
|
||||
using papi_vector_instances = omnitrace_thread_data<hw_counters, api::sampling>;
|
||||
using signal_type_instances = thread_data<std::set<int>, api::sampling>;
|
||||
using backtrace_init_instances = thread_data<backtrace, api::sampling>;
|
||||
using sampler_running_instances = thread_data<bool, api::sampling>;
|
||||
using papi_vector_instances = thread_data<hw_counters, api::sampling>;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -154,9 +157,31 @@ backtrace::preinit()
|
||||
sampling_cpu_clock::label() = "sampling_cpu_clock";
|
||||
sampling_cpu_clock::description() = "CPU clock time (via sampling)";
|
||||
|
||||
sampling_percent::label() = "sampling_percent";
|
||||
sampling_percent::description() = "Percentage of samples";
|
||||
sampling_percent::display_unit() = "%";
|
||||
sampling_percent::label() = "sampling_percent";
|
||||
sampling_percent::description() = "Percentage of samples";
|
||||
|
||||
sampling_gpu_busy::label() = "sampling_gpu_busy_percent";
|
||||
sampling_gpu_busy::description() = "Utilization of GPU(s)";
|
||||
sampling_gpu_busy::set_precision(0);
|
||||
sampling_gpu_busy::set_format_flags(sampling_gpu_busy::get_format_flags() &
|
||||
std::ios_base::showpoint);
|
||||
|
||||
sampling_gpu_memory::label() = "sampling_gpu_memory_usage";
|
||||
sampling_gpu_memory::description() = "Memory usage of GPU(s)";
|
||||
|
||||
sampling_gpu_power::label() = "sampling_gpu_power";
|
||||
sampling_gpu_power::description() = "Power usage of GPU(s)";
|
||||
sampling_gpu_power::unit() = units::watt;
|
||||
sampling_gpu_power::display_unit() = "watts";
|
||||
sampling_gpu_power::set_precision(2);
|
||||
sampling_gpu_power::set_format_flags(sampling_gpu_power::get_format_flags());
|
||||
|
||||
sampling_gpu_temp::label() = "sampling_gpu_temperature";
|
||||
sampling_gpu_temp::description() = "Temperature of GPU(s)";
|
||||
sampling_gpu_temp::unit() = 1;
|
||||
sampling_gpu_temp::display_unit() = "degC";
|
||||
sampling_gpu_temp::set_precision(1);
|
||||
sampling_gpu_temp::set_format_flags(sampling_gpu_temp::get_format_flags());
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -236,6 +261,7 @@ backtrace::sample(int signum)
|
||||
m_tid = threading::get_id();
|
||||
m_ts = clock_type::now();
|
||||
m_thr_cpu_ts = tim::get_clock_thread_now<int64_t, std::nano>();
|
||||
m_mem_peak = tim::get_peak_rss(RUSAGE_THREAD);
|
||||
m_data = tim::get_unw_backtrace<128, 4, false>();
|
||||
auto* itr = m_data.begin();
|
||||
for(; itr != m_data.end(); ++itr, ++m_size)
|
||||
@@ -295,11 +321,12 @@ backtrace::configure(bool _setup, int64_t _tid)
|
||||
sampling::block_signals(*_signal_types);
|
||||
if constexpr(tim::trait::is_available<hw_counters>::value)
|
||||
{
|
||||
perfetto_counter_track<hw_counters>::init();
|
||||
OMNITRACE_DEBUG("HW COUNTER: starting...\n");
|
||||
if(get_papi_vector(_tid)) get_papi_vector(_tid)->start();
|
||||
}
|
||||
|
||||
auto _alrm_freq = 1.0 / std::min<double>(get_sampling_freq(), 10.0);
|
||||
auto _alrm_freq = 1.0 / std::min<double>(get_sampling_freq(), 5.0);
|
||||
auto _prof_freq = 1.0 / get_sampling_freq();
|
||||
auto _delay = std::max<double>(1.0e-3, get_sampling_delay());
|
||||
|
||||
@@ -312,10 +339,14 @@ backtrace::configure(bool _setup, int64_t _tid)
|
||||
_sampler->set_delay(_delay);
|
||||
_sampler->set_frequency(_prof_freq, { SIGPROF });
|
||||
_sampler->set_frequency(_alrm_freq, { SIGALRM });
|
||||
|
||||
static_assert(tim::trait::buffer_size<sampling::sampler_t>::value > 0,
|
||||
"Error! Zero buffer size");
|
||||
if(_sampler->get_buffer_size() == 0)
|
||||
throw std::runtime_error("dynamic sampler has a zero buffer size");
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
_sampler->get_buffer_size() <= 0,
|
||||
"dynamic sampler requires a positive buffer size: %zu",
|
||||
_sampler->get_buffer_size());
|
||||
|
||||
OMNITRACE_DEBUG("Sampler for thread %lu will be triggered %5.1fx per second "
|
||||
"(every %5.2e seconds)...\n",
|
||||
@@ -365,6 +396,8 @@ backtrace::get_last_hwcounters()
|
||||
void
|
||||
backtrace::post_process(int64_t _tid)
|
||||
{
|
||||
namespace quirk = tim::quirk;
|
||||
|
||||
configure(false, _tid);
|
||||
|
||||
auto& _sampler = sampling::sampler_instances::instances().at(_tid);
|
||||
@@ -392,9 +425,12 @@ backtrace::post_process(int64_t _tid)
|
||||
// debugging feature
|
||||
static bool _keep_internal =
|
||||
tim::get_env<bool>("OMNITRACE_SAMPLING_KEEP_INTERNAL", get_debug());
|
||||
if(_keep_internal) return 1;
|
||||
const auto _npos = std::string::npos;
|
||||
if(_keep_internal) return 1;
|
||||
if(_lbl.find("omnitrace_init_tooling") != _npos) return -1;
|
||||
if(_lbl.find("omnitrace_push_trace") != _npos) return -1;
|
||||
if(_lbl.find("omnitrace_pop_trace") != _npos) return -1;
|
||||
if(_lbl.find("amd_comgr_") == 0) return -1;
|
||||
if(_check_internal)
|
||||
{
|
||||
if(std::regex_search(
|
||||
@@ -423,11 +459,141 @@ backtrace::post_process(int64_t _tid)
|
||||
return _lbl.replace(_pos, _dyninst.length(), "");
|
||||
};
|
||||
|
||||
auto _data = _sampler->get_allocator().get_data();
|
||||
using common_type_t = typename hw_counters::common_type;
|
||||
auto _hw_cnt_labels = (get_papi_vector(_tid))
|
||||
? comp::papi_common::get_events<common_type_t>()
|
||||
: std::vector<int>{};
|
||||
|
||||
auto _process_perfetto_counters = [&](const std::vector<sampling::bundle_t*>& _data) {
|
||||
if(!perfetto_counter_track<comp::peak_rss>::exists(_tid))
|
||||
{
|
||||
auto _thrname = TIMEMORY_JOIN("", "[Thread ", _tid, "] ");
|
||||
auto addendum = [&](const std::string& _v) { return _thrname + _v + " (S)"; };
|
||||
perfetto_counter_track<comp::peak_rss>::emplace(
|
||||
_tid, addendum("Peak Memory Usage"), "MB");
|
||||
}
|
||||
|
||||
if(!perfetto_counter_track<hw_counters>::exists(_tid) &&
|
||||
tim::trait::runtime_enabled<hw_counters>::get())
|
||||
{
|
||||
auto _thrname = TIMEMORY_JOIN("", "[Thread ", _tid, "] ");
|
||||
auto addendum = [&](const std::string& _v) { return _thrname + _v + " (S)"; };
|
||||
for(auto& itr : _hw_cnt_labels)
|
||||
{
|
||||
perfetto_counter_track<hw_counters>::emplace(
|
||||
_tid, addendum(tim::papi::get_event_info(itr).short_descr), "");
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto& ditr : _data)
|
||||
{
|
||||
const auto* _bt = ditr->get<backtrace>();
|
||||
if(_bt->m_tid != _tid) continue;
|
||||
|
||||
auto _ts = static_cast<uint64_t>(_bt->m_ts.time_since_epoch().count());
|
||||
|
||||
TRACE_COUNTER("sampling", perfetto_counter_track<comp::peak_rss>::at(_tid, 0),
|
||||
_ts, _bt->m_mem_peak / units::megabyte);
|
||||
|
||||
if(tim::trait::runtime_enabled<hw_counters>::get())
|
||||
{
|
||||
for(size_t i = 0; i < perfetto_counter_track<hw_counters>::size(_tid);
|
||||
++i)
|
||||
{
|
||||
if(i < _bt->m_hw_counter.size())
|
||||
{
|
||||
TRACE_COUNTER("sampling",
|
||||
perfetto_counter_track<hw_counters>::at(_tid, i),
|
||||
_ts, _bt->m_hw_counter.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto _process_perfetto = [&](const std::vector<sampling::bundle_t*>& _data,
|
||||
bool _rename) {
|
||||
if(_rename)
|
||||
threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid, "(S)").c_str());
|
||||
time_point_type _last_wall_ts = _init->get_timestamp();
|
||||
|
||||
for(const auto& ditr : _data)
|
||||
{
|
||||
const auto* _bt = ditr->get<backtrace>();
|
||||
if(_bt->m_tid != _tid) continue;
|
||||
|
||||
static std::set<std::string> _static_strings{};
|
||||
std::string _last = {};
|
||||
for(const auto& itr : _bt->get())
|
||||
{
|
||||
auto _name = tim::demangle(_patch_label(itr));
|
||||
auto _use =
|
||||
_use_label(_name, !_last.empty() &&
|
||||
(_last == "start_thread" || _last == "clone"));
|
||||
if(_use == -1) break;
|
||||
if(_use == 0) continue;
|
||||
auto sitr = _static_strings.emplace(_name);
|
||||
_last = *sitr.first;
|
||||
auto _ts = static_cast<uint64_t>(_bt->m_ts.time_since_epoch().count());
|
||||
|
||||
TRACE_EVENT_BEGIN(
|
||||
"sampling", perfetto::StaticString{ sitr.first->c_str() },
|
||||
static_cast<uint64_t>(_last_wall_ts.time_since_epoch().count()));
|
||||
TRACE_EVENT_END("sampling", _ts);
|
||||
}
|
||||
_last_wall_ts = _bt->m_ts;
|
||||
}
|
||||
};
|
||||
|
||||
auto _raw_data = _sampler->get_allocator().get_data();
|
||||
// single sample that is useless (backtrace to unblocking signals)
|
||||
if(_data.size() == 1 && _data.front().size() <= 1) _data.clear();
|
||||
OMNITRACE_DEBUG("Post-processing %zu sampling entries for thread %lu...\n",
|
||||
_data.size(), _tid);
|
||||
if(_raw_data.size() == 1 && _raw_data.front().size() <= 1) _raw_data.clear();
|
||||
|
||||
std::vector<sampling::bundle_t*> _data{};
|
||||
for(auto& ditr : _raw_data)
|
||||
{
|
||||
_data.reserve(_data.size() + ditr.size());
|
||||
for(auto& ritr : ditr)
|
||||
{
|
||||
auto* _bt = ritr.get<backtrace>();
|
||||
if(!_bt)
|
||||
{
|
||||
OMNITRACE_PRINT(
|
||||
"Warning! Nullptr to backtrace instance for thread %lu...\n", _tid);
|
||||
continue;
|
||||
}
|
||||
if(_bt->empty()) continue;
|
||||
_data.emplace_back(&ritr);
|
||||
}
|
||||
}
|
||||
|
||||
if(_data.empty()) return;
|
||||
|
||||
OMNITRACE_CONDITIONAL_PRINT(
|
||||
get_verbose() >= 0 || get_debug(),
|
||||
"Post-processing %zu sampling entries for thread %lu...\n", _data.size(), _tid);
|
||||
|
||||
std::sort(_data.begin(), _data.end(),
|
||||
[](const sampling::bundle_t* _lhs, const sampling::bundle_t* _rhs) {
|
||||
return _lhs->get<backtrace>()->m_ts < _rhs->get<backtrace>()->m_ts;
|
||||
});
|
||||
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
_process_perfetto_counters(_data);
|
||||
|
||||
if(_tid == 0 && get_mode() == Mode::Sampling)
|
||||
_process_perfetto(_data, false);
|
||||
else
|
||||
{
|
||||
auto _v = pthread_gotcha::enable_sampling_on_child_threads();
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
std::thread{ _process_perfetto, _data, true }.join();
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = _v;
|
||||
}
|
||||
}
|
||||
|
||||
if(!get_use_timemory()) return;
|
||||
|
||||
std::map<int64_t, std::map<int64_t, int64_t>> _depth_sum = {};
|
||||
auto _scope = tim::scope::config{};
|
||||
@@ -441,125 +607,101 @@ backtrace::post_process(int64_t _tid)
|
||||
using bundle_t = tim::lightweight_tuple<comp::trip_count, sampling_wall_clock,
|
||||
sampling_cpu_clock, hw_counters>;
|
||||
|
||||
for(auto& ritr : ditr)
|
||||
auto* _bt = ditr->get<backtrace>();
|
||||
|
||||
double _elapsed_wc = (_bt->m_ts - _last_wall_ts).count();
|
||||
double _elapsed_cc = (_bt->m_thr_cpu_ts - _last_cpu_ts);
|
||||
|
||||
std::vector<bundle_t> _tc{};
|
||||
_tc.reserve(_bt->size());
|
||||
|
||||
// generate the instances of the tuple of components and start them
|
||||
for(const auto& itr : _bt->get())
|
||||
{
|
||||
auto* _bt = ritr.get<backtrace>();
|
||||
if(!_bt)
|
||||
{
|
||||
OMNITRACE_PRINT(
|
||||
"Warning! Nullptr to backtrace instance for thread %lu...\n", _tid);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(_bt->empty()) continue;
|
||||
|
||||
double _elapsed_wc = (_bt->m_ts - _last_wall_ts).count();
|
||||
double _elapsed_cc = (_bt->m_thr_cpu_ts - _last_cpu_ts);
|
||||
|
||||
std::vector<bundle_t> _tc{};
|
||||
_tc.reserve(_bt->size());
|
||||
|
||||
// generate the instances of the tuple of components and start them
|
||||
for(const auto& itr : _bt->get())
|
||||
{
|
||||
auto _lbl = _patch_label(itr);
|
||||
auto _use = _use_label(_lbl, !_tc.empty() &&
|
||||
(_tc.back().key() == "start_thread" ||
|
||||
auto _lbl = _patch_label(itr);
|
||||
auto _use =
|
||||
_use_label(_lbl, !_tc.empty() && (_tc.back().key() == "start_thread" ||
|
||||
_tc.back().key() == "clone"));
|
||||
if(_use == -1) break;
|
||||
if(_use == 0) continue;
|
||||
_tc.emplace_back(tim::string_view_t{ _lbl }, _scope);
|
||||
_tc.back().push(_bt->m_tid);
|
||||
_tc.back().start();
|
||||
}
|
||||
|
||||
// stop the instances and update the values as needed
|
||||
for(size_t i = 0; i < _tc.size(); ++i)
|
||||
{
|
||||
auto& itr = _tc.at(_tc.size() - i - 1);
|
||||
size_t _depth = 0;
|
||||
_depth_sum[_bt->m_tid][_depth] += 1;
|
||||
itr.stop();
|
||||
if constexpr(tim::trait::is_available<sampling_wall_clock>::value)
|
||||
{
|
||||
auto* _sc = itr.get<sampling_wall_clock>();
|
||||
if(_sc)
|
||||
{
|
||||
auto _value = _elapsed_wc / sampling_wall_clock::get_unit();
|
||||
_sc->set_value(_value);
|
||||
_sc->set_accum(_value);
|
||||
}
|
||||
}
|
||||
if constexpr(tim::trait::is_available<sampling_cpu_clock>::value)
|
||||
{
|
||||
auto* _cc = itr.get<sampling_cpu_clock>();
|
||||
if(_cc)
|
||||
{
|
||||
_cc->set_value(_elapsed_cc / sampling_cpu_clock::get_unit());
|
||||
_cc->set_accum(_elapsed_cc / sampling_cpu_clock::get_unit());
|
||||
}
|
||||
}
|
||||
if constexpr(tim::trait::is_available<hw_counters>::value)
|
||||
{
|
||||
auto* _hw_counter = itr.get<hw_counters>();
|
||||
if(_hw_counter)
|
||||
{
|
||||
_hw_counter->set_value(_bt->m_hw_counter);
|
||||
_hw_counter->set_accum(_bt->m_hw_counter);
|
||||
}
|
||||
}
|
||||
itr.pop();
|
||||
}
|
||||
_last_wall_ts = _bt->m_ts;
|
||||
_last_cpu_ts = _bt->m_thr_cpu_ts;
|
||||
if(_use == -1) break;
|
||||
if(_use == 0) continue;
|
||||
_tc.emplace_back(tim::string_view_t{ _lbl }, _scope);
|
||||
_tc.back().push(_bt->m_tid);
|
||||
_tc.back().start();
|
||||
}
|
||||
}
|
||||
|
||||
namespace quirk = tim::quirk;
|
||||
// stop the instances and update the values as needed
|
||||
for(size_t i = 0; i < _tc.size(); ++i)
|
||||
{
|
||||
auto& itr = _tc.at(_tc.size() - i - 1);
|
||||
size_t _depth = 0;
|
||||
_depth_sum[_bt->m_tid][_depth] += 1;
|
||||
itr.stop();
|
||||
if constexpr(tim::trait::is_available<sampling_wall_clock>::value)
|
||||
{
|
||||
auto* _sc = itr.get<sampling_wall_clock>();
|
||||
if(_sc)
|
||||
{
|
||||
auto _value = _elapsed_wc / sampling_wall_clock::get_unit();
|
||||
_sc->set_value(_value);
|
||||
_sc->set_accum(_value);
|
||||
}
|
||||
}
|
||||
if constexpr(tim::trait::is_available<sampling_cpu_clock>::value)
|
||||
{
|
||||
auto* _cc = itr.get<sampling_cpu_clock>();
|
||||
if(_cc)
|
||||
{
|
||||
_cc->set_value(_elapsed_cc / sampling_cpu_clock::get_unit());
|
||||
_cc->set_accum(_elapsed_cc / sampling_cpu_clock::get_unit());
|
||||
}
|
||||
}
|
||||
if constexpr(tim::trait::is_available<hw_counters>::value)
|
||||
{
|
||||
auto* _hw_counter = itr.get<hw_counters>();
|
||||
if(_hw_counter)
|
||||
{
|
||||
_hw_counter->set_value(_bt->m_hw_counter);
|
||||
_hw_counter->set_accum(_bt->m_hw_counter);
|
||||
}
|
||||
}
|
||||
itr.pop();
|
||||
}
|
||||
_last_wall_ts = _bt->m_ts;
|
||||
_last_cpu_ts = _bt->m_thr_cpu_ts;
|
||||
}
|
||||
|
||||
for(auto&& ditr : _data)
|
||||
{
|
||||
using bundle_t =
|
||||
tim::lightweight_tuple<sampling_percent, quirk::config<quirk::tree_scope>>;
|
||||
|
||||
for(auto& ritr : ditr)
|
||||
auto* _bt = ditr->get<backtrace>();
|
||||
|
||||
std::vector<bundle_t> _tc{};
|
||||
_tc.reserve(_bt->size());
|
||||
|
||||
// generate the instances of the tuple of components and start them
|
||||
for(const auto& itr : _bt->get())
|
||||
{
|
||||
auto* _bt = ritr.get<backtrace>();
|
||||
if(!_bt)
|
||||
{
|
||||
OMNITRACE_PRINT(
|
||||
"Warning! Nullptr to backtrace instance for thread %lu...\n", _tid);
|
||||
continue;
|
||||
}
|
||||
auto _lbl = _patch_label(itr);
|
||||
auto _use =
|
||||
_use_label(_lbl, !_tc.empty() && _tc.back().key() == "start_thread");
|
||||
if(_use == -1) break;
|
||||
if(_use == 0) continue;
|
||||
_tc.emplace_back(tim::string_view_t{ _lbl });
|
||||
_tc.back().push(_bt->m_tid);
|
||||
_tc.back().start();
|
||||
}
|
||||
|
||||
if(_bt->empty()) continue;
|
||||
|
||||
std::vector<bundle_t> _tc{};
|
||||
_tc.reserve(_bt->size());
|
||||
|
||||
// generate the instances of the tuple of components and start them
|
||||
for(const auto& itr : _bt->get())
|
||||
{
|
||||
auto _lbl = _patch_label(itr);
|
||||
auto _use =
|
||||
_use_label(_lbl, !_tc.empty() && _tc.back().key() == "start_thread");
|
||||
if(_use == -1) break;
|
||||
if(_use == 0) continue;
|
||||
_tc.emplace_back(tim::string_view_t{ _lbl });
|
||||
_tc.back().push(_bt->m_tid);
|
||||
_tc.back().start();
|
||||
}
|
||||
|
||||
// stop the instances and update the values as needed
|
||||
for(size_t i = 0; i < _tc.size(); ++i)
|
||||
{
|
||||
auto& itr = _tc.at(_tc.size() - i - 1);
|
||||
size_t _depth = 0;
|
||||
double _value = (1.0 / _depth_sum[_bt->m_tid][_depth]) * 100.0;
|
||||
itr.store(std::plus<double>{}, _value);
|
||||
itr.stop();
|
||||
itr.pop();
|
||||
}
|
||||
// stop the instances and update the values as needed
|
||||
for(size_t i = 0; i < _tc.size(); ++i)
|
||||
{
|
||||
auto& itr = _tc.at(_tc.size() - i - 1);
|
||||
size_t _depth = 0;
|
||||
double _value = (1.0 / _depth_sum[_bt->m_tid][_depth]) * 100.0;
|
||||
itr.store(std::plus<double>{}, _value);
|
||||
itr.stop();
|
||||
itr.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/mpi_gotcha.hpp"
|
||||
#include "library/api.hpp"
|
||||
#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>
|
||||
@@ -35,7 +37,7 @@ namespace
|
||||
uint64_t mpip_index = std::numeric_limits<uint64_t>::max();
|
||||
std::string mpi_init_string = {};
|
||||
|
||||
// this ensures omnitrace_trace_finalize is called before MPI_Finalize
|
||||
// this ensures omnitrace_finalize is called before MPI_Finalize
|
||||
void
|
||||
omnitrace_mpi_set_attr()
|
||||
{
|
||||
@@ -49,9 +51,7 @@ omnitrace_mpi_set_attr()
|
||||
if(mpip_index != std::numeric_limits<uint64_t>::max())
|
||||
comp::deactivate_mpip<tim::component_tuple<omnitrace::component::omnitrace>,
|
||||
api::omnitrace>(mpip_index);
|
||||
if(!mpi_init_string.empty()) omnitrace_pop_trace(mpi_init_string.c_str());
|
||||
mpi_init_string = {};
|
||||
omnitrace_trace_finalize();
|
||||
omnitrace_finalize();
|
||||
return MPI_SUCCESS;
|
||||
};
|
||||
using copy_func_t = int (*)(MPI_Comm, int, void*, void*, void*, int*);
|
||||
@@ -73,8 +73,10 @@ mpi_gotcha::configure()
|
||||
mpi_gotcha_t::template configure<1, int, int*, char***, int, int*>(
|
||||
"MPI_Init_thread");
|
||||
mpi_gotcha_t::template configure<2, int>("MPI_Finalize");
|
||||
mpi_gotcha_t::template configure<3, int, tim::mpi::comm_t, int*>("MPI_Comm_rank");
|
||||
mpi_gotcha_t::template configure<4, int, tim::mpi::comm_t, int*>("MPI_Comm_size");
|
||||
#if defined(OMNITRACE_USE_MPI_HEADERS)
|
||||
mpi_gotcha_t::template configure<3, int, comm_t, int*>("MPI_Comm_rank");
|
||||
mpi_gotcha_t::template configure<4, int, comm_t, int*>("MPI_Comm_size");
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,15 +85,15 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s(int*, char***)\n",
|
||||
__FUNCTION__, _data.tool_id.c_str());
|
||||
|
||||
if(get_state() == ::omnitrace::State::DelayedInit)
|
||||
{
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
mpi_init_string = _data.tool_id;
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
|
||||
omnitrace_push_trace(_data.tool_id.c_str());
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
tim::mpi::is_initialized_callback() = []() { return true; };
|
||||
tim::mpi::is_finalized() = false;
|
||||
tim::mpi::is_initialized_callback() = []() { return true; };
|
||||
tim::mpi::is_finalized() = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -101,14 +103,13 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***, in
|
||||
"[%s] %s(int*, char***, int, int*)\n", __FUNCTION__,
|
||||
_data.tool_id.c_str());
|
||||
if(get_state() == ::omnitrace::State::DelayedInit)
|
||||
{
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
mpi_init_string = _data.tool_id;
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
|
||||
omnitrace_push_trace(_data.tool_id.c_str());
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
tim::mpi::is_initialized_callback() = []() { return true; };
|
||||
tim::mpi::is_finalized() = false;
|
||||
tim::mpi::is_initialized_callback() = []() { return true; };
|
||||
tim::mpi::is_finalized() = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -116,16 +117,16 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s()\n", __FUNCTION__,
|
||||
_data.tool_id.c_str());
|
||||
|
||||
if(mpip_index != std::numeric_limits<uint64_t>::max())
|
||||
comp::deactivate_mpip<tim::component_tuple<omnitrace::component::omnitrace>,
|
||||
api::omnitrace>(mpip_index);
|
||||
if(!mpi_init_string.empty()) omnitrace_pop_trace(mpi_init_string.c_str());
|
||||
mpi_init_string = {};
|
||||
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
tim::mpi::is_initialized_callback() = []() { return false; };
|
||||
tim::mpi::is_finalized() = true;
|
||||
#else
|
||||
omnitrace_trace_finalize();
|
||||
omnitrace_finalize();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -134,6 +135,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, comm_t, int* _val
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s()\n", __FUNCTION__,
|
||||
_data.tool_id.c_str());
|
||||
|
||||
omnitrace_push_trace(_data.tool_id.c_str());
|
||||
if(_data.tool_id == "MPI_Comm_rank")
|
||||
{
|
||||
m_rank_ptr = _val;
|
||||
@@ -144,8 +147,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, comm_t, int* _val
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_PRINT("[%s] %s(<comm>, %p) :: unexpected function wrapper\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), _val);
|
||||
OMNITRACE_BASIC_PRINT("[%s] %s(<comm>, %p) :: unexpected function wrapper\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), _val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,8 +157,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s() returned %i\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
if(_retval == tim::mpi::success_v && get_state() == ::omnitrace::State::PreInit &&
|
||||
_data.tool_id.find("MPI_Init") == 0)
|
||||
|
||||
if(_retval == tim::mpi::success_v && _data.tool_id.find("MPI_Init") == 0)
|
||||
{
|
||||
omnitrace_mpi_set_attr();
|
||||
// omnitrace will set this environement variable to true in binary rewrite mode
|
||||
@@ -165,8 +168,9 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval)
|
||||
// were excluded via a regex expression)
|
||||
if(get_use_mpip())
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_debug_env(), "[%s] Activating MPI wrappers...\n", __FUNCTION__);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env() || get_verbose_env() > 0,
|
||||
"[%s] Activating MPI wrappers...\n",
|
||||
__FUNCTION__);
|
||||
|
||||
// use env vars OMNITRACE_MPIP_PERMIT_LIST and OMNITRACE_MPIP_REJECT_LIST
|
||||
// to control the gotcha bindings at runtime
|
||||
@@ -176,7 +180,6 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval)
|
||||
comp::activate_mpip<tim::component_tuple<omnitrace::component::omnitrace>,
|
||||
api::omnitrace>();
|
||||
}
|
||||
omnitrace_push_trace(_data.tool_id.c_str());
|
||||
}
|
||||
else if(_retval == tim::mpi::success_v && _data.tool_id.find("MPI_Comm_") == 0)
|
||||
{
|
||||
@@ -185,17 +188,17 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval)
|
||||
if(m_rank_ptr)
|
||||
{
|
||||
m_rank = std::max<int>(*m_rank_ptr, m_rank);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(tim::settings::verbose() > 0,
|
||||
"MPI rank: %i\n", m_rank);
|
||||
tim::mpi::set_rank(m_rank);
|
||||
tim::settings::default_process_suffix() = m_rank;
|
||||
get_perfetto_output_filename().clear();
|
||||
(void) get_perfetto_output_filename();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_debug() || get_verbose() > 0, "[pid=%i] MPI rank: %i (%i)\n",
|
||||
process::get_id(), tim::mpi::rank(), m_rank);
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_PRINT("[%s] %s() returned %i :: nullptr to rank\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
OMNITRACE_BASIC_PRINT("[%s] %s() returned %i :: nullptr to rank\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
}
|
||||
}
|
||||
else if(_data.tool_id == "MPI_Comm_size")
|
||||
@@ -203,22 +206,25 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, int _retval)
|
||||
if(m_size_ptr)
|
||||
{
|
||||
m_size = std::max<int>(*m_size_ptr, m_size);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(tim::settings::verbose() > 0,
|
||||
"MPI size: %i\n", m_size);
|
||||
tim::mpi::set_size(m_size);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_debug() || get_verbose() > 0, "[pid=%i] MPI size: %i (%i)\n",
|
||||
process::get_id(), tim::mpi::size(), m_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_PRINT("[%s] %s() returned %i :: nullptr to size\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
OMNITRACE_BASIC_PRINT("[%s] %s() returned %i :: nullptr to size\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_PRINT("[%s] %s() returned %i :: unexpected function wrapper\n",
|
||||
__FUNCTION__, _data.tool_id.c_str(), (int) _retval);
|
||||
OMNITRACE_BASIC_PRINT(
|
||||
"[%s] %s() returned %i :: unexpected function wrapper\n", __FUNCTION__,
|
||||
_data.tool_id.c_str(), (int) _retval);
|
||||
}
|
||||
}
|
||||
omnitrace_pop_trace(_data.tool_id.c_str());
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/pthread_gotcha.hpp"
|
||||
#include "library/components/omnitrace.hpp"
|
||||
#include "library/components/roctracer.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <timemory/sampling/allocator.hpp>
|
||||
#include <timemory/utility/types.hpp>
|
||||
|
||||
@@ -40,6 +43,47 @@ std::set<int>
|
||||
shutdown();
|
||||
} // namespace sampling
|
||||
|
||||
namespace mpl = tim::mpl;
|
||||
|
||||
using bundle_t = tim::lightweight_tuple<comp::wall_clock, comp::roctracer_data>;
|
||||
using wall_pw_t = mpl::piecewise_select<comp::wall_clock>; // only wall-clock
|
||||
using main_pw_t = mpl::piecewise_ignore<comp::wall_clock>; // exclude wall-clock
|
||||
using omni_pw_t = mpl::piecewise_select<>;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<int64_t, std::shared_ptr<bundle_t>> bundles = {};
|
||||
std::mutex bundles_mutex{};
|
||||
|
||||
inline void
|
||||
start_bundle(bundle_t& _bundle)
|
||||
{
|
||||
if(comp::roctracer::is_setup())
|
||||
{
|
||||
_bundle.push(main_pw_t{});
|
||||
_bundle.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
_bundle.push(omni_pw_t{});
|
||||
_bundle.start(omni_pw_t{});
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
stop_bundle(bundle_t& _bundle, int64_t _tid)
|
||||
{
|
||||
_bundle.stop(wall_pw_t{}); // stop wall-clock so we can get the value
|
||||
// update roctracer_data
|
||||
_bundle.store(std::plus<double>{},
|
||||
_bundle.get<comp::wall_clock>()->get() * units::sec);
|
||||
// stop all other components including roctracer_data after update
|
||||
_bundle.stop(main_pw_t{});
|
||||
// exclude popping wall-clock
|
||||
_bundle.pop(main_pw_t{}, _tid);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
pthread_gotcha::wrapper::wrapper(routine_t _routine, void* _arg, bool _enable_sampling,
|
||||
promise_t* _p)
|
||||
: m_enable_sampling{ _enable_sampling }
|
||||
@@ -51,10 +95,41 @@ pthread_gotcha::wrapper::wrapper(routine_t _routine, void* _arg, bool _enable_sa
|
||||
void*
|
||||
pthread_gotcha::wrapper::operator()() const
|
||||
{
|
||||
std::set<int> _signals{};
|
||||
auto& _enable_sampling = pthread_gotcha::enable_sampling_on_child_threads();
|
||||
if(m_enable_sampling && _enable_sampling)
|
||||
std::shared_ptr<bundle_t> _bundle{};
|
||||
std::set<int> _signals{};
|
||||
auto& _enable_sampling = pthread_gotcha::enable_sampling_on_child_threads();
|
||||
auto _active = (get_state() == omnitrace::State::Active);
|
||||
int64_t _tid = -1;
|
||||
auto _is_sampling = false;
|
||||
auto _dtor = scope::destructor{ [&]() {
|
||||
if(_is_sampling)
|
||||
{
|
||||
sampling::block_signals(_signals);
|
||||
sampling::shutdown();
|
||||
}
|
||||
|
||||
if(_bundle)
|
||||
{
|
||||
std::unique_lock<std::mutex> _lk{ bundles_mutex };
|
||||
stop_bundle(*_bundle, _tid);
|
||||
_bundle.reset();
|
||||
bundles.erase(_tid);
|
||||
}
|
||||
} };
|
||||
|
||||
if(m_enable_sampling && _enable_sampling && _active)
|
||||
{
|
||||
_tid = threading::get_id();
|
||||
threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid).c_str());
|
||||
{
|
||||
std::unique_lock<std::mutex> _lk{ bundles_mutex };
|
||||
if(comp::roctracer::is_setup())
|
||||
_bundle =
|
||||
bundles.emplace(_tid, std::make_shared<bundle_t>("start_thread"))
|
||||
.first->second;
|
||||
}
|
||||
if(_bundle) start_bundle(*_bundle);
|
||||
_is_sampling = true;
|
||||
_enable_sampling = false;
|
||||
_signals = sampling::setup();
|
||||
_enable_sampling = true;
|
||||
@@ -64,15 +139,7 @@ pthread_gotcha::wrapper::operator()() const
|
||||
if(m_promise) m_promise->set_value();
|
||||
|
||||
// execute the original function
|
||||
auto* _ret = m_routine(m_arg);
|
||||
|
||||
if(m_enable_sampling && _enable_sampling)
|
||||
{
|
||||
sampling::block_signals(_signals);
|
||||
sampling::shutdown();
|
||||
}
|
||||
|
||||
return _ret;
|
||||
return m_routine(m_arg);
|
||||
}
|
||||
|
||||
void*
|
||||
@@ -95,6 +162,27 @@ pthread_gotcha::configure()
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
pthread_gotcha::shutdown()
|
||||
{
|
||||
std::unique_lock<std::mutex> _lk{ bundles_mutex };
|
||||
unsigned long _ndangling = 0;
|
||||
for(auto itr : bundles)
|
||||
{
|
||||
if(itr.second)
|
||||
{
|
||||
stop_bundle(*itr.second, itr.first);
|
||||
++_ndangling;
|
||||
}
|
||||
itr.second.reset();
|
||||
}
|
||||
|
||||
OMNITRACE_CONDITIONAL_PRINT(
|
||||
(get_verbose() > 0 || get_debug()) && _ndangling > 0,
|
||||
"pthread_gotcha::shutdown() cleaned up %lu dangling bundles\n", _ndangling);
|
||||
bundles.clear();
|
||||
}
|
||||
|
||||
bool&
|
||||
pthread_gotcha::enable_sampling_on_child_threads()
|
||||
{
|
||||
@@ -107,13 +195,18 @@ int
|
||||
pthread_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr,
|
||||
void* (*start_routine)(void*), void* arg) const
|
||||
{
|
||||
auto _enable_sampling = enable_sampling_on_child_threads();
|
||||
bundle_t _bundle{ "pthread_create" };
|
||||
auto _enable_sampling = enable_sampling_on_child_threads();
|
||||
|
||||
if(!_enable_sampling)
|
||||
if(!get_use_sampling() || !_enable_sampling)
|
||||
{
|
||||
// if(!get_use_sampling()) start_bundle(_bundle);
|
||||
auto* _obj = new wrapper(start_routine, arg, _enable_sampling, nullptr);
|
||||
// create the thread
|
||||
return pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_obj));
|
||||
auto _ret =
|
||||
pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_obj));
|
||||
// if(!get_use_sampling()) stop_bundle(_bundle, threading::get_id());
|
||||
return _ret;
|
||||
}
|
||||
|
||||
// block the signals in entire process
|
||||
@@ -121,18 +214,22 @@ pthread_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr,
|
||||
tim::sampling::block_signals({ SIGALRM, SIGPROF },
|
||||
tim::sampling::sigmask_scope::process);
|
||||
|
||||
start_bundle(_bundle);
|
||||
|
||||
// promise set by thread when signal handler is configured
|
||||
auto _promise = std::promise<void>{};
|
||||
auto _fut = _promise.get_future();
|
||||
auto* _obj = new wrapper(start_routine, arg, _enable_sampling, &_promise);
|
||||
auto* _wrap = new wrapper(start_routine, arg, _enable_sampling, &_promise);
|
||||
|
||||
// create the thread
|
||||
auto _ret = pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_obj));
|
||||
auto _ret = pthread_create(thread, attr, &wrapper::wrap, static_cast<void*>(_wrap));
|
||||
|
||||
// wait for thread to set promise
|
||||
OMNITRACE_DEBUG("waiting for child to signal it is setup...\n");
|
||||
_fut.wait();
|
||||
|
||||
stop_bundle(_bundle, threading::get_id());
|
||||
|
||||
// unblock the signals in the entire process
|
||||
OMNITRACE_DEBUG("unblocking signals...\n");
|
||||
tim::sampling::unblock_signals({ SIGALRM, SIGPROF },
|
||||
|
||||
@@ -0,0 +1,569 @@
|
||||
// Copyright (c) 2018 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
|
||||
// with 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the names of Advanced Micro Devices, Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this Software without specific prior written permission.
|
||||
//
|
||||
// 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
|
||||
// CONTRIBUTORS 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 WITH
|
||||
// THE SOFTWARE.
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include "library/components/rocm_smi.hpp"
|
||||
#include "library/common.hpp"
|
||||
#include "library/components/fwd.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/critical_trace.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/gpu.hpp"
|
||||
#include "library/perfetto.hpp"
|
||||
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/components/timing/backends.hpp>
|
||||
#include <timemory/units.hpp>
|
||||
#include <timemory/utility/locking.hpp>
|
||||
|
||||
#include <rocm_smi/rocm_smi.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <sys/resource.h>
|
||||
#include <thread>
|
||||
|
||||
#define OMNITRACE_ROCM_SMI_CALL(ERROR_CODE) ::omnitrace::rocm_smi::check_error(ERROR_CODE)
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace rocm_smi
|
||||
{
|
||||
using tim::type_mutex;
|
||||
using auto_lock_t = tim::auto_lock_t;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool&
|
||||
is_initialized()
|
||||
{
|
||||
static bool _v = false;
|
||||
return _v;
|
||||
}
|
||||
|
||||
void
|
||||
check_error(rsmi_status_t ec)
|
||||
{
|
||||
if(ec == RSMI_STATUS_SUCCESS) return;
|
||||
const char* _msg = nullptr;
|
||||
auto _err = rsmi_status_string(ec, &_msg);
|
||||
if(_err != RSMI_STATUS_SUCCESS)
|
||||
OMNITRACE_THROW(
|
||||
"rsmi_status_string(%i, ...) failed. No error message available\n", (int) ec);
|
||||
OMNITRACE_THROW("%s", _msg);
|
||||
}
|
||||
|
||||
std::atomic<State>&
|
||||
get_rocm_smi_state()
|
||||
{
|
||||
static std::atomic<State> _v{ State::PreInit };
|
||||
return _v;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
size_t data::device_count = 0;
|
||||
std::set<uint32_t> data::device_list = {};
|
||||
std::unique_ptr<data::promise_t> data::polling_finished = {};
|
||||
|
||||
data::data(uint32_t _dev_id) { sample(_dev_id); }
|
||||
|
||||
void
|
||||
data::sample(uint32_t _dev_id)
|
||||
{
|
||||
auto _ts = tim::get_clock_real_now<size_t, std::nano>();
|
||||
assert(_ts < std::numeric_limits<int64_t>::max());
|
||||
|
||||
m_dev_id = _dev_id;
|
||||
m_ts = _ts;
|
||||
|
||||
rsmi_dev_busy_percent_get(_dev_id, &m_busy_perc);
|
||||
rsmi_dev_temp_metric_get(_dev_id, RSMI_TEMP_TYPE_EDGE, RSMI_TEMP_CURRENT, &m_temp);
|
||||
rsmi_dev_power_ave_get(_dev_id, 0, &m_power);
|
||||
rsmi_dev_memory_usage_get(_dev_id, RSMI_MEM_TYPE_VRAM, &m_mem_usage);
|
||||
}
|
||||
|
||||
void
|
||||
data::print(std::ostream& _os) const
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
_ss << "device: " << m_dev_id << ", busy = " << m_busy_perc << "%, temp = " << m_temp
|
||||
<< ", power = " << m_power << ", memory usage = " << m_mem_usage;
|
||||
_os << _ss.str();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct cpu_freq
|
||||
{};
|
||||
using freq_pair_t = std::pair<size_t, double>;
|
||||
std::vector<std::vector<freq_pair_t>> cpu_frequencies = {};
|
||||
|
||||
struct cpu_mem
|
||||
{};
|
||||
using cpu_mem_usage_pair_t = std::pair<size_t, int64_t>;
|
||||
std::vector<cpu_mem_usage_pair_t> cpu_mem_usage = {};
|
||||
} // namespace
|
||||
|
||||
void
|
||||
data::poll(std::atomic<State>* _state, nsec_t _interval, promise_t* _ready)
|
||||
{
|
||||
threading::set_thread_name("omni.rocm_smi");
|
||||
|
||||
// notify thread started
|
||||
if(_ready) _ready->set_value();
|
||||
|
||||
std::vector<std::unique_ptr<bundle_t>*> _bundle_data{};
|
||||
_bundle_data.resize(device_count, nullptr);
|
||||
for(size_t i = 0; i < device_count; ++i)
|
||||
{
|
||||
if(device_list.count(i) > 0)
|
||||
{
|
||||
_bundle_data.at(i) = &sampler_instances::instances().at(i);
|
||||
if(!*_bundle_data.at(i)) *_bundle_data.at(i) = std::make_unique<bundle_t>();
|
||||
}
|
||||
}
|
||||
|
||||
auto _ncpu = threading::affinity::hw_concurrency();
|
||||
std::vector<size_t> _cpu_mhz_pos{};
|
||||
std::ifstream _ifs{ "/proc/cpuinfo" };
|
||||
if(_ifs)
|
||||
{
|
||||
for(size_t i = 0; i < _ncpu; ++i)
|
||||
{
|
||||
short _n = 0;
|
||||
std::string _st{};
|
||||
while(_ifs && _ifs.good())
|
||||
{
|
||||
std::string _s{};
|
||||
_ifs >> _s;
|
||||
if(!_ifs.good() || !_ifs) break;
|
||||
|
||||
if(_s == "cpu" || _s == "MHz" || _s == ":")
|
||||
{
|
||||
++_n;
|
||||
_st += _s + " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
_n = 0;
|
||||
_st = {};
|
||||
}
|
||||
|
||||
if(_n == 3)
|
||||
{
|
||||
size_t _pos = _ifs.tellg();
|
||||
_cpu_mhz_pos.emplace_back(_pos + 1);
|
||||
_ifs >> _s;
|
||||
if(!_ifs.good() || !_ifs) break;
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug() || get_verbose() > 1,
|
||||
"[%zu] %s %s (pos = %zu)\n", i,
|
||||
_st.c_str(), _s.c_str(), _pos + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpu_frequencies.resize(_ncpu);
|
||||
|
||||
_ifs = std::ifstream{ "/proc/cpuinfo", std::ifstream::binary };
|
||||
auto _read_cpu_freq = [&_cpu_mhz_pos, &_ifs](size_t _idx) {
|
||||
double _freq = 0;
|
||||
_ifs.seekg(_cpu_mhz_pos.at(_idx), _ifs.beg);
|
||||
_ifs >> _freq;
|
||||
return _freq;
|
||||
};
|
||||
|
||||
auto _read_cpu_mem_usage = []() {
|
||||
cpu_mem_usage.emplace_back(tim::get_clock_real_now<size_t, std::nano>(),
|
||||
tim::get_page_rss());
|
||||
};
|
||||
|
||||
auto _read_cpu_freqs = [&_read_cpu_freq, _ncpu]() {
|
||||
auto _ts = tim::get_clock_real_now<size_t, std::nano>();
|
||||
for(size_t i = 0; i < _ncpu; ++i)
|
||||
{
|
||||
auto _freq = _read_cpu_freq(i);
|
||||
cpu_frequencies.at(i).emplace_back(_ts, _freq);
|
||||
}
|
||||
};
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_verbose() > 0 || get_debug(),
|
||||
"Polling rocm-smi for %zu device(s) at an interval of %f seconds...\n",
|
||||
device_list.size(),
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(_interval).count());
|
||||
|
||||
get_initial().resize(device_count);
|
||||
for(auto itr : device_list)
|
||||
get_initial().at(itr).sample(itr);
|
||||
|
||||
auto _now = std::chrono::steady_clock::now();
|
||||
while(_state && _state->load() != State::Finalized && get_state() != State::Finalized)
|
||||
{
|
||||
std::this_thread::sleep_until(_now);
|
||||
if(_state->load() != State::Active) continue;
|
||||
_read_cpu_mem_usage();
|
||||
_read_cpu_freqs();
|
||||
for(auto itr : device_list)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(),
|
||||
"Polling rocm-smi for device %u...\n", itr);
|
||||
auto& _data = *_bundle_data.at(itr);
|
||||
if(!_data) continue;
|
||||
_data->emplace_back(data{ itr });
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), " %s\n",
|
||||
TIMEMORY_JOIN("", _data->back()).c_str());
|
||||
}
|
||||
while(_now < std::chrono::steady_clock::now())
|
||||
_now += _interval;
|
||||
}
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), "Polling rocm-smi completed...\n");
|
||||
|
||||
if(polling_finished) polling_finished->set_value();
|
||||
}
|
||||
|
||||
std::vector<data>&
|
||||
data::get_initial()
|
||||
{
|
||||
static std::vector<data> _v{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread>&
|
||||
data::get_thread()
|
||||
{
|
||||
static std::unique_ptr<std::thread> _v;
|
||||
return _v;
|
||||
}
|
||||
|
||||
void
|
||||
data::set_state(State _state)
|
||||
{
|
||||
get_rocm_smi_state().store(_state);
|
||||
}
|
||||
|
||||
bool
|
||||
data::setup()
|
||||
{
|
||||
perfetto_counter_track<cpu_freq>::init();
|
||||
perfetto_counter_track<cpu_mem>::init();
|
||||
perfetto_counter_track<data>::init();
|
||||
|
||||
// shutdown if already running
|
||||
shutdown();
|
||||
|
||||
OMNITRACE_DEBUG("Configuring rocm-smi...\n");
|
||||
|
||||
auto _freq = get_rocm_smi_freq();
|
||||
uint64_t _msec_freq = (1.0 / _freq) * 1.0e3;
|
||||
|
||||
promise_t _prom{};
|
||||
auto _fut = _prom.get_future();
|
||||
polling_finished = std::make_unique<promise_t>();
|
||||
|
||||
set_state(State::PreInit);
|
||||
get_thread() = std::make_unique<std::thread>(
|
||||
&data::poll<msec_t>, &get_rocm_smi_state(), msec_t{ _msec_freq }, &_prom);
|
||||
|
||||
_fut.wait();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
data::shutdown()
|
||||
{
|
||||
auto& _thread = get_thread();
|
||||
if(_thread)
|
||||
{
|
||||
OMNITRACE_DEBUG("Shutting down rocm-smi...\n");
|
||||
set_state(State::Finalized);
|
||||
if(polling_finished)
|
||||
{
|
||||
auto _fut = polling_finished->get_future();
|
||||
uint64_t _freq = (1.0 / get_rocm_smi_freq()) * 1.0e3;
|
||||
_fut.wait_for(msec_t{ 5 * _freq });
|
||||
_thread->join();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t _freq = (1.0 / get_rocm_smi_freq()) * 1.0e3;
|
||||
std::this_thread::sleep_for(msec_t{ 5 * _freq });
|
||||
pthread_cancel(_thread->native_handle());
|
||||
_thread->detach();
|
||||
}
|
||||
_thread = std::unique_ptr<std::thread>{};
|
||||
polling_finished = std::unique_ptr<promise_t>{};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define GPU_METRIC(COMPONENT, ...) \
|
||||
if constexpr(tim::trait::is_available<COMPONENT>::value) \
|
||||
{ \
|
||||
auto* _val = _v.get<COMPONENT>(); \
|
||||
if(_val) \
|
||||
{ \
|
||||
_val->set_value(itr.__VA_ARGS__); \
|
||||
_val->set_accum(itr.__VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
|
||||
void
|
||||
data::post_process(uint32_t _dev_id)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug() || get_verbose() > 0,
|
||||
"Post-processing rocm-smi data for device %u\n", _dev_id);
|
||||
|
||||
using component::sampling_gpu_busy;
|
||||
using component::sampling_gpu_memory;
|
||||
using component::sampling_gpu_power;
|
||||
using component::sampling_gpu_temp;
|
||||
using bundle_t = tim::lightweight_tuple<sampling_gpu_busy, sampling_gpu_temp,
|
||||
sampling_gpu_power, sampling_gpu_memory>;
|
||||
|
||||
auto _process_frequencies = [](size_t _idx) {
|
||||
using counter_track = perfetto_counter_track<cpu_freq>;
|
||||
if(!counter_track::exists(_idx))
|
||||
{
|
||||
auto _devname = TIMEMORY_JOIN("", "[CPU ", _idx, "] ");
|
||||
auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; };
|
||||
counter_track::emplace(_idx, addendum("Frequency (S)"), "MHz");
|
||||
}
|
||||
|
||||
for(auto& itr : cpu_frequencies.at(_idx))
|
||||
{
|
||||
uint64_t _ts = itr.first;
|
||||
double _freq = itr.second;
|
||||
TRACE_COUNTER("sampling", counter_track::at(_idx, 0), _ts, _freq);
|
||||
}
|
||||
};
|
||||
|
||||
auto _process_cpu_mem_usage = []() {
|
||||
using counter_track = perfetto_counter_track<cpu_mem>;
|
||||
if(!counter_track::exists(0))
|
||||
{
|
||||
auto _devname = TIMEMORY_JOIN("", "[CPU] ");
|
||||
auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; };
|
||||
counter_track::emplace(0, addendum("Memory Usage (S)"), "MB");
|
||||
}
|
||||
|
||||
for(auto& itr : cpu_mem_usage)
|
||||
{
|
||||
uint64_t _ts = itr.first;
|
||||
double _mem_usage = itr.second;
|
||||
TRACE_COUNTER("sampling", counter_track::at(0, 0), _ts,
|
||||
_mem_usage / units::megabyte);
|
||||
}
|
||||
};
|
||||
|
||||
static bool _once = false;
|
||||
if(!_once)
|
||||
{
|
||||
_once = true;
|
||||
_process_cpu_mem_usage();
|
||||
for(size_t i = 0; i < cpu_frequencies.size(); ++i)
|
||||
_process_frequencies(i);
|
||||
}
|
||||
|
||||
if(device_count < _dev_id) return;
|
||||
|
||||
auto& _rocm_smi_v = sampler_instances::instances().at(_dev_id);
|
||||
auto _rocm_smi = (_rocm_smi_v) ? *_rocm_smi_v : std::deque<rocm_smi::data>{};
|
||||
|
||||
auto _process_perfetto = [&]() {
|
||||
for(auto& itr : _rocm_smi)
|
||||
{
|
||||
using counter_track = perfetto_counter_track<data>;
|
||||
if(itr.m_dev_id != _dev_id) continue;
|
||||
if(!counter_track::exists(_dev_id))
|
||||
{
|
||||
auto _devname = TIMEMORY_JOIN("", "[GPU ", _dev_id, "] ");
|
||||
auto addendum = [&](const char* _v) {
|
||||
return _devname + std::string{ _v };
|
||||
};
|
||||
counter_track::emplace(_dev_id, addendum("Busy"), "%");
|
||||
counter_track::emplace(_dev_id, addendum("Temperature"), "deg C");
|
||||
counter_track::emplace(_dev_id, addendum("Power"), "watts");
|
||||
counter_track::emplace(_dev_id, addendum("Memory Usage"), "megabytes");
|
||||
}
|
||||
uint64_t _ts = itr.m_ts;
|
||||
double _busy = itr.m_busy_perc;
|
||||
double _temp = itr.m_temp / 1.0e3;
|
||||
double _power = itr.m_power / 1.0e6;
|
||||
double _usage = itr.m_mem_usage / static_cast<double>(units::megabyte);
|
||||
TRACE_COUNTER("rocm_smi", counter_track::at(_dev_id, 0), _ts, _busy);
|
||||
TRACE_COUNTER("rocm_smi", counter_track::at(_dev_id, 1), _ts, _temp);
|
||||
TRACE_COUNTER("rocm_smi", counter_track::at(_dev_id, 2), _ts, _power);
|
||||
TRACE_COUNTER("rocm_smi", counter_track::at(_dev_id, 3), _ts, _usage);
|
||||
}
|
||||
};
|
||||
|
||||
if(get_use_perfetto()) _process_perfetto();
|
||||
|
||||
if(!get_use_timemory()) return;
|
||||
|
||||
for(auto& itr : _rocm_smi)
|
||||
{
|
||||
using entry_t = critical_trace::entry;
|
||||
auto _ts = itr.m_ts;
|
||||
auto _entries = critical_trace::get_entries(_ts, [](const entry_t& _e) {
|
||||
return _e.device == critical_trace::Device::GPU;
|
||||
});
|
||||
|
||||
std::vector<bundle_t> _tc{};
|
||||
_tc.reserve(_entries.size());
|
||||
for(auto& eitr : _entries)
|
||||
{
|
||||
auto& _v = _tc.emplace_back(eitr.first);
|
||||
_v.push();
|
||||
_v.start();
|
||||
_v.stop();
|
||||
|
||||
GPU_METRIC(sampling_gpu_busy, m_busy_perc)
|
||||
GPU_METRIC(sampling_gpu_temp, m_temp / 1.0e3) // provided in milli-degree C
|
||||
GPU_METRIC(sampling_gpu_power,
|
||||
m_power * units::microwatt / static_cast<double>(units::watt))
|
||||
GPU_METRIC(sampling_gpu_memory,
|
||||
m_mem_usage / static_cast<double>(units::megabyte))
|
||||
|
||||
_v.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
auto_lock_t _lk{ type_mutex<api::rocm_smi>() };
|
||||
|
||||
if(is_initialized() || !get_use_rocm_smi()) return;
|
||||
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
|
||||
// assign the data value to determined by rocm-smi
|
||||
data::device_count = device_count();
|
||||
|
||||
auto _devices_v = get_rocm_smi_devices();
|
||||
for(auto& itr : _devices_v)
|
||||
itr = tolower(itr);
|
||||
bool _all_devices = _devices_v.find("all") != std::string::npos || _devices_v.empty();
|
||||
bool _no_devices = _devices_v.find("none") != std::string::npos;
|
||||
|
||||
std::set<uint32_t> _devices{};
|
||||
if(_all_devices)
|
||||
{
|
||||
for(uint32_t i = 0; i < data::device_count; ++i)
|
||||
_devices.emplace(i);
|
||||
}
|
||||
else if(!_no_devices)
|
||||
{
|
||||
for(auto&& itr : tim::delimit(get_rocm_smi_devices()))
|
||||
{
|
||||
uint32_t idx = std::stoul(itr);
|
||||
if(idx < data::device_count) _devices.emplace(idx);
|
||||
}
|
||||
}
|
||||
|
||||
data::device_list = _devices;
|
||||
|
||||
for(auto itr : _devices)
|
||||
{
|
||||
uint16_t dev_id = 0;
|
||||
OMNITRACE_ROCM_SMI_CALL(rsmi_dev_id_get(itr, &dev_id));
|
||||
// dev_id holds the device ID of device i, upon a successful call
|
||||
}
|
||||
|
||||
is_initialized() = true;
|
||||
|
||||
data::setup();
|
||||
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = true;
|
||||
omnitrace::rocm_smi::data::set_state(State::Active);
|
||||
}
|
||||
|
||||
void
|
||||
shutdown()
|
||||
{
|
||||
auto_lock_t _lk{ type_mutex<api::rocm_smi>() };
|
||||
|
||||
if(!is_initialized()) return;
|
||||
|
||||
if(data::shutdown())
|
||||
{
|
||||
OMNITRACE_ROCM_SMI_CALL(rsmi_shut_down());
|
||||
}
|
||||
|
||||
is_initialized() = false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
device_count()
|
||||
{
|
||||
uint32_t _num_devices = 0;
|
||||
try
|
||||
{
|
||||
static auto _rsmi_init_once = []() { OMNITRACE_ROCM_SMI_CALL(rsmi_init(0)); };
|
||||
static std::once_flag _once{};
|
||||
std::call_once(_once, _rsmi_init_once);
|
||||
|
||||
OMNITRACE_ROCM_SMI_CALL(rsmi_num_monitor_devices(&_num_devices));
|
||||
} catch(const std::exception& _e)
|
||||
{
|
||||
OMNITRACE_BASIC_PRINT("Exception: %s\n", _e.what());
|
||||
}
|
||||
return _num_devices;
|
||||
}
|
||||
} // namespace rocm_smi
|
||||
} // namespace omnitrace
|
||||
|
||||
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_busy>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_temp>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_power>), true,
|
||||
double)
|
||||
|
||||
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(
|
||||
TIMEMORY_ESC(data_tracker<double, omnitrace::component::backtrace_gpu_memory>), true,
|
||||
double)
|
||||
@@ -21,11 +21,16 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/roctracer.hpp"
|
||||
#include "library/components/pthread_gotcha.hpp"
|
||||
#include "library/components/rocm_smi.hpp"
|
||||
#include "library/components/roctracer_callbacks.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/redirect.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
|
||||
namespace rocm_smi = omnitrace::rocm_smi;
|
||||
using namespace omnitrace;
|
||||
|
||||
namespace tim
|
||||
@@ -35,11 +40,22 @@ namespace component
|
||||
void
|
||||
roctracer::preinit()
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
roctracer_data::label() = "roctracer";
|
||||
roctracer_data::description() = "ROCm tracer (activity API)";
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::start()
|
||||
{
|
||||
if(tracker_type::start() == 0) setup();
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::stop()
|
||||
{
|
||||
if(tracker_type::stop() == 0) shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
roctracer::is_setup()
|
||||
{
|
||||
@@ -53,9 +69,9 @@ roctracer::add_setup(const std::string& _lbl, std::function<void()>&& _func)
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::add_tear_down(const std::string& _lbl, std::function<void()>&& _func)
|
||||
roctracer::add_shutdown(const std::string& _lbl, std::function<void()>&& _func)
|
||||
{
|
||||
roctracer_tear_down_routines().emplace_back(_lbl, std::move(_func));
|
||||
roctracer_shutdown_routines().emplace_back(_lbl, std::move(_func));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -73,7 +89,7 @@ roctracer::remove_setup(const std::string& _lbl)
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::remove_tear_down(const std::string& _lbl)
|
||||
roctracer::remove_shutdown(const std::string& _lbl)
|
||||
{
|
||||
auto& _data = roctracer_setup_routines();
|
||||
for(auto itr = _data.begin(); itr != _data.end(); ++itr)
|
||||
@@ -89,31 +105,44 @@ roctracer::remove_tear_down(const std::string& _lbl)
|
||||
void
|
||||
roctracer::setup()
|
||||
{
|
||||
if(!get_use_timemory() && !get_use_perfetto()) return;
|
||||
trait::runtime_enabled<roctracer_data>::set(get_use_timemory());
|
||||
|
||||
if(!get_use_roctracer()) return;
|
||||
|
||||
auto_lock_t _lk{ type_mutex<roctracer>() };
|
||||
if(roctracer_is_setup()) return;
|
||||
roctracer_is_setup() = true;
|
||||
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
tim::set_env("HSA_TOOLS_LIB", "libomnitrace.so", 0);
|
||||
|
||||
#if OMNITRACE_HIP_VERSION_MAJOR == 4 && OMNITRACE_HIP_VERSION_MINOR < 4
|
||||
auto _kfdwrapper = dynamic_library{ "OMNITRACE_ROCTRACER_LIBKFDWRAPPER",
|
||||
OMNITRACE_ROCTRACER_LIBKFDWRAPPER };
|
||||
#endif
|
||||
|
||||
ROCTRACER_CALL(roctracer_set_properties(ACTIVITY_DOMAIN_HIP_API, nullptr));
|
||||
ROCTRACER_CALL(
|
||||
roctracer_set_properties(ACTIVITY_DOMAIN_HIP_API, (void*) hip_api_callback));
|
||||
|
||||
// if(roctracer_default_pool() == nullptr)
|
||||
if(roctracer_default_pool() == nullptr)
|
||||
{
|
||||
// Allocating tracing pool
|
||||
roctracer_properties_t properties{};
|
||||
memset(&properties, 0, sizeof(roctracer_properties_t));
|
||||
properties.mode = 0x1000;
|
||||
// properties.mode = 0x1000;
|
||||
properties.buffer_size = 0x1000;
|
||||
properties.buffer_callback_fun = hip_activity_callback;
|
||||
ROCTRACER_CALL(roctracer_open_pool(&properties));
|
||||
}
|
||||
|
||||
#if OMNITRACE_HIP_VERSION_MAJOR == 4 && OMNITRACE_HIP_VERSION_MINOR >= 4 && \
|
||||
OMNITRACE_HIP_VERSION_MINOR <= 5
|
||||
// HIP 4.5.0 has an invalid warning
|
||||
redirect _rd{ std::cerr, "roctracer_enable_callback(), get_op_end(), invalid domain "
|
||||
"ID(4) in: roctracer_enable_callback(hip_api_callback, "
|
||||
"nullptr)roctracer_enable_activity_expl(), get_op_end(), "
|
||||
"invalid domain ID(4) in: roctracer_enable_activity()" };
|
||||
#endif
|
||||
|
||||
// Enable API callbacks, all domains
|
||||
ROCTRACER_CALL(roctracer_enable_callback(hip_api_callback, nullptr));
|
||||
// Enable activity tracing, all domains
|
||||
@@ -125,7 +154,7 @@ roctracer::setup()
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::tear_down()
|
||||
roctracer::shutdown()
|
||||
{
|
||||
auto_lock_t _lk{ type_mutex<roctracer>() };
|
||||
if(!roctracer_is_setup()) return;
|
||||
@@ -133,37 +162,48 @@ roctracer::tear_down()
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
|
||||
// flush all the activity
|
||||
// if(roctracer_default_pool() != nullptr)
|
||||
if(roctracer_default_pool() != nullptr)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] roctracer_flush_activity\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(roctracer_flush_activity());
|
||||
}
|
||||
// flush all buffers
|
||||
roctracer_flush_buf();
|
||||
|
||||
// flush all buffers
|
||||
OMNITRACE_DEBUG("[%s] roctracer_flush_buf\n", __FUNCTION__);
|
||||
roctracer_flush_buf();
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("[%s] executing hip_exec_activity_callbacks\n", __FUNCTION__);
|
||||
// make sure all async operations are executed
|
||||
for(size_t i = 0; i < max_supported_threads; ++i)
|
||||
hip_exec_activity_callbacks(i);
|
||||
|
||||
// callback for hsa
|
||||
for(auto& itr : roctracer_tear_down_routines())
|
||||
OMNITRACE_DEBUG("[%s] executing roctracer_shutdown_routines...\n", __FUNCTION__);
|
||||
for(auto& itr : roctracer_shutdown_routines())
|
||||
itr.second();
|
||||
|
||||
#if OMNITRACE_HIP_VERSION_MAJOR == 4 && OMNITRACE_HIP_VERSION_MINOR >= 4 && \
|
||||
OMNITRACE_HIP_VERSION_MINOR <= 5
|
||||
OMNITRACE_DEBUG("[%s] redirecting roctracer warnings\n", __FUNCTION__);
|
||||
// HIP 4.5.0 has an invalid warning
|
||||
redirect _rd{
|
||||
std::cerr, "roctracer_disable_callback(), get_op_end(), invalid domain ID(4) "
|
||||
"in: roctracer_disable_callback()roctracer_disable_activity(), "
|
||||
"get_op_end(), invalid domain ID(4) in: roctracer_disable_activity()"
|
||||
};
|
||||
#endif
|
||||
|
||||
// Disable tracing and closing the pool
|
||||
OMNITRACE_DEBUG("[%s] roctracer_disable_callback\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(roctracer_disable_callback());
|
||||
|
||||
OMNITRACE_DEBUG("[%s] roctracer_disable_activity\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(roctracer_disable_activity());
|
||||
|
||||
OMNITRACE_DEBUG("[%s] roctracer_close_pool\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(roctracer_close_pool());
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::start()
|
||||
{
|
||||
if(tracker_type::start() == 0) setup();
|
||||
}
|
||||
|
||||
void
|
||||
roctracer::stop()
|
||||
{
|
||||
if(tracker_type::stop() == 0) tear_down();
|
||||
OMNITRACE_DEBUG("[%s] roctracer is shutdown\n", __FUNCTION__);
|
||||
}
|
||||
} // namespace component
|
||||
} // namespace tim
|
||||
@@ -181,92 +221,103 @@ extern "C"
|
||||
bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count,
|
||||
const char* const* failed_tool_names)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = false;
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env() || get_verbose_env() > 0,
|
||||
"[%s]\n", __FUNCTION__);
|
||||
tim::consume_parameters(table, runtime_version, failed_tool_count,
|
||||
failed_tool_names);
|
||||
|
||||
// ONLOAD_TRACE_BEG();
|
||||
// on_exit(exit_handler, nullptr);
|
||||
|
||||
auto _setup = [=]() {
|
||||
get_hsa_timer() =
|
||||
std::make_unique<hsa_timer_t>(table->core_->hsa_system_get_info_fn);
|
||||
|
||||
// const char* output_prefix = getenv("ROCP_OUTPUT_DIR");
|
||||
const char* output_prefix = nullptr;
|
||||
|
||||
// App begin timestamp begin_ts_file.txt
|
||||
// begin_ts_file_handle = open_output_file(output_prefix,
|
||||
// "begin_ts_file.txt"); const timestamp_t app_start_time =
|
||||
// timer->timestamp_fn_ns(); fprintf(begin_ts_file_handle, "%lu\n",
|
||||
// app_start_time);
|
||||
|
||||
bool trace_hsa_api = get_trace_hsa_api();
|
||||
std::vector<std::string> hsa_api_vec =
|
||||
tim::delimit(get_trace_hsa_api_types());
|
||||
|
||||
// Enable HSA API callbacks/activity
|
||||
if(trace_hsa_api)
|
||||
try
|
||||
{
|
||||
// hsa_api_file_handle = open_output_file(output_prefix,
|
||||
// "hsa_api_trace.txt");
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug() || get_verbose() > 1,
|
||||
"[%s] setting up HSA...\n",
|
||||
__FUNCTION__);
|
||||
|
||||
// initialize HSA tracing
|
||||
roctracer_set_properties(ACTIVITY_DOMAIN_HSA_API, (void*) table);
|
||||
get_hsa_timer() =
|
||||
std::make_unique<hsa_timer_t>(table->core_->hsa_system_get_info_fn);
|
||||
|
||||
OMNITRACE_DEBUG(" HSA-trace(");
|
||||
if(!hsa_api_vec.empty())
|
||||
// const char* output_prefix = getenv("ROCP_OUTPUT_DIR");
|
||||
const char* output_prefix = nullptr;
|
||||
|
||||
bool trace_hsa_api = get_trace_hsa_api();
|
||||
|
||||
// Enable HSA API callbacks/activity
|
||||
if(trace_hsa_api)
|
||||
{
|
||||
for(const auto& itr : hsa_api_vec)
|
||||
std::vector<std::string> hsa_api_vec =
|
||||
tim::delimit(get_trace_hsa_api_types());
|
||||
|
||||
// initialize HSA tracing
|
||||
roctracer_set_properties(ACTIVITY_DOMAIN_HSA_API, (void*) table);
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug() || get_verbose() > 1,
|
||||
" HSA-trace(");
|
||||
if(!hsa_api_vec.empty())
|
||||
{
|
||||
uint32_t cid = HSA_API_ID_NUMBER;
|
||||
const char* api = itr.c_str();
|
||||
ROCTRACER_CALL(roctracer_op_code(ACTIVITY_DOMAIN_HSA_API, api,
|
||||
&cid, nullptr));
|
||||
ROCTRACER_CALL(roctracer_enable_op_callback(
|
||||
ACTIVITY_DOMAIN_HSA_API, cid, hsa_api_callback, nullptr));
|
||||
for(const auto& itr : hsa_api_vec)
|
||||
{
|
||||
uint32_t cid = HSA_API_ID_NUMBER;
|
||||
const char* api = itr.c_str();
|
||||
ROCTRACER_CALL(roctracer_op_code(ACTIVITY_DOMAIN_HSA_API, api,
|
||||
&cid, nullptr));
|
||||
ROCTRACER_CALL(roctracer_enable_op_callback(
|
||||
ACTIVITY_DOMAIN_HSA_API, cid, hsa_api_callback, nullptr));
|
||||
|
||||
OMNITRACE_DEBUG(" %s", api);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_debug() || get_verbose() > 1, " %s", api);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCTRACER_CALL(roctracer_enable_domain_callback(
|
||||
ACTIVITY_DOMAIN_HSA_API, hsa_api_callback, nullptr));
|
||||
}
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug() || get_verbose() > 1,
|
||||
"\n");
|
||||
}
|
||||
else
|
||||
|
||||
bool trace_hsa_activity = get_trace_hsa_activity();
|
||||
// Enable HSA GPU activity
|
||||
if(trace_hsa_activity)
|
||||
{
|
||||
ROCTRACER_CALL(roctracer_enable_domain_callback(
|
||||
ACTIVITY_DOMAIN_HSA_API, hsa_api_callback, nullptr));
|
||||
// initialize HSA tracing
|
||||
::roctracer::hsa_ops_properties_t ops_properties{
|
||||
table,
|
||||
reinterpret_cast<activity_async_callback_t>(
|
||||
hsa_activity_callback),
|
||||
nullptr, output_prefix
|
||||
};
|
||||
roctracer_set_properties(ACTIVITY_DOMAIN_HSA_OPS, &ops_properties);
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug() || get_verbose() > 1,
|
||||
" HSA-activity-trace()\n");
|
||||
ROCTRACER_CALL(roctracer_enable_op_activity(ACTIVITY_DOMAIN_HSA_OPS,
|
||||
HSA_OP_ID_COPY));
|
||||
}
|
||||
OMNITRACE_DEBUG("\n");
|
||||
}
|
||||
|
||||
bool trace_hsa_activity = get_trace_hsa_activity();
|
||||
// Enable HSA GPU activity
|
||||
if(trace_hsa_activity)
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
// initialize HSA tracing
|
||||
::roctracer::hsa_ops_properties_t ops_properties{
|
||||
table,
|
||||
reinterpret_cast<activity_async_callback_t>(hsa_activity_callback),
|
||||
nullptr, output_prefix
|
||||
};
|
||||
roctracer_set_properties(ACTIVITY_DOMAIN_HSA_OPS, &ops_properties);
|
||||
|
||||
OMNITRACE_DEBUG(" HSA-activity-trace()\n");
|
||||
ROCTRACER_CALL(roctracer_enable_op_activity(ACTIVITY_DOMAIN_HSA_OPS,
|
||||
HSA_OP_ID_COPY));
|
||||
OMNITRACE_BASIC_PRINT("Exception was thrown in HSA setup: %s\n",
|
||||
_e.what());
|
||||
}
|
||||
};
|
||||
|
||||
auto _tear_down = []() {
|
||||
auto _shutdown = []() {
|
||||
OMNITRACE_DEBUG("[%s] roctracer_disable_domain_callback\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API));
|
||||
|
||||
OMNITRACE_DEBUG("[%s] roctracer_disable_op_activity\n", __FUNCTION__);
|
||||
ROCTRACER_CALL(
|
||||
roctracer_disable_op_activity(ACTIVITY_DOMAIN_HSA_OPS, HSA_OP_ID_COPY));
|
||||
};
|
||||
|
||||
if(comp::roctracer::is_setup()) _setup();
|
||||
|
||||
comp::roctracer::add_setup("hsa", std::move(_setup));
|
||||
comp::roctracer::add_tear_down("hsa", std::move(_tear_down));
|
||||
comp::roctracer::add_shutdown("hsa", std::move(_shutdown));
|
||||
|
||||
rocm_smi::setup();
|
||||
comp::roctracer::setup();
|
||||
|
||||
pthread_gotcha::enable_sampling_on_child_threads() = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -274,6 +325,7 @@ extern "C"
|
||||
void OnUnload()
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s]\n", __FUNCTION__);
|
||||
// ONLOAD_TRACE("");
|
||||
rocm_smi::shutdown();
|
||||
comp::roctracer::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "library.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/critical_trace.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
|
||||
#include <timemory/backends/threading.hpp>
|
||||
@@ -46,7 +47,7 @@ auto&
|
||||
get_roctracer_hip_data(int64_t _tid = threading::get_id())
|
||||
{
|
||||
using data_t = std::unordered_map<uint64_t, roctracer_bundle_t>;
|
||||
using thread_data_t = omnitrace_thread_data<data_t, api::roctracer>;
|
||||
using thread_data_t = thread_data<data_t, api::roctracer>;
|
||||
static auto& _v = thread_data_t::instances(thread_data_t::construct_on_init{});
|
||||
return _v.at(_tid);
|
||||
}
|
||||
@@ -76,9 +77,8 @@ get_roctracer_cid_data()
|
||||
auto&
|
||||
get_hip_activity_callbacks(int64_t _tid = threading::get_id())
|
||||
{
|
||||
using thread_data_t =
|
||||
omnitrace_thread_data<std::vector<std::function<void()>>, api::roctracer>;
|
||||
static auto& _v = thread_data_t::instances(thread_data_t::construct_on_init{});
|
||||
using thread_data_t = thread_data<std::vector<std::function<void()>>, api::roctracer>;
|
||||
static auto& _v = thread_data_t::instances(thread_data_t::construct_on_init{});
|
||||
return _v.at(_tid);
|
||||
}
|
||||
|
||||
@@ -214,11 +214,17 @@ hsa_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
void
|
||||
hsa_activity_callback(uint32_t op, activity_record_t* record, void* arg)
|
||||
{
|
||||
if(get_state() != State::Active || !trait::runtime_enabled<comp::roctracer>::get())
|
||||
return;
|
||||
|
||||
static const char* copy_op_name = "hsa_async_copy";
|
||||
static const char* dispatch_op_name = "hsa_dispatch";
|
||||
static const char* barrier_op_name = "hsa_barrier";
|
||||
const char** _name = nullptr;
|
||||
|
||||
static thread_local auto _once = (threading::set_thread_name("omni.roctracer"), true);
|
||||
(void) _once;
|
||||
|
||||
switch(op)
|
||||
{
|
||||
case HSA_OP_ID_DISPATCH: _name = &dispatch_op_name; break;
|
||||
@@ -318,7 +324,7 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
data->args.hipLaunchKernel.stream);
|
||||
if(_name != nullptr)
|
||||
{
|
||||
if(get_use_perfetto() || get_use_timemory())
|
||||
if(get_use_perfetto() || get_use_timemory() || get_use_rocm_smi())
|
||||
{
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<key_data_mutex_t>() };
|
||||
get_roctracer_key_data().emplace(data->correlation_id, _name);
|
||||
@@ -333,7 +339,7 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
const char* _name = hipKernelNameRef(data->args.hipModuleLaunchKernel.f);
|
||||
if(_name != nullptr)
|
||||
{
|
||||
if(get_use_perfetto() || get_use_timemory())
|
||||
if(get_use_perfetto() || get_use_timemory() || get_use_rocm_smi())
|
||||
{
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<key_data_mutex_t>() };
|
||||
get_roctracer_key_data().emplace(data->correlation_id, _name);
|
||||
@@ -345,7 +351,7 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(get_use_perfetto() || get_use_timemory())
|
||||
if(get_use_perfetto() || get_use_timemory() || get_use_rocm_smi())
|
||||
{
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<key_data_mutex_t>() };
|
||||
get_roctracer_key_data().emplace(data->correlation_id, op_name);
|
||||
@@ -373,7 +379,7 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
get_roctracer_hip_data()->erase(itr.first);
|
||||
}
|
||||
}
|
||||
if(get_use_critical_trace())
|
||||
if(get_use_critical_trace() || get_use_rocm_smi())
|
||||
{
|
||||
auto _cid = get_cpu_cid()++;
|
||||
uint16_t _depth = (get_cpu_cid_stack()->empty())
|
||||
@@ -422,7 +428,7 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
}
|
||||
}
|
||||
}
|
||||
if(get_use_critical_trace())
|
||||
if(get_use_critical_trace() || get_use_rocm_smi())
|
||||
{
|
||||
uint16_t _depth = 0;
|
||||
uint64_t _cid = 0;
|
||||
@@ -445,6 +451,14 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
void
|
||||
hip_activity_callback(const char* begin, const char* end, void*)
|
||||
{
|
||||
if(get_state() != State::Active || !trait::runtime_enabled<comp::roctracer>::get())
|
||||
return;
|
||||
|
||||
sampling::block_signals();
|
||||
|
||||
static thread_local auto _once = (threading::set_thread_name("omni.roctracer"), true);
|
||||
(void) _once;
|
||||
|
||||
using Device = critical_trace::Device;
|
||||
using Phase = critical_trace::Phase;
|
||||
|
||||
@@ -494,7 +508,7 @@ hip_activity_callback(const char* begin, const char* end, void*)
|
||||
auto _laps = _indexes[_corr_id]++; // see note #1
|
||||
const char* _name = nullptr;
|
||||
bool _found = false;
|
||||
bool _critical_trace = get_use_critical_trace();
|
||||
bool _critical_trace = get_use_critical_trace() || get_use_rocm_smi();
|
||||
|
||||
{
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<key_data_mutex_t>() };
|
||||
@@ -597,7 +611,7 @@ roctracer_setup_routines()
|
||||
}
|
||||
|
||||
roctracer_functions_t&
|
||||
roctracer_tear_down_routines()
|
||||
roctracer_shutdown_routines()
|
||||
{
|
||||
static auto _v = roctracer_functions_t{};
|
||||
return _v;
|
||||
|
||||
@@ -54,12 +54,30 @@ get_config()
|
||||
(void) _once;
|
||||
}
|
||||
|
||||
std::string
|
||||
get_setting_name(std::string _v)
|
||||
{
|
||||
static const auto _prefix = tim::string_view_t{ "omnitrace_" };
|
||||
for(auto& itr : _v)
|
||||
itr = tolower(itr);
|
||||
auto _pos = _v.find(_prefix);
|
||||
if(_pos == 0) return _v.substr(_prefix.length());
|
||||
return _v;
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONFIG_SETTING(TYPE, ENV_NAME, DESCRIPTION, INITIAL_VALUE, ...) \
|
||||
_config->insert<TYPE, TYPE>( \
|
||||
ENV_NAME, ENV_NAME, DESCRIPTION, INITIAL_VALUE, \
|
||||
std::set<std::string>{ "custom", "omnitrace", __VA_ARGS__ })
|
||||
{ \
|
||||
auto _ret = _config->insert<TYPE, TYPE>( \
|
||||
ENV_NAME, get_setting_name(ENV_NAME), DESCRIPTION, INITIAL_VALUE, \
|
||||
std::set<std::string>{ "custom", "omnitrace", __VA_ARGS__ }); \
|
||||
if(!_ret.second) \
|
||||
OMNITRACE_PRINT("Warning! Duplicate setting: %s / %s\n", \
|
||||
get_setting_name(ENV_NAME).c_str(), ENV_NAME); \
|
||||
}
|
||||
} // namespace
|
||||
|
||||
inline namespace config
|
||||
{
|
||||
void
|
||||
configure_settings()
|
||||
{
|
||||
@@ -67,25 +85,24 @@ configure_settings()
|
||||
if(_once) return;
|
||||
_once = true;
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() < State::Init,
|
||||
"config::configure_settings() called before omnitrace_init_library. state = %s",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() > State::Init,
|
||||
"config::configure_settings() called after omnitrace was initialized. state = %s",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
static auto _config = settings::shared_instance();
|
||||
// auto* _config = settings::instance();
|
||||
|
||||
// if using timemory, default to perfetto being off
|
||||
auto _default_perfetto_v =
|
||||
!tim::get_env<bool>("OMNITRACE_USE_TIMEMORY", false, false);
|
||||
|
||||
auto _default_config_file =
|
||||
JOIN("/", tim::get_env<std::string>("HOME", "."), "omnitrace.cfg");
|
||||
|
||||
auto _system_backend = tim::get_env("OMNITRACE_BACKEND_SYSTEM", false, false);
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_CONFIG_FILE",
|
||||
"Configuration file of omnitrace and timemory settings",
|
||||
_default_config_file, "config");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_DEBUG", "Enable debugging output",
|
||||
_config->get_debug(), "debugging");
|
||||
|
||||
auto _omnitrace_debug = _config->get<bool>("OMNITRACE_DEBUG");
|
||||
if(_omnitrace_debug) tim::set_env("TIMEMORY_DEBUG_SETTINGS", "1", 0);
|
||||
|
||||
@@ -101,6 +118,22 @@ configure_settings()
|
||||
"backend", "roctracer");
|
||||
#endif
|
||||
|
||||
#if defined(OMNITRACE_USE_ROCM_SMI)
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
bool, "OMNITRACE_USE_ROCM_SMI",
|
||||
"Enable sampling GPU power, temp, utilization, and memory usage", true, "backend",
|
||||
"rocm-smi");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_ROCM_SMI_DEVICES",
|
||||
"Devices to query when OMNITRACE_USE_ROCM_SMI=ON", "all",
|
||||
"backend", "rocm-smi");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
double, "OMNITRACE_ROCM_SMI_FREQ",
|
||||
"Number of rocm-smi samples per second when OMNITTRACE_USE_ROCM_SMI=ON", 5.0,
|
||||
"backend", "rocm-smi");
|
||||
#endif
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_SAMPLING",
|
||||
"Enable statistical sampling of call-stack", false,
|
||||
"backend", "sampling");
|
||||
@@ -110,6 +143,9 @@ configure_settings()
|
||||
"Enable tagging filenames with process identifier (either MPI rank or pid)", true,
|
||||
"io");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_KOKKOSP",
|
||||
"Enable support for Kokkos Tools", true, "kokkos");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_INSTRUMENTATION_INTERVAL",
|
||||
"Instrumentation only takes measurements once every N "
|
||||
"function calls (not statistical)",
|
||||
@@ -225,6 +261,40 @@ configure_settings()
|
||||
_config->get_stack_clearing() = false;
|
||||
_config->get_time_output() = true;
|
||||
_config->get_timing_precision() = 6;
|
||||
_config->get_max_thread_bookmarks() = 1;
|
||||
_config->get_timing_units() = "sec";
|
||||
_config->get_memory_units() = "MB";
|
||||
_config->get_papi_events() = "PAPI_TOT_CYC, PAPI_TOT_INS";
|
||||
|
||||
#if defined(TIMEMORY_USE_PAPI)
|
||||
int _paranoid = 2;
|
||||
{
|
||||
std::ifstream _fparanoid{ "/proc/sys/kernel/perf_event_paranoid" };
|
||||
if(_fparanoid) _fparanoid >> _paranoid;
|
||||
}
|
||||
|
||||
if(_paranoid > 1)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_verbose_env() >= 0,
|
||||
"/proc/sys/kernel/perf_event_paranoid has a value of %i. "
|
||||
"Disabling PAPI (requires a value <= 1)...\n",
|
||||
_paranoid);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_verbose_env() >= 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<comp::papi_common>::set(false);
|
||||
tim::trait::runtime_enabled<comp::papi_array_t>::set(false);
|
||||
tim::trait::runtime_enabled<comp::papi_vector>::set(false);
|
||||
tim::trait::runtime_enabled<comp::cpu_roofline_flops>::set(false);
|
||||
tim::trait::runtime_enabled<comp::cpu_roofline_dp_flops>::set(false);
|
||||
tim::trait::runtime_enabled<comp::cpu_roofline_sp_flops>::set(false);
|
||||
_config->get_papi_events() = "";
|
||||
}
|
||||
#else
|
||||
_config->get_papi_quiet() = true;
|
||||
#endif
|
||||
|
||||
for(auto&& itr :
|
||||
tim::delimit(_config->get<std::string>("OMNITRACE_CONFIG_FILE"), ";:"))
|
||||
@@ -265,15 +335,39 @@ 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 defined(OMNITRACE_USE_ROCM_SMI)
|
||||
auto _rsmi_freq = _config->find("OMNITRACE_ROCM_SMI_FREQ");
|
||||
if(_rsmi_freq != _config->end())
|
||||
{
|
||||
double& _rsmi_freq_v =
|
||||
static_cast<tim::tsettings<double>&>(*_rsmi_freq->second).get();
|
||||
if(_rsmi_freq_v > 1000) _rsmi_freq_v = 1000.;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
print_config_settings(
|
||||
print_banner(std::ostream& _os)
|
||||
{
|
||||
static const char* _banner = R"banner(
|
||||
|
||||
______ .___ ___. .__ __. __ .___________..______ ___ ______ _______
|
||||
/ __ \ | \/ | | \ | | | | | || _ \ / \ / || ____|
|
||||
| | | | | \ / | | \| | | | `---| |----`| |_) | / ^ \ | ,----'| |__
|
||||
| | | | | |\/| | | . ` | | | | | | / / /_\ \ | | | __|
|
||||
| `--' | | | | | | |\ | | | | | | |\ \----./ _____ \ | `----.| |____
|
||||
\______/ |__| |__| |__| \__| |__| |__| | _| `._____/__/ \__\ \______||_______|
|
||||
|
||||
)banner";
|
||||
_os << _banner << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
print_settings(
|
||||
std::ostream& _ros,
|
||||
std::function<bool(const std::string_view&, const std::set<std::string>&)>&& _filter)
|
||||
{
|
||||
if(get_verbose() < 1) return;
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(true, "configuration:\n");
|
||||
|
||||
std::stringstream _os{};
|
||||
@@ -370,6 +464,61 @@ print_config_settings(
|
||||
_ros << _os.str() << std::flush;
|
||||
}
|
||||
|
||||
void
|
||||
print_settings()
|
||||
{
|
||||
if(dmp::rank() > 0) return;
|
||||
|
||||
static std::set<tim::string_view_t> _sample_options = {
|
||||
"OMNITRACE_SAMPLING_FREQ", "OMNITRACE_SAMPLING_DELAY",
|
||||
"OMNITRACE_FLAT_SAMPLING", "OMNITRACE_TIMELINE_SAMPLING",
|
||||
"OMNITRACE_FLAT_SAMPLING", "OMNITRACE_TIMELINE_SAMPLING",
|
||||
};
|
||||
static std::set<tim::string_view_t> _perfetto_options = {
|
||||
"OMNITRACE_OUTPUT_FILE",
|
||||
"OMNITRACE_BACKEND",
|
||||
"OMNITRACE_SHMEM_SIZE_HINT_KB",
|
||||
"OMNITRACE_BUFFER_SIZE_KB",
|
||||
};
|
||||
static std::set<tim::string_view_t> _timemory_options = {
|
||||
"OMNITRACE_ROCTRACER_FLAT_PROFILE", "OMNITRACE_ROCTRACER_TIMELINE_PROFILE"
|
||||
};
|
||||
// generic filter for filtering relevant options
|
||||
auto _is_omnitrace_option = [](const auto& _v, const auto& _c) {
|
||||
if(!get_use_roctracer() && _v.find("OMNITRACE_ROCTRACER_") == 0) return false;
|
||||
if(!get_use_critical_trace() && _v.find("OMNITRACE_CRITICAL_TRACE_") == 0)
|
||||
return false;
|
||||
if(!get_use_perfetto() && _perfetto_options.count(_v) > 0) return false;
|
||||
if(!get_use_timemory() && _timemory_options.count(_v) > 0) return false;
|
||||
if(!get_use_sampling() && _sample_options.count(_v) > 0) return false;
|
||||
const auto npos = std::string::npos;
|
||||
if(_v.find("WIDTH") != npos || _v.find("SEPARATOR_FREQ") != npos ||
|
||||
_v.find("AUTO_OUTPUT") != npos || _v.find("DART_OUTPUT") != npos ||
|
||||
_v.find("FILE_OUTPUT") != npos || _v.find("PLOT_OUTPUT") != npos ||
|
||||
_v.find("FLAMEGRAPH_OUTPUT") != npos)
|
||||
return false;
|
||||
if(!_c.empty())
|
||||
{
|
||||
if(_c.find("omnitrace") != _c.end()) return true;
|
||||
if(_c.find("debugging") != _c.end() && _v.find("DEBUG") != npos) return true;
|
||||
if(_c.find("config") != _c.end()) return true;
|
||||
if(_c.find("dart") != _c.end()) return false;
|
||||
if(_c.find("io") != _c.end() && _v.find("_OUTPUT") != npos) return true;
|
||||
if(_c.find("format") != _c.end()) return true;
|
||||
return false;
|
||||
}
|
||||
return (_v.find("OMNITRACE_") == 0);
|
||||
};
|
||||
|
||||
tim::print_env(std::cerr, [_is_omnitrace_option](const std::string& _v) {
|
||||
return _is_omnitrace_option(_v, std::set<std::string>{});
|
||||
});
|
||||
|
||||
print_settings(std::cerr, _is_omnitrace_option);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
std::string&
|
||||
get_exe_name()
|
||||
{
|
||||
@@ -384,12 +533,56 @@ get_config_file()
|
||||
return static_cast<tim::tsettings<std::string>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
Mode
|
||||
get_mode()
|
||||
{
|
||||
static auto _v = []() {
|
||||
auto _mode = tim::get_env_choice<std::string>("OMNITRACE_MODE", "trace",
|
||||
{ "trace", "sampling" });
|
||||
if(_mode == "sampling") return Mode::Sampling;
|
||||
return Mode::Trace;
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
|
||||
bool&
|
||||
is_attached()
|
||||
{
|
||||
static bool _v = false;
|
||||
return _v;
|
||||
}
|
||||
|
||||
bool&
|
||||
is_binary_rewrite()
|
||||
{
|
||||
static bool _v = false;
|
||||
return _v;
|
||||
}
|
||||
|
||||
bool
|
||||
get_debug_env()
|
||||
{
|
||||
return tim::get_env<bool>("OMNITRACE_DEBUG", false);
|
||||
}
|
||||
|
||||
bool
|
||||
get_is_continuous_integration()
|
||||
{
|
||||
return tim::get_env<bool>("OMNITRACE_CI", false);
|
||||
}
|
||||
|
||||
bool
|
||||
get_debug_init()
|
||||
{
|
||||
return tim::get_env<bool>("OMNITRACE_DEBUG_INIT", false);
|
||||
}
|
||||
|
||||
bool
|
||||
get_debug_finalize()
|
||||
{
|
||||
return tim::get_env<bool>("OMNITRACE_DEBUG_FINALIZE", false);
|
||||
}
|
||||
|
||||
bool
|
||||
get_debug()
|
||||
{
|
||||
@@ -430,6 +623,18 @@ get_use_roctracer()
|
||||
#if defined(OMNITRACE_USE_ROCTRACER)
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_ROCTRACER");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
#else
|
||||
static auto _v = false;
|
||||
return _v;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool&
|
||||
get_use_rocm_smi()
|
||||
{
|
||||
#if defined(OMNITRACE_USE_ROCM_SMI)
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_ROCM_SMI");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
#else
|
||||
static auto _v = false;
|
||||
return _v;
|
||||
@@ -443,10 +648,9 @@ get_use_sampling()
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_SAMPLING");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
#else
|
||||
OMNITRACE_THROW(
|
||||
"Error! sampling was enabled but omnitrace was not built with libunwind support");
|
||||
static bool _v = false;
|
||||
if(_v)
|
||||
throw std::runtime_error("Error! sampling was enabled but omnitrace was not "
|
||||
"built with libunwind support");
|
||||
return _v;
|
||||
#endif
|
||||
}
|
||||
@@ -472,6 +676,13 @@ get_use_critical_trace()
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
bool
|
||||
get_use_kokkosp()
|
||||
{
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_KOKKOSP");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
bool
|
||||
get_critical_trace_debug()
|
||||
{
|
||||
@@ -634,6 +845,20 @@ get_critical_trace_count()
|
||||
return static_cast<tim::tsettings<int64_t>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
double&
|
||||
get_rocm_smi_freq()
|
||||
{
|
||||
static auto _v = get_config()->find("OMNITRACE_ROCM_SMI_FREQ");
|
||||
return static_cast<tim::tsettings<double>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
std::string
|
||||
get_rocm_smi_devices()
|
||||
{
|
||||
static auto _v = get_config()->find("OMNITRACE_ROCM_SMI_DEVICES");
|
||||
return static_cast<tim::tsettings<std::string>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
bool
|
||||
get_debug_tid()
|
||||
{
|
||||
@@ -665,6 +890,7 @@ get_debug_pid()
|
||||
_vlist.count(dmp::rank()) > 0;
|
||||
return _v;
|
||||
}
|
||||
} // namespace config
|
||||
|
||||
State&
|
||||
get_state()
|
||||
@@ -685,8 +911,7 @@ get_cpu_cid_stack(int64_t _tid)
|
||||
{
|
||||
struct omnitrace_cpu_cid_stack
|
||||
{};
|
||||
using thread_data_t =
|
||||
omnitrace_thread_data<std::vector<uint64_t>, 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)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <PTL/ThreadPool.hh>
|
||||
#include <timemory/backends/dmp.hpp>
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/hash/types.hpp>
|
||||
#include <timemory/tpls/cereal/cereal/archives/json.hpp>
|
||||
#include <timemory/tpls/cereal/cereal/cereal.hpp>
|
||||
@@ -38,6 +39,7 @@
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
@@ -176,7 +178,8 @@ entry::operator+=(const entry& rhs)
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_PRINT(
|
||||
OMNITRACE_CONDITIONAL_PRINT(
|
||||
get_verbose() > 1,
|
||||
"Warning! Incorrect phase. entry::operator+=(entry) is only valid for "
|
||||
"Phase::BEGIN += Phase::END\n");
|
||||
}
|
||||
@@ -427,46 +430,80 @@ call_chain::query(FuncT&& _func) const
|
||||
|
||||
template <>
|
||||
void
|
||||
call_chain::generate_perfetto<Device::NONE>(std::set<entry>&) const
|
||||
call_chain::generate_perfetto<Device::NONE>(std::set<entry>&, bool) const
|
||||
{}
|
||||
|
||||
template <>
|
||||
void
|
||||
call_chain::generate_perfetto<Device::CPU>(std::set<entry>& _used) const
|
||||
call_chain::generate_perfetto<Device::CPU>(std::set<entry>& _used, bool _basic) const
|
||||
{
|
||||
static std::set<std::string> _static_strings{};
|
||||
static std::mutex _static_mutex{};
|
||||
for(const auto& itr : *this)
|
||||
{
|
||||
if(!_used.emplace(itr).second) continue;
|
||||
std::string _name = tim::demangle(tim::get_hash_identifier(itr.hash));
|
||||
_static_mutex.lock();
|
||||
auto sitr = _static_strings.emplace(_name);
|
||||
_static_mutex.unlock();
|
||||
TRACE_EVENT_BEGIN("host-critical-trace",
|
||||
perfetto::StaticString{ sitr.first->c_str() },
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
TRACE_EVENT_END("host-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
if(_basic)
|
||||
{
|
||||
if(itr.device == Device::CPU)
|
||||
{
|
||||
TRACE_EVENT_BEGIN("device-critical-trace", "CPU",
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
}
|
||||
else if(itr.device == Device::GPU)
|
||||
{
|
||||
TRACE_EVENT_BEGIN("device-critical-trace", "GPU",
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
}
|
||||
TRACE_EVENT_END("device-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!_used.emplace(itr).second) continue;
|
||||
std::string _name = tim::demangle(tim::get_hash_identifier(itr.hash));
|
||||
_static_mutex.lock();
|
||||
auto sitr = _static_strings.emplace(_name);
|
||||
_static_mutex.unlock();
|
||||
TRACE_EVENT_BEGIN("host-critical-trace",
|
||||
perfetto::StaticString{ sitr.first->c_str() },
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
TRACE_EVENT_END("host-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
call_chain::generate_perfetto<Device::GPU>(std::set<entry>& _used) const
|
||||
call_chain::generate_perfetto<Device::GPU>(std::set<entry>& _used, bool _basic) const
|
||||
{
|
||||
static std::set<std::string> _static_strings{};
|
||||
static std::mutex _static_mutex{};
|
||||
for(const auto& itr : *this)
|
||||
{
|
||||
if(!_used.emplace(itr).second) continue;
|
||||
std::string _name = tim::demangle(tim::get_hash_identifier(itr.hash));
|
||||
_static_mutex.lock();
|
||||
auto sitr = _static_strings.emplace(_name);
|
||||
_static_mutex.unlock();
|
||||
TRACE_EVENT_BEGIN("device-critical-trace",
|
||||
perfetto::StaticString{ sitr.first->c_str() },
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
TRACE_EVENT_END("device-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
if(_basic)
|
||||
{
|
||||
if(itr.device == Device::CPU)
|
||||
{
|
||||
TRACE_EVENT_BEGIN("device-critical-trace", "CPU",
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
}
|
||||
else if(itr.device == Device::GPU)
|
||||
{
|
||||
TRACE_EVENT_BEGIN("device-critical-trace", "GPU",
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
}
|
||||
TRACE_EVENT_END("device-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!_used.emplace(itr).second) continue;
|
||||
std::string _name = tim::demangle(tim::get_hash_identifier(itr.hash));
|
||||
_static_mutex.lock();
|
||||
auto sitr = _static_strings.emplace(_name);
|
||||
_static_mutex.unlock();
|
||||
TRACE_EVENT_BEGIN("device-critical-trace",
|
||||
perfetto::StaticString{ sitr.first->c_str() },
|
||||
static_cast<uint64_t>(itr.begin_ns));
|
||||
TRACE_EVENT_END("device-critical-trace", static_cast<uint64_t>(itr.end_ns));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,7 +522,7 @@ get_update_frequency()
|
||||
std::unique_ptr<call_chain>&
|
||||
get(int64_t _tid)
|
||||
{
|
||||
static auto& _v = omnitrace_thread_data<call_chain>::instances();
|
||||
static auto& _v = thread_data<call_chain>::instances();
|
||||
static thread_local auto _once = [_tid]() {
|
||||
if(!_v.at(0)) _v.at(0) = std::make_unique<call_chain>();
|
||||
if(!_v.at(_tid)) _v.at(_tid) = std::make_unique<call_chain>();
|
||||
@@ -515,10 +552,10 @@ size_t
|
||||
add_hash_id(const std::string& _label)
|
||||
{
|
||||
using critical_trace_hash_data =
|
||||
omnitrace_thread_data<critical_trace::hash_ids, critical_trace::id>;
|
||||
thread_data<critical_trace::hash_ids, critical_trace::id>;
|
||||
|
||||
auto _hash = tim::hash::add_hash_id(_label);
|
||||
if(get_use_critical_trace())
|
||||
if(get_use_critical_trace() || get_use_rocm_smi())
|
||||
{
|
||||
critical_trace_hash_data::construct();
|
||||
critical_trace_hash_data::instance()->emplace(_label);
|
||||
@@ -529,7 +566,7 @@ add_hash_id(const std::string& _label)
|
||||
void
|
||||
update(int64_t _tid)
|
||||
{
|
||||
if(!get_use_critical_trace()) return;
|
||||
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();
|
||||
@@ -604,7 +641,8 @@ save_call_graph(const std::string& _fname, const std::string& _label,
|
||||
if(_msg)
|
||||
{
|
||||
if(_func.empty()) _func = __FUNCTION__;
|
||||
OMNITRACE_PRINT("[%s] Outputting '%s'...\n", _func.c_str(), _fname.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0, "[%s] Outputting '%s'...\n",
|
||||
_func.c_str(), _fname.c_str());
|
||||
}
|
||||
ofs << oss.str() << std::endl;
|
||||
}
|
||||
@@ -648,7 +686,8 @@ save_critical_trace(const std::string& _fname, const std::string& _label,
|
||||
if(_msg)
|
||||
{
|
||||
if(_func.empty()) _func = __FUNCTION__;
|
||||
OMNITRACE_PRINT("[%s] Outputting '%s'...\n", _func.c_str(), _fname.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0, "[%s] Outputting '%s'...\n",
|
||||
_func.c_str(), _fname.c_str());
|
||||
}
|
||||
std::stringstream oss{};
|
||||
if(_cchain.size() > 1000)
|
||||
@@ -686,7 +725,8 @@ save_call_chain_text(const std::string& _fname, const call_chain& _call_chain,
|
||||
if(_msg)
|
||||
{
|
||||
if(_func.empty()) _func = __FUNCTION__;
|
||||
OMNITRACE_PRINT("[%s] Outputting '%s'...\n", _func.c_str(), _fname.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0, "[%s] Outputting '%s'...\n",
|
||||
_func.c_str(), _fname.c_str());
|
||||
}
|
||||
ofs << _call_chain << "\n";
|
||||
}
|
||||
@@ -730,7 +770,8 @@ save_call_chain_json(const std::string& _fname, const std::string& _label,
|
||||
if(_msg)
|
||||
{
|
||||
if(_func.empty()) _func = __FUNCTION__;
|
||||
OMNITRACE_PRINT("[%s] Outputting '%s'...\n", _func.c_str(), _fname.c_str());
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_verbose() >= 0, "[%s] Outputting '%s'...\n",
|
||||
_func.c_str(), _fname.c_str());
|
||||
}
|
||||
std::stringstream oss{};
|
||||
if(_call_chain.size() > 100000)
|
||||
@@ -1117,27 +1158,33 @@ get_top(const std::vector<call_chain>& _chain, size_t _count)
|
||||
|
||||
template <Device DevT>
|
||||
void
|
||||
generate_perfetto(const std::vector<call_chain>& _data)
|
||||
generate_perfetto(const std::vector<call_chain>& _data, bool _basic = false)
|
||||
{
|
||||
OMNITRACE_CT_DEBUG("[%s]\n", __FUNCTION__);
|
||||
auto _func = [&](size_t _beg, size_t _end) {
|
||||
|
||||
auto _nrows = std::min<size_t>(get_critical_trace_per_row(), _data.size());
|
||||
|
||||
// run in separate thread(s) so that it ends up in unique row
|
||||
if(_nrows < 1) _nrows = _data.size();
|
||||
|
||||
auto _func = [&](size_t _idx, size_t _beg, size_t _end) {
|
||||
if(_nrows != 1)
|
||||
threading::set_thread_name(TIMEMORY_JOIN(" ", "CriticalPath", _idx).c_str());
|
||||
else
|
||||
threading::set_thread_name("CritialPath");
|
||||
// ensure all hash ids exist
|
||||
copy_hash_ids();
|
||||
std::set<entry> _used{};
|
||||
for(size_t i = _beg; i < _end; ++i)
|
||||
{
|
||||
if(i >= _data.size()) break;
|
||||
_data.at(i).generate_perfetto<DevT>(_used);
|
||||
_data.at(i).generate_perfetto<DevT>(_used, _basic);
|
||||
}
|
||||
};
|
||||
|
||||
// run in separate thread(s) so that it ends up in unique row
|
||||
auto _nrows = get_critical_trace_per_row();
|
||||
if(_nrows < 1) _nrows = _data.size();
|
||||
|
||||
for(size_t i = 0; i < _data.size(); i += _nrows)
|
||||
{
|
||||
std::thread{ _func, i, i + _nrows }.join();
|
||||
std::thread{ _func, i, i, i + _nrows }.join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1225,6 +1272,8 @@ compute_critical_trace()
|
||||
|
||||
_perf.reset().start();
|
||||
|
||||
generate_perfetto<Device::GPU>({ complete_call_chain }, true);
|
||||
|
||||
OMNITRACE_CT_DEBUG("[%s] Finding sequences...\n", __FUNCTION__);
|
||||
// find the sequences
|
||||
std::vector<call_chain> _top{};
|
||||
@@ -1280,8 +1329,7 @@ compute_critical_trace()
|
||||
_tg.join();
|
||||
_tp.destroy_threadpool();
|
||||
_computed = true;
|
||||
|
||||
} catch(const std::exception& e)
|
||||
} catch(std::exception& e)
|
||||
{
|
||||
OMNITRACE_PRINT("Thread exited '%s' with exception: %s\n", __FUNCTION__,
|
||||
e.what());
|
||||
@@ -1295,5 +1343,36 @@ compute_critical_trace()
|
||||
OMNITRACE_PRINT("%s\n", _ct_msg.c_str());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::vector<std::pair<std::string, entry>>
|
||||
get_entries(int64_t _ts, const std::function<bool(const entry&)>& _eval)
|
||||
{
|
||||
copy_hash_ids();
|
||||
auto _func = [_eval, _ts](std::vector<std::pair<std::string, entry>>* _targ,
|
||||
size_t* _avail) {
|
||||
copy_hash_ids();
|
||||
squash_critical_path(complete_call_chain);
|
||||
*_avail = complete_call_chain.size();
|
||||
std::vector<std::pair<std::string, entry>> _v{};
|
||||
std::sort(complete_call_chain.begin(), complete_call_chain.end());
|
||||
for(const auto& itr : complete_call_chain)
|
||||
{
|
||||
if(itr.phase != Phase::DELTA) continue;
|
||||
if(itr.begin_ns <= _ts && itr.end_ns >= _ts)
|
||||
{
|
||||
if(_eval(itr)) _v.emplace_back(tim::get_hash_identifier(itr.hash), itr);
|
||||
}
|
||||
}
|
||||
*_targ = _v;
|
||||
};
|
||||
size_t _n = 0;
|
||||
std::vector<std::pair<std::string, entry>> _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",
|
||||
__FUNCTION__, _v.size(), _n, _ts);
|
||||
return _v;
|
||||
}
|
||||
|
||||
} // namespace critical_trace
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
|
||||
#include "library/gpu.hpp"
|
||||
|
||||
#if defined(OMNITRACE_USE_HIP)
|
||||
#if defined(OMNITRACE_USE_ROCM_SMI)
|
||||
# include "library/components/rocm_smi.hpp"
|
||||
#elif defined(OMNITRACE_USE_HIP)
|
||||
# if !defined(TIMEMORY_USE_HIP)
|
||||
# define TIMEMORY_USE_HIP 1
|
||||
# endif
|
||||
|
||||
# include "timemory/components/hip/backends.hpp"
|
||||
#endif
|
||||
|
||||
@@ -34,18 +35,18 @@ namespace omnitrace
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
#if defined(OMNITRACE_USE_HIP)
|
||||
int
|
||||
device_count()
|
||||
{
|
||||
#if defined(OMNITRACE_USE_ROCM_SMI)
|
||||
// store as static since calls after rsmi_shutdown will return zero
|
||||
static auto _v = rocm_smi::device_count();
|
||||
return _v;
|
||||
#elif defined(OMNITRACE_USE_HIP)
|
||||
return ::tim::hip::device_count();
|
||||
}
|
||||
#else
|
||||
int
|
||||
device_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace gpu
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
// 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.
|
||||
|
||||
// used by Kokkos decls
|
||||
#if !defined(TIMEMORY_LIBRARY_SOURCE)
|
||||
# define TIMEMORY_LIBRARY_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include "library/components/omnitrace.hpp"
|
||||
#include "library/config.hpp"
|
||||
|
||||
#include <timemory/api/kokkosp.hpp>
|
||||
|
||||
namespace kokkosp = tim::kokkosp;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
template <>
|
||||
inline auto
|
||||
invoke_preinit<kokkosp::memory_tracker>(long)
|
||||
{
|
||||
kokkosp::memory_tracker::label() = "kokkos_memory";
|
||||
kokkosp::memory_tracker::description() = "Kokkos Memory tracker";
|
||||
}
|
||||
} // namespace tim
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string kokkos_banner =
|
||||
"#---------------------------------------------------------------------------#";
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
bool enable_kernel_logger = false;
|
||||
|
||||
inline void
|
||||
add_kernel_logger()
|
||||
{
|
||||
static bool _first = true;
|
||||
if(!_first) return;
|
||||
_first = false;
|
||||
using strvec_t = std::vector<std::string>;
|
||||
|
||||
tim::settings::instance()->insert<bool, bool&>(
|
||||
std::string{ "OMNITRACE_KOKKOS_KERNEL_LOGGER" }, std::string{},
|
||||
std::string{ "Enables kernel logging" }, enable_kernel_logger,
|
||||
strvec_t({ "--omnitrace-kokkos-kernel-logger" }));
|
||||
}
|
||||
|
||||
inline void
|
||||
setup_kernel_logger()
|
||||
{
|
||||
if(tim::settings::debug() || tim::settings::verbose() > 3 || enable_kernel_logger)
|
||||
{
|
||||
kokkosp::logger_t::get_initializer() = [](kokkosp::logger_t& _obj) {
|
||||
_obj.initialize<kokkosp::kernel_logger>();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void kokkosp_print_help(char*) {}
|
||||
|
||||
void kokkosp_parse_args(int, char**) {}
|
||||
|
||||
void kokkosp_declare_metadata(const char* key, const char* value)
|
||||
{
|
||||
tim::manager::add_metadata(key, value);
|
||||
}
|
||||
|
||||
void kokkosp_init_library(const int loadSeq, const uint64_t interfaceVer,
|
||||
const uint32_t devInfoCount, void* deviceInfo)
|
||||
{
|
||||
add_kernel_logger();
|
||||
|
||||
tim::consume_parameters(devInfoCount, deviceInfo);
|
||||
|
||||
printf("%s\n", kokkos_banner.c_str());
|
||||
printf("# KokkosP: omnitrace connector (sequence is %d, version: %llu)\n",
|
||||
loadSeq, (unsigned long long) interfaceVer);
|
||||
printf("%s\n", kokkos_banner.c_str());
|
||||
|
||||
setup_kernel_logger();
|
||||
|
||||
tim::trait::runtime_enabled<kokkosp::memory_tracker>::set(
|
||||
omnitrace::config::get_use_timemory());
|
||||
}
|
||||
|
||||
void kokkosp_finalize_library()
|
||||
{
|
||||
printf("%s\n", kokkos_banner.c_str());
|
||||
printf("# KokkosP: Finalization of omnitrace connector. Complete.\n");
|
||||
printf("%s\n", kokkos_banner.c_str());
|
||||
|
||||
kokkosp::cleanup();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_begin_parallel_for(const char* name, uint32_t devid, uint64_t* kernid)
|
||||
{
|
||||
auto pname =
|
||||
(devid > std::numeric_limits<uint16_t>::max()) // junk device number
|
||||
? TIMEMORY_JOIN(" ", "[kokkos]", name)
|
||||
: TIMEMORY_JOIN(" ", TIMEMORY_JOIN("", "[kokkos][dev", devid, ']'), name);
|
||||
*kernid = kokkosp::get_unique_id();
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, name, *kernid);
|
||||
kokkosp::create_profiler<omnitrace::component::omnitrace>(pname, *kernid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(*kernid);
|
||||
}
|
||||
|
||||
void kokkosp_end_parallel_for(uint64_t kernid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__, kernid);
|
||||
kokkosp::stop_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
kokkosp::destroy_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_begin_parallel_reduce(const char* name, uint32_t devid, uint64_t* kernid)
|
||||
{
|
||||
auto pname =
|
||||
(devid > std::numeric_limits<uint16_t>::max()) // junk device number
|
||||
? TIMEMORY_JOIN(" ", "[kokkos]", name)
|
||||
: TIMEMORY_JOIN(" ", TIMEMORY_JOIN("", "[kokkos][dev", devid, ']'), name);
|
||||
*kernid = kokkosp::get_unique_id();
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, name, *kernid);
|
||||
kokkosp::create_profiler<omnitrace::component::omnitrace>(pname, *kernid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(*kernid);
|
||||
}
|
||||
|
||||
void kokkosp_end_parallel_reduce(uint64_t kernid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__, kernid);
|
||||
kokkosp::stop_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
kokkosp::destroy_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_begin_parallel_scan(const char* name, uint32_t devid, uint64_t* kernid)
|
||||
{
|
||||
auto pname =
|
||||
(devid > std::numeric_limits<uint16_t>::max()) // junk device number
|
||||
? TIMEMORY_JOIN(" ", "[kokkos]", name)
|
||||
: TIMEMORY_JOIN(" ", TIMEMORY_JOIN("", "[kokkos][dev", devid, ']'), name);
|
||||
*kernid = kokkosp::get_unique_id();
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, name, *kernid);
|
||||
kokkosp::create_profiler<omnitrace::component::omnitrace>(pname, *kernid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(*kernid);
|
||||
}
|
||||
|
||||
void kokkosp_end_parallel_scan(uint64_t kernid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__, kernid);
|
||||
kokkosp::stop_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
kokkosp::destroy_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_begin_fence(const char* name, uint32_t devid, uint64_t* kernid)
|
||||
{
|
||||
auto pname =
|
||||
(devid > std::numeric_limits<uint16_t>::max()) // junk device number
|
||||
? TIMEMORY_JOIN(" ", "[kokkos]", name)
|
||||
: TIMEMORY_JOIN(" ", TIMEMORY_JOIN("", "[kokkos][dev", devid, ']'), name);
|
||||
*kernid = kokkosp::get_unique_id();
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, name, *kernid);
|
||||
kokkosp::create_profiler<omnitrace::component::omnitrace>(pname, *kernid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(*kernid);
|
||||
}
|
||||
|
||||
void kokkosp_end_fence(uint64_t kernid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__, kernid);
|
||||
kokkosp::stop_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
kokkosp::destroy_profiler<omnitrace::component::omnitrace>(kernid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_push_profile_region(const char* name)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, name);
|
||||
kokkosp::get_profiler_stack<omnitrace::component::omnitrace>().push_back(
|
||||
kokkosp::profiler_t<omnitrace::component::omnitrace>(name));
|
||||
kokkosp::get_profiler_stack<omnitrace::component::omnitrace>().back().start();
|
||||
}
|
||||
|
||||
void kokkosp_pop_profile_region()
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__);
|
||||
if(kokkosp::get_profiler_stack<omnitrace::component::omnitrace>().empty()) return;
|
||||
kokkosp::get_profiler_stack<omnitrace::component::omnitrace>().back().stop();
|
||||
kokkosp::get_profiler_stack<omnitrace::component::omnitrace>().pop_back();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_create_profile_section(const char* name, uint32_t* secid)
|
||||
{
|
||||
*secid = kokkosp::get_unique_id();
|
||||
auto pname = TIMEMORY_JOIN(" ", "[kokkos]", name);
|
||||
kokkosp::create_profiler<omnitrace::component::omnitrace>(pname, *secid);
|
||||
}
|
||||
|
||||
void kokkosp_destroy_profile_section(uint32_t secid)
|
||||
{
|
||||
kokkosp::destroy_profiler<omnitrace::component::omnitrace>(secid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_start_profile_section(uint32_t secid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, secid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(secid);
|
||||
}
|
||||
|
||||
void kokkosp_stop_profile_section(uint32_t secid)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__, secid);
|
||||
kokkosp::start_profiler<omnitrace::component::omnitrace>(secid);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_allocate_data(const SpaceHandle space, const char* label,
|
||||
const void* const ptr, const uint64_t size)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(0, __FUNCTION__, space.name, label,
|
||||
TIMEMORY_JOIN("", '[', ptr, ']'), size);
|
||||
kokkosp::profiler_alloc_t<>{ TIMEMORY_JOIN(" ", "[kokkos][allocate]", space.name,
|
||||
label) }
|
||||
.store(std::plus<int64_t>{}, size);
|
||||
}
|
||||
|
||||
void kokkosp_deallocate_data(const SpaceHandle space, const char* label,
|
||||
const void* const ptr, const uint64_t size)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(0, __FUNCTION__, space.name, label,
|
||||
TIMEMORY_JOIN("", '[', ptr, ']'), size);
|
||||
kokkosp::profiler_alloc_t<>{ TIMEMORY_JOIN(" ", "[kokkos][deallocate]",
|
||||
space.name, label) }
|
||||
.store(std::plus<int64_t>{}, size);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_begin_deep_copy(SpaceHandle dst_handle, const char* dst_name,
|
||||
const void* dst_ptr, SpaceHandle src_handle,
|
||||
const char* src_name, const void* src_ptr, uint64_t size)
|
||||
{
|
||||
kokkosp::logger_t{}.mark(1, __FUNCTION__, dst_handle.name, dst_name,
|
||||
TIMEMORY_JOIN("", '[', dst_ptr, ']'), src_handle.name,
|
||||
src_name, TIMEMORY_JOIN("", '[', src_ptr, ']'), size);
|
||||
|
||||
auto name = TIMEMORY_JOIN(" ", "[kokkos][deep_copy]",
|
||||
TIMEMORY_JOIN('=', dst_handle.name, dst_name),
|
||||
TIMEMORY_JOIN('=', src_handle.name, src_name));
|
||||
|
||||
auto& _data = kokkosp::get_profiler_stack<omnitrace::component::omnitrace>();
|
||||
_data.emplace_back(name);
|
||||
_data.back().audit(dst_handle, dst_name, dst_ptr, src_handle, src_name, src_ptr,
|
||||
size);
|
||||
_data.back().start();
|
||||
_data.back().store(std::plus<int64_t>{}, size);
|
||||
}
|
||||
|
||||
void kokkosp_end_deep_copy()
|
||||
{
|
||||
kokkosp::logger_t{}.mark(-1, __FUNCTION__);
|
||||
auto& _data = kokkosp::get_profiler_stack<omnitrace::component::omnitrace>();
|
||||
if(_data.empty()) return;
|
||||
_data.back().store(std::minus<int64_t>{}, 0);
|
||||
_data.back().stop();
|
||||
_data.pop_back();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
void kokkosp_profile_event(const char* name)
|
||||
{
|
||||
kokkosp::profiler_t<omnitrace::component::omnitrace>{}.mark(name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_INITIALIZE_STORAGE(kokkosp::memory_tracker)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
|
||||
#include <PTL/ThreadPool.hh>
|
||||
#include <timemory/utility/declaration.hpp>
|
||||
@@ -39,10 +40,14 @@ auto _thread_pool_cfg = []() {
|
||||
_v.init = true;
|
||||
_v.use_affinity = false;
|
||||
_v.use_tbb = false;
|
||||
_v.initializer = []() {};
|
||||
_v.finalizer = []() {};
|
||||
_v.priority = 5;
|
||||
_v.pool_size = 1;
|
||||
_v.initializer = []() {
|
||||
sampling::block_signals();
|
||||
threading::set_thread_name(
|
||||
TIMEMORY_JOIN('.', "ptl", PTL::Threading::GetThreadId()).c_str());
|
||||
};
|
||||
_v.finalizer = []() {};
|
||||
_v.priority = 5;
|
||||
_v.pool_size = 1;
|
||||
return _v;
|
||||
}();
|
||||
}
|
||||
|
||||
@@ -76,10 +76,10 @@ namespace omnitrace
|
||||
namespace sampling
|
||||
{
|
||||
using hw_counters = typename component::backtrace::hw_counters;
|
||||
using signal_type_instances = omnitrace_thread_data<std::set<int>, api::sampling>;
|
||||
using backtrace_init_instances = omnitrace_thread_data<backtrace, api::sampling>;
|
||||
using sampler_running_instances = omnitrace_thread_data<bool, api::sampling>;
|
||||
using papi_vector_instances = omnitrace_thread_data<hw_counters, api::sampling>;
|
||||
using signal_type_instances = thread_data<std::set<int>, api::sampling>;
|
||||
using backtrace_init_instances = thread_data<backtrace, api::sampling>;
|
||||
using sampler_running_instances = thread_data<bool, api::sampling>;
|
||||
using papi_vector_instances = thread_data<hw_counters, api::sampling>;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -134,6 +134,7 @@ get_signal_types(int64_t _tid)
|
||||
std::set<int>
|
||||
setup()
|
||||
{
|
||||
if(!get_use_sampling()) return std::set<int>{};
|
||||
return backtrace::configure(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/state.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
std::string
|
||||
to_string(omnitrace::State _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::State::DelayedInit: return "DelayedInit";
|
||||
case omnitrace::State::PreInit: return "PreInit";
|
||||
case omnitrace::State::Init: return "Init";
|
||||
case omnitrace::State::Active: return "Active";
|
||||
case omnitrace::State::Finalized: return "Finalized";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::Mode _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::Mode::Trace: return "Trace";
|
||||
case omnitrace::Mode::Sampling: return "Sampling";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} // namespace std
|
||||
@@ -23,52 +23,55 @@
|
||||
#include "omnitrace.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
bool debug_print = false;
|
||||
int verbose_level = tim::get_env<int>("TIMEMORY_RUN_VERBOSE", 0);
|
||||
|
||||
static bool binary_rewrite = false;
|
||||
static bool is_attached = false;
|
||||
static bool loop_level_instr = false;
|
||||
static bool werror = false;
|
||||
static bool stl_func_instr = false;
|
||||
static bool use_mpi = false;
|
||||
static bool is_static_exe = false;
|
||||
static bool is_driver = false;
|
||||
static bool allow_overlapping = false;
|
||||
static bool instr_dynamic_callsites = false;
|
||||
static bool instr_traps = false;
|
||||
static bool instr_loop_traps = false;
|
||||
static size_t batch_size = 50;
|
||||
static strset_t extra_libs = {};
|
||||
static size_t min_address_range = (1 << 8); // 256
|
||||
static size_t min_loop_address_range = (1 << 8); // 256
|
||||
static std::vector<std::pair<uint64_t, string_t>> hash_ids = {};
|
||||
static std::map<string_t, bool> use_stubs = {};
|
||||
static std::map<string_t, procedure_t*> beg_stubs = {};
|
||||
static std::map<string_t, procedure_t*> end_stubs = {};
|
||||
static strvec_t init_stub_names = {};
|
||||
static strvec_t fini_stub_names = {};
|
||||
static strset_t used_stub_names = {};
|
||||
static std::vector<call_expr_pointer_t> env_variables = {};
|
||||
static std::map<string_t, call_expr_pointer_t> beg_expr = {};
|
||||
static std::map<string_t, call_expr_pointer_t> end_expr = {};
|
||||
static const auto npos_v = string_t::npos;
|
||||
static string_t instr_mode = "trace";
|
||||
static string_t instr_push_func = "omnitrace_push_trace";
|
||||
static string_t instr_pop_func = "omnitrace_pop_trace";
|
||||
static string_t instr_push_hash = "omnitrace_push_trace_hash";
|
||||
static string_t instr_pop_hash = "omnitrace_pop_trace_hash";
|
||||
static string_t print_instrumented = {};
|
||||
static string_t print_available = {};
|
||||
static string_t print_overlapping = {};
|
||||
static std::string modfunc_dump_dir = {};
|
||||
static auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize;
|
||||
namespace
|
||||
{
|
||||
bool binary_rewrite = false;
|
||||
bool is_attached = false;
|
||||
bool loop_level_instr = false;
|
||||
bool werror = false;
|
||||
bool stl_func_instr = false;
|
||||
bool use_mpi = false;
|
||||
bool is_static_exe = false;
|
||||
bool is_driver = false;
|
||||
bool allow_overlapping = false;
|
||||
bool instr_dynamic_callsites = false;
|
||||
bool instr_traps = false;
|
||||
bool instr_loop_traps = false;
|
||||
size_t batch_size = 50;
|
||||
strset_t extra_libs = {};
|
||||
size_t min_address_range = (1 << 8); // 256
|
||||
size_t min_loop_address_range = (1 << 8); // 256
|
||||
std::vector<std::pair<uint64_t, string_t>> hash_ids = {};
|
||||
std::map<string_t, bool> use_stubs = {};
|
||||
std::map<string_t, procedure_t*> beg_stubs = {};
|
||||
std::map<string_t, procedure_t*> end_stubs = {};
|
||||
strvec_t init_stub_names = {};
|
||||
strvec_t fini_stub_names = {};
|
||||
strset_t used_stub_names = {};
|
||||
std::vector<call_expr_pointer_t> env_variables = {};
|
||||
std::map<string_t, call_expr_pointer_t> beg_expr = {};
|
||||
std::map<string_t, call_expr_pointer_t> end_expr = {};
|
||||
const auto npos_v = string_t::npos;
|
||||
string_t instr_mode = "trace";
|
||||
string_t print_instrumented = {};
|
||||
string_t print_available = {};
|
||||
string_t print_overlapping = {};
|
||||
std::string modfunc_dump_dir = {};
|
||||
auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize;
|
||||
} // namespace
|
||||
|
||||
std::string
|
||||
get_absolute_exe_filepath(std::string exe_name);
|
||||
@@ -132,10 +135,10 @@ main(int argc, char** argv)
|
||||
bpatch->setLivenessAnalysis(false);
|
||||
bpatch->setBaseTrampDeletion(false);
|
||||
bpatch->setTrampRecursive(false);
|
||||
bpatch->setMergeTramp(false);
|
||||
bpatch->setMergeTramp(true);
|
||||
|
||||
std::set<std::string> dyninst_defs = { "TypeChecking", "SaveFPR", "DelayedParsing",
|
||||
"InstrStackFrames" };
|
||||
"MergeTramp" };
|
||||
|
||||
int _argc = argc;
|
||||
int _cmdc = 0;
|
||||
@@ -598,7 +601,8 @@ main(int argc, char** argv)
|
||||
// Helper function for adding regex expressions
|
||||
//
|
||||
auto add_regex = [](auto& regex_array, const string_t& regex_expr) {
|
||||
if(!regex_expr.empty()) regex_array.push_back(std::regex(regex_expr, regex_opts));
|
||||
if(!regex_expr.empty())
|
||||
regex_array.emplace_back(std::regex(regex_expr, regex_opts));
|
||||
};
|
||||
|
||||
add_regex(func_include, tim::get_env<string_t>("OMNITRACE_REGEX_INCLUDE", ""));
|
||||
@@ -638,7 +642,7 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
int dyninst_verb = 1;
|
||||
int dyninst_verb = 2;
|
||||
if(parser.exists("dyninst-options"))
|
||||
{
|
||||
dyninst_defs = parser.get<std::set<std::string>>("dyninst-options");
|
||||
@@ -704,6 +708,26 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
// for runtime instrumentation, we need to set this before the process gets created
|
||||
if(!binary_rewrite)
|
||||
{
|
||||
tim::set_env("HSA_ENABLE_INTERRUPT", "0", 0);
|
||||
if(_pid >= 0)
|
||||
{
|
||||
verbprintf(-10, "#-------------------------------------------------------"
|
||||
"-------------------------------------------#\n");
|
||||
verbprintf(-10, "\n");
|
||||
verbprintf(-10, "WARNING! Sampling may result in ioctl() deadlock within "
|
||||
"the ROCR runtime.\n");
|
||||
verbprintf(-10,
|
||||
"To avoid this, set HSA_ENABLE_INTERRUPT=0 in the environment "
|
||||
"before starting your ROCm/HIP application\n");
|
||||
verbprintf(-10, "\n");
|
||||
verbprintf(-10, "#-------------------------------------------------------"
|
||||
"-------------------------------------------#\n");
|
||||
}
|
||||
}
|
||||
|
||||
addr_space =
|
||||
omnitrace_get_address_space(bpatch, _cmdc, _cmdv, binary_rewrite, _pid, mutname);
|
||||
|
||||
@@ -750,7 +774,7 @@ main(int argc, char** argv)
|
||||
if(app_modules && !app_modules->empty())
|
||||
{
|
||||
modules = *app_modules;
|
||||
for(auto* itr : *app_modules)
|
||||
for(auto* itr : modules)
|
||||
{
|
||||
auto* procedures = itr->getProcedures();
|
||||
if(procedures)
|
||||
@@ -774,7 +798,7 @@ main(int argc, char** argv)
|
||||
if(app_functions && !app_functions->empty())
|
||||
{
|
||||
functions = *app_functions;
|
||||
for(auto* itr : *app_functions)
|
||||
for(auto* itr : functions)
|
||||
{
|
||||
module_t* mod = itr->getModule();
|
||||
if(mod && itr->isInstrumentable())
|
||||
@@ -792,9 +816,9 @@ main(int argc, char** argv)
|
||||
}
|
||||
|
||||
verbprintf(0, "Module size before loading instrumentation library: %lu\n",
|
||||
(long unsigned) app_modules->size());
|
||||
(long unsigned) modules.size());
|
||||
|
||||
if(debug_print || verbose_level > 1)
|
||||
if(debug_print || verbose_level > 2)
|
||||
{
|
||||
module_function::reset_width();
|
||||
for(const auto& itr : available_module_functions)
|
||||
@@ -931,21 +955,18 @@ main(int argc, char** argv)
|
||||
|
||||
verbprintf(0, "Finding functions in image...\n");
|
||||
|
||||
auto* entr_trace = find_function(app_image, instr_push_func.c_str());
|
||||
auto* exit_trace = find_function(app_image, instr_pop_func.c_str());
|
||||
auto* entr_hash = find_function(app_image, instr_push_hash.c_str());
|
||||
auto* exit_hash = find_function(app_image, instr_pop_hash.c_str());
|
||||
auto* init_func = find_function(app_image, "omnitrace_trace_init");
|
||||
auto* fini_func = find_function(app_image, "omnitrace_trace_finalize");
|
||||
auto* env_func = find_function(app_image, "omnitrace_trace_set_env");
|
||||
auto* mpi_func = find_function(app_image, "omnitrace_trace_set_mpi");
|
||||
auto* entr_trace = find_function(app_image, "omnitrace_push_trace");
|
||||
auto* exit_trace = find_function(app_image, "omnitrace_pop_trace");
|
||||
auto* entr_hash = find_function(app_image, "omnitrace_push_trace_hash");
|
||||
auto* exit_hash = find_function(app_image, "omnitrace_pop_trace_hash");
|
||||
auto* init_func = find_function(app_image, "omnitrace_init");
|
||||
auto* fini_func = find_function(app_image, "omnitrace_finalize");
|
||||
auto* env_func = find_function(app_image, "omnitrace_set_env");
|
||||
auto* mpi_func = find_function(app_image, "omnitrace_set_mpi");
|
||||
auto* hash_func = find_function(app_image, "omnitrace_add_hash_id");
|
||||
|
||||
if(!main_func && main_fname == "main") main_func = find_function(app_image, "_main");
|
||||
|
||||
verbprintf(0, "Instrumenting with '%s' and '%s'...\n", instr_push_func.c_str(),
|
||||
instr_pop_func.c_str());
|
||||
|
||||
if(mpi_init_func && mpi_fini_func) use_mpi = true;
|
||||
|
||||
bool use_mpip = false;
|
||||
@@ -1085,10 +1106,10 @@ main(int argc, char** argv)
|
||||
using pair_t = std::pair<procedure_t*, string_t>;
|
||||
|
||||
for(const auto& itr :
|
||||
{ pair_t(main_func, main_fname), pair_t(entr_trace, instr_push_func),
|
||||
pair_t(exit_trace, instr_pop_func), pair_t(init_func, "omnitrace_trace_init"),
|
||||
pair_t(fini_func, "omnitrace_trace_finalize"),
|
||||
pair_t(env_func, "omnitrace_trace_set_env") })
|
||||
{ pair_t(main_func, main_fname), pair_t(entr_trace, "omnitrace_push_trace"),
|
||||
pair_t(exit_trace, "omnitrace_pop_trace"), pair_t(init_func, "omnitrace_init"),
|
||||
pair_t(fini_func, "omnitrace_finalize"),
|
||||
pair_t(env_func, "omnitrace_set_env") })
|
||||
{
|
||||
if(itr.first == main_func && !is_driver) continue;
|
||||
if(!itr.first)
|
||||
@@ -1182,7 +1203,7 @@ main(int argc, char** argv)
|
||||
verbprintf(2, "Getting call expressions... ");
|
||||
|
||||
auto main_call_args = omnitrace_call_expr(main_sign.get());
|
||||
auto init_call_args = omnitrace_call_expr(default_components, binary_rewrite, cmdv0);
|
||||
auto init_call_args = omnitrace_call_expr(instr_mode, binary_rewrite, cmdv0);
|
||||
auto fini_call_args = omnitrace_call_expr();
|
||||
auto umpi_call_args = omnitrace_call_expr(use_mpi, is_attached);
|
||||
auto none_call_args = omnitrace_call_expr();
|
||||
@@ -1208,11 +1229,19 @@ main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
std::string _libname = {};
|
||||
for(auto&& itr : sharedlibname)
|
||||
_libname = get_absolute_lib_filepath(itr);
|
||||
if(_libname.empty()) _libname = "libomnitrace.so";
|
||||
|
||||
auto env_vars = parser.get<strvec_t>("env");
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "OMNITRACE_MODE", instr_mode));
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "HSA_ENABLE_INTERRUPT", "0"));
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "HSA_TOOLS_LIB", _libname));
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "OMNITRACE_MPI_INIT", "OFF"));
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "OMNITRACE_MPI_FINALIZE", "OFF"));
|
||||
env_vars.emplace_back(TIMEMORY_JOIN('=', "OMNITRACE_COMPONENTS", default_components));
|
||||
env_vars.emplace_back(
|
||||
TIMEMORY_JOIN('=', "OMNITRACE_TIMEMORY_COMPONENTS", default_components));
|
||||
env_vars.emplace_back(
|
||||
TIMEMORY_JOIN('=', "OMNITRACE_USE_MPIP",
|
||||
(binary_rewrite && use_mpi && use_mpip) ? "ON" : "OFF"));
|
||||
@@ -1229,7 +1258,7 @@ main(int argc, char** argv)
|
||||
}
|
||||
tim::set_env(p.at(0), p.at(1));
|
||||
auto _expr = omnitrace_call_expr(p.at(0), p.at(1));
|
||||
env_variables.push_back(_expr.get(env_func));
|
||||
env_variables.emplace_back(_expr.get(env_func));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
@@ -1240,7 +1269,7 @@ main(int argc, char** argv)
|
||||
|
||||
for(const auto& itr : env_variables)
|
||||
{
|
||||
if(itr) init_names.push_back(itr.get());
|
||||
if(itr) init_names.emplace_back(itr.get());
|
||||
}
|
||||
|
||||
for(const auto& itr : beg_expr)
|
||||
@@ -1248,7 +1277,7 @@ main(int argc, char** argv)
|
||||
if(itr.second)
|
||||
{
|
||||
verbprintf(1, "+ Adding %s instrumentation...\n", itr.first.c_str());
|
||||
init_names.push_back(itr.second.get());
|
||||
init_names.emplace_back(itr.second.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1256,55 +1285,35 @@ main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if(use_mpi && umpi_call) init_names.push_back(umpi_call.get());
|
||||
|
||||
if(init_call && binary_rewrite) init_names.push_back(init_call.get());
|
||||
if(umpi_call) init_names.emplace_back(umpi_call.get());
|
||||
if(init_call) init_names.emplace_back(init_call.get());
|
||||
|
||||
if(binary_rewrite)
|
||||
{
|
||||
if(mpi_init_func && mpi_fini_func)
|
||||
{
|
||||
verbprintf(2, "Patching MPI init functions\n");
|
||||
if(init_call)
|
||||
insert_instr(addr_space, mpi_init_func, init_call, BPatch_exit, nullptr,
|
||||
nullptr);
|
||||
if(fini_call)
|
||||
insert_instr(addr_space, mpi_fini_func, fini_call, BPatch_entry, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(2, "Adding main begin and end snippets...\n");
|
||||
init_names.push_back(main_beg_call.get());
|
||||
fini_names.push_back(main_end_call.get());
|
||||
}
|
||||
verbprintf(2, "Adding main begin and end snippets...\n");
|
||||
if(main_beg_call) init_names.emplace_back(main_beg_call.get());
|
||||
if(main_end_call) fini_names.emplace_back(main_end_call.get());
|
||||
}
|
||||
else if(app_thread)
|
||||
{
|
||||
verbprintf(2, "Patching main function\n");
|
||||
if(init_call)
|
||||
insert_instr(addr_space, main_func, init_call, BPatch_entry, nullptr,
|
||||
nullptr);
|
||||
if(!use_mpi)
|
||||
{
|
||||
if(main_beg_call)
|
||||
insert_instr(addr_space, main_func, main_beg_call, BPatch_entry, nullptr,
|
||||
nullptr);
|
||||
if(main_end_call)
|
||||
insert_instr(addr_space, main_func, main_end_call, BPatch_exit, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
if(fini_call)
|
||||
insert_instr(addr_space, main_func, fini_call, BPatch_exit, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(0, "No binary_rewrite and no app_thread!...\n");
|
||||
}
|
||||
|
||||
if(fini_call) fini_names.push_back(fini_call.get());
|
||||
if(fini_call) fini_names.emplace_back(fini_call.get());
|
||||
|
||||
for(const auto& itr : end_expr)
|
||||
{
|
||||
if(itr.second) fini_names.push_back(itr.second.get());
|
||||
if(itr.second) fini_names.emplace_back(itr.second.get());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
@@ -1316,7 +1325,7 @@ main(int argc, char** argv)
|
||||
//----------------------------------------------------------------------------------//
|
||||
std::vector<std::function<void()>> instr_procedure_functions;
|
||||
auto instr_procedures = [&](const procedure_vec_t& procedures) {
|
||||
verbprintf(2, "Instrumenting %lu procedures...\n",
|
||||
verbprintf(3, "Instrumenting %lu procedures...\n",
|
||||
(unsigned long) procedures.size());
|
||||
for(auto* itr : procedures)
|
||||
{
|
||||
@@ -1356,7 +1365,7 @@ main(int argc, char** argv)
|
||||
|
||||
if(name.get().empty())
|
||||
{
|
||||
verbprintf(1, "Skipping function [empty name]: %s\n", fname);
|
||||
verbprintf(2, "Skipping function [empty name]: %s\n", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1366,7 +1375,7 @@ main(int argc, char** argv)
|
||||
if(is_static_exe && has_debug_info && string_t{ fname } == "_fini" &&
|
||||
string_t{ modname } == "DEFAULT_MODULE")
|
||||
{
|
||||
verbprintf(1, "Skipping function [DEFAULT_MODULE]: %s\n", fname);
|
||||
verbprintf(2, "Skipping function [DEFAULT_MODULE]: %s\n", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1385,7 @@ main(int argc, char** argv)
|
||||
overlapping_module_functions.find(module_function{ mod, itr }) !=
|
||||
overlapping_module_functions.end())
|
||||
{
|
||||
verbprintf(1, "Skipping function [overlapping]: %s / %s\n",
|
||||
verbprintf(2, "Skipping function [overlapping]: %s / %s\n",
|
||||
name.m_name.c_str(), name.get().c_str());
|
||||
continue;
|
||||
}
|
||||
@@ -1402,8 +1411,33 @@ main(int argc, char** argv)
|
||||
? std::max<size_t>(_loop_entries->size(), basic_loop.size())
|
||||
: basic_loop.size();
|
||||
auto _has_loop_entries = (_num_loop_entries > 0);
|
||||
auto _skip_range =
|
||||
(_has_loop_entries) ? false : (_address_range < min_address_range);
|
||||
auto _skip_loop_range =
|
||||
(_has_loop_entries) ? (_address_range < min_loop_address_range) : false;
|
||||
|
||||
if(_address_range < min_address_range && !_has_loop_entries && !_force_instr)
|
||||
if(_force_instr && _skip_range)
|
||||
{
|
||||
verbprintf(
|
||||
1,
|
||||
"Instrumenting function [dynamic-callsite]: %s / %s despite not "
|
||||
"satisfy minimum address range (address range = %lu, minimum "
|
||||
"= %lu) because contains dynamic callsites\n",
|
||||
name.m_name.c_str(), name.get().c_str(),
|
||||
(unsigned long) _address_range, (unsigned long) min_address_range);
|
||||
}
|
||||
else if(_force_instr && _skip_loop_range)
|
||||
{
|
||||
verbprintf(
|
||||
1,
|
||||
"Instrumenting function [dynamic-callsite]: %s / %s despite not "
|
||||
"satisfy minimum loop address range (address range = %lu, minimum "
|
||||
"= %lu) because contains dynamic callsites\n",
|
||||
name.m_name.c_str(), name.get().c_str(),
|
||||
(unsigned long) _address_range,
|
||||
(unsigned long) min_loop_address_range);
|
||||
}
|
||||
else if(_skip_range)
|
||||
{
|
||||
verbprintf(1,
|
||||
"Skipping function [min-address-range]: %s / %s (address "
|
||||
@@ -1413,8 +1447,7 @@ main(int argc, char** argv)
|
||||
(unsigned long) min_address_range);
|
||||
continue;
|
||||
}
|
||||
else if(_address_range < min_loop_address_range && _has_loop_entries &&
|
||||
!_force_instr)
|
||||
else if(_skip_loop_range)
|
||||
{
|
||||
verbprintf(1,
|
||||
"Skipping function [min-loop-address-range]: %s / %s (address "
|
||||
@@ -1424,16 +1457,6 @@ main(int argc, char** argv)
|
||||
(unsigned long) min_loop_address_range);
|
||||
continue;
|
||||
}
|
||||
else if(_force_instr)
|
||||
{
|
||||
verbprintf(1,
|
||||
"Enabling function [dynamic-callsite]: %s / %s despite not "
|
||||
"satisfy minimum address range (address range = %lu, minimum "
|
||||
"= %lu) because contains dynamic callsites\n",
|
||||
name.m_name.c_str(), name.get().c_str(),
|
||||
(unsigned long) _address_range,
|
||||
(unsigned long) min_address_range);
|
||||
}
|
||||
|
||||
bool _entr_success =
|
||||
query_instr(itr, BPatch_entry, nullptr, nullptr, instr_traps);
|
||||
@@ -1562,7 +1585,7 @@ main(int argc, char** argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
verbprintf(1, "Parsing module: %s\n", modname);
|
||||
verbprintf(3, "Parsing module: %s\n", modname);
|
||||
bpvector_t<procedure_t*>* p = m->getProcedures();
|
||||
if(!p) continue;
|
||||
|
||||
@@ -1590,7 +1613,7 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
if(is_attached)
|
||||
if(app_thread)
|
||||
{
|
||||
assert(app_thread != nullptr);
|
||||
verbprintf(1, "Executing initial snippets...\n");
|
||||
@@ -1827,58 +1850,52 @@ main(int argc, char** argv)
|
||||
{
|
||||
verbprintf(0, "Executing...\n");
|
||||
|
||||
// bpatch->setDebugParsing(false);
|
||||
// bpatch->setTypeChecking(false);
|
||||
// bpatch->setDelayedParsing(true);
|
||||
// bpatch->setInstrStackFrames(true);
|
||||
// bpatch->setLivenessAnalysis(false);
|
||||
// addr_space->beginInsertionSet();
|
||||
|
||||
verbprintf(4, "Registering fork callbacks...\n");
|
||||
auto _prefork = bpatch->registerPreForkCallback(&omnitrace_fork_callback);
|
||||
auto _postfork = bpatch->registerPostForkCallback(&omnitrace_fork_callback);
|
||||
|
||||
auto _wait_exec = [&]() {
|
||||
while(!app_thread->isTerminated())
|
||||
if(!app_thread->isTerminated())
|
||||
{
|
||||
app_thread->detach(true);
|
||||
pid_t cpid = app_thread->getPid();
|
||||
pid_t w;
|
||||
int status = 0;
|
||||
do
|
||||
{
|
||||
verbprintf(3, "Continuing execution...\n");
|
||||
app_thread->continueExecution();
|
||||
verbprintf(4, "Process is not terminated...\n");
|
||||
bpatch->waitForStatusChange();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
|
||||
verbprintf(4, "Process status change...\n");
|
||||
if(app_thread->isStopped())
|
||||
w = waitpid(cpid, &status, WUNTRACED);
|
||||
if(w == -1)
|
||||
{
|
||||
verbprintf(4, "Process is stopped, continuing execution...\n");
|
||||
if(!app_thread->continueExecution())
|
||||
{
|
||||
fprintf(stderr, "continueExecution failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
perror("waitpid");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(WIFEXITED(status))
|
||||
{
|
||||
code = WEXITSTATUS(status);
|
||||
}
|
||||
else if(WIFSIGNALED(status))
|
||||
{
|
||||
code = WTERMSIG(status);
|
||||
}
|
||||
else if(WIFSTOPPED(status))
|
||||
{
|
||||
code = WSTOPSIG(status);
|
||||
}
|
||||
else if(WIFCONTINUED(status))
|
||||
{
|
||||
code = WIFCONTINUED(status);
|
||||
}
|
||||
} while(!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(app_thread->terminationStatus() == ExitedNormally)
|
||||
{
|
||||
if(app_thread->isTerminated()) verbprintf(0, "End of omnitrace\n");
|
||||
}
|
||||
};
|
||||
|
||||
verbprintf(4, "Entering wait for status change mode...\n");
|
||||
_wait_exec();
|
||||
|
||||
if(app_thread->terminationStatus() == ExitedNormally)
|
||||
{
|
||||
if(app_thread->isTerminated())
|
||||
printf("\nEnd of omnitrace\n");
|
||||
else
|
||||
_wait_exec();
|
||||
else if(app_thread->terminationStatus() == ExitedViaSignal)
|
||||
{
|
||||
auto sign = app_thread->getExitSignal();
|
||||
fprintf(stderr, "\nApplication exited with signal: %i\n", int(sign));
|
||||
}
|
||||
code = app_thread->getExitCode();
|
||||
}
|
||||
else if(app_thread->terminationStatus() == ExitedViaSignal)
|
||||
{
|
||||
auto sign = app_thread->getExitSignal();
|
||||
fprintf(stderr, "\nApplication exited with signal: %i\n", int(sign));
|
||||
}
|
||||
|
||||
// addr_space->finalizeInsertionSet(false, nullptr);
|
||||
|
||||
code = app_thread->getExitCode();
|
||||
consume_parameters(_prefork, _postfork);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
@@ -1888,6 +1905,9 @@ main(int argc, char** argv)
|
||||
for(int i = 0; i < _cmdc; ++i)
|
||||
delete[] _cmdv[i];
|
||||
delete[] _cmdv;
|
||||
|
||||
verbprintf(0, "End of omnitrace\n");
|
||||
verbprintf(1, "Exit code: %i\n", code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -1943,7 +1963,7 @@ instrument_module(const string_t& file_name)
|
||||
static std::regex corelib_regex(
|
||||
"^lib(c|z|rt|dl|dw|util|zstd|elf|pthread|open[\\-]rte|open[\\-]pal|"
|
||||
"hwloc|numa|event|udev|dyninstAPI_RT|gcc_s|tcmalloc|profiler|tbbmalloc|"
|
||||
"tbbmalloc_proxy)(-|\\.)",
|
||||
"tbbmalloc_proxy|event_pthreads|ltdl)(-|\\.)",
|
||||
regex_opts);
|
||||
// these are all due to TAU
|
||||
static std::regex prefix_regex(
|
||||
@@ -2049,11 +2069,13 @@ instrument_entity(const string_t& function_name)
|
||||
regex_opts);
|
||||
static std::regex exclude_cxx("(std::_Sp_counted_base|std::use_facet)", regex_opts);
|
||||
static std::regex leading(
|
||||
"^(_|\\.|frame_dummy|\\(|targ|new|delete|operator new|operator "
|
||||
"delete|std::allocat|"
|
||||
"nvtx|gcov|main\\.cold|TAU|tau|Tau|dyn|RT|dl|sys|pthread|posix|clone|virtual "
|
||||
"thunk|non-virtual thunk|transaction "
|
||||
"clone|RtsLayer|DYNINST|PthreadLayer|threaded_func|targ8|PMPI)",
|
||||
"^(_|\\.|frame_dummy|\\(|targ|new|delete|operator new|operator delete|"
|
||||
"std::allocat|nvtx|gcov|main\\.cold|TAU|tau|Tau|dyn|RT|"
|
||||
"sys|pthread|posix|clone|"
|
||||
"virtual thunk|non-virtual thunk|transaction clone|"
|
||||
"RtsLayer|DYNINST|PthreadLayer|threaded_func|PMPI|"
|
||||
"Kokkos::Impl::|Kokkos::Experimental::Impl::|Kokkos::impl_|"
|
||||
"Kokkos::[A-Za-z]+::impl_|Kokkos::Tools::|Kokkos::Profiling::)",
|
||||
regex_opts);
|
||||
static std::regex trailing("(\\.part\\.[0-9]+|\\.constprop\\.[0-9]+|\\.|\\.[0-9]+)$",
|
||||
regex_opts);
|
||||
@@ -2328,7 +2350,8 @@ get_absolute_lib_filepath(std::string lib_name)
|
||||
std::regex_match(lib_name, std::regex("^[A-Za-z0-9].*"))))
|
||||
{
|
||||
auto _lib_orig = lib_name;
|
||||
auto _paths = tim::delimit(tim::get_env<std::string>("LD_LIBRARY_PATH", ""), ":");
|
||||
auto _paths = tim::delimit(
|
||||
std::string{ ".:" } + tim::get_env<std::string>("LD_LIBRARY_PATH", ""), ":");
|
||||
for(auto& pitr : _paths)
|
||||
{
|
||||
if(file_exists(TIMEMORY_JOIN('/', pitr, lib_name)))
|
||||
|
||||
@@ -101,6 +101,14 @@ get_whole_function_names()
|
||||
"daemon",
|
||||
"des_setparity",
|
||||
"div",
|
||||
"dlopen",
|
||||
"dlsym",
|
||||
"dlerror",
|
||||
"dladdr",
|
||||
"dlinfo",
|
||||
"dlvsym",
|
||||
"dlmopen",
|
||||
"dl_iterate_phdr",
|
||||
"dysize",
|
||||
"endutxent",
|
||||
"envz_add",
|
||||
|
||||
@@ -26,7 +26,29 @@ endif()
|
||||
set(_base_environment
|
||||
"OMNITRACE_USE_PERFETTO=ON"
|
||||
"OMNITRACE_USE_TIMEMORY=ON"
|
||||
"OMNITRACE_USE_SAMPLING=OFF"
|
||||
"OMNITRACE_USE_SAMPLING=ON"
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_perfetto_environment
|
||||
"OMNITRACE_USE_PERFETTO=ON"
|
||||
"OMNITRACE_USE_TIMEMORY=OFF"
|
||||
"OMNITRACE_USE_SAMPLING=ON"
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_timemory_environment
|
||||
"OMNITRACE_USE_PERFETTO=OFF"
|
||||
"OMNITRACE_USE_TIMEMORY=ON"
|
||||
"OMNITRACE_USE_SAMPLING=ON"
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
@@ -48,12 +70,15 @@ set(_fast_environment
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
function(OMNITRACE_ADD_TEST)
|
||||
cmake_parse_arguments(
|
||||
TEST
|
||||
"" # options
|
||||
"NAME;TARGET;MPI;NUM_PROCS" # single value args
|
||||
"REWRITE_ARGS;RUNTIME_ARGS;RUN_ARGS;ENVIRONMENT;LABELS" # multiple value args
|
||||
"NAME;TARGET;MPI;NUM_PROCS;REWRITE_TIMEOUT;RUNTIME_TIMEOUT" # single value args
|
||||
"REWRITE_ARGS;RUNTIME_ARGS;RUN_ARGS;ENVIRONMENT;LABELS;PROPERTIES" # multiple
|
||||
# value args
|
||||
${ARGN})
|
||||
|
||||
if("${TEST_MPI}" STREQUAL "")
|
||||
@@ -68,10 +93,20 @@ function(OMNITRACE_ADD_TEST)
|
||||
set(TEST_NUM_PROCS 0)
|
||||
endif()
|
||||
|
||||
if(NOT TEST_REWRITE_TIMEOUT)
|
||||
set(TEST_REWRITE_TIMEOUT 120)
|
||||
endif()
|
||||
|
||||
if(NOT TEST_RUNTIME_TIMEOUT)
|
||||
set(TEST_RUNTIME_TIMEOUT 300)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED TEST_ENVIRONMENT OR "${TEST_ENVIRONMENT}" STREQUAL "")
|
||||
set(TEST_ENVIRONMENT "${_test_environment}")
|
||||
endif()
|
||||
|
||||
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON")
|
||||
|
||||
if(TARGET ${TEST_TARGET})
|
||||
if(DEFINED TEST_MPI
|
||||
AND ${TEST_MPI}
|
||||
@@ -88,14 +123,14 @@ function(OMNITRACE_ADD_TEST)
|
||||
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-baseline
|
||||
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_RUN_ARGS}
|
||||
COMMAND ${COMMAND_PREFIX} $<TARGET_FILE:${TEST_TARGET}> ${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-binary-rewrite
|
||||
COMMAND
|
||||
$<TARGET_FILE:omnitrace-exe> -o
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_TARGET}.inst ${TEST_REWRITE_ARGS}
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_NAME}.inst ${TEST_REWRITE_ARGS}
|
||||
-- $<TARGET_FILE:${TEST_TARGET}>
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
@@ -103,20 +138,20 @@ function(OMNITRACE_ADD_TEST)
|
||||
NAME ${TEST_NAME}-binary-rewrite-sampling
|
||||
COMMAND
|
||||
$<TARGET_FILE:omnitrace-exe> -o
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_TARGET}.samp -M sampling
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_NAME}.samp -M sampling
|
||||
${TEST_REWRITE_ARGS} -- $<TARGET_FILE:${TEST_TARGET}>
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-binary-rewrite-run
|
||||
COMMAND ${COMMAND_PREFIX}
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_TARGET}.inst ${TEST_RUN_ARGS}
|
||||
COMMAND ${COMMAND_PREFIX} $<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_NAME}.inst
|
||||
${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-binary-rewrite-run-sampling
|
||||
COMMAND ${COMMAND_PREFIX}
|
||||
$<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_TARGET}.samp ${TEST_RUN_ARGS}
|
||||
COMMAND ${COMMAND_PREFIX} $<TARGET_FILE_DIR:${TEST_TARGET}>/${TEST_NAME}.samp
|
||||
${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
add_test(
|
||||
@@ -127,10 +162,8 @@ function(OMNITRACE_ADD_TEST)
|
||||
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-runtime-instrument-sampling
|
||||
COMMAND
|
||||
$<TARGET_FILE:omnitrace-exe> -M sampling --env
|
||||
OMNITRACE_OUTPUT_PREFIX=sampling- ${TEST_RUNTIME_ARGS} --
|
||||
$<TARGET_FILE:${TEST_TARGET}> ${TEST_RUN_ARGS}
|
||||
COMMAND $<TARGET_FILE:omnitrace-exe> -M sampling ${TEST_RUNTIME_ARGS} --
|
||||
$<TARGET_FILE:${TEST_TARGET}> ${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
set_tests_properties(${TEST_NAME}-binary-rewrite-run
|
||||
@@ -143,36 +176,52 @@ function(OMNITRACE_ADD_TEST)
|
||||
_TEST
|
||||
baseline binary-rewrite binary-rewrite-run binary-rewrite-sampling
|
||||
binary-rewrite-run-sampling runtime-instrument runtime-instrument-sampling)
|
||||
string(REPLACE "-run-" "-" _PREFIX "${TEST_NAME}-${_TEST}-")
|
||||
string(REPLACE "-run-" "-" _prefix "${TEST_NAME}-${_TEST}-")
|
||||
set(_environ "${TEST_ENVIRONMENT}")
|
||||
set(_labels "${_TEST}")
|
||||
set(_timeout ${TEST_REWRITE_TIMEOUT})
|
||||
list(APPEND _environ "OMNITRACE_OUTPUT_PATH=omnitrace-tests-output"
|
||||
"OMNITRACE_OUTPUT_PREFIX=${_PREFIX}")
|
||||
set(_LABELS "${_TEST}")
|
||||
string(REPLACE "-run" "" _LABELS "${_TEST}")
|
||||
string(REPLACE "-sampling" ";sampling" _LABELS "${_LABELS}")
|
||||
set_tests_properties(
|
||||
${TEST_NAME}-${_TEST} PROPERTIES ENVIRONMENT "${_environ}" TIMEOUT 600
|
||||
LABELS "${_LABELS};${TEST_LABELS}")
|
||||
"OMNITRACE_OUTPUT_PREFIX=${_prefix}")
|
||||
string(REPLACE "-run" "" _labels "${_TEST}")
|
||||
string(REPLACE "-sampling" ";sampling" _labels "${_labels}")
|
||||
if("${_TEST}" MATCHES "runtime-instrument")
|
||||
set(_timeout ${TEST_RUNTIME_TIMEOUT})
|
||||
endif()
|
||||
set(_props)
|
||||
if("${_TEST}" MATCHES "run|baseline")
|
||||
set(_props ${TEST_PROPERTIES})
|
||||
if(NOT "RUN_SERIAL" IN_LIST _props)
|
||||
list(APPEND _props RUN_SERIAL ON)
|
||||
endif()
|
||||
endif()
|
||||
if(TEST ${TEST_NAME}-${_TEST})
|
||||
set_tests_properties(
|
||||
${TEST_NAME}-${_TEST}
|
||||
PROPERTIES ENVIRONMENT "${_environ}" TIMEOUT ${_timeout} LABELS
|
||||
"${_labels};${TEST_LABELS}" ${_props})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME transpose
|
||||
TARGET transpose
|
||||
MPI ${TRANSPOSE_USE_MPI}
|
||||
NUM_PROCS ${NUM_PROCS}
|
||||
REWRITE_ARGS -e -v 1
|
||||
REWRITE_ARGS -e -v 2
|
||||
RUNTIME_ARGS -e -v 1 --label file line return args
|
||||
RUN_ARGS ""
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=ON")
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME transpose-no-save-fpr
|
||||
TARGET transpose
|
||||
MPI ${TRANSPOSE_USE_MPI}
|
||||
NUM_PROCS ${NUM_PROCS}
|
||||
REWRITE_ARGS -e -v 1 --dyninst-options DelayedParsing TypeChecking
|
||||
REWRITE_ARGS -e -v 2 --dyninst-options DelayedParsing TypeChecking
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
@@ -191,7 +240,7 @@ omnitrace_add_test(
|
||||
omnitrace_add_test(
|
||||
NAME parallel-overhead
|
||||
TARGET parallel-overhead
|
||||
REWRITE_ARGS -e -v 1 --min-address-range-loop=64
|
||||
REWRITE_ARGS -e -v 2 --min-address-range-loop=64
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
@@ -202,13 +251,13 @@ omnitrace_add_test(
|
||||
line
|
||||
return
|
||||
args
|
||||
RUN_ARGS 10 ${NUM_THREADS}
|
||||
RUN_ARGS 10 ${NUM_THREADS} 1000
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME parallel-overhead-no-save-fpr
|
||||
TARGET parallel-overhead
|
||||
REWRITE_ARGS -e -v 1 --min-address-range-loop=32 --dyninst-options DelayedParsing
|
||||
REWRITE_ARGS -e -v 2 --min-address-range-loop=32 --dyninst-options DelayedParsing
|
||||
TypeChecking
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
@@ -223,7 +272,7 @@ omnitrace_add_test(
|
||||
--dyninst-options
|
||||
DelayedParsing
|
||||
TypeChecking
|
||||
RUN_ARGS 10 ${NUM_THREADS}
|
||||
RUN_ARGS 10 ${NUM_THREADS} 1000
|
||||
ENVIRONMENT "${_fast_environment}")
|
||||
|
||||
omnitrace_add_test(
|
||||
@@ -231,7 +280,7 @@ omnitrace_add_test(
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
REWRITE_ARGS -e -v 1
|
||||
REWRITE_ARGS -e -v 2
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
@@ -242,6 +291,69 @@ omnitrace_add_test(
|
||||
return
|
||||
args
|
||||
-ME
|
||||
[==['lib(gomp|m-)']==]
|
||||
[==[lib(gomp|m-)]==]
|
||||
RUN_ARGS -i 10 -s 20 -p
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF")
|
||||
ENVIRONMENT
|
||||
"${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=OFF")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME lulesh-kokkosp
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
REWRITE_ARGS -e -v 2
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
1
|
||||
--label
|
||||
file
|
||||
line
|
||||
return
|
||||
args
|
||||
-ME
|
||||
[==[lib(gomp|m-)]==]
|
||||
RUN_ARGS -i 10 -s 20 -p
|
||||
ENVIRONMENT
|
||||
"${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=ON")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME lulesh-perfetto
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
REWRITE_ARGS -e -v 2
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
1
|
||||
-l
|
||||
--dynamic-callsites
|
||||
--traps
|
||||
--allow-overlapping
|
||||
-ME
|
||||
[==[libgomp]==]
|
||||
RUN_ARGS -i 10 -s 20 -p
|
||||
ENVIRONMENT
|
||||
"${_perfetto_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=OFF")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME lulesh-timemory
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
REWRITE_ARGS -e -v 2 -l --dynamic-callsites --traps --allow-overlapping
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
1
|
||||
-l
|
||||
--dynamic-callsites
|
||||
-ME
|
||||
[==[libgomp]==]
|
||||
-d
|
||||
wall_clock
|
||||
peak_rss
|
||||
RUN_ARGS -i 10 -s 20 -p
|
||||
ENVIRONMENT
|
||||
"${_timemory_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=OFF")
|
||||
|
||||
مرجع در شماره جدید
Block a user