Support external (i.e. user-defined) trace annotations (#195)
* Support external (i.e. user-defined) trace annotations
- tweaked the python examples to be more balanced
- updated the user-api example to conform to user API changes
- moved the get/set for State and ThreadState to state.{hpp,cpp}
- introduced user-provided trace annotations
- added perfetto python category
- moved coverage impl files around
- created enumerations for mapping category enums to category types
- created enumerations for mapping annotation type enums to annotation values
- moved tracing::add_perfetto_annotations to tracing/annotation.hpp
- utility make_index_sequence_range
- libomnitrace-dl: omnitrace_push_category_region
- libomnitrace-dl: omnitrace_pop_category_region
- libomnitrace-user: omnitrace_user_push_annotated_region
- libomnitrace-user: omnitrace_user_pop_annotated_region
- libpyomnitrace: support extra annotations via annotate_trace config value
- filename
- line
- last attempted instr in bytecode (lasti)
- argcount
- num local variables
- stacksize
- omnitrace-python: -a / --annotate-traces option
* tweak ubuntu-focal workflow
* Fix installation of omnitrace-user headers
* ubuntu-focal-codecov workflow update
- Install texinfo
* Update timemory submodule
[ROCm/rocprofiler-systems commit: 642b6b95ca]
This commit is contained in:
committed by
GitHub
parent
0e963e47c8
commit
91627797a0
@@ -573,4 +573,3 @@ jobs:
|
||||
-DOMNITRACE_MAX_THREADS=32
|
||||
-DOMNITRACE_DISABLE_EXAMPLES="transpose;rccl"
|
||||
-DOMNITRACE_BUILD_NUMBER=${{ github.run_attempt }}
|
||||
-DMPI_HEADERS_ALLOW_MPICH=ON
|
||||
|
||||
@@ -49,8 +49,10 @@ set(OMNITRACE_EXTENSION_LIBRARIES
|
||||
omnitrace::omnitrace-perfetto)
|
||||
|
||||
target_include_directories(
|
||||
omnitrace-headers INTERFACE ${PROJECT_SOURCE_DIR}/source/lib/omnitrace
|
||||
${PROJECT_BINARY_DIR}/source/lib/omnitrace)
|
||||
omnitrace-headers
|
||||
INTERFACE ${PROJECT_BINARY_DIR}/source/lib ${PROJECT_BINARY_DIR}/source/lib/omnitrace
|
||||
${PROJECT_SOURCE_DIR}/source/lib ${PROJECT_SOURCE_DIR}/source/lib/omnitrace
|
||||
${PROJECT_SOURCE_DIR}/source/lib/omnitrace-user)
|
||||
|
||||
# include threading because of rooflines
|
||||
target_link_libraries(omnitrace-headers INTERFACE omnitrace::omnitrace-threading)
|
||||
@@ -372,7 +374,7 @@ else()
|
||||
OMNITRACE_DYNINST_API_RT dyninstAPI_RT
|
||||
HINTS ${Dyninst_ROOT_DIR} ${Dyninst_DIR}
|
||||
PATHS ${Dyninst_ROOT_DIR} ${Dyninst_DIR}
|
||||
PATH_SUFFIXES lib)
|
||||
PATH_SUFFIXES lib NO_CACHE)
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
omnitrace_target_compile_definitions(
|
||||
|
||||
@@ -18,7 +18,7 @@ def inefficient(n):
|
||||
a += i
|
||||
for j in range(n):
|
||||
a += j
|
||||
_len = a * n * n * n
|
||||
_len = a * n * n
|
||||
_arr = [random.random() for _ in range(_len)]
|
||||
_sum = sum(_arr)
|
||||
print(f"[{_prefix}] ... sum of {_len} random elements: {_sum}")
|
||||
|
||||
@@ -18,7 +18,7 @@ def inefficient(n):
|
||||
a += i
|
||||
for j in range(n):
|
||||
a += j
|
||||
_len = a * n * n * n
|
||||
_len = a * n * n
|
||||
_arr = [random.random() for _ in range(_len)]
|
||||
_sum = sum(_arr)
|
||||
print(f"[{_prefix}] ... sum of {_len} random elements: {_sum}")
|
||||
|
||||
@@ -20,7 +20,7 @@ def inefficient(n):
|
||||
a += i
|
||||
for j in range(n):
|
||||
a += j
|
||||
_len = a * n * n * n
|
||||
_len = a * n * n
|
||||
_arr = [random.random() for _ in range(_len)]
|
||||
_sum = sum(_arr)
|
||||
print(f"[{_prefix}] ... sum of {_len} random elements: {_sum}")
|
||||
|
||||
@@ -23,7 +23,7 @@ try:
|
||||
a += i
|
||||
for j in range(n):
|
||||
a += j
|
||||
_len = a * n * n * n
|
||||
_len = a * n * n
|
||||
_ret = np.random.rand(_len).sum()
|
||||
print(f"[{_prefix}] ... sum of {_len} random elements: {_ret}")
|
||||
return _ret
|
||||
@@ -41,7 +41,7 @@ except ImportError:
|
||||
a += i
|
||||
for j in range(n):
|
||||
a += j
|
||||
_len = a * n * n * n
|
||||
_len = a * n * n
|
||||
_arr = [random.random() for _ in range(_len)]
|
||||
_ret = _sum(_arr)
|
||||
print(f"[{_prefix}] ... sum of {_len} random elements: {_ret}")
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
|
||||
#include "omnitrace/categories.h"
|
||||
#include "omnitrace/types.h"
|
||||
#include <omnitrace/user.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
@@ -22,19 +26,16 @@ custom_push_region(const char* name);
|
||||
|
||||
namespace
|
||||
{
|
||||
int (*omnitrace_push_region_f)(const char*) = nullptr;
|
||||
}
|
||||
omnitrace_user_callbacks_t custom_callbacks = OMNITRACE_USER_CALLBACKS_INIT;
|
||||
omnitrace_user_callbacks_t original_callbacks = OMNITRACE_USER_CALLBACKS_INIT;
|
||||
} // namespace
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
// get the internal callback to start a user-defined region
|
||||
omnitrace_user_get_callbacks(OMNITRACE_USER_REGION, (void**) &omnitrace_push_region_f,
|
||||
nullptr);
|
||||
// assign the custom callback to start a user-defined region
|
||||
if(omnitrace_push_region_f)
|
||||
omnitrace_user_configure(OMNITRACE_USER_REGION, (void*) &custom_push_region,
|
||||
nullptr);
|
||||
custom_callbacks.push_region = &custom_push_region;
|
||||
omnitrace_user_configure(OMNITRACE_USER_UNION_CONFIG, custom_callbacks,
|
||||
&original_callbacks);
|
||||
|
||||
omnitrace_user_push_region(argv[0]);
|
||||
omnitrace_user_push_region("initialization");
|
||||
@@ -100,6 +101,26 @@ run(size_t nitr, long n)
|
||||
int
|
||||
custom_push_region(const char* name)
|
||||
{
|
||||
if(!original_callbacks.push_region || !original_callbacks.push_annotated_region)
|
||||
return OMNITRACE_USER_ERROR_NO_BINDING;
|
||||
|
||||
printf("Pushing custom region :: %s\n", name);
|
||||
return (*omnitrace_push_region_f)(name);
|
||||
|
||||
if(original_callbacks.push_annotated_region)
|
||||
{
|
||||
int32_t _err = errno;
|
||||
char* _msg = nullptr;
|
||||
char _buff[1024];
|
||||
if(_err != 0) _msg = strerror_r(_err, _buff, sizeof(_buff));
|
||||
|
||||
omnitrace_annotation_t _annotations[] = {
|
||||
{ "errno", OMNITRACE_INT32, &_err }, { "strerror", OMNITRACE_STRING, _msg }
|
||||
};
|
||||
|
||||
errno = 0; // reset errno
|
||||
return (*original_callbacks.push_annotated_region)(
|
||||
name, _annotations, sizeof(_annotations) / sizeof(omnitrace_annotation_t));
|
||||
}
|
||||
|
||||
return (*original_callbacks.push_region)(name);
|
||||
}
|
||||
|
||||
+1
-1
Submodule projects/rocprofiler-systems/external/timemory updated: 7a6a361eb8...040456175a
@@ -74,6 +74,7 @@
|
||||
#define OMNITRACE_INLINE OMNITRACE_ATTRIBUTE(always_inline) inline
|
||||
#define OMNITRACE_NOINLINE OMNITRACE_ATTRIBUTE(noinline)
|
||||
#define OMNITRACE_HOT OMNITRACE_ATTRIBUTE(hot)
|
||||
#define OMNITRACE_COLD OMNITRACE_ATTRIBUTE(cold)
|
||||
#define OMNITRACE_CONST OMNITRACE_ATTRIBUTE(const)
|
||||
#define OMNITRACE_PURE OMNITRACE_ATTRIBUTE(pure)
|
||||
#define OMNITRACE_WEAK OMNITRACE_ATTRIBUTE(weak)
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "common/join.hpp"
|
||||
#include "common/setup.hpp"
|
||||
#include "dl.hpp"
|
||||
#include "omnitrace/categories.h"
|
||||
#include "omnitrace/types.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <gnu/libc-version.h>
|
||||
@@ -256,6 +258,10 @@ struct OMNITRACE_HIDDEN_API indirect
|
||||
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_omnihandle, "omnitrace_pop_trace");
|
||||
OMNITRACE_DLSYM(omnitrace_push_region_f, m_omnihandle, "omnitrace_push_region");
|
||||
OMNITRACE_DLSYM(omnitrace_pop_region_f, m_omnihandle, "omnitrace_pop_region");
|
||||
OMNITRACE_DLSYM(omnitrace_push_category_region_f, m_omnihandle,
|
||||
"omnitrace_push_category_region");
|
||||
OMNITRACE_DLSYM(omnitrace_pop_category_region_f, m_omnihandle,
|
||||
"omnitrace_pop_category_region");
|
||||
OMNITRACE_DLSYM(omnitrace_register_source_f, m_omnihandle,
|
||||
"omnitrace_register_source");
|
||||
OMNITRACE_DLSYM(omnitrace_register_coverage_f, m_omnihandle,
|
||||
@@ -330,37 +336,43 @@ struct OMNITRACE_HIDDEN_API indirect
|
||||
|
||||
if(omnitrace_user_configure_f)
|
||||
{
|
||||
(*omnitrace_user_configure_f)(
|
||||
OMNITRACE_USER_START_STOP,
|
||||
reinterpret_cast<void*>(&omnitrace_user_start_trace_dl),
|
||||
reinterpret_cast<void*>(&omnitrace_user_stop_trace_dl));
|
||||
(*omnitrace_user_configure_f)(
|
||||
OMNITRACE_USER_START_STOP_THREAD,
|
||||
reinterpret_cast<void*>(&omnitrace_user_start_thread_trace_dl),
|
||||
reinterpret_cast<void*>(&omnitrace_user_stop_thread_trace_dl));
|
||||
(*omnitrace_user_configure_f)(
|
||||
OMNITRACE_USER_REGION,
|
||||
reinterpret_cast<void*>(&omnitrace_user_push_region_dl),
|
||||
reinterpret_cast<void*>(&omnitrace_user_pop_region_dl));
|
||||
omnitrace_user_callbacks_t _cb = {};
|
||||
_cb.start_trace = &omnitrace_user_start_trace_dl;
|
||||
_cb.stop_trace = &omnitrace_user_stop_trace_dl;
|
||||
_cb.start_thread_trace = &omnitrace_user_start_thread_trace_dl;
|
||||
_cb.stop_thread_trace = &omnitrace_user_stop_thread_trace_dl;
|
||||
_cb.push_region = &omnitrace_user_push_region_dl;
|
||||
_cb.pop_region = &omnitrace_user_pop_region_dl;
|
||||
_cb.push_annotated_region = &omnitrace_user_push_annotated_region_dl;
|
||||
_cb.pop_annotated_region = &omnitrace_user_pop_annotated_region_dl;
|
||||
(*omnitrace_user_configure_f)(OMNITRACE_USER_REPLACE_CONFIG, _cb, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// omnitrace functions
|
||||
void (*omnitrace_init_library_f)(void) = nullptr;
|
||||
void (*omnitrace_init_tooling_f)(void) = nullptr;
|
||||
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
|
||||
void (*omnitrace_finalize_f)(void) = nullptr;
|
||||
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
|
||||
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
|
||||
using user_cb_t = omnitrace_user_callbacks_t;
|
||||
|
||||
// libomnitrace functions
|
||||
void (*omnitrace_init_library_f)(void) = nullptr;
|
||||
void (*omnitrace_init_tooling_f)(void) = nullptr;
|
||||
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
|
||||
void (*omnitrace_finalize_f)(void) = nullptr;
|
||||
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
|
||||
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
|
||||
void (*omnitrace_register_source_f)(const char*, const char*, size_t, size_t,
|
||||
const char*) = nullptr;
|
||||
void (*omnitrace_register_coverage_f)(const char*, const char*, size_t) = nullptr;
|
||||
void (*omnitrace_push_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
|
||||
int (*omnitrace_push_region_f)(const char*) = nullptr;
|
||||
int (*omnitrace_pop_region_f)(const char*) = nullptr;
|
||||
int (*omnitrace_user_configure_f)(int, void*, void*) = nullptr;
|
||||
const char*) = nullptr;
|
||||
void (*omnitrace_register_coverage_f)(const char*, const char*, size_t) = nullptr;
|
||||
void (*omnitrace_push_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
|
||||
int (*omnitrace_push_region_f)(const char*) = nullptr;
|
||||
int (*omnitrace_pop_region_f)(const char*) = nullptr;
|
||||
int (*omnitrace_push_category_region_f)(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*, size_t) = nullptr;
|
||||
int (*omnitrace_pop_category_region_f)(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*, size_t) = nullptr;
|
||||
|
||||
// libomnitrace-user functions
|
||||
int (*omnitrace_user_configure_f)(int, user_cb_t, user_cb_t*) = nullptr;
|
||||
|
||||
// KokkosP functions
|
||||
void (*kokkosp_print_help_f)(char*) = nullptr;
|
||||
@@ -626,30 +638,66 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
void omnitrace_push_region(const char* name)
|
||||
int omnitrace_push_region(const char* name)
|
||||
{
|
||||
if(!dl::get_active()) return;
|
||||
if(!dl::get_active()) return 0;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_region_f, name);
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_region_f, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
++dl::get_thread_count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void omnitrace_pop_region(const char* name)
|
||||
int omnitrace_pop_region(const char* name)
|
||||
{
|
||||
if(!dl::get_active()) return;
|
||||
if(!dl::get_active()) return 0;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dl::get_thread_count()-- == 0) omnitrace_user_start_thread_trace_dl();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omnitrace_push_category_region(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
if(!dl::get_active()) return 0;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_category_region_f,
|
||||
_category, name, _annotations, _annotation_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
++dl::get_thread_count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omnitrace_pop_category_region(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
if(!dl::get_active()) return 0;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_category_region_f,
|
||||
_category, name, _annotations, _annotation_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
++dl::get_thread_count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void omnitrace_set_env(const char* a, const char* b)
|
||||
@@ -724,6 +772,26 @@ extern "C"
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
|
||||
}
|
||||
|
||||
int omnitrace_user_push_annotated_region_dl(const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
if(!dl::get_active()) return 0;
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_category_region_f,
|
||||
OMNITRACE_CATEGORY_USER, name, _annotations,
|
||||
_annotation_count);
|
||||
}
|
||||
|
||||
int omnitrace_user_pop_annotated_region_dl(const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
if(!dl::get_active()) return 0;
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_category_region_f,
|
||||
OMNITRACE_CATEGORY_USER, name, _annotations,
|
||||
_annotation_count);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
// KokkosP
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef OMNITRACE_DL_HPP_
|
||||
#define OMNITRACE_DL_HPP_ 1
|
||||
#define OMNITRACE_DL_HPP_
|
||||
|
||||
#if defined(OMNITRACE_DL_SOURCE) && (OMNITRACE_DL_SOURCE > 0)
|
||||
# include "common/defines.h"
|
||||
@@ -78,8 +78,15 @@ extern "C"
|
||||
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_push_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_push_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_pop_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_push_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_pop_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_push_category_region(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_pop_category_region(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
|
||||
void omnitrace_register_source(const char* file, const char* func, size_t line,
|
||||
size_t address,
|
||||
const char* source) OMNITRACE_PUBLIC_API;
|
||||
@@ -99,6 +106,11 @@ extern "C"
|
||||
int omnitrace_user_push_region_dl(const char*) OMNITRACE_HIDDEN_API;
|
||||
int omnitrace_user_pop_region_dl(const char*) OMNITRACE_HIDDEN_API;
|
||||
|
||||
int omnitrace_user_push_annotated_region_dl(const char*, omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_HIDDEN_API;
|
||||
int omnitrace_user_pop_annotated_region_dl(const char*, omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_HIDDEN_API;
|
||||
|
||||
// KokkosP
|
||||
struct OMNITRACE_HIDDEN_API SpaceHandle
|
||||
{
|
||||
|
||||
@@ -35,9 +35,11 @@ set_target_properties(
|
||||
|
||||
omnitrace_strip_target(omnitrace-user-library)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/types.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/omnitrace)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/categories.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/omnitrace)
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-user-library
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef OMNITRACE_CATEGORIES_H_
|
||||
#define OMNITRACE_CATEGORIES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// @typedef omnitrace_category_t
|
||||
/// @brief Identifier for categories
|
||||
///
|
||||
typedef enum OMNITRACE_CATEGORIES
|
||||
{
|
||||
// Do not use first enum value
|
||||
OMNITRACE_CATEGORY_NONE = 0,
|
||||
// arrange these in the order most likely to
|
||||
// be used since they have to be iterated over
|
||||
OMNITRACE_CATEGORY_PYTHON,
|
||||
OMNITRACE_CATEGORY_USER,
|
||||
OMNITRACE_CATEGORY_HOST,
|
||||
OMNITRACE_CATEGORY_DEVICE_HIP,
|
||||
OMNITRACE_CATEGORY_DEVICE_HSA,
|
||||
OMNITRACE_CATEGORY_ROCM_HIP,
|
||||
OMNITRACE_CATEGORY_ROCM_HSA,
|
||||
OMNITRACE_CATEGORY_ROCM_ROCTX,
|
||||
OMNITRACE_CATEGORY_ROCM_SMI,
|
||||
OMNITRACE_CATEGORY_ROCM_SMI_BUSY,
|
||||
OMNITRACE_CATEGORY_ROCM_SMI_TEMP,
|
||||
OMNITRACE_CATEGORY_ROCM_SMI_POWER,
|
||||
OMNITRACE_CATEGORY_ROCM_SMI_MEMORY_USAGE,
|
||||
OMNITRACE_CATEGORY_ROCM_RCCL,
|
||||
OMNITRACE_CATEGORY_ROCTRACER,
|
||||
OMNITRACE_CATEGORY_ROCPROFILER,
|
||||
OMNITRACE_CATEGORY_SAMPLING,
|
||||
OMNITRACE_CATEGORY_PTHREAD,
|
||||
OMNITRACE_CATEGORY_KOKKOS,
|
||||
OMNITRACE_CATEGORY_MPI,
|
||||
OMNITRACE_CATEGORY_OMPT,
|
||||
OMNITRACE_CATEGORY_PROCESS_SAMPLING,
|
||||
OMNITRACE_CATEGORY_COMM_DATA,
|
||||
OMNITRACE_CATEGORY_CRITICAL_TRACE,
|
||||
OMNITRACE_CATEGORY_HOST_CRITICAL_TRACE,
|
||||
OMNITRACE_CATEGORY_DEVICE_CRITICAL_TRACE,
|
||||
OMNITRACE_CATEGORY_CAUSAL,
|
||||
OMNITRACE_CATEGORY_CPU_FREQ,
|
||||
OMNITRACE_CATEGORY_PROCESS_PAGE,
|
||||
OMNITRACE_CATEGORY_PROCESS_VIRT,
|
||||
OMNITRACE_CATEGORY_PROCESS_PEAK,
|
||||
OMNITRACE_CATEGORY_PROCESS_CONTEXT_SWITCH,
|
||||
OMNITRACE_CATEGORY_PROCESS_PAGE_FAULT,
|
||||
OMNITRACE_CATEGORY_PROCESS_USER_MODE_TIME,
|
||||
OMNITRACE_CATEGORY_PROCESS_KERNEL_MODE_TIME,
|
||||
OMNITRACE_CATEGORY_THREAD_PAGE_FAULT,
|
||||
OMNITRACE_CATEGORY_THREAD_PEAK_MEMORY,
|
||||
OMNITRACE_CATEGORY_THREAD_CONTEXT_SWITCH,
|
||||
OMNITRACE_CATEGORY_THREAD_HARDWARE_COUNTER,
|
||||
OMNITRACE_CATEGORY_KERNEL_HARDWARE_COUNTER,
|
||||
OMNITRACE_CATEGORY_NUMA,
|
||||
OMNITRACE_CATEGORY_LAST
|
||||
// the value of below enum is used for iterating
|
||||
// over the enum in C++ templates. It MUST
|
||||
// be the last enumerated id
|
||||
} omnitrace_category_t;
|
||||
|
||||
/// @typedef omnitrace_annotation_type_t
|
||||
/// @brief Identifier for the data type of the annotation.
|
||||
/// if the data type is not a pointer, pass the address of
|
||||
/// data.
|
||||
typedef enum OMNITRACE_ANNOTATION_TYPE
|
||||
{
|
||||
// Do not use first enum value
|
||||
OMNITRACE_VALUE_NONE = 0,
|
||||
// arrange these in the order most likely to
|
||||
// be used since they have to be iterated over
|
||||
OMNITRACE_VALUE_CSTR = 1,
|
||||
OMNITRACE_STRING = OMNITRACE_VALUE_CSTR,
|
||||
OMNITRACE_VALUE_SIZE_T = 2,
|
||||
OMNITRACE_SIZE_T = OMNITRACE_VALUE_SIZE_T,
|
||||
OMNITRACE_VALUE_INT64 = 3,
|
||||
OMNITRACE_INT64 = OMNITRACE_VALUE_INT64,
|
||||
OMNITRACE_I64 = OMNITRACE_VALUE_INT64,
|
||||
OMNITRACE_VALUE_UINT64 = 4,
|
||||
OMNITRACE_UINT64 = OMNITRACE_VALUE_UINT64,
|
||||
OMNITRACE_U64 = OMNITRACE_VALUE_UINT64,
|
||||
OMNITRACE_VALUE_FLOAT64 = 5,
|
||||
OMNITRACE_FLOAT64 = OMNITRACE_VALUE_FLOAT64,
|
||||
OMNITRACE_FP64 = OMNITRACE_VALUE_FLOAT64,
|
||||
OMNITRACE_VALUE_VOID_P = 6,
|
||||
OMNITRACE_VOID_P = OMNITRACE_VALUE_VOID_P,
|
||||
OMNITRACE_PTR = OMNITRACE_VALUE_VOID_P,
|
||||
OMNITRACE_VALUE_INT32 = 7,
|
||||
OMNITRACE_INT32 = OMNITRACE_VALUE_INT32,
|
||||
OMNITRACE_I32 = OMNITRACE_VALUE_INT32,
|
||||
OMNITRACE_VALUE_UINT32 = 8,
|
||||
OMNITRACE_UINT32 = OMNITRACE_VALUE_UINT32,
|
||||
OMNITRACE_U32 = OMNITRACE_VALUE_UINT32,
|
||||
OMNITRACE_VALUE_FLOAT32 = 9,
|
||||
OMNITRACE_FLOAT32 = OMNITRACE_VALUE_FLOAT32,
|
||||
OMNITRACE_FP32 = OMNITRACE_VALUE_FLOAT32,
|
||||
OMNITRACE_VALUE_INT16 = 10,
|
||||
OMNITRACE_INT16 = OMNITRACE_VALUE_INT16,
|
||||
OMNITRACE_I16 = OMNITRACE_VALUE_INT16,
|
||||
OMNITRACE_VALUE_UINT16 = 11,
|
||||
OMNITRACE_UINT16 = OMNITRACE_VALUE_UINT16,
|
||||
OMNITRACE_U16 = OMNITRACE_VALUE_UINT16,
|
||||
// the value of below enum is used for iterating
|
||||
// over the enum in C++ templates. It MUST
|
||||
// be the last enumerated id
|
||||
OMNITRACE_VALUE_LAST
|
||||
} omnitrace_annotation_type_t;
|
||||
|
||||
/// @typedef omnitrace_annotation
|
||||
/// @brief A struct containing annotation data to be included in the perfetto trace.
|
||||
///
|
||||
/// @code{.cpp}
|
||||
/// #include <cstddef>
|
||||
/// #include <cstdint>
|
||||
///
|
||||
/// #include <omnitrace/user.h>
|
||||
///
|
||||
/// double
|
||||
/// compute_residual(size_t n, double* data);
|
||||
///
|
||||
/// double
|
||||
/// compute(size_t n, double* data, size_t nitr, double tolerance)
|
||||
/// {
|
||||
/// omnitrace_annotation_t _annotations[] = {
|
||||
/// { "iteration", OMNITRACE_VALUE_SIZE_T, nullptr },
|
||||
/// { "residual", OMNITRACE_VALUE_FLOAT64, nullptr },
|
||||
/// { "data", OMNITRACE_VALUE_PTR, data },
|
||||
/// { "size", OMNITRACE_VALUE_SIZE_T, &n },
|
||||
/// { "tolerance", OMNITRACE_VALUE_FLOAT64, &tolerance },
|
||||
/// nullptr
|
||||
/// };
|
||||
///
|
||||
/// double residual = tolerance;
|
||||
/// for(size_t i = 0; i < nitr; ++i)
|
||||
/// {
|
||||
/// omnitrace_user_push_annotated_region("compute", &_annotations);
|
||||
///
|
||||
/// residual = compute_residual(n, data);
|
||||
///
|
||||
/// _annotations[0].value = &i;
|
||||
/// _annotations[1].value = &residual;
|
||||
/// omnitrace_user_pop_annotated_region("compute", &_annotations);
|
||||
/// }
|
||||
///
|
||||
/// return residual;
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
typedef struct omnitrace_annotation
|
||||
{
|
||||
const char* name;
|
||||
uintptr_t type;
|
||||
void* value;
|
||||
} omnitrace_annotation_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OMNITRACE_TYPES_H_
|
||||
@@ -21,8 +21,9 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef OMNITRACE_TYPES_H_
|
||||
#define OMNITRACE_TYPES_H_ 1
|
||||
#define OMNITRACE_TYPES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -30,7 +31,77 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// @enum OMNITRACE_USER_ERROR
|
||||
struct omnitrace_annotation;
|
||||
typedef int (*omnitrace_trace_func_t)(void);
|
||||
typedef int (*omnitrace_region_func_t)(const char*);
|
||||
typedef int (*omnitrace_annotated_region_func_t)(const char*, omnitrace_annotation*,
|
||||
size_t);
|
||||
|
||||
/// @typedef omnitrace_user_callbacks_t
|
||||
/// @brief Struct containing the callbacks for the user API
|
||||
/// @code{.cpp}
|
||||
///
|
||||
/// #include <cerrno>
|
||||
/// #include <cstring>
|
||||
///
|
||||
/// omnitrace_user_callbacks_t custom_callbacks = OMNITRACE_USER_CALLBACKS_INIT;
|
||||
/// omnitrace_user_callbacks_t original_callbacks = OMNITRACE_USER_CALLBACKS_INIT;
|
||||
///
|
||||
/// // in our custom push region, we are going to redirect the unannotated user push
|
||||
/// // region to annotate the trace entries with the global errno and if errno is
|
||||
/// // non-zero, store the message
|
||||
/// int
|
||||
/// custom_push_region(const char* name)
|
||||
/// {
|
||||
/// if(!original_callbacks.push_annotated_region)
|
||||
/// return OMNITRACE_USER_ERROR_NO_BINDING;
|
||||
///
|
||||
/// int32_t _err = errno;
|
||||
/// const char* _msg = nullptr;
|
||||
/// char _buff[1024];
|
||||
/// if(_err != 0) _msg = strerror_r(_err, _buff, sizeof(_buff));
|
||||
///
|
||||
/// omnitrace_annotation_t _annotates[] = { { "errno", OMNITRACE_INT32, &_err },
|
||||
/// { "msg", OMNITRACE_STRING, _msg } };
|
||||
/// return (*original_callbacks.push_annotated_region)(name, &_annotations, 2);
|
||||
/// }
|
||||
///
|
||||
/// int
|
||||
/// main(int argc, char** argv)
|
||||
/// {
|
||||
/// custom_callbacks.push_region = &custom_push_region;
|
||||
/// omnitrace_user_configure(OMNITRACE_USER_UNION_CONFIG, custom_callbacks,
|
||||
/// &original_callbacks);
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// @endcode
|
||||
typedef struct omnitrace_user_callbacks
|
||||
{
|
||||
omnitrace_trace_func_t start_trace;
|
||||
omnitrace_trace_func_t stop_trace;
|
||||
omnitrace_trace_func_t start_thread_trace;
|
||||
omnitrace_trace_func_t stop_thread_trace;
|
||||
omnitrace_region_func_t push_region;
|
||||
omnitrace_region_func_t pop_region;
|
||||
omnitrace_annotated_region_func_t push_annotated_region;
|
||||
omnitrace_annotated_region_func_t pop_annotated_region;
|
||||
} omnitrace_user_callbacks_t;
|
||||
|
||||
/// @typedef omnitrace_user_configure_mode_t
|
||||
/// @brief Identifier for errors
|
||||
///
|
||||
typedef enum OMNITRACE_USER_CONFIGURE_MODE
|
||||
{
|
||||
// clang-format off
|
||||
OMNITRACE_USER_UNION_CONFIG = 0, ///< Replace the callbacks in the current config with the non-null callbacks in the provided config
|
||||
OMNITRACE_USER_REPLACE_CONFIG, ///< Replace the entire config even if the provided config has null callbacks
|
||||
OMNITRACE_USER_INTERSECT_CONFIG, ///< Produce a config which is the intersection of the current config and the provided config
|
||||
OMNITRACE_USER_CONFIGURE_MODE_LAST
|
||||
// clang-format on
|
||||
} omnitrace_user_configure_mode_t;
|
||||
|
||||
/// @typedef omnitrace_user_error_t
|
||||
/// @brief Identifier for errors
|
||||
///
|
||||
typedef enum OMNITRACE_USER_ERROR
|
||||
@@ -43,46 +114,15 @@ extern "C"
|
||||
OMNITRACE_USER_ERROR_LAST
|
||||
} omnitrace_user_error_t;
|
||||
|
||||
/// @enum OMNITRACE_USER_BINDINGS
|
||||
/// @brief Identifier for function pointer categories
|
||||
/// @code{.cpp}
|
||||
/// int (*omnitrace_push_region_f)(const char*) = nullptr;
|
||||
///
|
||||
/// int custom_push_region(const char* name)
|
||||
/// {
|
||||
/// // custom push region prints message before calling internal callback
|
||||
/// printf("Pushing region %s\n", name);
|
||||
/// return (*omnitrace_push_region_f)(name);
|
||||
/// }
|
||||
///
|
||||
/// int main(int argc, char** argv)
|
||||
/// {
|
||||
/// // get the internal callback to start a user-defined region
|
||||
/// omnitrace_user_get_callbacks(OMNITRACE_USER_REGION,
|
||||
/// (void**) &omnitrace_push_region_f,
|
||||
/// nullptr);
|
||||
/// // assign the custom callback to start a user-defined region
|
||||
/// if(omnitrace_push_region_f)
|
||||
/// omnitrace_user_configure(OMNITRACE_USER_REGION,
|
||||
/// (void*) &custom_push_region,
|
||||
/// nullptr);
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// @endcode
|
||||
typedef enum OMNITRACE_USER_BINDINGS
|
||||
{
|
||||
OMNITRACE_USER_START_STOP =
|
||||
0, ///< Function pointers which control global start/stop
|
||||
OMNITRACE_USER_START_STOP_THREAD, ///< Function pointers which control per-thread
|
||||
///< start/stop
|
||||
OMNITRACE_USER_REGION, ///< Function pointers which generate user-defined regions
|
||||
OMNITRACE_USER_SAMPLE, ///< Function pointer which generate samples
|
||||
OMNITRACE_USER_BINDINGS_LAST
|
||||
} omnitrace_user_bindings_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OMNITRACE_USER_CALLBACKS_INIT
|
||||
# define OMNITRACE_USER_CALLBACKS_INIT \
|
||||
{ \
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OMNITRACE_TYPES_H_
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef OMNITRACE_USER_H_
|
||||
#define OMNITRACE_USER_H_ 1
|
||||
#define OMNITRACE_USER_H_
|
||||
|
||||
#if defined(OMNITRACE_USER_SOURCE) && (OMNITRACE_USER_SOURCE > 0)
|
||||
# if !defined(OMNITRACE_PUBLIC_API)
|
||||
@@ -33,6 +33,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "omnitrace/categories.h"
|
||||
#include "omnitrace/types.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -79,16 +80,47 @@ extern "C"
|
||||
/// results in timemory vs. perfetto.
|
||||
extern int omnitrace_user_pop_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// @fn int omnitrace_user_configure(int category, void* begin_func, void* end_func)
|
||||
/// @param category An @ref OMNITRACE_USER_BINDINGS value
|
||||
/// @param begin_func The pointer to the function which corresponds to "starting" the
|
||||
/// category, e.g. omnitrace_user_start_trace or omnitrace_user_push_region
|
||||
/// @param end_func The pointer to the function which corresponds to "ending" the
|
||||
/// category, e.g. omnitrace_user_stop_trace or omnitrace_user_pop_region
|
||||
/// @fn int omnitrace_user_push_annotated_region(const char* id,
|
||||
/// omnitrace_annotation_t* annotations,
|
||||
/// size_t num_annotations)
|
||||
/// @param id The string identifier for the region
|
||||
/// @param annotations Array of @ref omnitrace_annotation_t instances
|
||||
/// @param num_annotations Number of annotations
|
||||
/// @return @ref OMNITRACE_USER_ERROR value
|
||||
/// @brief Configure the function pointers for a given category. This is handled by
|
||||
/// omnitrace-dl at start up but the user can specify their own if desired.
|
||||
extern int omnitrace_user_configure(int, void*, void*) OMNITRACE_PUBLIC_API;
|
||||
/// @brief Start a user defined region and adds the annotations to the perfetto trace.
|
||||
extern int omnitrace_user_push_annotated_region(const char*, omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// @fn int omnitrace_user_pop_annotated_region(const char* id,
|
||||
/// omnitrace_annotation_t* annotations,
|
||||
/// size_t num_annotations)
|
||||
/// @param id The string identifier for the region
|
||||
/// @param annotations Array of @ref omnitrace_annotation_t instances
|
||||
/// @param num_annotations Number of annotations
|
||||
/// @return @ref OMNITRACE_USER_ERROR value
|
||||
/// @brief Stop a user defined region and adds the annotations to the perfetto trace.
|
||||
extern int omnitrace_user_pop_annotated_region(const char*, omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// @fn int omnitrace_user_configure(omnitrace_user_configure_mode_t cfg,
|
||||
/// omnitrace_user_callbacks_t new_callbacks,
|
||||
/// omnitrace_user_callbacks_t* old_callbacks)
|
||||
/// @param[in] config Specifies how the new callbacks are merged with the old callbacks
|
||||
/// @param[in] new_callbacks An @ref omnitrace_user_callbacks_t instance specifying
|
||||
/// the callbacks which should be invoked by the user API.
|
||||
/// @param[out] old_callbacks Pointer to @ref omnitrace_user_callbacks_t which,
|
||||
/// when non-NULL, will be assigned the former callbacks.
|
||||
/// @return @ref omnitrace_user_error_t value
|
||||
/// @brief Configure the function pointers invoked by the omnitrace user API.
|
||||
/// The initial callbacks are set via the omnitrace-dl library when it is loaded but
|
||||
/// the user can user this feature to turn on/off the user API or customize how the
|
||||
/// the user callbacks occur. For example, the user could maintain one set of
|
||||
/// callbacks which discard any annotation data or redirect all unannotated user
|
||||
/// regions to the annotated user regions with annotations about some global state.
|
||||
/// Changing the callbacks is thread-safe but not thread-local.
|
||||
extern int omnitrace_user_configure(
|
||||
omnitrace_user_configure_mode_t, omnitrace_user_callbacks_t new_callbacks,
|
||||
omnitrace_user_callbacks_t* old_callbacks) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// @fn int omnitrace_user_get_callbacks(int category, void** begin_func, void**
|
||||
/// end_func)
|
||||
@@ -100,7 +132,8 @@ extern "C"
|
||||
/// @return @ref OMNITRACE_USER_ERROR value
|
||||
/// @brief Get the current function pointers for a given category. The initial values
|
||||
/// are assigned by omnitrace-dl at start up.
|
||||
extern int omnitrace_user_get_callbacks(int, void**, void**) OMNITRACE_PUBLIC_API;
|
||||
extern int omnitrace_user_get_callbacks(omnitrace_user_callbacks_t*)
|
||||
OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// @fn const char* omnitrace_user_error_string(int error_category)
|
||||
/// @param error_category OMNITRACE_USER_ERROR value
|
||||
|
||||
@@ -25,41 +25,24 @@
|
||||
#endif
|
||||
|
||||
#include "omnitrace/user.h"
|
||||
#include "omnitrace/categories.h"
|
||||
#include "omnitrace/types.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <optional>
|
||||
|
||||
using annotation_t = omnitrace_annotation_t;
|
||||
|
||||
namespace
|
||||
{
|
||||
using trace_func_t = int (*)(void);
|
||||
using region_func_t = int (*)(const char*);
|
||||
using trace_func_t = omnitrace_trace_func_t;
|
||||
using region_func_t = omnitrace_region_func_t;
|
||||
using annotated_region_func_t = omnitrace_annotated_region_func_t;
|
||||
using user_callbacks_t = omnitrace_user_callbacks_t;
|
||||
|
||||
trace_func_t _start_trace = nullptr;
|
||||
trace_func_t _stop_trace = nullptr;
|
||||
trace_func_t _start_thread_trace = nullptr;
|
||||
trace_func_t _stop_thread_trace = nullptr;
|
||||
region_func_t _push_region = nullptr;
|
||||
region_func_t _pop_region = nullptr;
|
||||
|
||||
const char*
|
||||
as_string(OMNITRACE_USER_BINDINGS _category)
|
||||
{
|
||||
switch(_category)
|
||||
{
|
||||
case OMNITRACE_USER_START_STOP: return "OMNITRACE_USER_START_STOP";
|
||||
case OMNITRACE_USER_START_STOP_THREAD: return "OMNITRACE_USER_START_STOP_THREAD";
|
||||
case OMNITRACE_USER_REGION: return "OMNITRACE_USER_REGION";
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "[omnitrace][user] Unknown user binding category: %i\n",
|
||||
static_cast<int>(_category));
|
||||
fflush(stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "OMNITRACE_USER_BINDINGS_unknown";
|
||||
}
|
||||
user_callbacks_t _callbacks = OMNITRACE_USER_CALLBACKS_INIT;
|
||||
|
||||
template <typename... Args>
|
||||
inline auto
|
||||
@@ -73,74 +56,106 @@ invoke(int (*_func)(Args...), Args... args)
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int omnitrace_user_start_trace(void) { return invoke(_start_trace); }
|
||||
int omnitrace_user_stop_trace(void) { return invoke(_stop_trace); }
|
||||
int omnitrace_user_start_thread_trace(void) { return invoke(_start_thread_trace); }
|
||||
int omnitrace_user_stop_thread_trace(void) { return invoke(_stop_thread_trace); }
|
||||
int omnitrace_user_push_region(const char* id) { return invoke(_push_region, id); }
|
||||
int omnitrace_user_pop_region(const char* id) { return invoke(_pop_region, id); }
|
||||
int omnitrace_user_start_trace(void) { return invoke(_callbacks.start_trace); }
|
||||
|
||||
int omnitrace_user_configure(int category, void* begin_func, void* end_func)
|
||||
int omnitrace_user_stop_trace(void) { return invoke(_callbacks.stop_trace); }
|
||||
|
||||
int omnitrace_user_start_thread_trace(void)
|
||||
{
|
||||
switch(category)
|
||||
{
|
||||
case OMNITRACE_USER_START_STOP:
|
||||
{
|
||||
if(begin_func) _start_trace = reinterpret_cast<trace_func_t>(begin_func);
|
||||
if(end_func) _stop_trace = reinterpret_cast<trace_func_t>(end_func);
|
||||
break;
|
||||
}
|
||||
case OMNITRACE_USER_START_STOP_THREAD:
|
||||
{
|
||||
if(begin_func)
|
||||
_start_thread_trace = reinterpret_cast<trace_func_t>(begin_func);
|
||||
if(end_func)
|
||||
_stop_thread_trace = reinterpret_cast<trace_func_t>(end_func);
|
||||
break;
|
||||
}
|
||||
case OMNITRACE_USER_REGION:
|
||||
{
|
||||
if(begin_func) _push_region = reinterpret_cast<region_func_t>(begin_func);
|
||||
if(end_func) _pop_region = reinterpret_cast<region_func_t>(end_func);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return OMNITRACE_USER_ERROR_INVALID_CATEGORY;
|
||||
}
|
||||
}
|
||||
|
||||
return OMNITRACE_USER_SUCCESS;
|
||||
return invoke(_callbacks.start_thread_trace);
|
||||
}
|
||||
|
||||
int omnitrace_user_get_callbacks(int category, void** begin_func, void** end_func)
|
||||
int omnitrace_user_stop_thread_trace(void)
|
||||
{
|
||||
switch(category)
|
||||
return invoke(_callbacks.stop_thread_trace);
|
||||
}
|
||||
|
||||
int omnitrace_user_push_region(const char* id)
|
||||
{
|
||||
return invoke(_callbacks.push_region, id);
|
||||
}
|
||||
|
||||
int omnitrace_user_pop_region(const char* id)
|
||||
{
|
||||
return invoke(_callbacks.pop_region, id);
|
||||
}
|
||||
|
||||
int omnitrace_user_push_annotated_region(const char* id, annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
return invoke(_callbacks.push_annotated_region, id, _annotations,
|
||||
_annotation_count);
|
||||
}
|
||||
|
||||
int omnitrace_user_pop_annotated_region(const char* id, annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
return invoke(_callbacks.pop_annotated_region, id, _annotations,
|
||||
_annotation_count);
|
||||
}
|
||||
|
||||
int omnitrace_user_configure(omnitrace_user_configure_mode_t _mode,
|
||||
omnitrace_user_callbacks_t _inp,
|
||||
omnitrace_user_callbacks_t* _out)
|
||||
{
|
||||
auto _former = _callbacks;
|
||||
|
||||
switch(_mode)
|
||||
{
|
||||
case OMNITRACE_USER_START_STOP:
|
||||
case OMNITRACE_USER_REPLACE_CONFIG:
|
||||
{
|
||||
if(begin_func) *begin_func = reinterpret_cast<void*>(_start_trace);
|
||||
if(end_func) *end_func = reinterpret_cast<void*>(_stop_trace);
|
||||
_callbacks = _inp;
|
||||
break;
|
||||
}
|
||||
case OMNITRACE_USER_START_STOP_THREAD:
|
||||
case OMNITRACE_USER_UNION_CONFIG:
|
||||
{
|
||||
if(begin_func) *begin_func = reinterpret_cast<void*>(_start_thread_trace);
|
||||
if(end_func) *end_func = reinterpret_cast<void*>(_stop_thread_trace);
|
||||
auto _update = [](auto& _lhs, auto _rhs) {
|
||||
if(_rhs) _lhs = _rhs;
|
||||
};
|
||||
|
||||
user_callbacks_t _v = _callbacks;
|
||||
|
||||
_update(_v.start_trace, _inp.start_trace);
|
||||
_update(_v.stop_trace, _inp.stop_trace);
|
||||
_update(_v.start_thread_trace, _inp.start_thread_trace);
|
||||
_update(_v.stop_thread_trace, _inp.stop_thread_trace);
|
||||
_update(_v.push_region, _inp.push_region);
|
||||
_update(_v.pop_region, _inp.pop_region);
|
||||
_update(_v.push_annotated_region, _inp.push_annotated_region);
|
||||
_update(_v.pop_annotated_region, _inp.pop_annotated_region);
|
||||
|
||||
_callbacks = _v;
|
||||
break;
|
||||
}
|
||||
case OMNITRACE_USER_REGION:
|
||||
case OMNITRACE_USER_INTERSECT_CONFIG:
|
||||
{
|
||||
if(begin_func) *begin_func = reinterpret_cast<void*>(_push_region);
|
||||
if(end_func) *end_func = reinterpret_cast<void*>(_pop_region);
|
||||
auto _update = [](auto& _lhs, auto _rhs) {
|
||||
if(_lhs != _rhs) _lhs = nullptr;
|
||||
};
|
||||
|
||||
user_callbacks_t _v = _callbacks;
|
||||
|
||||
_update(_v.start_trace, _inp.start_trace);
|
||||
_update(_v.stop_trace, _inp.stop_trace);
|
||||
_update(_v.start_thread_trace, _inp.start_thread_trace);
|
||||
_update(_v.stop_thread_trace, _inp.stop_thread_trace);
|
||||
_update(_v.push_region, _inp.push_region);
|
||||
_update(_v.pop_region, _inp.pop_region);
|
||||
_update(_v.push_annotated_region, _inp.push_annotated_region);
|
||||
_update(_v.pop_annotated_region, _inp.pop_annotated_region);
|
||||
|
||||
_callbacks = _v;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(_out) *_out = _former;
|
||||
return OMNITRACE_USER_ERROR_INVALID_CATEGORY;
|
||||
}
|
||||
}
|
||||
|
||||
if(_out) *_out = _former;
|
||||
|
||||
return OMNITRACE_USER_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,40 @@ omnitrace_pop_region(const char* _name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
omnitrace_push_category_region(omnitrace_category_t _category, const char* _name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
try
|
||||
{
|
||||
omnitrace_push_category_region_hidden(_category, _name, _annotations,
|
||||
_annotation_count);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
omnitrace_pop_category_region(omnitrace_category_t _category, const char* _name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
try
|
||||
{
|
||||
omnitrace_pop_category_region_hidden(_category, _name, _annotations,
|
||||
_annotation_count);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_init_library(void)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "library/defines.hpp"
|
||||
#include "omnitrace/categories.h" // in omnitrace-user
|
||||
|
||||
#include <timemory/compat/macros.h>
|
||||
|
||||
@@ -47,23 +48,34 @@ extern "C"
|
||||
void omnitrace_reset_preload(void) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// sets an environment variable
|
||||
void omnitrace_set_env(const char* env_name,
|
||||
const char* env_val) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_set_env(const char*, const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// sets whether MPI should be used
|
||||
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_set_mpi(bool, bool) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// starts an instrumentation region
|
||||
void omnitrace_push_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_push_trace(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// stops an instrumentation region
|
||||
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_pop_trace(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// starts an instrumentation region (user-defined)
|
||||
int omnitrace_push_region(const char* name) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_push_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// stops an instrumentation region (user-defined)
|
||||
int omnitrace_pop_region(const char* name) OMNITRACE_PUBLIC_API;
|
||||
int omnitrace_pop_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// starts an instrumentation region in a user-defined category and (optionally)
|
||||
/// adds annotations to the perfetto trace.
|
||||
int omnitrace_push_category_region(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// stops an instrumentation region in a user-defined category and (optionally)
|
||||
/// adds annotations to the perfetto trace.
|
||||
int omnitrace_pop_category_region(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// stores source code information
|
||||
void omnitrace_register_source(const char* file, const char* func, size_t line,
|
||||
@@ -80,16 +92,20 @@ extern "C"
|
||||
void omnitrace_init_hidden(const char*, bool, const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_finalize_hidden(void) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_reset_preload_hidden(void) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_set_env_hidden(const char* env_name,
|
||||
const char* env_val) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_set_mpi_hidden(bool use, bool attached) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_register_source_hidden(const char* file, const char* func, size_t line,
|
||||
size_t address,
|
||||
const char* source) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_register_coverage_hidden(const char* file, const char* func,
|
||||
size_t address) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_set_env_hidden(const char*, const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_set_mpi_hidden(bool, bool) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_trace_hidden(const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_trace_hidden(const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_region_hidden(const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_region_hidden(const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_category_region_hidden(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_category_region_hidden(omnitrace_category_t, const char*,
|
||||
omnitrace_annotation_t*,
|
||||
size_t) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_register_source_hidden(const char*, const char*, size_t, size_t,
|
||||
const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_register_coverage_hidden(const char*, const char*,
|
||||
size_t) OMNITRACE_HIDDEN_API;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#include "library/thread_info.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
#include "library/tracing.hpp"
|
||||
#include "library/utility.hpp"
|
||||
#include "omnitrace/categories.h" // in omnitrace-user
|
||||
|
||||
#include <timemory/signals/signal_handlers.hpp>
|
||||
#include <timemory/signals/types.hpp>
|
||||
@@ -65,6 +67,7 @@
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
using namespace omnitrace;
|
||||
|
||||
@@ -187,6 +190,100 @@ omnitrace_pop_region_hidden(const char* name)
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_start(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
component::category_region<category_type>::start(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations)
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_start(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_stop(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
component::category_region<category_type>::stop(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations)
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_stop(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
invoke_category_region_start(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
invoke_category_region_stop(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
namespace
|
||||
{
|
||||
struct set_env_s // NOLINT
|
||||
|
||||
@@ -82,4 +82,6 @@ if(OMNITRACE_USE_ROCM_SMI)
|
||||
endif()
|
||||
|
||||
add_subdirectory(components)
|
||||
add_subdirectory(coverage)
|
||||
add_subdirectory(rocm)
|
||||
add_subdirectory(tracing)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "common/join.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "omnitrace/categories.h" // in omnitrace-user
|
||||
|
||||
#if defined(TIMEMORY_PERFETTO_CATEGORIES)
|
||||
# error "TIMEMORY_PERFETTO_CATEGORIES is already defined. Please include \"" __FILE__ "\" before including any timemory files"
|
||||
@@ -48,57 +49,87 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define OMNITRACE_DECLARE_CATEGORY(NS, VALUE, NAME, DESC) \
|
||||
namespace omnitrace
|
||||
{
|
||||
template <size_t>
|
||||
struct category_type_id;
|
||||
|
||||
template <typename Tp>
|
||||
struct category_enum_id;
|
||||
|
||||
template <size_t Idx>
|
||||
using category_type_id_t = typename category_type_id<Idx>::type;
|
||||
} // namespace omnitrace
|
||||
|
||||
#define OMNITRACE_DEFINE_CATEGORY_TRAIT(TYPE, ENUM) \
|
||||
namespace omnitrace \
|
||||
{ \
|
||||
template <> \
|
||||
struct category_type_id<ENUM> \
|
||||
{ \
|
||||
using type = TYPE; \
|
||||
}; \
|
||||
template <> \
|
||||
struct category_enum_id<TYPE> \
|
||||
{ \
|
||||
static constexpr auto value = ENUM; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define OMNITRACE_DECLARE_CATEGORY(NS, VALUE, ENUM, NAME, DESC) \
|
||||
TIMEMORY_DECLARE_NS_API(NS, VALUE) \
|
||||
OMNITRACE_DEFINE_NAME_TRAIT(NAME, DESC, NS::VALUE)
|
||||
#define OMNITRACE_DEFINE_CATEGORY(NS, VALUE, NAME, DESC) \
|
||||
OMNITRACE_DEFINE_NAME_TRAIT(NAME, DESC, NS::VALUE) \
|
||||
OMNITRACE_DEFINE_CATEGORY_TRAIT(::tim::NS::VALUE, ENUM)
|
||||
#define OMNITRACE_DEFINE_CATEGORY(NS, VALUE, ENUM, NAME, DESC) \
|
||||
TIMEMORY_DEFINE_NS_API(NS, VALUE) \
|
||||
OMNITRACE_DEFINE_NAME_TRAIT(NAME, DESC, NS::VALUE)
|
||||
OMNITRACE_DEFINE_NAME_TRAIT(NAME, DESC, NS::VALUE) \
|
||||
OMNITRACE_DEFINE_CATEGORY_TRAIT(::tim::NS::VALUE, ENUM)
|
||||
|
||||
// clang-format off
|
||||
// these are defined by omnitrace
|
||||
OMNITRACE_DEFINE_CATEGORY(project, omnitrace, "omnitrace", "Omnitrace project")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, host, "host", "Host-side function tracing")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, user, "user", "User-defined regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_hip, "device_hip", "Device-side functions submitted via HIP API")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_hsa, "device_hsa", "Device-side functions submitted via HSA API")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_hip, "rocm_hip", "Host-side HIP functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_hsa, "rocm_hsa", "Host-side HSA functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_roctx, "rocm_roctx", "ROCTx labels")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi, "rocm_smi", "rocm-smi data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_busy, "device_busy", "Busy percentage of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_temp, "device_temp", "Temperature of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_power, "device_power", "Power consumption of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_memory_usage, "device_memory_usage", "Memory usage of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_rccl, "rccl", "ROCm Communication Collectives Library (RCCL) regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, roctracer, "roctracer", "Kernel tracing provided by roctracer")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocprofiler, "rocprofiler", "HW counter data provided by rocprofiler")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, pthread, "pthread", "POSIX threading functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, kokkos, "kokkos", "KokkosTools regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, mpi, "mpi", "MPI regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, ompt, "ompt", "OpenMP tools regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_sampling, "process_sampling", "Process-level data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, comm_data, "comm_data", "MPI/RCCL counters for tracking amount of data sent or received")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, critical_trace, "critical-trace", "Critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, host_critical_trace, "host-critical-trace", "Host-side critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_critical_trace, "device-critical-trace", "Device-side critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, causal, "causal", "Causal profiling data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, cpu_freq, "cpu_frequency", "CPU frequency (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_page, "process_page_fault", "Memory page faults in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_virt, "process_virtual_memory", "Virtual memory usage in process in MB (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_peak, "process_memory_hwm", "Memory High-Water Mark i.e. peak memory usage (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_context_switch, "process_context_switch", "Context switches in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_page_fault, "process_page_fault", "Memory page faults in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_user_mode_time, "process_user_cpu_time", "CPU time of functions executing in user-space in process in seconds (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_kernel_mode_time, "process_kernel_cpu_time", "CPU time of functions executing in kernel-space in process in seconds (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_page_fault, "thread_page_fault", "Memory page faults on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_peak_memory, "thread_peak_memory", "Peak memory usage on thread in MB (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_context_switch, "thread_context_switch", "Context switches on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_hardware_counter, "thread_hardware_counter", "Hardware counter value on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, kernel_hardware_counter, "kernel_hardware_counter", "Hardware counter value for kernel (deterministic)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, numa, "numa", "Non-unified memory architecture")
|
||||
OMNITRACE_DEFINE_CATEGORY(project, omnitrace, OMNITRACE_CATEGORY_NONE, "omnitrace", "Omnitrace project")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, host, OMNITRACE_CATEGORY_HOST, "host", "Host-side function tracing")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, user, OMNITRACE_CATEGORY_USER, "user", "User-defined regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, python, OMNITRACE_CATEGORY_PYTHON, "python", "Python regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_hip, OMNITRACE_CATEGORY_DEVICE_HIP, "device_hip", "Device-side functions submitted via HIP API")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_hsa, OMNITRACE_CATEGORY_DEVICE_HSA, "device_hsa", "Device-side functions submitted via HSA API")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_hip, OMNITRACE_CATEGORY_ROCM_HIP, "rocm_hip", "Host-side HIP functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_hsa, OMNITRACE_CATEGORY_ROCM_HSA, "rocm_hsa", "Host-side HSA functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_roctx, OMNITRACE_CATEGORY_ROCM_ROCTX, "rocm_roctx", "ROCTx labels")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi, OMNITRACE_CATEGORY_ROCM_SMI, "rocm_smi", "rocm-smi data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_busy, OMNITRACE_CATEGORY_ROCM_SMI_BUSY, "device_busy", "Busy percentage of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_temp, OMNITRACE_CATEGORY_ROCM_SMI_TEMP, "device_temp", "Temperature of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_power, OMNITRACE_CATEGORY_ROCM_SMI_POWER, "device_power", "Power consumption of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_smi_memory_usage, OMNITRACE_CATEGORY_ROCM_SMI_MEMORY_USAGE, "device_memory_usage", "Memory usage of a GPU device")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocm_rccl, OMNITRACE_CATEGORY_ROCM_RCCL, "rccl", "ROCm Communication Collectives Library (RCCL) regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, roctracer, OMNITRACE_CATEGORY_ROCTRACER, "roctracer", "Kernel tracing provided by roctracer")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, rocprofiler, OMNITRACE_CATEGORY_ROCPROFILER, "rocprofiler", "HW counter data provided by rocprofiler")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, pthread, OMNITRACE_CATEGORY_PTHREAD, "pthread", "POSIX threading functions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, kokkos, OMNITRACE_CATEGORY_KOKKOS, "kokkos", "KokkosTools regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, mpi, OMNITRACE_CATEGORY_MPI, "mpi", "MPI regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, ompt, OMNITRACE_CATEGORY_OMPT, "ompt", "OpenMP tools regions")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_sampling, OMNITRACE_CATEGORY_PROCESS_SAMPLING, "process_sampling", "Process-level data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, comm_data, OMNITRACE_CATEGORY_COMM_DATA, "comm_data", "MPI/RCCL counters for tracking amount of data sent or received")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, critical_trace, OMNITRACE_CATEGORY_CRITICAL_TRACE, "critical-trace", "Critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, host_critical_trace, OMNITRACE_CATEGORY_HOST_CRITICAL_TRACE, "host-critical-trace", "Host-side critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, device_critical_trace, OMNITRACE_CATEGORY_DEVICE_CRITICAL_TRACE, "device-critical-trace", "Device-side critical trace data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, causal, OMNITRACE_CATEGORY_CAUSAL, "causal", "Causal profiling data")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, cpu_freq, OMNITRACE_CATEGORY_CPU_FREQ, "cpu_frequency", "CPU frequency (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_page, OMNITRACE_CATEGORY_PROCESS_PAGE, "process_page_fault", "Memory page faults in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_virt, OMNITRACE_CATEGORY_PROCESS_VIRT, "process_virtual_memory", "Virtual memory usage in process in MB (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_peak, OMNITRACE_CATEGORY_PROCESS_PEAK, "process_memory_hwm", "Memory High-Water Mark i.e. peak memory usage (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_context_switch, OMNITRACE_CATEGORY_PROCESS_CONTEXT_SWITCH, "process_context_switch", "Context switches in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_page_fault, OMNITRACE_CATEGORY_PROCESS_PAGE_FAULT, "process_page_fault", "Memory page faults in process (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_user_mode_time, OMNITRACE_CATEGORY_PROCESS_USER_MODE_TIME, "process_user_cpu_time", "CPU time of functions executing in user-space in process in seconds (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, process_kernel_mode_time, OMNITRACE_CATEGORY_PROCESS_KERNEL_MODE_TIME, "process_kernel_cpu_time", "CPU time of functions executing in kernel-space in process in seconds (collected in background thread)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_page_fault, OMNITRACE_CATEGORY_THREAD_PAGE_FAULT, "thread_page_fault", "Memory page faults on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_peak_memory, OMNITRACE_CATEGORY_THREAD_PEAK_MEMORY, "thread_peak_memory", "Peak memory usage on thread in MB (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_context_switch, OMNITRACE_CATEGORY_THREAD_CONTEXT_SWITCH, "thread_context_switch", "Context switches on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_hardware_counter, OMNITRACE_CATEGORY_THREAD_HARDWARE_COUNTER, "thread_hardware_counter", "Hardware counter value on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, kernel_hardware_counter, OMNITRACE_CATEGORY_KERNEL_HARDWARE_COUNTER, "kernel_hardware_counter", "Hardware counter value for kernel (deterministic)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, numa, OMNITRACE_CATEGORY_NUMA, "numa", "Non-unified memory architecture")
|
||||
|
||||
OMNITRACE_DECLARE_CATEGORY(category, sampling, "sampling", "Host-side call-stack sampling")
|
||||
OMNITRACE_DECLARE_CATEGORY(category, sampling, OMNITRACE_CATEGORY_SAMPLING, "sampling", "Host-side call-stack sampling")
|
||||
// clang-format on
|
||||
|
||||
namespace tim
|
||||
@@ -117,6 +148,7 @@ using name = perfetto_category<Tp...>;
|
||||
#define OMNITRACE_PERFETTO_CATEGORIES \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::host), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::user), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::python), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::sampling), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::device_hip), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::device_hsa), \
|
||||
|
||||
+1
@@ -28,6 +28,7 @@
|
||||
#include "library/runtime.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
#include "library/tracing.hpp"
|
||||
#include "library/tracing/annotation.hpp"
|
||||
|
||||
#include <timemory/components/gotcha/backends.hpp>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
|
||||
@@ -2051,25 +2051,4 @@ get_tmp_file(std::string _basename, std::string _ext)
|
||||
return _existing_files.at(_fname);
|
||||
}
|
||||
} // namespace config
|
||||
|
||||
State&
|
||||
get_state()
|
||||
{
|
||||
static State _v{ State::PreInit };
|
||||
return _v;
|
||||
}
|
||||
|
||||
State
|
||||
set_state(State _n)
|
||||
{
|
||||
auto _o = get_state();
|
||||
OMNITRACE_CONDITIONAL_PRINT_F(get_debug_init(), "Setting state :: %s -> %s\n",
|
||||
std::to_string(_o).c_str(), std::to_string(_n).c_str());
|
||||
// state should always be increased, not decreased
|
||||
OMNITRACE_CI_BASIC_THROW(_n < _o,
|
||||
"State is being assigned to a lesser value :: %s -> %s",
|
||||
std::to_string(_o).c_str(), std::to_string(_n).c_str());
|
||||
get_state() = _n;
|
||||
return _o;
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -355,13 +355,4 @@ struct tmp_file
|
||||
std::shared_ptr<tmp_file>
|
||||
get_tmp_file(std::string _basename, std::string _ext = "dat");
|
||||
} // namespace config
|
||||
|
||||
//
|
||||
// Runtime configuration data
|
||||
//
|
||||
State&
|
||||
get_state() TIMEMORY_HOT;
|
||||
|
||||
/// returns old state
|
||||
State set_state(State);
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include "library/coverage.hpp"
|
||||
#include "api.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/coverage/impl.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/impl/coverage.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
|
||||
#include <timemory/backends/threading.hpp>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#
|
||||
set(coverage_sources)
|
||||
set(coverage_headers ${CMAKE_CURRENT_LIST_DIR}/impl.hpp)
|
||||
|
||||
target_sources(omnitrace-object-library PRIVATE ${coverage_sources} ${coverage_headers})
|
||||
@@ -244,55 +244,6 @@ get_preinit_bundle()
|
||||
return _v;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
auto&
|
||||
get_thread_state_history(int64_t _idx = utility::get_thread_index())
|
||||
{
|
||||
static auto _v = utility::get_filled_array<OMNITRACE_MAX_THREADS>(
|
||||
[]() { return utility::get_reserved_vector<ThreadState>(32); });
|
||||
|
||||
return _v.at(_idx);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ThreadState&
|
||||
get_thread_state()
|
||||
{
|
||||
static thread_local ThreadState _v{ ThreadState::Enabled };
|
||||
return _v;
|
||||
}
|
||||
|
||||
ThreadState
|
||||
set_thread_state(ThreadState _n)
|
||||
{
|
||||
auto _o = get_thread_state();
|
||||
get_thread_state() = _n;
|
||||
return _o;
|
||||
}
|
||||
|
||||
ThreadState
|
||||
push_thread_state(ThreadState _v)
|
||||
{
|
||||
if(get_thread_state() >= ThreadState::Completed) return get_thread_state();
|
||||
|
||||
return get_thread_state_history().emplace_back(set_thread_state(_v));
|
||||
}
|
||||
|
||||
ThreadState
|
||||
pop_thread_state()
|
||||
{
|
||||
if(get_thread_state() >= ThreadState::Completed) return get_thread_state();
|
||||
|
||||
auto& _hist = get_thread_state_history();
|
||||
if(!_hist.empty())
|
||||
{
|
||||
set_thread_state(_hist.back());
|
||||
_hist.pop_back();
|
||||
}
|
||||
return get_thread_state();
|
||||
}
|
||||
|
||||
bool
|
||||
sampling_enabled_on_child_threads()
|
||||
{
|
||||
|
||||
@@ -107,23 +107,6 @@ get_cpu_cid_entry(uint64_t _cid, int64_t _tid = threading::get_id()) TIMEMORY_HO
|
||||
tim::mutex_t&
|
||||
get_cpu_cid_stack_lock(int64_t _tid = threading::get_id()) TIMEMORY_HOT;
|
||||
|
||||
ThreadState&
|
||||
get_thread_state() TIMEMORY_HOT;
|
||||
|
||||
/// returns old state
|
||||
ThreadState set_thread_state(ThreadState) TIMEMORY_HOT;
|
||||
|
||||
ThreadState push_thread_state(ThreadState) TIMEMORY_HOT;
|
||||
|
||||
ThreadState
|
||||
pop_thread_state() TIMEMORY_HOT;
|
||||
|
||||
struct scoped_thread_state
|
||||
{
|
||||
scoped_thread_state(ThreadState _v) { push_thread_state(_v); }
|
||||
~scoped_thread_state() { pop_thread_state(); }
|
||||
};
|
||||
|
||||
// query current value
|
||||
bool
|
||||
sampling_enabled_on_child_threads();
|
||||
@@ -147,12 +130,6 @@ struct scoped_child_sampling
|
||||
};
|
||||
} // namespace omnitrace
|
||||
|
||||
#define OMNITRACE_SCOPED_THREAD_STATE(STATE) \
|
||||
::omnitrace::scoped_thread_state OMNITRACE_VARIABLE(_scoped_thread_state_, __LINE__) \
|
||||
{ \
|
||||
::omnitrace::STATE \
|
||||
}
|
||||
|
||||
#define OMNITRACE_SCOPED_SAMPLING_ON_CHILD_THREADS(VALUE) \
|
||||
::omnitrace::scoped_child_sampling OMNITRACE_VARIABLE(_scoped_child_sampling_, \
|
||||
__LINE__) \
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "library/thread_data.hpp"
|
||||
#include "library/thread_info.hpp"
|
||||
#include "library/tracing.hpp"
|
||||
#include "library/tracing/annotation.hpp"
|
||||
#include "library/utility.hpp"
|
||||
|
||||
#include <timemory/backends/papi.hpp>
|
||||
|
||||
@@ -21,9 +21,96 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/state.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/utility.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace
|
||||
{
|
||||
auto&
|
||||
get_state_value()
|
||||
{
|
||||
static State _v{ State::PreInit };
|
||||
return _v;
|
||||
}
|
||||
|
||||
ThreadState&
|
||||
get_thread_state_value()
|
||||
{
|
||||
static thread_local ThreadState _v{ ThreadState::Enabled };
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_thread_state_history(int64_t _idx = utility::get_thread_index())
|
||||
{
|
||||
static auto _v = utility::get_filled_array<OMNITRACE_MAX_THREADS>(
|
||||
[]() { return utility::get_reserved_vector<ThreadState>(32); });
|
||||
|
||||
return _v.at(_idx);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
State
|
||||
get_state()
|
||||
{
|
||||
return get_state_value();
|
||||
}
|
||||
|
||||
ThreadState
|
||||
get_thread_state()
|
||||
{
|
||||
return get_thread_state_value();
|
||||
}
|
||||
|
||||
State
|
||||
set_state(State _n)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_PRINT_F(get_debug_init(), "Setting state :: %s -> %s\n",
|
||||
std::to_string(get_state()).c_str(),
|
||||
std::to_string(_n).c_str());
|
||||
// state should always be increased, not decreased
|
||||
OMNITRACE_CI_BASIC_THROW(
|
||||
_n < get_state(), "State is being assigned to a lesser value :: %s -> %s",
|
||||
std::to_string(get_state()).c_str(), std::to_string(_n).c_str());
|
||||
std::swap(get_state_value(), _n);
|
||||
return _n;
|
||||
}
|
||||
|
||||
ThreadState
|
||||
set_thread_state(ThreadState _n)
|
||||
{
|
||||
std::swap(get_thread_state_value(), _n);
|
||||
return _n;
|
||||
}
|
||||
|
||||
ThreadState
|
||||
push_thread_state(ThreadState _v)
|
||||
{
|
||||
if(get_thread_state() >= ThreadState::Completed) return get_thread_state();
|
||||
|
||||
return get_thread_state_history().emplace_back(set_thread_state(_v));
|
||||
}
|
||||
|
||||
ThreadState
|
||||
pop_thread_state()
|
||||
{
|
||||
if(get_thread_state() >= ThreadState::Completed) return get_thread_state();
|
||||
|
||||
auto& _hist = get_thread_state_history();
|
||||
if(!_hist.empty())
|
||||
{
|
||||
set_thread_state(_hist.back());
|
||||
_hist.pop_back();
|
||||
}
|
||||
return get_thread_state();
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
namespace std
|
||||
{
|
||||
std::string
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "library/defines.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
// used for specifying the state of omnitrace
|
||||
@@ -51,9 +53,41 @@ enum class Mode : unsigned short
|
||||
Sampling,
|
||||
Coverage
|
||||
};
|
||||
|
||||
//
|
||||
// Runtime configuration data
|
||||
//
|
||||
State
|
||||
get_state() OMNITRACE_HOT;
|
||||
|
||||
ThreadState
|
||||
get_thread_state() OMNITRACE_HOT;
|
||||
|
||||
/// returns old state
|
||||
State set_state(State) OMNITRACE_COLD; // does not change often
|
||||
|
||||
/// returns old state
|
||||
ThreadState set_thread_state(ThreadState) OMNITRACE_HOT; // changes often
|
||||
|
||||
/// return current state (state change may be ignored)
|
||||
ThreadState push_thread_state(ThreadState) OMNITRACE_HOT;
|
||||
|
||||
/// return current state (state change may be ignored)
|
||||
ThreadState
|
||||
pop_thread_state() OMNITRACE_HOT;
|
||||
|
||||
struct scoped_thread_state
|
||||
{
|
||||
OMNITRACE_INLINE scoped_thread_state(ThreadState _v) { push_thread_state(_v); }
|
||||
OMNITRACE_INLINE ~scoped_thread_state() { pop_thread_state(); }
|
||||
};
|
||||
} // namespace omnitrace
|
||||
|
||||
#include <string>
|
||||
#define OMNITRACE_SCOPED_THREAD_STATE(STATE) \
|
||||
::omnitrace::scoped_thread_state OMNITRACE_VARIABLE(_scoped_thread_state_, __LINE__) \
|
||||
{ \
|
||||
::omnitrace::STATE \
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
@@ -200,76 +200,6 @@ pop_timemory(CategoryT, const char* name, Args&&... args)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Np, typename Tp>
|
||||
auto
|
||||
add_perfetto_annotation(perfetto::EventContext& ctx, Np&& _name, Tp&& _val,
|
||||
int64_t _idx = -1)
|
||||
{
|
||||
using named_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Np>>>;
|
||||
using value_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Tp>>>;
|
||||
|
||||
static_assert(concepts::is_string_type<named_type>::value,
|
||||
"Error! name is not a string type");
|
||||
|
||||
auto _get_dbg = [&]() {
|
||||
auto* _dbg = ctx.event()->add_debug_annotations();
|
||||
if(_idx >= 0)
|
||||
{
|
||||
auto _arg_name = JOIN("", "arg", _idx, "-", std::forward<Np>(_name));
|
||||
_dbg->set_name(_arg_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dbg->set_name(std::string_view{ std::forward<Np>(_name) }.data());
|
||||
}
|
||||
return _dbg;
|
||||
};
|
||||
|
||||
if constexpr(std::is_same<value_type, std::string_view>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(_val.data());
|
||||
}
|
||||
else if constexpr(concepts::is_string_type<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_same<value_type, bool>::value)
|
||||
{
|
||||
_get_dbg()->set_bool_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_enum<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_int_value(static_cast<int64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(std::is_floating_point<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_double_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_integral<value_type>::value)
|
||||
{
|
||||
if constexpr(std::is_unsigned<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_uint_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
_get_dbg()->set_int_value(std::forward<Tp>(_val));
|
||||
}
|
||||
}
|
||||
else if constexpr(std::is_pointer<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_pointer_value(reinterpret_cast<uint64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(concepts::can_stringify<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(JOIN("", std::forward<Tp>(_val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_empty<value_type>::value, "Error! unsupported data type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
push_perfetto(CategoryT, const char* name, Args&&... args)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#
|
||||
set(tracing_sources ${CMAKE_CURRENT_LIST_DIR}/annotation.cpp)
|
||||
set(tracing_headers ${CMAKE_CURRENT_LIST_DIR}/annotation.hpp)
|
||||
|
||||
target_sources(omnitrace-object-library PRIVATE ${tracing_sources} ${tracing_headers})
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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/tracing/annotation.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace tracing
|
||||
{
|
||||
void
|
||||
add_perfetto_annotation(perfetto_event_context_t& ctx,
|
||||
const omnitrace_annotation_t& _annotation)
|
||||
{
|
||||
add_perfetto_annotation(
|
||||
ctx, _annotation, utility::make_index_sequence_range<1, OMNITRACE_VALUE_LAST>{});
|
||||
}
|
||||
} // namespace tracing
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,207 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "library/common.hpp"
|
||||
#include "library/concepts.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/perfetto.hpp"
|
||||
#include "library/state.hpp"
|
||||
#include "library/utility.hpp"
|
||||
#include "omnitrace/categories.h" // in omnitrace-user
|
||||
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace tracing
|
||||
{
|
||||
using perfetto_event_context_t = ::perfetto::EventContext;
|
||||
|
||||
template <size_t Idx>
|
||||
struct annotation_value_type;
|
||||
|
||||
template <size_t Idx>
|
||||
using annotation_value_type_t = typename annotation_value_type<Idx>::type;
|
||||
|
||||
#define OMNITRACE_DEFINE_ANNOTATION_TYPE(ENUM, TYPE) \
|
||||
template <> \
|
||||
struct annotation_value_type<ENUM> \
|
||||
{ \
|
||||
using type = TYPE; \
|
||||
};
|
||||
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_CSTR, const char*)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_SIZE_T, size_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_INT16, int16_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_INT32, int32_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_INT64, int64_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_UINT16, uint16_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_UINT32, uint32_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_UINT64, uint64_t)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_FLOAT32, float)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_FLOAT64, double)
|
||||
OMNITRACE_DEFINE_ANNOTATION_TYPE(OMNITRACE_VALUE_VOID_P, void*)
|
||||
|
||||
#undef OMNITRACE_DEFINE_ANNOTATION_TYPE
|
||||
|
||||
template <typename Np, typename Tp>
|
||||
auto
|
||||
add_perfetto_annotation(
|
||||
perfetto_event_context_t& ctx, Np&& _name, Tp&& _val, int64_t _idx = -1,
|
||||
std::enable_if_t<
|
||||
!std::is_same<std::remove_pointer_t<concepts::unqualified_type_t<Np>>,
|
||||
omnitrace_annotation_t>::value,
|
||||
int> = 0)
|
||||
{
|
||||
using named_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Np>>>;
|
||||
using value_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Tp>>>;
|
||||
|
||||
static_assert(concepts::is_string_type<named_type>::value,
|
||||
"Error! name is not a string type");
|
||||
|
||||
auto _get_dbg = [&]() {
|
||||
auto* _dbg = ctx.event()->add_debug_annotations();
|
||||
if(_idx >= 0)
|
||||
{
|
||||
auto _arg_name = JOIN("", "arg", _idx, "-", std::forward<Np>(_name));
|
||||
_dbg->set_name(_arg_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dbg->set_name(std::string_view{ std::forward<Np>(_name) }.data());
|
||||
}
|
||||
return _dbg;
|
||||
};
|
||||
|
||||
if constexpr(std::is_same<value_type, std::string_view>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(_val.data());
|
||||
}
|
||||
else if constexpr(concepts::is_string_type<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_same<value_type, bool>::value)
|
||||
{
|
||||
_get_dbg()->set_bool_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_enum<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_int_value(static_cast<int64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(std::is_floating_point<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_double_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_integral<value_type>::value)
|
||||
{
|
||||
if constexpr(std::is_unsigned<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_uint_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
_get_dbg()->set_int_value(std::forward<Tp>(_val));
|
||||
}
|
||||
}
|
||||
else if constexpr(std::is_pointer<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_pointer_value(reinterpret_cast<uint64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(concepts::can_stringify<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(JOIN("", std::forward<Tp>(_val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_empty<value_type>::value, "Error! unsupported data type");
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
add_perfetto_annotation(perfetto_event_context_t& ctx,
|
||||
const omnitrace_annotation_t& _annotation,
|
||||
std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_VALUE_NONE && Idx < OMNITRACE_VALUE_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_VALUE_NONE and less than OMNITRACE_VALUE_LAST");
|
||||
|
||||
// in some situations the user might want to short circuit by setting
|
||||
// the name to a null pointer, type to none, or value to a null pointer
|
||||
if(_annotation.name == nullptr || _annotation.type == 0 ||
|
||||
_annotation.value == nullptr)
|
||||
return;
|
||||
|
||||
if(_annotation.type == Idx)
|
||||
{
|
||||
using type = annotation_value_type_t<Idx>;
|
||||
// if the type is a pointer, pass the pointer. otherwise,
|
||||
// cast to pointer of that type and dereference it
|
||||
if constexpr(std::is_pointer<type>::value)
|
||||
{
|
||||
auto _value = reinterpret_cast<type>(_annotation.value);
|
||||
add_perfetto_annotation(ctx, _annotation.name, _value);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* _value = reinterpret_cast<type*>(_annotation.value);
|
||||
add_perfetto_annotation(ctx, _annotation.name, *_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the first "iteration": check whether annotation type has valid range
|
||||
if constexpr(Idx == OMNITRACE_VALUE_NONE + 1)
|
||||
{
|
||||
if(!(_annotation.type > OMNITRACE_VALUE_NONE &&
|
||||
_annotation.type < OMNITRACE_VALUE_LAST))
|
||||
{
|
||||
OMNITRACE_FAIL_F("Error! annotation '%s' has an invalid type designation "
|
||||
"%lu which is outside of acceptable range [%i, %i]\n",
|
||||
_annotation.name, _annotation.type,
|
||||
OMNITRACE_VALUE_NONE + 1, OMNITRACE_VALUE_LAST - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr(sizeof...(Tail) > 0)
|
||||
{
|
||||
add_perfetto_annotation(ctx, _annotation, std::index_sequence<Tail...>{});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("invalid annotation value type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_perfetto_annotation(perfetto_event_context_t& ctx,
|
||||
const omnitrace_annotation_t& _annotation);
|
||||
} // namespace tracing
|
||||
} // namespace omnitrace
|
||||
@@ -63,5 +63,29 @@ get_reserved_vector(size_t _n)
|
||||
_v.reserve(_n);
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t Offset>
|
||||
struct offset_index_sequence;
|
||||
|
||||
template <size_t Idx, size_t Offset>
|
||||
struct offset_index_value
|
||||
{
|
||||
static constexpr size_t value = Idx + Offset;
|
||||
};
|
||||
|
||||
template <size_t Offset, size_t... Idx>
|
||||
struct offset_index_sequence<std::index_sequence<Idx...>, Offset>
|
||||
{
|
||||
using type = std::integer_sequence<size_t, offset_index_value<Idx, Offset>::value...>;
|
||||
};
|
||||
|
||||
template <size_t N, size_t OffsetN>
|
||||
using make_offset_index_sequence =
|
||||
offset_index_sequence<std::make_index_sequence<N>, OffsetN>;
|
||||
|
||||
template <size_t StartN, size_t EndN>
|
||||
using make_index_sequence_range =
|
||||
typename offset_index_sequence<std::make_index_sequence<(EndN - StartN)>,
|
||||
StartN>::type;
|
||||
} // namespace utility
|
||||
} // namespace omnitrace
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include "libpyomnitrace.hpp"
|
||||
#include "dl.hpp"
|
||||
#include "library/coverage.hpp"
|
||||
#include "library/impl/coverage.hpp"
|
||||
#include "library/coverage/impl.hpp"
|
||||
#include "omnitrace/categories.h"
|
||||
#include "omnitrace/user.h"
|
||||
|
||||
#include <timemory/backends/process.hpp>
|
||||
@@ -179,6 +180,8 @@ using profiler_vec_t = std::vector<profiler_t>;
|
||||
using profiler_label_map_t = std::unordered_map<std::string, profiler_vec_t>;
|
||||
using profiler_index_map_t = std::unordered_map<uint32_t, profiler_label_map_t>;
|
||||
using strset_t = std::unordered_set<std::string>;
|
||||
using note_t = omnitrace_annotation_t;
|
||||
using annotations_t = std::array<note_t, 6>;
|
||||
//
|
||||
namespace
|
||||
{
|
||||
@@ -202,6 +205,7 @@ struct config
|
||||
bool include_line = false;
|
||||
bool include_filename = false;
|
||||
bool full_filepath = false;
|
||||
bool annotate_trace = false;
|
||||
int32_t ignore_stack_depth = 0;
|
||||
int32_t base_stack_depth = -1;
|
||||
int32_t verbose = 0;
|
||||
@@ -214,6 +218,12 @@ struct config
|
||||
strset_t exclude_functions = default_exclude_functions;
|
||||
strset_t exclude_filenames = default_exclude_filenames;
|
||||
std::vector<profiler_t> records = {};
|
||||
annotations_t annotations = { note_t{ "file", OMNITRACE_STRING, nullptr },
|
||||
note_t{ "line", OMNITRACE_INT32, nullptr },
|
||||
note_t{ "lasti", OMNITRACE_INT32, nullptr },
|
||||
note_t{ "argcount", OMNITRACE_INT32, nullptr },
|
||||
note_t{ "nlocals", OMNITRACE_INT32, nullptr },
|
||||
note_t{ "stacksize", OMNITRACE_INT32, nullptr } };
|
||||
};
|
||||
//
|
||||
inline config&
|
||||
@@ -233,6 +243,7 @@ get_config()
|
||||
_tmp->include_line = _instance->include_line;
|
||||
_tmp->include_filename = _instance->include_filename;
|
||||
_tmp->full_filepath = _instance->full_filepath;
|
||||
_tmp->annotate_trace = _instance->annotate_trace;
|
||||
_tmp->base_module_path = _instance->base_module_path;
|
||||
_tmp->restrict_functions = _instance->restrict_functions;
|
||||
_tmp->restrict_filenames = _instance->restrict_filenames;
|
||||
@@ -241,6 +252,7 @@ get_config()
|
||||
_tmp->exclude_functions = _instance->exclude_functions;
|
||||
_tmp->exclude_filenames = _instance->exclude_filenames;
|
||||
_tmp->verbose = _instance->verbose;
|
||||
_tmp->annotations = _instance->annotations;
|
||||
// if full filepath is specified, include filename is implied
|
||||
if(_tmp->full_filepath && !_tmp->include_filename) _tmp->include_filename = true;
|
||||
return _tmp;
|
||||
@@ -454,12 +466,29 @@ profiler_function(py::object pframe, const char* swhat, py::object arg)
|
||||
|
||||
static thread_local strset_t _labels{};
|
||||
const auto& _label_ref = *_labels.emplace(_label).first;
|
||||
auto _annotate = _config.annotate_trace;
|
||||
|
||||
// start function
|
||||
auto _profiler_call = [&]() {
|
||||
_config.records.emplace_back(
|
||||
[&_label_ref]() { omnitrace_pop_region(_label_ref.c_str()); });
|
||||
omnitrace_push_region(_label_ref.c_str());
|
||||
if(_annotate)
|
||||
{
|
||||
_config.annotations.at(0).value = const_cast<char*>(_full.c_str());
|
||||
_config.annotations.at(1).value = &frame->f_lineno;
|
||||
_config.annotations.at(2).value = &frame->f_lasti;
|
||||
_config.annotations.at(3).value = &frame->f_code->co_argcount;
|
||||
_config.annotations.at(4).value = &frame->f_code->co_nlocals;
|
||||
_config.annotations.at(5).value = &frame->f_code->co_stacksize;
|
||||
}
|
||||
|
||||
_config.records.emplace_back([&_label_ref, _annotate]() {
|
||||
omnitrace_pop_category_region(OMNITRACE_CATEGORY_PYTHON, _label_ref.c_str(),
|
||||
(_annotate) ? _config.annotations.data()
|
||||
: nullptr,
|
||||
_config.annotations.size());
|
||||
});
|
||||
omnitrace_push_category_region(OMNITRACE_CATEGORY_PYTHON, _label_ref.c_str(),
|
||||
(_annotate) ? _config.annotations.data() : nullptr,
|
||||
_config.annotations.size());
|
||||
};
|
||||
|
||||
// stop function
|
||||
@@ -554,6 +583,10 @@ generate(py::module& _pymod)
|
||||
CONFIGURATION_PROPERTY("full_filepath", bool,
|
||||
"Display the full filepath (instead of file basename)",
|
||||
get_config().full_filepath)
|
||||
CONFIGURATION_PROPERTY(
|
||||
"annotate_trace", bool,
|
||||
"Add detailed annotations to the trace about the executing function",
|
||||
get_config().annotate_trace)
|
||||
CONFIGURATION_PROPERTY("verbosity", int32_t, "Verbosity of the logging",
|
||||
get_config().verbose)
|
||||
|
||||
|
||||
@@ -220,6 +220,16 @@ def parse_args(args=None):
|
||||
default=_profiler_config.trace_c,
|
||||
help="Enable profiling C functions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--annotate-trace",
|
||||
type=str2bool,
|
||||
nargs="?",
|
||||
metavar="BOOL",
|
||||
const=True,
|
||||
default=_profiler_config.annotate_trace,
|
||||
help="Enable perfetto debug annotations",
|
||||
)
|
||||
|
||||
return parser.parse_args(args)
|
||||
|
||||
@@ -322,6 +332,7 @@ def main():
|
||||
_profiler_config.exclude_modules = opts.module_exclude
|
||||
_profiler_config.restrict_functions = opts.function_restrict
|
||||
_profiler_config.restrict_modules = opts.module_restrict
|
||||
_profiler_config.annotate_trace = opts.annotate_trace
|
||||
_profiler_config.verbosity = opts.verbosity
|
||||
|
||||
print("[omnitrace]> profiling: {}".format(argv))
|
||||
|
||||
@@ -513,8 +513,7 @@ function(OMNITRACE_ADD_PYTHON_TEST)
|
||||
|
||||
if(NOT TEST_COMMAND)
|
||||
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON"
|
||||
"OMNITRACE_OUTPUT_PATH=${PROJECT_BINARY_DIR}/omnitrace-tests-output"
|
||||
"OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/${TEST_PYTHON_VERSION}/")
|
||||
"OMNITRACE_OUTPUT_PATH=${PROJECT_BINARY_DIR}/omnitrace-tests-output")
|
||||
get_filename_component(_TEST_FILE "${TEST_FILE}" NAME)
|
||||
set(_TEST_FILE
|
||||
${PROJECT_BINARY_DIR}/python/tests/${TEST_PYTHON_VERSION}/${_TEST_FILE})
|
||||
@@ -530,6 +529,11 @@ function(OMNITRACE_ADD_PYTHON_TEST)
|
||||
COMMAND ${TEST_PYTHON_EXECUTABLE} -m omnitrace ${TEST_PROFILE_ARGS} --
|
||||
${_TEST_FILE} ${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-${TEST_PYTHON_VERSION}-annotated
|
||||
COMMAND ${TEST_PYTHON_EXECUTABLE} -m omnitrace ${TEST_PROFILE_ARGS}
|
||||
--annotate-trace -- ${_TEST_FILE} ${TEST_RUN_ARGS}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
else()
|
||||
list(APPEND TEST_LABELS "python-check" "python-${TEST_PYTHON_VERSION}-check")
|
||||
@@ -543,13 +547,20 @@ function(OMNITRACE_ADD_PYTHON_TEST)
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
foreach(_TEST ${TEST_NAME}-${TEST_PYTHON_VERSION}
|
||||
${TEST_NAME}-${TEST_PYTHON_VERSION}-inverse)
|
||||
foreach(
|
||||
_TEST
|
||||
${TEST_NAME}-${TEST_PYTHON_VERSION} ${TEST_NAME}-${TEST_PYTHON_VERSION}-inverse
|
||||
${TEST_NAME}-${TEST_PYTHON_VERSION}-annotated)
|
||||
|
||||
if(NOT TEST "${_TEST}")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
string(REPLACE "${TEST_NAME}-${TEST_PYTHON_VERSION}" "${TEST_NAME}" _TEST_DIR
|
||||
"${_TEST}")
|
||||
set(_TEST_ENV "${TEST_ENVIRONMENT}"
|
||||
"OMNITRACE_OUTPUT_PREFIX=${_TEST_DIR}/${TEST_PYTHON_VERSION}/")
|
||||
|
||||
set(_TEST_PROPERTIES "${TEST_PROPERTIES}")
|
||||
if(NOT "${_TEST}" MATCHES "inverse")
|
||||
# assign pass variable to pass regex
|
||||
@@ -568,7 +579,7 @@ function(OMNITRACE_ADD_PYTHON_TEST)
|
||||
set_tests_properties(
|
||||
${_TEST}
|
||||
PROPERTIES ENVIRONMENT
|
||||
"${TEST_ENVIRONMENT}"
|
||||
"${_TEST_ENV}"
|
||||
TIMEOUT
|
||||
${TEST_TIMEOUT}
|
||||
LABELS
|
||||
@@ -809,6 +820,10 @@ omnitrace_add_test(
|
||||
args
|
||||
RUN_ARGS 10 ${NUM_THREADS} 1000
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF"
|
||||
REWRITE_RUN_PASS_REGEX "Pushing custom region :: run.10. x 1000"
|
||||
RUNTIME_PASS_REGEX "Pushing custom region :: run.10. x 1000"
|
||||
PRELOAD_PASS_REGEX "Pushing custom region :: run.10. x 1000"
|
||||
BASELINE_FAIL_REGEX "Pushing custom region"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure")
|
||||
|
||||
if(OMNITRACE_USE_MPI OR OMNITRACE_USE_MPI_HEADERS)
|
||||
|
||||
Reference in New Issue
Block a user