restructure libomnitrace + tasking and omnitrace-causal updates (#237)
* restructured libomnitrace - this is necessary to incorporate some of the binary analysis capabilities into omnitrace exe - created libomnitrace-core (static) - created libomnitrace-binary (static) - created libomnitrace (static) - omnitrace-avail links to libomnitrace.a - omnitrace-critical-trace links to libomnitrace.a - tweaked the testing - reduced verbosity on some of MPI tests - excluded trace-time-window from tests on Ubuntu 18.04 - reduced causal e2e iterations - minor tweak to tasking - manually create `PTL::UserTaskQueue` instance instead of relying on `PTL::ThreadPool` to create it * Update formatting workflow - source formatting uses ubuntu-22.04 - check-includes doesn't generate false positive for 'include "timemory.hpp"' * omnitrace-causal --generate-configs - fix config generation in omnitrace causal - add test for omnitrace-causal + generating configs * Fix omnitrace-object-library build - accidentally included rocm sources in non-rocm builds * Fix rocm compilation w/o rocprofiler * update timemory submodule with mpi_get warning messages * sampling offload file updates - more verbose messages - disable offload before stopping * testing updates - increase causal e2e iterations to 12 - increase lock_environment verbose to 2 (for sampling offload messages) - fix return for omnitrace_add_validation_test
This commit is contained in:
committed by
GitHub
parent
8feb6bf8b6
commit
e7d3125459
@@ -0,0 +1,52 @@
|
||||
#
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/defines.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/defines.hpp @ONLY)
|
||||
|
||||
set(core_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/categories.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/constraint.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/debug.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dynamic_library.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/exception.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/gpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/locking.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mproc.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perfetto.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/state.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/timemory.cpp)
|
||||
|
||||
set(core_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/categories.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/common.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/concepts.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/config.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/constraint.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/debug.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dynamic_library.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/exception.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/gpu.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/locking.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mproc.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perfetto.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/redirect.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/state.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/timemory.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/utility.hpp)
|
||||
|
||||
add_library(omnitrace-core-library STATIC)
|
||||
add_library(omnitrace::omnitrace-core ALIAS omnitrace-core-library)
|
||||
|
||||
target_sources(omnitrace-core-library PRIVATE ${core_sources} ${core_headers}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/defines.hpp)
|
||||
add_subdirectory(binary)
|
||||
add_subdirectory(components)
|
||||
add_subdirectory(containers)
|
||||
|
||||
target_include_directories(omnitrace-core-library BEFORE
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
target_link_libraries(omnitrace-core-library
|
||||
PRIVATE omnitrace::omnitrace-interface-library)
|
||||
|
||||
set_target_properties(omnitrace-core-library PROPERTIES OUTPUT_NAME omnitrace-core)
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
set(binary_sources ${CMAKE_CURRENT_LIST_DIR}/address_range.cpp)
|
||||
|
||||
set(binary_headers ${CMAKE_CURRENT_LIST_DIR}/address_range.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/fwd.hpp)
|
||||
|
||||
target_sources(omnitrace-core-library PRIVATE ${binary_sources} ${binary_headers})
|
||||
@@ -0,0 +1,190 @@
|
||||
// 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 "binary/address_range.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace binary
|
||||
{
|
||||
address_range::address_range(uintptr_t _v)
|
||||
: low{ _v }
|
||||
, high{ _v }
|
||||
{}
|
||||
|
||||
address_range::address_range(uintptr_t _low, uintptr_t _high)
|
||||
: low{ _low }
|
||||
, high{ _high }
|
||||
{
|
||||
TIMEMORY_REQUIRE(high >= low)
|
||||
<< "Error! address_range high must be >= low. low=" << as_hex(low)
|
||||
<< ", high=" << as_hex(high) << "\n";
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::is_range() const
|
||||
{
|
||||
return (low < high);
|
||||
}
|
||||
|
||||
std::string
|
||||
address_range::as_string(int _depth) const
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
_ss << std::hex;
|
||||
_ss << std::setw(2 * _depth) << "";
|
||||
_ss.fill('0');
|
||||
_ss << "0x" << std::setw(16) << low << "-"
|
||||
<< "0x" << std::setw(16) << high;
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
address_range::size() const
|
||||
{
|
||||
return (low == high) ? 1 : (high > low) ? (high - low + 1) : (low - high + 1);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::is_valid() const
|
||||
{
|
||||
return (low <= high && (low + 1) > 1);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::contains(uintptr_t _v) const
|
||||
{
|
||||
return (is_range()) ? (low <= _v && high > _v) : (_v == low);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::contains(address_range _v) const
|
||||
{
|
||||
return (*this == _v) || (contains(_v.low) && contains(_v.high));
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::overlaps(address_range _v) const
|
||||
{
|
||||
if(contains(_v)) return false;
|
||||
int64_t _lhs_diff = (high - low);
|
||||
int64_t _rhs_diff = (_v.high - _v.low);
|
||||
int64_t _diff = (std::max(high, _v.high) - std::min(low, _v.low));
|
||||
return (_diff < (_lhs_diff + _rhs_diff));
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::contiguous_with(address_range _v) const
|
||||
{
|
||||
return (_v.low == high || low == _v.high);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::operator==(address_range _v) const
|
||||
{
|
||||
// if arg is range and this is not range, call this function with arg
|
||||
// if(_v.is_range() && !is_range()) return false;
|
||||
// check if arg is in range
|
||||
// if(is_range() && !_v.is_range()) return false;
|
||||
// both are ranges or both are just address
|
||||
return std::tie(low, high) == std::tie(_v.low, _v.high);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::operator<(address_range _v) const
|
||||
{
|
||||
if(is_range() && !_v.is_range())
|
||||
{
|
||||
return (low == _v.low) ? true : (low < _v.low);
|
||||
}
|
||||
else if(!is_range() && _v.is_range())
|
||||
{
|
||||
return (low == _v.low) ? false : (low < _v.low);
|
||||
}
|
||||
else if(!is_range() && !_v.is_range())
|
||||
{
|
||||
return (low < _v.low);
|
||||
}
|
||||
return std::tie(low, high) < std::tie(_v.low, _v.high);
|
||||
// if(_v.low == _v.high && _v.low >= low && _v.low < high) return false;
|
||||
// return (low == _v.low) ? (high > _v.high) : (low < _v.low);
|
||||
}
|
||||
|
||||
bool
|
||||
address_range::operator>(address_range _v) const
|
||||
{
|
||||
return !(*this < _v) && !(*this == _v);
|
||||
}
|
||||
|
||||
address_range&
|
||||
address_range::operator+=(uintptr_t _v)
|
||||
{
|
||||
if(is_valid())
|
||||
{
|
||||
low += _v;
|
||||
high += _v;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = _v;
|
||||
high = _v;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
address_range&
|
||||
address_range::operator-=(uintptr_t _v)
|
||||
{
|
||||
if(is_valid())
|
||||
{
|
||||
low -= _v;
|
||||
high -= _v;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = _v;
|
||||
high = _v;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
address_range&
|
||||
address_range::operator+=(address_range _v)
|
||||
{
|
||||
if(!contiguous_with(_v))
|
||||
throw exception<std::runtime_error>(
|
||||
"attempting to add two address ranges that are not contiguous");
|
||||
|
||||
low = std::min(low, _v.low);
|
||||
high = std::max(high, _v.high);
|
||||
return *this;
|
||||
}
|
||||
|
||||
hash_value_t
|
||||
address_range::hash() const
|
||||
{
|
||||
return (is_range()) ? tim::get_combined_hash_id(hash_value_t{ low }, high)
|
||||
: hash_value_t{ low };
|
||||
}
|
||||
} // namespace binary
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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 "core/binary/fwd.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
|
||||
#include <timemory/hash/types.hpp>
|
||||
#include <timemory/utility/macros.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace binary
|
||||
{
|
||||
struct address_range
|
||||
{
|
||||
// set to low to max and high to min to support std::min(...)
|
||||
// and std::max(...) assignment
|
||||
uintptr_t low = std::numeric_limits<uintptr_t>::max();
|
||||
uintptr_t high = std::numeric_limits<uintptr_t>::min();
|
||||
|
||||
OMNITRACE_DEFAULT_OBJECT(address_range)
|
||||
|
||||
explicit address_range(uintptr_t _v);
|
||||
address_range(uintptr_t _low, uintptr_t _high);
|
||||
|
||||
bool contains(uintptr_t) const;
|
||||
bool contains(address_range) const;
|
||||
bool overlaps(address_range) const;
|
||||
bool contiguous_with(address_range) const;
|
||||
|
||||
bool operator==(address_range _v) const;
|
||||
bool operator!=(address_range _v) const { return !(*this == _v); }
|
||||
bool operator<(address_range _v) const;
|
||||
bool operator>(address_range _v) const;
|
||||
|
||||
address_range& operator+=(uintptr_t);
|
||||
address_range& operator-=(uintptr_t);
|
||||
address_range& operator+=(address_range);
|
||||
|
||||
bool is_range() const;
|
||||
hash_value_t hash() const;
|
||||
std::string as_string(int _depth = 0) const;
|
||||
bool is_valid() const;
|
||||
uintptr_t size() const;
|
||||
explicit operator bool() const { return is_valid(); }
|
||||
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& ar, const unsigned)
|
||||
{
|
||||
ar(cereal::make_nvp("low", low));
|
||||
ar(cereal::make_nvp("high", high));
|
||||
}
|
||||
};
|
||||
} // namespace binary
|
||||
|
||||
inline binary::address_range
|
||||
operator+(binary::address_range _lhs, uintptr_t _v)
|
||||
{
|
||||
return (_lhs += _v);
|
||||
}
|
||||
|
||||
inline binary::address_range
|
||||
operator+(uintptr_t _v, binary::address_range _lhs)
|
||||
{
|
||||
return (_lhs += _v);
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<::omnitrace::binary::address_range>
|
||||
{
|
||||
using address_range_t = ::omnitrace::binary::address_range;
|
||||
|
||||
auto operator()(const address_range_t& _v) const { return _v.hash(); }
|
||||
auto operator()(address_range_t&& _v) const { return _v.hash(); }
|
||||
};
|
||||
} // namespace std
|
||||
@@ -0,0 +1,62 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "core/common.hpp"
|
||||
#include "core/defines.hpp"
|
||||
#include "core/exception.hpp"
|
||||
|
||||
#include <timemory/hash/types.hpp>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/tpls/cereal/cereal/cereal.hpp>
|
||||
#include <timemory/unwind/bfd.hpp>
|
||||
#include <timemory/unwind/types.hpp>
|
||||
#include <timemory/utility/procfs/maps.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace binary
|
||||
{
|
||||
namespace procfs = ::tim::procfs; // NOLINT
|
||||
|
||||
using bfd_file = ::tim::unwind::bfd_file;
|
||||
using hash_value_t = ::tim::hash_value_t;
|
||||
|
||||
struct address_range;
|
||||
struct address_multirange;
|
||||
struct scope_filter;
|
||||
struct symbol;
|
||||
struct dwarf_entry;
|
||||
struct binary_info;
|
||||
} // namespace binary
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,141 @@
|
||||
// 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 "core/categories.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/constraint.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
#include "core/utility.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace categories
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename Tp>
|
||||
void
|
||||
configure_categories(bool _enable, const std::set<std::string>& _categories)
|
||||
{
|
||||
auto _name = trait::name<Tp>::value;
|
||||
if(_categories.count(_name) > 0)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(3, "%s category: %s\n", (_enable) ? "Enabling" : "Disabling",
|
||||
_name);
|
||||
trait::runtime_enabled<Tp>::set(_enable);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t... Idx>
|
||||
void
|
||||
configure_categories(bool _enable, const std::set<std::string>& _categories,
|
||||
std::index_sequence<Idx...>)
|
||||
{
|
||||
(configure_categories<category_type_id_t<Idx>>(_enable, _categories), ...);
|
||||
}
|
||||
|
||||
void
|
||||
configure_categories(bool _enable, const std::set<std::string>& _categories)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "%s categories...\n", (_enable) ? "Enabling" : "Disabling");
|
||||
|
||||
configure_categories(
|
||||
_enable, _categories,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void
|
||||
enable_categories(const std::set<std::string>& _categories)
|
||||
{
|
||||
configure_categories(
|
||||
true, _categories,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
void
|
||||
disable_categories(const std::set<std::string>& _categories)
|
||||
{
|
||||
configure_categories(
|
||||
false, _categories,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
// disable specified categories
|
||||
disable_categories();
|
||||
|
||||
auto _trace_specs = constraint::get_trace_specs();
|
||||
|
||||
if(!_trace_specs.empty())
|
||||
{
|
||||
auto _trace_stages = constraint::get_trace_stages();
|
||||
|
||||
_trace_stages.init = [](const constraint::spec& _spec) {
|
||||
if(_spec.delay > 1.0e-3) disable_categories(config::get_enabled_categories());
|
||||
return get_state() < State::Finalized;
|
||||
};
|
||||
|
||||
_trace_stages.start = [](const constraint::spec&) {
|
||||
enable_categories(config::get_enabled_categories());
|
||||
return get_state() < State::Finalized;
|
||||
};
|
||||
|
||||
_trace_stages.stop = [](const constraint::spec&) {
|
||||
// only disable categories if not finalized since this might run in background
|
||||
// during finalization and disable output of data in those categories
|
||||
if(get_state() < State::Finalized)
|
||||
disable_categories(config::get_enabled_categories());
|
||||
return get_state() < State::Finalized;
|
||||
};
|
||||
|
||||
auto _promise = std::promise<void>();
|
||||
std::thread{ [_trace_specs, _trace_stages](std::promise<void>* _prom) {
|
||||
// ensure all categories are disabled before proceeding
|
||||
// if a delay is requested
|
||||
if(_trace_specs.front().delay > 1.0e-3)
|
||||
disable_categories(config::get_enabled_categories());
|
||||
_prom->set_value();
|
||||
for(const auto& itr : _trace_specs)
|
||||
itr(_trace_stages);
|
||||
},
|
||||
&_promise }
|
||||
.detach();
|
||||
|
||||
_promise.get_future().wait_for(std::chrono::seconds{ 1 });
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shutdown()
|
||||
{
|
||||
disable_categories(config::get_enabled_categories());
|
||||
}
|
||||
} // namespace categories
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,229 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/join.hpp"
|
||||
#include "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"
|
||||
#endif
|
||||
|
||||
#include <timemory/api.hpp>
|
||||
#include <timemory/api/macros.hpp>
|
||||
#include <timemory/mpl/macros.hpp>
|
||||
#include <timemory/mpl/types.hpp>
|
||||
|
||||
#define OMNITRACE_DEFINE_NAME_TRAIT(NAME, DESC, ...) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace trait \
|
||||
{ \
|
||||
template <> \
|
||||
struct perfetto_category<__VA_ARGS__> \
|
||||
{ \
|
||||
static constexpr auto value = NAME; \
|
||||
static constexpr auto description = 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) \
|
||||
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_CATEGORY_TRAIT(::tim::NS::VALUE, ENUM)
|
||||
|
||||
// clang-format off
|
||||
// these are defined by omnitrace
|
||||
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_wall_time, OMNITRACE_CATEGORY_THREAD_WALL_TIME, "thread_wall_time", "Wall-clock time on thread (derived from sampling)")
|
||||
OMNITRACE_DEFINE_CATEGORY(category, thread_cpu_time, OMNITRACE_CATEGORY_THREAD_CPU_TIME, "thread_cpu_time", "CPU time on thread (derived from sampling)")
|
||||
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, OMNITRACE_CATEGORY_SAMPLING, "sampling", "Host-side call-stack sampling")
|
||||
// clang-format on
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace trait
|
||||
{
|
||||
template <typename... Tp>
|
||||
using name = perfetto_category<Tp...>;
|
||||
}
|
||||
} // namespace tim
|
||||
|
||||
#define OMNITRACE_PERFETTO_CATEGORY(TYPE) \
|
||||
::perfetto::Category(::tim::trait::perfetto_category<::tim::TYPE>::value) \
|
||||
.SetDescription(::tim::trait::perfetto_category<::tim::TYPE>::description)
|
||||
|
||||
#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), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_hip), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_hsa), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_roctx), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_smi), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_smi_busy), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_smi_temp), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_smi_power), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_smi_memory_usage), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocm_rccl), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::roctracer), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::rocprofiler), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::pthread), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::kokkos), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::mpi), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::ompt), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::sampling), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_sampling), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::comm_data), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::critical_trace), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::host_critical_trace), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::device_critical_trace), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::causal), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::cpu_freq), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_page), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_virt), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_peak), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_context_switch), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_page_fault), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_user_mode_time), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::process_kernel_mode_time), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_wall_time), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_cpu_time), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_page_fault), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_peak_memory), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_context_switch), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::thread_hardware_counter), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::kernel_hardware_counter), \
|
||||
OMNITRACE_PERFETTO_CATEGORY(category::numa), \
|
||||
::perfetto::Category("timemory").SetDescription("Events from the timemory API")
|
||||
|
||||
#if defined(TIMEMORY_USE_PERFETTO)
|
||||
# define TIMEMORY_PERFETTO_CATEGORIES OMNITRACE_PERFETTO_CATEGORIES
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace config
|
||||
{
|
||||
std::set<std::string>
|
||||
get_enabled_categories();
|
||||
|
||||
std::set<std::string>
|
||||
get_disabled_categories();
|
||||
} // namespace config
|
||||
|
||||
namespace categories
|
||||
{
|
||||
void
|
||||
enable_categories(const std::set<std::string>& = config::get_enabled_categories());
|
||||
|
||||
void
|
||||
disable_categories(const std::set<std::string>& = config::get_disabled_categories());
|
||||
|
||||
void
|
||||
setup();
|
||||
|
||||
void
|
||||
shutdown();
|
||||
} // namespace categories
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,134 @@
|
||||
// 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 "categories.hpp"
|
||||
#include "common/join.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <timemory/api.hpp>
|
||||
#include <timemory/api/macros.hpp>
|
||||
#include <timemory/backends/process.hpp>
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/environment/types.hpp>
|
||||
#include <timemory/mpl/types.hpp>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
#include <timemory/utility/locking.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define OMNITRACE_DECLARE_COMPONENT(NAME) \
|
||||
namespace omnitrace \
|
||||
{ \
|
||||
namespace component \
|
||||
{ \
|
||||
struct NAME; \
|
||||
} \
|
||||
} \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace trait \
|
||||
{ \
|
||||
template <> \
|
||||
struct is_component<omnitrace::component::NAME> : true_type \
|
||||
{}; \
|
||||
} \
|
||||
} \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace component \
|
||||
{ \
|
||||
using ::omnitrace::component::NAME; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OMNITRACE_COMPONENT_ALIAS(NAME, ...) \
|
||||
namespace omnitrace \
|
||||
{ \
|
||||
namespace component \
|
||||
{ \
|
||||
using NAME = __VA_ARGS__; \
|
||||
} \
|
||||
} \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace component \
|
||||
{ \
|
||||
using ::omnitrace::component::NAME; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OMNITRACE_DEFINE_CONCRETE_TRAIT(TRAIT, TYPE, VALUE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace trait \
|
||||
{ \
|
||||
template <> \
|
||||
struct TRAIT<::omnitrace::TYPE> : VALUE \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace api = ::tim::api; // NOLINT
|
||||
namespace category = ::tim::category; // NOLINT
|
||||
namespace filepath = ::tim::filepath; // NOLINT
|
||||
namespace project = ::tim::project; // NOLINT
|
||||
namespace process = ::tim::process; // NOLINT
|
||||
namespace threading = ::tim::threading; // NOLINT
|
||||
namespace scope = ::tim::scope; // NOLINT
|
||||
namespace policy = ::tim::policy; // NOLINT
|
||||
namespace trait = ::tim::trait; // NOLINT
|
||||
namespace cereal = ::tim::cereal; // NOLINT
|
||||
|
||||
using ::tim::auto_lock_t; // NOLINT
|
||||
using ::tim::demangle; // NOLINT
|
||||
using ::tim::get_env; // NOLINT
|
||||
using ::tim::set_env; // NOLINT
|
||||
using ::tim::try_demangle; // NOLINT
|
||||
using ::tim::type_mutex; // NOLINT
|
||||
|
||||
struct construct_on_thread
|
||||
{
|
||||
int64_t index = threading::get_id();
|
||||
};
|
||||
} // namespace omnitrace
|
||||
|
||||
// same sort of functionality as python's " ".join([...])
|
||||
#if !defined(JOIN)
|
||||
# define JOIN(...) ::omnitrace::common::join(__VA_ARGS__)
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
set(component_sources)
|
||||
|
||||
set(component_headers ${CMAKE_CURRENT_LIST_DIR}/fwd.hpp)
|
||||
|
||||
target_sources(omnitrace-core-library PRIVATE ${component_sources} ${component_headers})
|
||||
@@ -0,0 +1,270 @@
|
||||
// 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 "core/categories.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/defines.hpp"
|
||||
|
||||
#include <timemory/api.hpp>
|
||||
#include <timemory/api/macros.hpp>
|
||||
#include <timemory/components/base/types.hpp>
|
||||
#include <timemory/components/data_tracker/types.hpp>
|
||||
#include <timemory/components/macros.hpp>
|
||||
#include <timemory/components/user_bundle/types.hpp>
|
||||
#include <timemory/enum.h>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/mpl/type_traits.hpp>
|
||||
#include <timemory/mpl/types.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
OMNITRACE_DECLARE_COMPONENT(roctracer)
|
||||
OMNITRACE_DECLARE_COMPONENT(rocprofiler)
|
||||
OMNITRACE_DECLARE_COMPONENT(rcclp_handle)
|
||||
OMNITRACE_DECLARE_COMPONENT(comm_data)
|
||||
|
||||
OMNITRACE_COMPONENT_ALIAS(comm_data_tracker_t,
|
||||
::tim::component::data_tracker<float, project::omnitrace>)
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace policy = ::tim::policy; // NOLINT
|
||||
namespace comp = ::tim::component; // NOLINT
|
||||
|
||||
namespace component
|
||||
{
|
||||
template <typename Tp, typename ValueT>
|
||||
using base = ::tim::component::base<Tp, ValueT>;
|
||||
|
||||
template <typename... Tp>
|
||||
using data_tracker = tim::component::data_tracker<Tp...>;
|
||||
|
||||
template <typename... Tp>
|
||||
using functor_t = std::function<void(Tp...)>;
|
||||
|
||||
using default_functor_t = functor_t<const char*>;
|
||||
|
||||
struct backtrace;
|
||||
struct backtrace_metrics;
|
||||
struct backtrace_timestamp;
|
||||
struct backtrace_wall_clock
|
||||
{};
|
||||
struct backtrace_cpu_clock
|
||||
{};
|
||||
struct backtrace_fraction
|
||||
{};
|
||||
struct backtrace_gpu_busy
|
||||
{};
|
||||
struct backtrace_gpu_temp
|
||||
{};
|
||||
struct backtrace_gpu_power
|
||||
{};
|
||||
struct backtrace_gpu_memory
|
||||
{};
|
||||
using sampling_wall_clock = data_tracker<double, backtrace_wall_clock>;
|
||||
using sampling_cpu_clock = data_tracker<double, backtrace_cpu_clock>;
|
||||
using sampling_percent = data_tracker<double, backtrace_fraction>;
|
||||
using sampling_gpu_busy = data_tracker<double, backtrace_gpu_busy>;
|
||||
using sampling_gpu_temp = data_tracker<double, backtrace_gpu_temp>;
|
||||
using sampling_gpu_power = data_tracker<double, backtrace_gpu_power>;
|
||||
using sampling_gpu_memory = data_tracker<double, backtrace_gpu_memory>;
|
||||
|
||||
template <typename ApiT, typename StartFuncT = default_functor_t,
|
||||
typename StopFuncT = default_functor_t>
|
||||
struct functors;
|
||||
} // namespace component
|
||||
} // namespace omnitrace
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCTRACER)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::roctracer, false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCPROFILER)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::rocprofiler, false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_USE_RCCL)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, category::rocm_rccl, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::rcclp_handle, false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_USE_RCCL) && !defined(OMNITRACE_USE_MPI)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::comm_data_tracker_t, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::comm_data, false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_USE_LIBUNWIND)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, category::sampling, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::backtrace, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::backtrace_metrics, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::backtrace_timestamp, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_wall_clock, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_cpu_clock, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_percent, false_type)
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_USE_LIBUNWIND) || !defined(OMNITRACE_USE_ROCM_SMI)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_gpu_busy, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_gpu_temp, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_gpu_power, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_available, component::sampling_gpu_memory, false_type)
|
||||
#endif
|
||||
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::roctracer, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux,
|
||||
category::external)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::rocprofiler, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux,
|
||||
category::external, category::hardware_counter)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_wall_clock, project::omnitrace,
|
||||
category::timing, os::supports_unix, category::sampling,
|
||||
category::interrupt_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_cpu_clock, project::omnitrace,
|
||||
category::timing, os::supports_unix, category::sampling,
|
||||
category::interrupt_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_percent, project::omnitrace,
|
||||
category::timing, os::supports_unix, category::sampling,
|
||||
category::interrupt_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_busy, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux,
|
||||
category::sampling, category::process_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_memory, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux, category::memory,
|
||||
category::sampling, category::process_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_power, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux, category::power,
|
||||
category::sampling, category::process_sampling)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_temp, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux,
|
||||
category::temperature, category::sampling,
|
||||
category::process_sampling)
|
||||
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
|
||||
"roctracer", "omnitrace_roctracer")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::rocprofiler, OMNITRACE_ROCPROFILER,
|
||||
"rocprofiler", "omnitrace_rocprofiler")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
|
||||
OMNITRACE_SAMPLING_WALL_CLOCK, "sampling_wall_clock", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_cpu_clock,
|
||||
OMNITRACE_SAMPLING_CPU_CLOCK, "sampling_cpu_clock", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_percent,
|
||||
OMNITRACE_SAMPLING_PERCENT, "sampling_percent", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_busy,
|
||||
OMNITRACE_SAMPLING_GPU_BUSY, "sampling_gpu_busy",
|
||||
"sampling_gpu_util")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_memory,
|
||||
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE,
|
||||
"sampling_gpu_memory_usage", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
|
||||
OMNITRACE_SAMPLING_GPU_POWER, "sampling_gpu_power", "")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
|
||||
OMNITRACE_SAMPLING_GPU_TEMP, "sampling_gpu_temp", "")
|
||||
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
|
||||
"High-precision ROCm API and kernel tracing", "")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::rocprofiler, "rocprofiler",
|
||||
"ROCm kernel hardware counters", "")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
|
||||
"sampling_wall_clock", "Wall-clock timing",
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_cpu_clock,
|
||||
"sampling_cpu_clock", "CPU-clock timing",
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_percent,
|
||||
"sampling_percent",
|
||||
"Fraction of wall-clock time spent in functions",
|
||||
"Derived from statistical sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_busy,
|
||||
"sampling_gpu_busy",
|
||||
"GPU Utilization (% busy) via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_memory,
|
||||
"sampling_gpu_memory_usage",
|
||||
"GPU Memory Usage via ROCm-SMI", "Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
|
||||
"sampling_gpu_power", "GPU Power Usage via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
|
||||
"sampling_gpu_temp", "GPU Temperature via ROCm-SMI",
|
||||
"Derived from sampling")
|
||||
|
||||
// statistics type
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_wall_clock, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_cpu_clock, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_busy, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_temp, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_power, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::sampling_gpu_memory, double)
|
||||
TIMEMORY_STATISTICS_TYPE(omnitrace::component::comm_data_tracker_t, float)
|
||||
|
||||
// enable timing units
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_timing_category, component::sampling_wall_clock,
|
||||
true_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_timing_category, component::sampling_cpu_clock,
|
||||
true_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_timing_category, component::sampling_percent,
|
||||
true_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(uses_timing_units, component::sampling_wall_clock,
|
||||
true_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(uses_timing_units, component::sampling_cpu_clock,
|
||||
true_type)
|
||||
|
||||
// enable percent units
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(uses_percent_units, component::sampling_gpu_busy,
|
||||
true_type)
|
||||
|
||||
// enable memory units
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(is_memory_category, component::sampling_gpu_memory,
|
||||
true_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(uses_memory_units, component::sampling_gpu_memory,
|
||||
true_type)
|
||||
|
||||
// reporting categories (sum)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_sum, component::sampling_gpu_busy, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_sum, component::sampling_gpu_temp, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_sum, component::sampling_gpu_power, false_type)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_sum, component::sampling_gpu_memory, false_type)
|
||||
|
||||
// reporting categories (mean)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_mean, component::sampling_percent, false_type)
|
||||
|
||||
// reporting categories (stats)
|
||||
OMNITRACE_DEFINE_CONCRETE_TRAIT(report_statistics, component::sampling_percent,
|
||||
false_type)
|
||||
|
||||
#define OMNITRACE_DECLARE_EXTERN_COMPONENT(NAME, HAS_DATA, ...) \
|
||||
TIMEMORY_DECLARE_EXTERN_TEMPLATE( \
|
||||
struct tim::component::base<TIMEMORY_ESC(omnitrace::component::NAME), \
|
||||
__VA_ARGS__>) \
|
||||
TIMEMORY_DECLARE_EXTERN_OPERATIONS(TIMEMORY_ESC(omnitrace::component::NAME), \
|
||||
HAS_DATA) \
|
||||
TIMEMORY_DECLARE_EXTERN_STORAGE(TIMEMORY_ESC(omnitrace::component::NAME))
|
||||
|
||||
#define OMNITRACE_INSTANTIATE_EXTERN_COMPONENT(NAME, HAS_DATA, ...) \
|
||||
TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE( \
|
||||
struct tim::component::base<TIMEMORY_ESC(omnitrace::component::NAME), \
|
||||
__VA_ARGS__>) \
|
||||
TIMEMORY_INSTANTIATE_EXTERN_OPERATIONS(TIMEMORY_ESC(omnitrace::component::NAME), \
|
||||
HAS_DATA) \
|
||||
TIMEMORY_INSTANTIATE_EXTERN_STORAGE(TIMEMORY_ESC(omnitrace::component::NAME))
|
||||
@@ -0,0 +1,126 @@
|
||||
// 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 "defines.hpp"
|
||||
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/utility/types.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace concepts = ::tim::concepts; // NOLINT
|
||||
|
||||
static constexpr size_t max_supported_threads = OMNITRACE_MAX_THREADS;
|
||||
|
||||
template <typename Tp>
|
||||
struct thread_deleter;
|
||||
|
||||
// unique ptr type for omnitrace
|
||||
template <typename Tp>
|
||||
using unique_ptr_t = std::unique_ptr<Tp, thread_deleter<Tp>>;
|
||||
|
||||
using construct_on_init = std::true_type;
|
||||
|
||||
using tim::identity; // NOLINT
|
||||
using tim::identity_t; // NOLINT
|
||||
|
||||
template <typename Tp>
|
||||
struct use_placement_new_when_generating_unique_ptr : std::false_type
|
||||
{};
|
||||
} // namespace omnitrace
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace concepts
|
||||
{
|
||||
template <typename Tp>
|
||||
struct is_unique_pointer : std::false_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct is_unique_pointer<::omnitrace::unique_ptr_t<Tp>> : std::true_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct is_unique_pointer<std::unique_ptr<Tp>> : std::true_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct is_optional : std::false_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct is_optional<std::optional<Tp>> : std::true_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct can_stringify
|
||||
{
|
||||
private:
|
||||
static constexpr auto sfinae(int)
|
||||
-> decltype(std::declval<std::ostream&>() << std::declval<Tp>(), bool())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr auto sfinae(long) { return false; }
|
||||
|
||||
public:
|
||||
static constexpr bool value = sfinae(0);
|
||||
constexpr auto operator()() const { return sfinae(0); }
|
||||
};
|
||||
|
||||
template <size_t N, typename Tp, bool>
|
||||
struct tuple_element_impl;
|
||||
|
||||
template <size_t N, typename... Tp>
|
||||
struct tuple_element_impl<N, std::tuple<Tp...>, true>
|
||||
{
|
||||
using type = typename std::tuple_element<N, std::tuple<Tp...>>::type;
|
||||
};
|
||||
|
||||
template <size_t N, typename... Tp>
|
||||
struct tuple_element_impl<N, std::tuple<Tp...>, false>
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <size_t N, typename Tp>
|
||||
struct tuple_element;
|
||||
|
||||
template <size_t N, typename... Tp>
|
||||
struct tuple_element<N, std::tuple<Tp...>>
|
||||
{
|
||||
using type =
|
||||
typename tuple_element_impl<N, std::tuple<Tp...>, (N < sizeof...(Tp))>::type;
|
||||
};
|
||||
|
||||
template <size_t N, typename Tp>
|
||||
using tuple_element_t = typename tuple_element<N, Tp>::type;
|
||||
} // namespace concepts
|
||||
} // namespace tim
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,433 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "state.hpp"
|
||||
#include "timemory.hpp"
|
||||
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/macros/language.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
//
|
||||
// Initialization routines
|
||||
//
|
||||
inline namespace config
|
||||
{
|
||||
using signal_handler_t = void (*)(void);
|
||||
|
||||
// if arg is nullptr, returns current signal handler
|
||||
// if arg is non-null, returns replaced signal handler
|
||||
signal_handler_t set_signal_handler(signal_handler_t);
|
||||
|
||||
bool
|
||||
settings_are_configured() OMNITRACE_HOT;
|
||||
|
||||
void
|
||||
configure_settings(bool _init = true);
|
||||
|
||||
void
|
||||
configure_mode_settings();
|
||||
|
||||
void
|
||||
configure_signal_handler();
|
||||
|
||||
int
|
||||
get_realtime_signal();
|
||||
|
||||
int
|
||||
get_cputime_signal();
|
||||
|
||||
std::set<int>
|
||||
get_sampling_signals(int64_t _tid = 0);
|
||||
|
||||
void
|
||||
configure_disabled_settings();
|
||||
|
||||
void
|
||||
finalize();
|
||||
|
||||
void
|
||||
handle_deprecated_setting(const std::string& _old, const std::string& _new,
|
||||
int _verbose = 0);
|
||||
|
||||
void
|
||||
print_banner(std::ostream& _os = std::cerr);
|
||||
|
||||
void
|
||||
print_settings(
|
||||
std::ostream& _os,
|
||||
std::function<bool(const std::string_view&, const std::set<std::string>&)>&& _filter);
|
||||
|
||||
void
|
||||
print_settings(bool include_env = true);
|
||||
|
||||
std::string&
|
||||
get_exe_name();
|
||||
|
||||
std::string&
|
||||
get_exe_realpath();
|
||||
|
||||
template <typename Tp>
|
||||
bool
|
||||
set_setting_value(const std::string& _name, Tp&& _v)
|
||||
{
|
||||
auto _instance = tim::settings::shared_instance();
|
||||
auto _setting = _instance->find(_name);
|
||||
if(_setting == _instance->end()) return false;
|
||||
if(!_setting->second) return false;
|
||||
return _setting->second->set(std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
bool
|
||||
set_default_setting_value(const std::string& _name, Tp&& _v)
|
||||
{
|
||||
auto _instance = tim::settings::shared_instance();
|
||||
auto _setting = _instance->find(_name);
|
||||
if(_setting == _instance->end()) return false;
|
||||
if(!_setting->second) return false;
|
||||
if(_setting->second->get_config_updated() || _setting->second->get_environ_updated())
|
||||
return false;
|
||||
return _setting->second->set(std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
std::pair<bool, Tp>
|
||||
get_setting_value(const std::string& _name)
|
||||
{
|
||||
auto _instance = tim::settings::shared_instance();
|
||||
if(!_instance) return std::make_pair(false, Tp{});
|
||||
auto _setting = _instance->find(_name);
|
||||
if(_setting == _instance->end() || !_setting->second)
|
||||
return std::make_pair(false, Tp{});
|
||||
return _setting->second->get<Tp>();
|
||||
}
|
||||
|
||||
//
|
||||
// User-configurable settings
|
||||
//
|
||||
std::string
|
||||
get_config_file();
|
||||
|
||||
Mode
|
||||
get_mode();
|
||||
|
||||
bool&
|
||||
is_attached();
|
||||
|
||||
bool&
|
||||
is_binary_rewrite();
|
||||
|
||||
bool
|
||||
get_is_continuous_integration() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_env() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_init();
|
||||
|
||||
bool
|
||||
get_debug_finalize();
|
||||
|
||||
bool
|
||||
get_debug() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_sampling() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_tid() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_pid() OMNITRACE_HOT;
|
||||
|
||||
int
|
||||
get_verbose_env() OMNITRACE_HOT;
|
||||
|
||||
int
|
||||
get_verbose() OMNITRACE_HOT;
|
||||
|
||||
bool&
|
||||
get_use_perfetto() OMNITRACE_HOT;
|
||||
|
||||
bool&
|
||||
get_use_timemory() OMNITRACE_HOT;
|
||||
|
||||
bool&
|
||||
get_use_causal() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_use_roctracer() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_use_rocprofiler() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_use_rocm_smi() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_use_roctx();
|
||||
|
||||
bool&
|
||||
get_use_sampling() OMNITRACE_HOT;
|
||||
|
||||
bool&
|
||||
get_use_process_sampling() OMNITRACE_HOT;
|
||||
|
||||
bool&
|
||||
get_use_pid();
|
||||
|
||||
bool&
|
||||
get_use_mpip();
|
||||
|
||||
bool&
|
||||
get_use_critical_trace() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_use_kokkosp();
|
||||
|
||||
bool
|
||||
get_use_kokkosp_kernel_logger();
|
||||
|
||||
bool
|
||||
get_use_ompt();
|
||||
|
||||
bool
|
||||
get_use_code_coverage();
|
||||
|
||||
bool
|
||||
get_sampling_keep_internal();
|
||||
|
||||
bool
|
||||
get_use_sampling_realtime();
|
||||
|
||||
bool
|
||||
get_use_sampling_cputime();
|
||||
|
||||
int
|
||||
get_sampling_rtoffset();
|
||||
|
||||
bool
|
||||
get_use_rcclp();
|
||||
|
||||
bool
|
||||
get_trace_hip_api();
|
||||
|
||||
bool
|
||||
get_trace_hip_activity();
|
||||
|
||||
bool
|
||||
get_trace_hsa_api();
|
||||
|
||||
bool
|
||||
get_trace_hsa_activity();
|
||||
|
||||
bool
|
||||
get_critical_trace_debug();
|
||||
|
||||
bool
|
||||
get_critical_trace_serialize_names();
|
||||
|
||||
size_t
|
||||
get_perfetto_shmem_size_hint();
|
||||
|
||||
size_t
|
||||
get_perfetto_buffer_size();
|
||||
|
||||
bool
|
||||
get_perfetto_combined_traces();
|
||||
|
||||
std::string
|
||||
get_perfetto_fill_policy();
|
||||
|
||||
std::set<std::string>
|
||||
get_enabled_categories();
|
||||
|
||||
std::set<std::string>
|
||||
get_disabled_categories();
|
||||
|
||||
bool
|
||||
get_perfetto_annotations() OMNITRACE_HOT;
|
||||
|
||||
uint64_t
|
||||
get_critical_trace_update_freq();
|
||||
|
||||
uint64_t
|
||||
get_thread_pool_size();
|
||||
|
||||
std::string
|
||||
get_trace_hsa_api_types();
|
||||
|
||||
std::string&
|
||||
get_backend();
|
||||
|
||||
// make this visible so omnitrace-avail can call it
|
||||
std::string
|
||||
get_perfetto_output_filename();
|
||||
|
||||
bool
|
||||
get_perfetto_roctracer_per_stream() OMNITRACE_HOT;
|
||||
|
||||
int64_t
|
||||
get_critical_trace_count();
|
||||
|
||||
double
|
||||
get_trace_delay();
|
||||
|
||||
double
|
||||
get_trace_duration();
|
||||
|
||||
double
|
||||
get_sampling_freq();
|
||||
|
||||
double
|
||||
get_sampling_cpu_freq();
|
||||
|
||||
double
|
||||
get_sampling_real_freq();
|
||||
|
||||
double
|
||||
get_sampling_delay();
|
||||
|
||||
double
|
||||
get_sampling_cpu_delay();
|
||||
|
||||
double
|
||||
get_sampling_real_delay();
|
||||
|
||||
double
|
||||
get_sampling_duration();
|
||||
|
||||
std::string
|
||||
get_sampling_cpus();
|
||||
|
||||
std::set<int64_t>
|
||||
get_sampling_cpu_tids();
|
||||
|
||||
std::set<int64_t>
|
||||
get_sampling_real_tids();
|
||||
|
||||
bool
|
||||
get_sampling_include_inlines();
|
||||
|
||||
size_t
|
||||
get_num_threads_hint();
|
||||
|
||||
size_t
|
||||
get_sampling_allocator_size();
|
||||
|
||||
double
|
||||
get_process_sampling_freq();
|
||||
|
||||
double
|
||||
get_process_sampling_duration();
|
||||
|
||||
std::string
|
||||
get_sampling_gpus();
|
||||
|
||||
int64_t
|
||||
get_critical_trace_per_row();
|
||||
|
||||
bool
|
||||
get_trace_thread_locks();
|
||||
|
||||
bool
|
||||
get_trace_thread_rwlocks();
|
||||
|
||||
bool
|
||||
get_trace_thread_spin_locks();
|
||||
|
||||
bool
|
||||
get_trace_thread_barriers();
|
||||
|
||||
bool
|
||||
get_trace_thread_join();
|
||||
|
||||
std::string
|
||||
get_rocm_events();
|
||||
|
||||
bool
|
||||
get_use_tmp_files();
|
||||
|
||||
std::string
|
||||
get_tmpdir();
|
||||
|
||||
struct tmp_file
|
||||
{
|
||||
tmp_file(std::string);
|
||||
~tmp_file();
|
||||
|
||||
void open(std::ios::openmode = std::ios::binary | std::ios::in | std::ios::out);
|
||||
void close();
|
||||
void remove();
|
||||
|
||||
explicit operator bool() const { return stream.is_open() && stream.good(); }
|
||||
|
||||
std::string filename = {};
|
||||
std::fstream stream = {};
|
||||
};
|
||||
|
||||
std::shared_ptr<tmp_file>
|
||||
get_tmp_file(std::string _basename, std::string _ext = "dat");
|
||||
|
||||
CausalMode
|
||||
get_causal_mode();
|
||||
|
||||
bool
|
||||
get_causal_end_to_end();
|
||||
|
||||
std::vector<int64_t>
|
||||
get_causal_fixed_speedup();
|
||||
|
||||
std::string
|
||||
get_causal_output_filename();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_binary_scope();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_source_scope();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_function_scope();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_binary_exclude();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_source_exclude();
|
||||
|
||||
std::vector<std::string>
|
||||
get_causal_function_exclude();
|
||||
} // namespace config
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,349 @@
|
||||
// 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 "constraint.hpp"
|
||||
#include "config.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "state.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <timemory/units.hpp>
|
||||
#include <timemory/utility/delimit.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace constraint
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace units = ::tim::units;
|
||||
|
||||
using clock_type = std::chrono::high_resolution_clock;
|
||||
using duration_type = std::chrono::duration<double, std::nano>;
|
||||
|
||||
#define OMNITRACE_CLOCK_IDENTIFIER(VAL) \
|
||||
clock_identifier { #VAL, VAL }
|
||||
|
||||
auto
|
||||
clock_name(std::string _v)
|
||||
{
|
||||
constexpr auto _clock_prefix = std::string_view{ "clock_" };
|
||||
for(auto& itr : _v)
|
||||
itr = tolower(itr);
|
||||
auto _pos = _v.find(_clock_prefix);
|
||||
if(_pos == 0) _v = _v.substr(_pos + _clock_prefix.length());
|
||||
if(_v == "process_cputime_id") _v = "cputime";
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto accepted_clock_ids =
|
||||
std::set<clock_identifier>{ OMNITRACE_CLOCK_IDENTIFIER(CLOCK_REALTIME),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_MONOTONIC),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_PROCESS_CPUTIME_ID),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_MONOTONIC_RAW),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_REALTIME_COARSE),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_MONOTONIC_COARSE),
|
||||
OMNITRACE_CLOCK_IDENTIFIER(CLOCK_BOOTTIME) };
|
||||
|
||||
template <typename Tp>
|
||||
clock_identifier
|
||||
find_clock_identifier(const Tp& _v)
|
||||
{
|
||||
const char* _descript = "";
|
||||
if constexpr(std::is_integral<Tp>::value)
|
||||
{
|
||||
_descript = "value";
|
||||
for(const auto& itr : accepted_clock_ids)
|
||||
{
|
||||
if(itr.value == _v)
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_descript = "name";
|
||||
auto _clock_name = clock_name(_v);
|
||||
for(const auto& itr : accepted_clock_ids)
|
||||
{
|
||||
if(itr.name == _clock_name || itr.raw_name == _v ||
|
||||
std::to_string(itr.value) == _v)
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OMNITRACE_THROW("Unknown clock id %s: %s. Valid choices: %s\n", _descript,
|
||||
timemory::join::join("", _v).c_str(),
|
||||
timemory::join::join("", accepted_clock_ids).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
sleep(uint64_t _n)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::nanoseconds{ _n });
|
||||
}
|
||||
|
||||
timespec
|
||||
get_timespec(clockid_t clock_id) noexcept
|
||||
{
|
||||
struct timespec _ts;
|
||||
clock_gettime(clock_id, &_ts);
|
||||
return _ts;
|
||||
}
|
||||
|
||||
template <typename Tp = uint64_t, typename Precision = std::nano>
|
||||
Tp
|
||||
get_clock_now(clockid_t clock_id) noexcept
|
||||
{
|
||||
constexpr Tp factor = (Precision::den == std::nano::den)
|
||||
? 1
|
||||
: (Precision::den / static_cast<Tp>(std::nano::den));
|
||||
auto _ts = get_timespec(clock_id);
|
||||
return (_ts.tv_sec * std::nano::den + _ts.tv_nsec) * factor;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// stages implementation
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
stages::stages()
|
||||
: init{ [](const spec&) { return get_state() < State::Finalized; } }
|
||||
, wait{ [](const spec& _spec) {
|
||||
sleep(std::min<uint64_t>(100 * units::msec, _spec.delay * units::sec));
|
||||
return get_state() < State::Finalized;
|
||||
} }
|
||||
, start{ [](const spec&) { return get_state() < State::Finalized; } }
|
||||
, collect{ [](const spec& _spec) {
|
||||
sleep(std::min<uint64_t>(100 * units::msec, _spec.duration * units::sec));
|
||||
return get_state() < State::Finalized;
|
||||
} }
|
||||
, stop{ [](const spec&) { return get_state() < State::Finalized; } }
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// clock identifier implementation
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
clock_identifier::clock_identifier(std::string_view _name, int _val)
|
||||
: value{ _val }
|
||||
, raw_name{ _name }
|
||||
, name{ clock_name(std::string{ _name }) }
|
||||
{}
|
||||
|
||||
bool
|
||||
clock_identifier::operator<(const clock_identifier& _rhs) const
|
||||
{
|
||||
return value < _rhs.value;
|
||||
}
|
||||
|
||||
bool
|
||||
clock_identifier::operator==(const clock_identifier& _rhs) const
|
||||
{
|
||||
return std::tie(raw_name, value) == std::tie(_rhs.raw_name, _rhs.value);
|
||||
}
|
||||
|
||||
bool
|
||||
clock_identifier::operator==(int _rhs) const
|
||||
{
|
||||
return (value == _rhs);
|
||||
}
|
||||
|
||||
bool
|
||||
clock_identifier::operator==(std::string _rhs) const
|
||||
{
|
||||
return (raw_name == std::string_view{ _rhs }) ||
|
||||
(name == clock_name(std::move(_rhs)));
|
||||
}
|
||||
|
||||
std::string
|
||||
clock_identifier::as_string() const
|
||||
{
|
||||
auto _name = name;
|
||||
for(auto& itr : _name)
|
||||
itr = tolower(itr);
|
||||
auto _ss = std::stringstream{};
|
||||
_ss << _name << "(id=" << raw_name << ", value=" << value << ")";
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// spec implementation
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
spec::spec(clock_identifier _id, double _delay, double _dur, uint64_t _n, uint64_t _rep)
|
||||
: delay{ _delay }
|
||||
, duration{ _dur }
|
||||
, count{ _n }
|
||||
, repeat{ _rep }
|
||||
, clock_id{ std::move(_id) }
|
||||
{}
|
||||
|
||||
spec::spec(int _clock_id, double _delay, double _dur, uint64_t _n, uint64_t _rep)
|
||||
: delay{ _delay }
|
||||
, duration{ _dur }
|
||||
, count{ _n }
|
||||
, repeat{ _rep }
|
||||
, clock_id{ find_clock_identifier(_clock_id) }
|
||||
{}
|
||||
|
||||
spec::spec(const std::string& _clock_id, double _delay, double _dur, uint64_t _n,
|
||||
uint64_t _rep)
|
||||
: delay{ _delay }
|
||||
, duration{ _dur }
|
||||
, count{ _n }
|
||||
, repeat{ _rep }
|
||||
, clock_id{ find_clock_identifier(_clock_id) }
|
||||
{}
|
||||
|
||||
spec::spec(const std::string& _line)
|
||||
: spec{ config::get_setting_value<std::string>("OMNITRACE_TRACE_PERIOD_CLOCK_ID").second,
|
||||
config::get_setting_value<double>("OMNITRACE_TRACE_DELAY").second,
|
||||
config::get_setting_value<double>("OMNITRACE_TRACE_DURATION").second }
|
||||
{
|
||||
auto _delim = tim::delimit(_line, ":");
|
||||
if(!_delim.empty()) delay = utility::convert<double>(_delim.at(0));
|
||||
if(_delim.size() > 1) duration = utility::convert<double>(_delim.at(1));
|
||||
if(_delim.size() > 2) repeat = utility::convert<uint64_t>(_delim.at(2));
|
||||
if(_delim.size() > 3) clock_id = find_clock_identifier(_delim.at(3));
|
||||
}
|
||||
|
||||
void
|
||||
spec::operator()(const stages& _stages) const
|
||||
{
|
||||
auto _n = repeat;
|
||||
if(_n < 1) _n = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
while(get_state() < State::Active)
|
||||
sleep(1 * units::usec);
|
||||
|
||||
for(uint64_t i = 0; i < _n; ++i)
|
||||
{
|
||||
auto _spec = spec{ clock_id, delay, duration, i, repeat };
|
||||
auto _wait = [_spec](const auto& _func, auto _dur) {
|
||||
auto _ret = true;
|
||||
auto _now = get_clock_now(_spec.clock_id.value);
|
||||
auto _del = (_dur * units::sec);
|
||||
auto _end = _now + _del;
|
||||
while(get_clock_now(_spec.clock_id.value) < _end && (_ret = _func(_spec)))
|
||||
{}
|
||||
return _ret;
|
||||
};
|
||||
|
||||
OMNITRACE_VERBOSE(2,
|
||||
"Executing constraint spec %lu of %lu :: delay: %6.3f, "
|
||||
"duration: %6.3f, clock: %s\n",
|
||||
i, _spec.repeat, _spec.delay, _spec.duration,
|
||||
_spec.clock_id.as_string().c_str());
|
||||
|
||||
if(_stages.init(_spec) && _wait(_stages.wait, _spec.delay) &&
|
||||
_stages.start(_spec) && _wait(_stages.collect, _spec.duration) &&
|
||||
_stages.stop(_spec))
|
||||
{}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// global usage functions
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
const std::set<clock_identifier>&
|
||||
get_valid_clock_ids()
|
||||
{
|
||||
return accepted_clock_ids;
|
||||
}
|
||||
|
||||
std::vector<spec>
|
||||
get_trace_specs()
|
||||
{
|
||||
auto _v = std::vector<constraint::spec>{};
|
||||
|
||||
{
|
||||
auto _delay_v = config::get_setting_value<double>("OMNITRACE_TRACE_DELAY").second;
|
||||
auto _duration_v =
|
||||
config::get_setting_value<double>("OMNITRACE_TRACE_DURATION").second;
|
||||
auto _clock_v = find_clock_identifier(
|
||||
config::get_setting_value<std::string>("OMNITRACE_TRACE_PERIOD_CLOCK_ID")
|
||||
.second);
|
||||
|
||||
if(_delay_v > 0.0 || _duration_v > 0.0)
|
||||
{
|
||||
_v.emplace_back(_clock_v, _delay_v, _duration_v);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto _periods_v =
|
||||
config::get_setting_value<std::string>("OMNITRACE_TRACE_PERIODS").second;
|
||||
if(!_periods_v.empty())
|
||||
{
|
||||
for(auto itr : tim::delimit(_periods_v, " ;\t\n"))
|
||||
_v.emplace_back(itr);
|
||||
}
|
||||
}
|
||||
|
||||
return _v;
|
||||
}
|
||||
|
||||
stages
|
||||
get_trace_stages()
|
||||
{
|
||||
auto _v = stages{};
|
||||
|
||||
_v.init = [](const spec&) { return get_state() < State::Finalized; };
|
||||
_v.wait = [](const spec& _spec) {
|
||||
sleep(std::min<uint64_t>(100 * units::msec, _spec.delay * units::sec));
|
||||
return get_state() < State::Finalized;
|
||||
};
|
||||
_v.start = [](const spec&) { return get_state() < State::Finalized; };
|
||||
_v.collect = [](const spec& _spec) {
|
||||
sleep(std::min<uint64_t>(100 * units::msec, _spec.duration * units::sec));
|
||||
return get_state() < State::Finalized;
|
||||
};
|
||||
_v.stop = [](const spec&) { return get_state() < State::Finalized; };
|
||||
|
||||
return _v;
|
||||
}
|
||||
} // namespace constraint
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,114 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
/// @file
|
||||
/// This provides generic functionality for constraining data collection within
|
||||
/// a windows of time. E.g., delay, delay + duration, (delay + duration) * nrepeat
|
||||
///
|
||||
/// @todo Migrate delay/duration for sampling, process sampling, and causal profiling
|
||||
/// to use this
|
||||
///
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace constraint
|
||||
{
|
||||
struct spec;
|
||||
|
||||
struct stages
|
||||
{
|
||||
using functor_t = std::function<bool(const spec&)>;
|
||||
|
||||
stages();
|
||||
|
||||
OMNITRACE_DEFAULT_COPY_MOVE(stages)
|
||||
|
||||
functor_t init = [](const spec&) { return true; };
|
||||
functor_t wait = [](const spec&) { return true; };
|
||||
functor_t start = [](const spec&) { return true; };
|
||||
functor_t collect = [](const spec&) { return true; };
|
||||
functor_t stop = [](const spec&) { return true; };
|
||||
};
|
||||
|
||||
struct clock_identifier
|
||||
{
|
||||
int value = -1;
|
||||
std::string_view raw_name = {};
|
||||
std::string name = {};
|
||||
|
||||
clock_identifier();
|
||||
clock_identifier(std::string_view, int);
|
||||
|
||||
OMNITRACE_DEFAULT_COPY_MOVE(clock_identifier)
|
||||
|
||||
std::string as_string() const;
|
||||
|
||||
bool operator<(const clock_identifier& _rhs) const;
|
||||
bool operator==(const clock_identifier& _rhs) const;
|
||||
bool operator==(int _rhs) const;
|
||||
bool operator==(std::string _rhs) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& _os, const clock_identifier& _v)
|
||||
{
|
||||
return (_os << _v.as_string());
|
||||
}
|
||||
};
|
||||
|
||||
struct spec
|
||||
{
|
||||
spec(int, double, double, uint64_t = 0, uint64_t = 1);
|
||||
spec(clock_identifier, double, double, uint64_t = 0, uint64_t = 1);
|
||||
spec(const std::string&, double, double, uint64_t = 0, uint64_t = 1);
|
||||
spec(const std::string&);
|
||||
|
||||
OMNITRACE_DEFAULT_COPY_MOVE(spec)
|
||||
|
||||
void operator()(const stages&) const;
|
||||
|
||||
double delay = 0.0;
|
||||
double duration = 0.0;
|
||||
uint64_t count = 0;
|
||||
uint64_t repeat = 1;
|
||||
clock_identifier clock_id = {};
|
||||
};
|
||||
|
||||
const std::set<clock_identifier>&
|
||||
get_valid_clock_ids();
|
||||
|
||||
std::vector<spec>
|
||||
get_trace_specs();
|
||||
|
||||
stages
|
||||
get_trace_stages();
|
||||
} // namespace constraint
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
set(containers_sources)
|
||||
|
||||
set(containers_headers ${CMAKE_CURRENT_LIST_DIR}/stable_vector.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/static_vector.hpp)
|
||||
|
||||
target_sources(omnitrace-core-library PRIVATE ${containers_sources} ${containers_headers})
|
||||
@@ -0,0 +1,132 @@
|
||||
// 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 "core/exception.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp>
|
||||
struct c_array
|
||||
{
|
||||
// Construct an array wrapper from a base pointer and array size
|
||||
c_array(Tp* _base, size_t _size)
|
||||
: m_base{ _base }
|
||||
, m_size{ _size }
|
||||
{}
|
||||
|
||||
~c_array() = default;
|
||||
c_array(const c_array&) = default;
|
||||
c_array& operator=(const c_array&) = default;
|
||||
c_array& operator=(c_array&&) noexcept = default;
|
||||
|
||||
// Get the size of the wrapped array
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
// Access an element by index
|
||||
Tp& operator[](size_t i) { return m_base[i]; }
|
||||
|
||||
// Access an element by index
|
||||
const Tp& operator[](size_t i) const { return m_base[i]; }
|
||||
|
||||
// Access an element by index with bounds check
|
||||
Tp& at(size_t i)
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw ::omnitrace::exception<std::out_of_range>(
|
||||
std::string{ typeid(*this).name() } + std::to_string(i) + " exceeds size " +
|
||||
std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Access an element by index with bounds check
|
||||
const Tp& at(size_t i) const
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw ::omnitrace::exception<std::out_of_range>(
|
||||
std::string{ typeid(*this).name() } + std::to_string(i) + " exceeds size " +
|
||||
std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Get a slice of this array, from a start index (inclusive) to end index (exclusive)
|
||||
c_array<Tp> slice(size_t start, size_t end)
|
||||
{
|
||||
return c_array<Tp>(&m_base[start], end - start);
|
||||
}
|
||||
|
||||
operator Tp*() const { return m_base; }
|
||||
|
||||
// Iterator class for convenient range-based for loop support
|
||||
template <typename Up>
|
||||
struct iterator
|
||||
{
|
||||
// Start the iterator at a given pointer
|
||||
iterator(Tp* p)
|
||||
: m_ptr{ p }
|
||||
{}
|
||||
|
||||
// Advance to the next element
|
||||
void operator++() { ++m_ptr; }
|
||||
void operator++(int) { m_ptr++; }
|
||||
|
||||
// Get the current element
|
||||
Up& operator*() const { return *m_ptr; }
|
||||
|
||||
// Compare iterators
|
||||
bool operator==(const iterator& rhs) const { return m_ptr == rhs.m_ptr; }
|
||||
bool operator!=(const iterator& rhs) const { return m_ptr != rhs.m_ptr; }
|
||||
|
||||
private:
|
||||
Tp* m_ptr = nullptr;
|
||||
};
|
||||
|
||||
// Get an iterator positioned at the beginning of the wrapped array
|
||||
iterator<Tp> begin() { return iterator<Tp>{ m_base }; }
|
||||
iterator<const Tp> begin() const { return iterator<const Tp>{ m_base }; }
|
||||
|
||||
// Get an iterator positioned at the end of the wrapped array
|
||||
iterator<Tp> end() { return iterator<Tp>{ &m_base[m_size] }; }
|
||||
iterator<const Tp> end() const { return iterator<const Tp>{ &m_base[m_size] }; }
|
||||
|
||||
private:
|
||||
Tp* m_base = nullptr;
|
||||
size_t m_size = 0;
|
||||
};
|
||||
|
||||
// Function for automatic template argument deduction
|
||||
template <typename Tp>
|
||||
c_array<Tp>
|
||||
wrap_c_array(Tp* base, size_t size)
|
||||
{
|
||||
return c_array<Tp>(base, size);
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,240 @@
|
||||
// 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 "core/defines.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#define OMNITRACE_IMPORT_TEMPLATE2(template_name)
|
||||
#define OMNITRACE_IMPORT_TEMPLATE1(template_name)
|
||||
|
||||
// Import a 2-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
#define OMNITRACE_OPERATOR_TEMPLATE2(template_name2) \
|
||||
OMNITRACE_IMPORT_TEMPLATE2(template_name2) \
|
||||
template <typename T, typename U, typename B> \
|
||||
struct is_chained_base<::omnitrace::container::template_name2<T, U, B>> \
|
||||
{ \
|
||||
using value = ::omnitrace::container::true_t; \
|
||||
};
|
||||
|
||||
// Import a 1-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
#define OMNITRACE_OPERATOR_TEMPLATE1(template_name1) \
|
||||
OMNITRACE_IMPORT_TEMPLATE1(template_name1) \
|
||||
template <typename T, typename B> \
|
||||
struct is_chained_base<::omnitrace::container::template_name1<T, B>> \
|
||||
{ \
|
||||
using value = ::omnitrace::container::true_t; \
|
||||
};
|
||||
|
||||
#define OMNITRACE_OPERATOR_TEMPLATE(template_name) \
|
||||
template <typename T, typename U = T, typename B = empty_base<T>, \
|
||||
typename O = typename is_chained_base<U>::value> \
|
||||
struct template_name; \
|
||||
\
|
||||
template <typename T, typename U, typename B> \
|
||||
struct template_name<T, U, B, false_t> : template_name##2 < T \
|
||||
, U \
|
||||
, B > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename U> \
|
||||
struct template_name<T, U, empty_base<T>, true_t> : template_name##1 < T \
|
||||
, U > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename B> \
|
||||
struct template_name<T, T, B, false_t> : template_name##1 < T \
|
||||
, B > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename U, typename B, typename O> \
|
||||
struct is_chained_base<template_name<T, U, B, O>> \
|
||||
{ \
|
||||
using value = ::omnitrace::container::true_t; \
|
||||
}; \
|
||||
\
|
||||
OMNITRACE_OPERATOR_TEMPLATE2(template_name##2) \
|
||||
OMNITRACE_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
#define OMNITRACE_BINARY_OPERATOR_COMMUTATIVE(NAME, OP) \
|
||||
template <typename T, typename U, typename B = empty_base<T>> \
|
||||
struct NAME##2 \
|
||||
: B{ friend T operator OP(T lhs, const U& rhs){ return lhs OP## = rhs; \
|
||||
} \
|
||||
friend T operator OP(const U& lhs, T rhs) { return rhs OP## = lhs; } \
|
||||
} \
|
||||
; \
|
||||
\
|
||||
template <typename T, typename B = empty_base<T>> \
|
||||
struct NAME##1 \
|
||||
: B{ friend T operator OP(T lhs, const T& rhs){ return lhs OP## = rhs; \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
#define OMNITRACE_BINARY_OPERATOR_NON_COMMUTATIVE(NAME, OP) \
|
||||
template <typename T, typename U, typename B = empty_base<T>> \
|
||||
struct NAME##2 \
|
||||
: B{ friend T operator OP(T lhs, const U& rhs){ return lhs OP## = rhs; \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
struct true_t
|
||||
{};
|
||||
|
||||
struct false_t
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
class empty_base
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct is_chained_base
|
||||
{
|
||||
using value = true_t;
|
||||
};
|
||||
|
||||
OMNITRACE_BINARY_OPERATOR_COMMUTATIVE(addable, +)
|
||||
OMNITRACE_BINARY_OPERATOR_NON_COMMUTATIVE(subtractable, -)
|
||||
|
||||
OMNITRACE_OPERATOR_TEMPLATE(addable)
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type nrv(x);
|
||||
++x;
|
||||
return nrv;
|
||||
}
|
||||
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type nrv(x);
|
||||
--x;
|
||||
return nrv;
|
||||
}
|
||||
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T decrementable_type;
|
||||
};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct dereferenceable : B
|
||||
{
|
||||
P operator->() const { return ::std::addressof(*static_cast<const T&>(*this)); }
|
||||
};
|
||||
|
||||
template <typename T, typename I, typename R, typename B = empty_base<T>>
|
||||
struct indexable : B
|
||||
{
|
||||
R operator[](I n) const { return *(static_cast<const T&>(*this) + n); }
|
||||
};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct equality_comparable1 : B
|
||||
{
|
||||
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T, incrementable<T, dereferenceable<T, P, B>>>
|
||||
{};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct output_iteratable : incrementable<T, B>
|
||||
{};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct forward_iteratable : input_iteratable<T, P, B>
|
||||
{};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct bidirectional_iteratable : forward_iteratable<T, P, decrementable<T, B>>
|
||||
{};
|
||||
|
||||
// template <typename T, typename U, typename B = empty_base<T>>
|
||||
// struct subtractable2;
|
||||
|
||||
template <typename T, typename U, typename B = empty_base<T>>
|
||||
struct additive2 : addable2<T, U, subtractable2<T, U, B>>
|
||||
{};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct less_than_comparable1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
|
||||
};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base typename of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <typename T, typename P, typename D, typename R, typename B = empty_base<T>>
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<
|
||||
T, P, less_than_comparable1<T, additive2<T, D, indexable<T, D, R, B>>>>
|
||||
{};
|
||||
|
||||
template <typename CategoryT, typename Tp, typename DistanceT = std::ptrdiff_t,
|
||||
typename PointerT = Tp*, typename ReferenceT = Tp&>
|
||||
struct iterator_helper
|
||||
{
|
||||
using iterator_category = CategoryT;
|
||||
using value_type = Tp;
|
||||
using difference_type = DistanceT;
|
||||
using pointer = PointerT;
|
||||
using reference = ReferenceT;
|
||||
};
|
||||
|
||||
template <typename T, typename V, typename D = std::ptrdiff_t, typename P = V*,
|
||||
typename R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R,
|
||||
iterator_helper<std::random_access_iterator_tag, V, D, P, R>>
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) { return x - y; }
|
||||
}; // random_access_iterator_helper
|
||||
} // namespace container
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,391 @@
|
||||
// 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 "core/containers/operators.hpp"
|
||||
#include "core/containers/static_vector.hpp"
|
||||
#include "core/defines.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp, size_t ChunkSizeV = OMNITRACE_MAX_THREADS>
|
||||
class stable_vector
|
||||
{
|
||||
public:
|
||||
using value_type = Tp;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
static constexpr const size_t chunk_size = ChunkSizeV;
|
||||
|
||||
private:
|
||||
template <size_t N>
|
||||
struct is_pow2
|
||||
{
|
||||
static constexpr bool value = (N & (N - 1)) == 0;
|
||||
};
|
||||
|
||||
static_assert(ChunkSizeV > 0, "ChunkSize needs to be greater than zero");
|
||||
static_assert(is_pow2<ChunkSizeV>::value, "ChunkSize needs to be a power of 2");
|
||||
|
||||
using this_type = stable_vector<Tp, ChunkSizeV>;
|
||||
using const_this_type = const stable_vector<Tp, ChunkSizeV>;
|
||||
|
||||
template <typename ContainerT>
|
||||
struct iterator_base
|
||||
{
|
||||
iterator_base(ContainerT* c = nullptr, size_type i = 0)
|
||||
: m_container(c)
|
||||
, m_index(i)
|
||||
{}
|
||||
|
||||
iterator_base& operator+=(size_type i)
|
||||
{
|
||||
m_index += i;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator-=(size_type i)
|
||||
{
|
||||
m_index -= i;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator++()
|
||||
{
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator--()
|
||||
{
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
difference_type operator-(const iterator_base& it)
|
||||
{
|
||||
assert(m_container == it.m_container);
|
||||
return m_index - it.m_index;
|
||||
}
|
||||
|
||||
bool operator<(const iterator_base& it) const
|
||||
{
|
||||
assert(m_container == it.m_container);
|
||||
return m_index < it.m_index;
|
||||
}
|
||||
bool operator==(const iterator_base& it) const
|
||||
{
|
||||
return m_container == it.m_container && m_index == it.m_index;
|
||||
}
|
||||
|
||||
protected:
|
||||
ContainerT* m_container;
|
||||
size_type m_index;
|
||||
};
|
||||
|
||||
public:
|
||||
struct const_iterator;
|
||||
|
||||
struct iterator
|
||||
: public iterator_base<this_type>
|
||||
//, std::iterator<std::random_access_iterator_tag, value_type>
|
||||
, public random_access_iterator_helper<iterator, value_type>
|
||||
{
|
||||
using iterator_base<this_type>::iterator_base;
|
||||
friend struct const_iterator;
|
||||
|
||||
reference operator*() { return (*this->m_container)[this->m_index]; }
|
||||
};
|
||||
|
||||
struct const_iterator
|
||||
: public iterator_base<const_this_type>
|
||||
//, std::iterator<std::random_access_iterator_tag, const value_type>
|
||||
, public random_access_iterator_helper<const_iterator, const value_type>
|
||||
{
|
||||
using iterator_base<const_this_type>::iterator_base;
|
||||
|
||||
const_iterator(const iterator& it)
|
||||
: iterator_base<const_this_type>(it.m_container, it.m_index)
|
||||
{}
|
||||
|
||||
const_reference operator*() const { return (*this->m_container)[this->m_index]; }
|
||||
|
||||
bool operator==(const const_iterator& it) const
|
||||
{
|
||||
return iterator_base<const_this_type>::operator==(it);
|
||||
}
|
||||
|
||||
friend bool operator==(const iterator& l, const const_iterator& r)
|
||||
{
|
||||
return r == l;
|
||||
}
|
||||
};
|
||||
|
||||
stable_vector() = default;
|
||||
explicit stable_vector(size_type count, const Tp& value);
|
||||
explicit stable_vector(size_type count);
|
||||
|
||||
template <typename InputItrT,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
typename std::iterator_traits<InputItrT>::iterator_category,
|
||||
std::input_iterator_tag>::value>>
|
||||
stable_vector(InputItrT first, InputItrT last);
|
||||
|
||||
stable_vector(std::initializer_list<Tp>);
|
||||
|
||||
stable_vector(const stable_vector& other);
|
||||
stable_vector(stable_vector&& other) noexcept;
|
||||
|
||||
stable_vector& operator=(stable_vector v);
|
||||
|
||||
iterator begin() noexcept { return { this, 0 }; }
|
||||
const_iterator begin() const noexcept { return { this, 0 }; }
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
iterator end() noexcept { return { this, size() }; }
|
||||
const_iterator end() const noexcept { return { this, size() }; }
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return empty() ? 0 : (m_chunks.size() - 1) * ChunkSizeV + m_chunks.back()->size();
|
||||
}
|
||||
size_type max_size() const noexcept { return std::numeric_limits<size_type>::max(); }
|
||||
size_type capacity() const noexcept { return m_chunks.size() * ChunkSizeV; }
|
||||
|
||||
bool empty() const noexcept { return m_chunks.size() == 0; }
|
||||
|
||||
void reserve(size_type new_capacity);
|
||||
void shrink_to_fit() noexcept {}
|
||||
|
||||
bool operator==(const this_type& c) const
|
||||
{
|
||||
return size() == c.size() && std::equal(cbegin(), cend(), c.cbegin());
|
||||
}
|
||||
bool operator!=(const this_type& c) const { return !operator==(c); }
|
||||
|
||||
void swap(this_type& v) { std::swap(m_chunks, v.m_chunks); }
|
||||
|
||||
friend void swap(this_type& l, this_type& r) { l.swap(r); }
|
||||
|
||||
reference front() { return m_chunks.front()->front(); }
|
||||
const_reference front() const { return front(); }
|
||||
|
||||
reference back() { return m_chunks.back()->back(); }
|
||||
const_reference back() const { return back(); }
|
||||
|
||||
void push_back(const Tp& t);
|
||||
void push_back(Tp&& t);
|
||||
|
||||
template <typename... Args>
|
||||
void emplace_back(Args&&... args);
|
||||
|
||||
reference operator[](size_type i);
|
||||
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
reference at(size_type i);
|
||||
|
||||
const_reference at(size_type i) const;
|
||||
|
||||
private:
|
||||
using chunk_type = container::static_vector<Tp, ChunkSizeV, true>;
|
||||
using storage_type = std::vector<std::unique_ptr<chunk_type>>;
|
||||
|
||||
void add_chunk();
|
||||
chunk_type& last_chunk();
|
||||
|
||||
storage_type m_chunks;
|
||||
};
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(size_type count, const Tp& value)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(size_type count)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
emplace_back();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
template <typename InputItrT, typename>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(InputItrT first, InputItrT last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
push_back(*first);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(const stable_vector& other)
|
||||
{
|
||||
for(const auto& chunk : other.m_chunks)
|
||||
{
|
||||
m_chunks.emplace_back(std::make_unique<chunk_type>(*chunk));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(stable_vector&& other) noexcept
|
||||
: m_chunks(std::move(other.m_chunks))
|
||||
{}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(std::initializer_list<Tp> ilist)
|
||||
{
|
||||
for(const auto& t : ilist)
|
||||
{
|
||||
push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>&
|
||||
stable_vector<Tp, ChunkSizeV>::operator=(stable_vector v)
|
||||
{
|
||||
swap(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::add_chunk()
|
||||
{
|
||||
m_chunks.emplace_back(std::make_unique<chunk_type>());
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::chunk_type&
|
||||
stable_vector<Tp, ChunkSizeV>::last_chunk()
|
||||
{
|
||||
if(OMNITRACE_UNLIKELY(m_chunks.empty() || m_chunks.back()->size() == ChunkSizeV))
|
||||
{
|
||||
add_chunk();
|
||||
}
|
||||
|
||||
return *m_chunks.back();
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::reserve(size_type new_capacity)
|
||||
{
|
||||
const size_t initial_capacity = capacity();
|
||||
for(difference_type i = new_capacity - initial_capacity; i > 0; i -= ChunkSizeV)
|
||||
{
|
||||
add_chunk();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::push_back(const Tp& t)
|
||||
{
|
||||
last_chunk().push_back(t);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::push_back(Tp&& t)
|
||||
{
|
||||
last_chunk().push_back(std::move(t));
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
template <typename... Args>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::emplace_back(Args&&... args)
|
||||
{
|
||||
last_chunk().emplace_back(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::reference
|
||||
stable_vector<Tp, ChunkSizeV>::operator[](size_type i)
|
||||
{
|
||||
return (*m_chunks[i / ChunkSizeV])[i % ChunkSizeV];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::const_reference
|
||||
stable_vector<Tp, ChunkSizeV>::operator[](size_type i) const
|
||||
{
|
||||
return const_cast<this_type&>(*this)[i];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::reference
|
||||
stable_vector<Tp, ChunkSizeV>::at(size_type i)
|
||||
{
|
||||
if(OMNITRACE_UNLIKELY(i >= size()))
|
||||
{
|
||||
throw ::omnitrace::exception<std::out_of_range>(
|
||||
"stable_vector::at(" + std::to_string(i) + "). size is " +
|
||||
std::to_string(size()));
|
||||
}
|
||||
|
||||
return operator[](i);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::const_reference
|
||||
stable_vector<Tp, ChunkSizeV>::at(size_type i) const
|
||||
{
|
||||
return const_cast<this_type&>(*this).at(i);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV, typename... Args>
|
||||
auto
|
||||
resize(stable_vector<Tp, ChunkSizeV>& _v, size_t _n, Args&&... args)
|
||||
{
|
||||
if(_n > _v.capacity()) _v.reserve(_n);
|
||||
|
||||
while(_v.size() < _n)
|
||||
_v.emplace_back(std::forward<Args>(args)...);
|
||||
|
||||
return _v.size();
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,194 @@
|
||||
// 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 "core/common.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/exception.hpp"
|
||||
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp, size_t N, bool AtomicSizeV = false>
|
||||
struct static_vector
|
||||
{
|
||||
using count_type = std::conditional_t<AtomicSizeV, std::atomic<size_t>, size_t>;
|
||||
using this_type = static_vector<Tp, N>;
|
||||
using value_type = Tp;
|
||||
|
||||
static_vector() = default;
|
||||
static_vector(const static_vector&) = default;
|
||||
static_vector(static_vector&&) noexcept = default;
|
||||
static_vector& operator=(const static_vector&) = default;
|
||||
static_vector& operator=(static_vector&&) noexcept = default;
|
||||
|
||||
static_vector(size_t _n, Tp _v = {});
|
||||
|
||||
static_vector& operator=(std::initializer_list<Tp>&& _v);
|
||||
static_vector& operator=(std::pair<std::array<Tp, N>, size_t>&&);
|
||||
|
||||
template <typename... Args>
|
||||
value_type& emplace_back(Args&&... _v);
|
||||
|
||||
template <typename Up>
|
||||
decltype(auto) push_back(Up&& _v)
|
||||
{
|
||||
return emplace_back(Tp{ std::forward<Up>(_v) });
|
||||
}
|
||||
|
||||
void pop_back() { --m_size; }
|
||||
|
||||
void clear();
|
||||
void reserve(size_t) noexcept {}
|
||||
void shrink_to_fit() noexcept {}
|
||||
auto capacity() noexcept { return N; }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
bool empty() const { return (size() == 0); }
|
||||
|
||||
auto begin() { return m_data.begin(); }
|
||||
auto begin() const { return m_data.begin(); }
|
||||
auto cbegin() const { return m_data.cbegin(); }
|
||||
|
||||
auto end() { return m_data.begin() + size(); }
|
||||
auto end() const { return m_data.begin() + size(); }
|
||||
auto cend() const { return m_data.cbegin() + size(); }
|
||||
|
||||
decltype(auto) operator[](size_t _idx) { return m_data[_idx]; }
|
||||
decltype(auto) operator[](size_t _idx) const { return m_data[_idx]; }
|
||||
|
||||
decltype(auto) at(size_t _idx) { return m_data.at(_idx); }
|
||||
decltype(auto) at(size_t _idx) const { return m_data.at(_idx); }
|
||||
|
||||
decltype(auto) front() { return m_data.front(); }
|
||||
decltype(auto) front() const { return m_data.front(); }
|
||||
decltype(auto) back() { return *(m_data.begin() + size() - 1); }
|
||||
decltype(auto) back() const { return *(m_data.begin() + size() - 1); }
|
||||
|
||||
void swap(this_type& _v);
|
||||
|
||||
friend void swap(this_type& _lhs, this_type& _rhs) { _lhs.swap(_rhs); }
|
||||
|
||||
private:
|
||||
count_type m_size = count_type{ 0 };
|
||||
std::array<Tp, N> m_data = {};
|
||||
};
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>::static_vector(size_t _n, Tp _v)
|
||||
{
|
||||
m_size.store(_n);
|
||||
m_data.fill(_v);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>&
|
||||
static_vector<Tp, N, AtomicSizeV>::operator=(std::initializer_list<Tp>&& _v)
|
||||
{
|
||||
if(OMNITRACE_UNLIKELY(_v.size() > N))
|
||||
{
|
||||
throw exception<std::out_of_range>(
|
||||
std::string{ "static_vector::operator=(initializer_list) size > " } +
|
||||
std::to_string(N));
|
||||
}
|
||||
|
||||
clear();
|
||||
for(auto&& itr : _v)
|
||||
m_data[m_size++] = itr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>&
|
||||
static_vector<Tp, N, AtomicSizeV>::operator=(std::pair<std::array<Tp, N>, size_t>&& _v)
|
||||
{
|
||||
if constexpr(AtomicSizeV) m_size.store(0);
|
||||
|
||||
m_data = std::move(_v.first);
|
||||
|
||||
if constexpr(AtomicSizeV)
|
||||
m_size.store(_v.second);
|
||||
else
|
||||
m_size = _v.second;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
void
|
||||
static_vector<Tp, N, AtomicSizeV>::clear()
|
||||
{
|
||||
if constexpr(AtomicSizeV)
|
||||
m_size.store(0);
|
||||
else
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
void
|
||||
static_vector<Tp, N, AtomicSizeV>::swap(this_type& _v)
|
||||
{
|
||||
if constexpr(AtomicSizeV)
|
||||
{
|
||||
auto _t_size = m_size;
|
||||
auto _v_size = _v.m_size;
|
||||
std::swap(m_data, _v.m_data);
|
||||
m_size.store(_v_size);
|
||||
_v.m_size.store(_t_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(m_size, _v.m_size);
|
||||
std::swap(m_data, _v.m_data);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
template <typename... Args>
|
||||
Tp&
|
||||
static_vector<Tp, N, AtomicSizeV>::emplace_back(Args&&... _v)
|
||||
{
|
||||
auto _idx = m_size++;
|
||||
if(_idx >= N)
|
||||
{
|
||||
throw exception<std::out_of_range>(
|
||||
std::string{ "static_vector::emplace_back - reached capacity " } +
|
||||
std::to_string(N));
|
||||
}
|
||||
|
||||
if constexpr(std::is_assignable<Tp, decltype(std::forward<Args>(_v))...>::value)
|
||||
m_data[_idx] = { std::forward<Args>(_v)... };
|
||||
else
|
||||
m_data[_idx] = Tp{ std::forward<Args>(_v)... };
|
||||
return m_data[_idx];
|
||||
}
|
||||
|
||||
} // namespace container
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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 "debug.hpp"
|
||||
#include "binary/address_range.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
#include <timemory/log/color.hpp>
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace debug
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct source_location_history
|
||||
{
|
||||
std::array<source_location, 10> data = {};
|
||||
size_t size = 0;
|
||||
};
|
||||
|
||||
auto&
|
||||
get_source_location_history()
|
||||
{
|
||||
static thread_local auto _v = source_location_history{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto _protect_lock = std::atomic<bool>{ false };
|
||||
auto _protect_unlock = std::atomic<bool>{ false };
|
||||
} // namespace
|
||||
|
||||
void
|
||||
set_source_location(source_location&& _v)
|
||||
{
|
||||
auto& _hist = get_source_location_history();
|
||||
auto _idx = _hist.size++;
|
||||
_hist.data.at(_idx % _hist.data.size()) = _v;
|
||||
}
|
||||
|
||||
lock::lock()
|
||||
: m_lk{ tim::type_mutex<decltype(std::cerr)>(), std::defer_lock }
|
||||
{
|
||||
if(!m_lk.owns_lock() && !_protect_lock)
|
||||
{
|
||||
_protect_lock.store(true);
|
||||
push_thread_state(ThreadState::Internal);
|
||||
m_lk.lock();
|
||||
_protect_lock.store(false);
|
||||
}
|
||||
}
|
||||
|
||||
lock::~lock()
|
||||
{
|
||||
if(m_lk.owns_lock() && !_protect_unlock)
|
||||
{
|
||||
_protect_unlock.store(true);
|
||||
m_lk.unlock();
|
||||
pop_thread_state();
|
||||
_protect_unlock.store(false);
|
||||
}
|
||||
}
|
||||
|
||||
FILE*
|
||||
get_file()
|
||||
{
|
||||
static FILE* _v = []() {
|
||||
auto&& _fname = tim::get_env<std::string>("OMNITRACE_LOG_FILE", "");
|
||||
if(!_fname.empty()) tim::log::monochrome() = true;
|
||||
return (_fname.empty()) ? stderr : tim::filepath::fopen(_fname, "w");
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
} // namespace debug
|
||||
|
||||
template <typename Tp>
|
||||
std::string
|
||||
as_hex(Tp _v, size_t _width)
|
||||
{
|
||||
std::stringstream _ss;
|
||||
_ss.fill('0');
|
||||
_ss << "0x" << std::hex << std::setw(_width) << _v;
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string
|
||||
as_hex<address_range_t>(address_range_t _v, size_t _width)
|
||||
{
|
||||
return (_v.is_range()) ? JOIN('-', as_hex(_v.low, _width), as_hex(_v.high, _width))
|
||||
: as_hex(_v.low, _width);
|
||||
}
|
||||
|
||||
template std::string as_hex<int32_t>(int32_t, size_t);
|
||||
template std::string as_hex<uint32_t>(uint32_t, size_t);
|
||||
template std::string as_hex<int64_t>(int64_t, size_t);
|
||||
template std::string as_hex<uint64_t>(uint64_t, size_t);
|
||||
template std::string
|
||||
as_hex<void*>(void*, size_t);
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,672 @@
|
||||
// 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 "defines.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
#include <timemory/api.hpp>
|
||||
#include <timemory/backends/dmp.hpp>
|
||||
#include <timemory/backends/process.hpp>
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/log/logger.hpp>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/signals/signal_handlers.hpp>
|
||||
#include <timemory/utility/backtrace.hpp>
|
||||
#include <timemory/utility/locking.hpp>
|
||||
#include <timemory/utility/utility.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace config
|
||||
{
|
||||
bool
|
||||
get_debug() OMNITRACE_HOT;
|
||||
|
||||
int
|
||||
get_verbose() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_env() OMNITRACE_HOT;
|
||||
|
||||
int
|
||||
get_verbose_env() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_is_continuous_integration() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_tid() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_debug_pid() OMNITRACE_HOT;
|
||||
|
||||
bool
|
||||
get_critical_trace_debug() OMNITRACE_HOT;
|
||||
} // namespace config
|
||||
|
||||
namespace debug
|
||||
{
|
||||
struct source_location
|
||||
{
|
||||
std::string_view function = {};
|
||||
std::string_view file = {};
|
||||
int line = 0;
|
||||
};
|
||||
//
|
||||
void
|
||||
set_source_location(source_location&&);
|
||||
//
|
||||
FILE*
|
||||
get_file();
|
||||
//
|
||||
inline void
|
||||
flush()
|
||||
{
|
||||
fprintf(stdout, "%s", ::tim::log::color::end());
|
||||
fflush(stdout);
|
||||
std::cout << ::tim::log::color::end() << std::flush;
|
||||
fprintf(::omnitrace::debug::get_file(), "%s", ::tim::log::color::end());
|
||||
fflush(::omnitrace::debug::get_file());
|
||||
std::cerr << ::tim::log::color::end() << std::flush;
|
||||
}
|
||||
//
|
||||
struct lock
|
||||
{
|
||||
lock();
|
||||
~lock();
|
||||
|
||||
private:
|
||||
tim::auto_lock_t m_lk;
|
||||
};
|
||||
//
|
||||
template <typename Arg, typename... Args>
|
||||
bool
|
||||
is_bracket(Arg&& _arg, Args&&...)
|
||||
{
|
||||
if constexpr(::tim::concepts::is_string_type<Arg>::value)
|
||||
return (::std::string_view{ _arg }.empty()) ? false : _arg[0] == '[';
|
||||
else
|
||||
return false;
|
||||
}
|
||||
//
|
||||
namespace
|
||||
{
|
||||
template <typename T, size_t... Idx>
|
||||
auto
|
||||
get_chars(T&& _c, std::index_sequence<Idx...>)
|
||||
{
|
||||
return std::array<const char, sizeof...(Idx) + 1>{ std::forward<T>(_c)[Idx]...,
|
||||
'\0' };
|
||||
}
|
||||
} // namespace
|
||||
} // namespace debug
|
||||
|
||||
namespace binary
|
||||
{
|
||||
struct address_range;
|
||||
}
|
||||
|
||||
using address_range_t = binary::address_range;
|
||||
|
||||
template <typename Tp>
|
||||
std::string
|
||||
as_hex(Tp, size_t _wdith = 16);
|
||||
|
||||
template <>
|
||||
std::string as_hex<address_range_t>(address_range_t, size_t);
|
||||
|
||||
extern template std::string as_hex<int32_t>(int32_t, size_t);
|
||||
extern template std::string as_hex<uint32_t>(uint32_t, size_t);
|
||||
extern template std::string as_hex<int64_t>(int64_t, size_t);
|
||||
extern template std::string as_hex<uint64_t>(uint64_t, size_t);
|
||||
extern template std::string
|
||||
as_hex<void*>(void*, size_t);
|
||||
} // namespace omnitrace
|
||||
|
||||
#if !defined(OMNITRACE_DEBUG_BUFFER_LEN)
|
||||
# define OMNITRACE_DEBUG_BUFFER_LEN 1024
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_DEBUG_PROCESS_IDENTIFIER)
|
||||
# if defined(TIMEMORY_USE_MPI)
|
||||
# define OMNITRACE_DEBUG_PROCESS_IDENTIFIER static_cast<int>(::tim::dmp::rank())
|
||||
# elif defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
# define OMNITRACE_DEBUG_PROCESS_IDENTIFIER \
|
||||
(::tim::dmp::is_initialized()) ? static_cast<int>(::tim::dmp::rank()) \
|
||||
: static_cast<int>(::tim::process::get_id())
|
||||
# else
|
||||
# define OMNITRACE_DEBUG_PROCESS_IDENTIFIER \
|
||||
static_cast<int>(::tim::process::get_id())
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_DEBUG_THREAD_IDENTIFIER)
|
||||
# define OMNITRACE_DEBUG_THREAD_IDENTIFIER ::tim::threading::get_id()
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_SOURCE_LOCATION)
|
||||
# define OMNITRACE_SOURCE_LOCATION \
|
||||
::omnitrace::debug::source_location { __PRETTY_FUNCTION__, __FILE__, __LINE__ }
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_RECORD_SOURCE_LOCATION)
|
||||
# define OMNITRACE_RECORD_SOURCE_LOCATION \
|
||||
::omnitrace::debug::set_source_location(OMNITRACE_SOURCE_LOCATION)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || (__GNUC__ < 9)
|
||||
# define OMNITRACE_FUNCTION \
|
||||
std::string{ __FUNCTION__ } \
|
||||
.substr(0, std::string_view{ __FUNCTION__ }.find("_hidden")) \
|
||||
.c_str()
|
||||
# define OMNITRACE_PRETTY_FUNCTION \
|
||||
std::string{ __PRETTY_FUNCTION__ } \
|
||||
.substr(0, std::string_view{ __PRETTY_FUNCTION__ }.find("_hidden")) \
|
||||
.c_str()
|
||||
#else
|
||||
# define OMNITRACE_FUNCTION \
|
||||
::omnitrace::debug::get_chars( \
|
||||
std::string_view{ __FUNCTION__ }, \
|
||||
std::make_index_sequence<std::min( \
|
||||
std::string_view{ __FUNCTION__ }.find("_hidden"), \
|
||||
std::string_view{ __FUNCTION__ }.length())>{}) \
|
||||
.data()
|
||||
# define OMNITRACE_PRETTY_FUNCTION \
|
||||
::omnitrace::debug::get_chars( \
|
||||
std::string_view{ __PRETTY_FUNCTION__ }, \
|
||||
std::make_index_sequence<std::min( \
|
||||
std::string_view{ __PRETTY_FUNCTION__ }.find("_hidden"), \
|
||||
std::string_view{ __PRETTY_FUNCTION__ }.length())>{}) \
|
||||
.data()
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_FPRINTF_STDERR_COLOR(COLOR) \
|
||||
fprintf(::omnitrace::debug::get_file(), "%s", ::tim::log::color::COLOR())
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_PRINT(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(info); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_PRINT(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(info); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_PRINT_F(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(info); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_PRINT_F(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(info); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_WARN(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(warning); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_WARN(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(warning); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_WARN_F(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(warning); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_WARN_F(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::debug::lock _debug_lk{}; \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(warning); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_THROW_E(COND, TYPE, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[OMNITRACE_DEBUG_BUFFER_LEN]; \
|
||||
snprintf(_msg_buffer, OMNITRACE_DEBUG_BUFFER_LEN, "[omnitrace][%i][%li][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, OMNITRACE_DEBUG_BUFFER_LEN - len, __VA_ARGS__); \
|
||||
throw ::omnitrace::exception<TYPE>( \
|
||||
::tim::log::string(::tim::log::color::fatal(), _msg_buffer)); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_THROW_E(COND, TYPE, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[OMNITRACE_DEBUG_BUFFER_LEN]; \
|
||||
snprintf(_msg_buffer, OMNITRACE_DEBUG_BUFFER_LEN, "[omnitrace][%i][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, OMNITRACE_DEBUG_BUFFER_LEN - len, __VA_ARGS__); \
|
||||
throw ::omnitrace::exception<TYPE>( \
|
||||
::tim::log::string(::tim::log::color::fatal(), _msg_buffer)); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CI_THROW_E(COND, TYPE, ...) \
|
||||
OMNITRACE_CONDITIONAL_THROW_E( \
|
||||
::omnitrace::get_is_continuous_integration() && (COND), TYPE, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_THROW_E(COND, TYPE, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_THROW_E( \
|
||||
::omnitrace::get_is_continuous_integration() && (COND), TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_THROW(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_THROW_E((COND), std::runtime_error, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_THROW(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_THROW_E((COND), std::runtime_error, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_THROW(COND, ...) \
|
||||
OMNITRACE_CI_THROW_E((COND), std::runtime_error, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_THROW(COND, ...) \
|
||||
OMNITRACE_CI_BASIC_THROW_E((COND), std::runtime_error, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_FAILURE(COND, METHOD, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::set_state(::omnitrace::State::Finalized); \
|
||||
::tim::signals::disable_signal_detection(); \
|
||||
timemory_print_demangled_backtrace<64>(); \
|
||||
METHOD; \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_FAILURE(COND, METHOD, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::set_state(::omnitrace::State::Finalized); \
|
||||
::tim::signals::disable_signal_detection(); \
|
||||
timemory_print_demangled_backtrace<64>(); \
|
||||
METHOD; \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_FAILURE_F(COND, METHOD, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%li][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_DEBUG_THREAD_IDENTIFIER, \
|
||||
OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::set_state(::omnitrace::State::Finalized); \
|
||||
::tim::signals::disable_signal_detection(); \
|
||||
timemory_print_demangled_backtrace<64>(); \
|
||||
METHOD; \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_FAILURE_F(COND, METHOD, ...) \
|
||||
if(COND) \
|
||||
{ \
|
||||
::omnitrace::debug::flush(); \
|
||||
OMNITRACE_FPRINTF_STDERR_COLOR(fatal); \
|
||||
fprintf(::omnitrace::debug::get_file(), "[omnitrace][%i][%s]%s", \
|
||||
OMNITRACE_DEBUG_PROCESS_IDENTIFIER, OMNITRACE_FUNCTION, \
|
||||
::omnitrace::debug::is_bracket(__VA_ARGS__) ? "" : " "); \
|
||||
fprintf(::omnitrace::debug::get_file(), __VA_ARGS__); \
|
||||
::omnitrace::debug::flush(); \
|
||||
::omnitrace::set_state(::omnitrace::State::Finalized); \
|
||||
::tim::signals::disable_signal_detection(); \
|
||||
timemory_print_demangled_backtrace<64>(); \
|
||||
METHOD; \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CI_FAILURE(COND, METHOD, ...) \
|
||||
OMNITRACE_CONDITIONAL_FAILURE( \
|
||||
::omnitrace::get_is_continuous_integration() && (COND), METHOD, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_FAILURE(COND, METHOD, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_FAILURE( \
|
||||
::omnitrace::get_is_continuous_integration() && (COND), METHOD, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_FAIL(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_FAILURE(COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_FAIL(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_FAILURE(COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_FAIL_F(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_FAILURE_F(COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_FAIL_F(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_FAILURE_F( \
|
||||
COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_FAIL(COND, ...) \
|
||||
OMNITRACE_CI_FAILURE(COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_FAIL(COND, ...) \
|
||||
OMNITRACE_CI_BASIC_FAILURE(COND, OMNITRACE_ESC(::std::exit(EXIT_FAILURE)), \
|
||||
__VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_ABORT(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_FAILURE(COND, OMNITRACE_ESC(::std::abort()), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_ABORT(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_FAILURE(COND, OMNITRACE_ESC(::std::abort()), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_ABORT_F(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_FAILURE_F(COND, OMNITRACE_ESC(::std::abort()), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_BASIC_ABORT_F(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_FAILURE_F(COND, OMNITRACE_ESC(::std::abort()), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_ABORT(COND, ...) \
|
||||
OMNITRACE_CI_FAILURE(COND, OMNITRACE_ESC(::std::abort()), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_ABORT(COND, ...) \
|
||||
OMNITRACE_CI_BASIC_FAILURE(COND, OMNITRACE_ESC(::std::abort()), __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Debug macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_DEBUG(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT(::omnitrace::get_debug(), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_DEBUG(...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(::omnitrace::get_debug_env(), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_DEBUG_F(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT_F(::omnitrace::get_debug(), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_DEBUG_F(...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(::omnitrace::get_debug_env(), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CT_DEBUG(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT(::omnitrace::get_critical_trace_debug(), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CT_DEBUG_F(...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT_F(::omnitrace::get_critical_trace_debug(), __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Verbose macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_VERBOSE(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT( \
|
||||
::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_VERBOSE(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(::omnitrace::get_debug_env() || \
|
||||
(::omnitrace::get_verbose_env() >= LEVEL), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_VERBOSE_F(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_PRINT_F( \
|
||||
::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_VERBOSE_F(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(::omnitrace::get_debug_env() || \
|
||||
(::omnitrace::get_verbose_env() >= LEVEL), \
|
||||
__VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Warning macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_WARNING(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_WARN( \
|
||||
::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_WARNING(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_WARN(::omnitrace::get_debug_env() || \
|
||||
(::omnitrace::get_verbose_env() >= LEVEL), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_WARNING_F(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_WARN_F( \
|
||||
::omnitrace::get_debug() || (::omnitrace::get_verbose() >= LEVEL), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_WARNING_F(LEVEL, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_WARN_F(::omnitrace::get_debug_env() || \
|
||||
(::omnitrace::get_verbose_env() >= LEVEL), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_WARNING_IF(COND, ...) OMNITRACE_CONDITIONAL_WARN((COND), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_WARNING_IF_F(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_WARN_F((COND), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_WARNING_OR_CI_THROW(LEVEL, ...) \
|
||||
{ \
|
||||
if(::omnitrace::get_is_continuous_integration()) \
|
||||
{ \
|
||||
OMNITRACE_CI_THROW(true, __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
OMNITRACE_CONDITIONAL_WARN(::omnitrace::get_debug() || \
|
||||
(::omnitrace::get_verbose() >= LEVEL), \
|
||||
__VA_ARGS__) \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OMNITRACE_REQUIRE(...) TIMEMORY_REQUIRE(__VA_ARGS__)
|
||||
#define OMNITRACE_PREFER(COND) \
|
||||
(COND) ? ::tim::log::base() \
|
||||
: (::omnitrace::get_is_continuous_integration()) ? TIMEMORY_FATAL \
|
||||
: TIMEMORY_WARNING
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Basic print macros (basic means it will not provide PID/RANK or TID) and will not
|
||||
// initialize the settings.
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_BASIC_PRINT(...) OMNITRACE_CONDITIONAL_BASIC_PRINT(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_PRINT_F(...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(true, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Print macros. Will provide PID/RANK and TID (will initialize settings)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_PRINT(...) OMNITRACE_CONDITIONAL_PRINT(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_PRINT_F(...) OMNITRACE_CONDITIONAL_PRINT_F(true, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Throw macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_THROW(...) OMNITRACE_CONDITIONAL_THROW(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_THROW(...) OMNITRACE_CONDITIONAL_BASIC_THROW(true, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Fail macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_FAIL(...) OMNITRACE_CONDITIONAL_FAIL(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_FAIL_F(...) OMNITRACE_CONDITIONAL_FAIL_F(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_FAIL(...) OMNITRACE_CONDITIONAL_BASIC_FAIL(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_FAIL_F(...) OMNITRACE_CONDITIONAL_BASIC_FAIL_F(true, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Abort macros
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_ABORT(...) OMNITRACE_CONDITIONAL_ABORT(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_ABORT_F(...) OMNITRACE_CONDITIONAL_ABORT_F(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_ABORT(...) OMNITRACE_CONDITIONAL_BASIC_ABORT(true, __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_BASIC_ABORT_F(...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_ABORT_F(true, __VA_ARGS__)
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
inline std::string
|
||||
to_string(bool _v)
|
||||
{
|
||||
return (_v) ? "true" : "false";
|
||||
}
|
||||
} // namespace std
|
||||
@@ -0,0 +1,61 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/defines.h"
|
||||
|
||||
#define TIMEMORY_USER_COMPONENT_ENUM \
|
||||
OMNITRACE_ROCTRACER_idx, OMNITRACE_ROCPROFILER_idx, \
|
||||
OMNITRACE_SAMPLING_WALL_CLOCK_idx, OMNITRACE_SAMPLING_CPU_CLOCK_idx, \
|
||||
OMNITRACE_SAMPLING_PERCENT_idx, OMNITRACE_SAMPLING_GPU_POWER_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_TEMP_idx, OMNITRACE_SAMPLING_GPU_BUSY_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
|
||||
|
||||
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
|
||||
#define OMNITRACE_ROCPROFILER OMNITRACE_ROCPROFILER_idx
|
||||
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_PERCENT OMNITRACE_SAMPLING_PERCENT_idx
|
||||
#define OMNITRACE_SAMPLING_GPU_POWER OMNITRACE_SAMPLING_GPU_POWER_idx
|
||||
#define OMNITRACE_SAMPLING_GPU_TEMP OMNITRACE_SAMPLING_GPU_TEMP_idx
|
||||
#define OMNITRACE_SAMPLING_GPU_BUSY OMNITRACE_SAMPLING_GPU_BUSY_idx
|
||||
#define OMNITRACE_SAMPLING_GPU_MEMORY_USAGE OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx
|
||||
|
||||
#define OMNITRACE_METADATA(...) ::tim::manager::add_metadata(__VA_ARGS__)
|
||||
|
||||
#if !defined(OMNITRACE_DEFAULT_OBJECT)
|
||||
# define OMNITRACE_DEFAULT_OBJECT(NAME) \
|
||||
NAME() = default; \
|
||||
NAME(const NAME&) = default; \
|
||||
NAME(NAME&&) noexcept = default; \
|
||||
NAME& operator=(const NAME&) = default; \
|
||||
NAME& operator=(NAME&&) noexcept = default;
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_DEFAULT_COPY_MOVE)
|
||||
# define OMNITRACE_DEFAULT_COPY_MOVE(NAME) \
|
||||
NAME(const NAME&) = default; \
|
||||
NAME(NAME&&) noexcept = default; \
|
||||
NAME& operator=(const NAME&) = default; \
|
||||
NAME& operator=(NAME&&) noexcept = default;
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
// 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 "dynamic_library.hpp"
|
||||
#include "common.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <timemory/environment.hpp>
|
||||
#include <timemory/utility/delimit.hpp>
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
#include <timemory/utility/procfs/maps.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace procfs = ::tim::procfs;
|
||||
|
||||
std::string
|
||||
find_library_path(const std::string& _name, const std::vector<std::string>& _env_vars,
|
||||
const std::vector<std::string>& _hints,
|
||||
const std::vector<std::string>& _path_suffixes)
|
||||
{
|
||||
if(_name.find('/') == 0) return _name;
|
||||
|
||||
for(const auto& itr : procfs::get_maps(process::get_id(), true))
|
||||
{
|
||||
auto&& _path = itr.pathname;
|
||||
if(_path.find(_name) != std::string::npos && filepath::exists(_path))
|
||||
return _path;
|
||||
}
|
||||
|
||||
auto _paths = std::vector<std::string>{};
|
||||
for(const std::string& itr : _env_vars)
|
||||
{
|
||||
auto _env_val = get_env(itr, std::string{});
|
||||
for(auto vitr : tim::delimit(_env_val, ":"))
|
||||
if(!vitr.empty()) _paths.emplace_back(vitr);
|
||||
}
|
||||
|
||||
for(const std::string& itr : _hints)
|
||||
{
|
||||
if(!itr.empty()) _paths.emplace_back(itr);
|
||||
}
|
||||
|
||||
for(auto& itr : _paths)
|
||||
{
|
||||
auto _v = JOIN('/', itr, _name);
|
||||
if(filepath::exists(_v)) return _v;
|
||||
for(const auto& litr : _path_suffixes)
|
||||
{
|
||||
_v = JOIN('/', itr, litr, _name);
|
||||
if(filepath::exists(_v)) return _v;
|
||||
}
|
||||
}
|
||||
|
||||
return _name;
|
||||
}
|
||||
|
||||
dynamic_library::dynamic_library(std::string _env, std::string _fname, int _flags,
|
||||
bool _open, bool _query_env, bool _store)
|
||||
: envname{ std::move(_env) }
|
||||
, filename{ std::move(_fname) }
|
||||
, flags{ _flags }
|
||||
{
|
||||
// check the memory maps
|
||||
filename = find_library_path(filename, {}, {});
|
||||
|
||||
if(_query_env)
|
||||
{
|
||||
auto _env_val = get_env(envname, std::string{}, _store);
|
||||
// if the environment variable is set to an absolute path that exists,
|
||||
// override with value
|
||||
if(!_env_val.empty())
|
||||
{
|
||||
if(_env_val.find('/') == 0 && filepath::exists(_env_val))
|
||||
{
|
||||
filename = _env_val;
|
||||
}
|
||||
else if(_env_val.find('/') == 0)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1,
|
||||
"Ignoring environment variable %s=\"%s\" because the "
|
||||
"filepath does not exist. Using \"%s\" instead...\n",
|
||||
envname.c_str(), _env_val.c_str(), filename.c_str())
|
||||
}
|
||||
else if(_env_val.find('/') != 0 && filename.find('/') == 0)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(
|
||||
1,
|
||||
"Ignoring environment variable %s=\"%s\" because the "
|
||||
"filepath is relative. Using absolute path \"%s\" instead...\n",
|
||||
envname.c_str(), _env_val.c_str(), filename.c_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(_open) open();
|
||||
}
|
||||
|
||||
dynamic_library::~dynamic_library() { close(); }
|
||||
|
||||
bool
|
||||
dynamic_library::open()
|
||||
{
|
||||
if(!filename.empty())
|
||||
{
|
||||
handle = dlopen(filename.c_str(), flags);
|
||||
if(!handle)
|
||||
{
|
||||
OMNITRACE_VERBOSE(2, "[dynamic_library] Error opening %s=\"%s\" :: %s.\n",
|
||||
envname.c_str(), filename.c_str(), dlerror());
|
||||
}
|
||||
dlerror(); // Clear any existing error
|
||||
}
|
||||
return (handle != nullptr);
|
||||
}
|
||||
|
||||
int
|
||||
dynamic_library::close() const
|
||||
{
|
||||
if(handle) return dlclose(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
dynamic_library::is_open() const
|
||||
{
|
||||
return (handle != nullptr);
|
||||
}
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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 "defines.hpp"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
std::string
|
||||
find_library_path(const std::string& _name, const std::vector<std::string>& _env_vars,
|
||||
const std::vector<std::string>& _hints,
|
||||
const std::vector<std::string>& _path_suffixes = { "lib", "lib64" });
|
||||
|
||||
struct dynamic_library
|
||||
{
|
||||
dynamic_library() = delete;
|
||||
dynamic_library(const dynamic_library&) = delete;
|
||||
dynamic_library(dynamic_library&&) noexcept = default;
|
||||
dynamic_library& operator=(const dynamic_library&) = delete;
|
||||
dynamic_library& operator=(dynamic_library&&) noexcept = default;
|
||||
|
||||
dynamic_library(std::string _env, std::string _fname,
|
||||
int _flags = (RTLD_LAZY | RTLD_GLOBAL), bool _open = true,
|
||||
bool _query_env = true, bool _store = true);
|
||||
|
||||
~dynamic_library();
|
||||
|
||||
bool open();
|
||||
int close() const;
|
||||
bool is_open() const;
|
||||
|
||||
template <typename RetT, typename... Args>
|
||||
RetT invoke(std::string_view, RetT (*&_func)(Args...), Args...);
|
||||
|
||||
std::string envname = {};
|
||||
std::string filename = {};
|
||||
int flags = 0;
|
||||
void* handle = nullptr;
|
||||
};
|
||||
|
||||
template <typename RetT, typename... Args>
|
||||
inline RetT
|
||||
dynamic_library::invoke(std::string_view _name, RetT (*&_func)(Args...), Args... _args)
|
||||
{
|
||||
if(!handle) open();
|
||||
if(handle)
|
||||
{
|
||||
*(void**) (&_func) = dlsym(handle, _name.data());
|
||||
if(_func)
|
||||
{
|
||||
return (*_func)(_args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "[omnitrace][pid=%i]> %s :: %s\n", getpid(), _name.data(),
|
||||
dlerror());
|
||||
}
|
||||
}
|
||||
return RetT{};
|
||||
}
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,128 @@
|
||||
// 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 "exception.hpp"
|
||||
|
||||
#include <any>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <timemory/unwind/backtrace.hpp>
|
||||
#include <timemory/utility/backtrace.hpp>
|
||||
#include <typeinfo>
|
||||
#include <variant>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename... Args>
|
||||
void
|
||||
consume_args(Args&&...)
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
get_backtrace(Args... _arg)
|
||||
{
|
||||
auto _bt = std::stringstream{};
|
||||
if constexpr(sizeof...(Args) > 0)
|
||||
{
|
||||
((_bt << _arg), ...) << "\n";
|
||||
}
|
||||
tim::unwind::detailed_backtrace<2>(_bt, true);
|
||||
return strdup(_bt.str().c_str());
|
||||
consume_args(_arg...);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename Tp>
|
||||
exception<Tp>::exception(const std::string& _msg)
|
||||
: Tp{ _msg }
|
||||
, m_what{ get_backtrace(_msg) }
|
||||
{}
|
||||
|
||||
template <typename Tp>
|
||||
exception<Tp>::exception(const char* _msg)
|
||||
: Tp{ _msg }
|
||||
, m_what{ get_backtrace(_msg) }
|
||||
{}
|
||||
|
||||
template <typename Tp>
|
||||
exception<Tp>::~exception()
|
||||
{
|
||||
free(m_what);
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
exception<Tp>::exception(const exception& _rhs)
|
||||
: Tp{ _rhs }
|
||||
, m_what{ strdup(_rhs.m_what) }
|
||||
{}
|
||||
|
||||
template <typename Tp>
|
||||
exception<Tp>&
|
||||
exception<Tp>::operator=(const exception& _rhs)
|
||||
{
|
||||
if(this != &_rhs)
|
||||
{
|
||||
Tp::operator=(_rhs);
|
||||
m_what = strdup(_rhs.m_what);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
const char*
|
||||
exception<Tp>::what() const noexcept
|
||||
{
|
||||
return (m_what) ? m_what : Tp::what();
|
||||
}
|
||||
|
||||
template class exception<std::runtime_error>;
|
||||
template class exception<std::logic_error>;
|
||||
template class exception<std::length_error>;
|
||||
template class exception<std::out_of_range>;
|
||||
template class exception<std::invalid_argument>;
|
||||
template class exception<std::domain_error>;
|
||||
template class exception<std::range_error>;
|
||||
template class exception<std::overflow_error>;
|
||||
template class exception<std::underflow_error>;
|
||||
// template class exception<std::future_error>;
|
||||
// template class exception<std::regex_error>;
|
||||
// template class exception<std::system_error>;
|
||||
// template class exception<std::bad_exception>;
|
||||
// template class exception<std::bad_function_call>;
|
||||
// template class exception<std::bad_alloc>;
|
||||
// template class exception<std::bad_array_new_length>;
|
||||
// template class exception<std::bad_cast>;
|
||||
// template class exception<std::bad_typeid>;
|
||||
// template class exception<std::bad_weak_ptr>;
|
||||
// template class exception<std::bad_any_cast>;
|
||||
// template class exception<std::bad_variant_access>;
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,53 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <timemory/unwind/backtrace.hpp>
|
||||
#include <timemory/utility/backtrace.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
template <typename Tp>
|
||||
class exception : public Tp
|
||||
{
|
||||
public:
|
||||
explicit exception(const std::string& _msg);
|
||||
explicit exception(const char* _msg);
|
||||
|
||||
~exception() override;
|
||||
|
||||
exception(exception&&) noexcept = default;
|
||||
exception& operator=(exception&&) noexcept = default;
|
||||
|
||||
exception(const exception&);
|
||||
exception& operator=(const exception&);
|
||||
|
||||
const char* what() const noexcept override;
|
||||
|
||||
private:
|
||||
char* m_what = nullptr;
|
||||
};
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,299 @@
|
||||
// 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.
|
||||
|
||||
#if !defined(OMNITRACE_USE_ROCM_SMI)
|
||||
# define OMNITRACE_USE_ROCM_SMI 0
|
||||
#endif
|
||||
|
||||
#if !defined(OMNITRACE_USE_HIP)
|
||||
# define OMNITRACE_USE_HIP 0
|
||||
#endif
|
||||
|
||||
#if OMNITRACE_USE_HIP > 0
|
||||
# if !defined(TIMEMORY_USE_HIP)
|
||||
# define TIMEMORY_USE_HIP 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "gpu.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <timemory/manager.hpp>
|
||||
|
||||
#if OMNITRACE_USE_ROCM_SMI > 0
|
||||
# include <rocm_smi/rocm_smi.h>
|
||||
#endif
|
||||
|
||||
#if OMNITRACE_USE_HIP > 0
|
||||
# include <hip/hip_runtime.h>
|
||||
# include <hip/hip_runtime_api.h>
|
||||
# include <timemory/components/hip/backends.hpp>
|
||||
|
||||
# if !defined(OMNITRACE_HIP_RUNTIME_CALL)
|
||||
# define OMNITRACE_HIP_RUNTIME_CALL(err) \
|
||||
{ \
|
||||
if(err != ::tim::hip::success_v && (int) err != 0) \
|
||||
{ \
|
||||
OMNITRACE_THROW( \
|
||||
"[%s:%d] Warning! HIP API call failed with code %i :: %s\n", \
|
||||
__FILE__, __LINE__, (int) err, hipGetErrorString(err)); \
|
||||
} \
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace scope = ::tim::scope;
|
||||
|
||||
#if OMNITRACE_USE_ROCM_SMI > 0
|
||||
# define OMNITRACE_ROCM_SMI_CALL(ERROR_CODE) \
|
||||
::omnitrace::gpu::check_rsmi_error(ERROR_CODE, __FILE__, __LINE__)
|
||||
|
||||
void
|
||||
check_rsmi_error(rsmi_status_t _code, const char* _file, int _line)
|
||||
{
|
||||
if(_code == RSMI_STATUS_SUCCESS) return;
|
||||
const char* _msg = nullptr;
|
||||
auto _err = rsmi_status_string(_code, &_msg);
|
||||
if(_err != RSMI_STATUS_SUCCESS)
|
||||
OMNITRACE_THROW("rsmi_status_string failed. No error message available. "
|
||||
"Error code %i originated at %s:%i\n",
|
||||
static_cast<int>(_code), _file, _line);
|
||||
OMNITRACE_THROW("[%s:%i] Error code %i :: %s", _file, _line, static_cast<int>(_code),
|
||||
_msg);
|
||||
}
|
||||
|
||||
bool
|
||||
rsmi_init()
|
||||
{
|
||||
auto _rsmi_init = []() {
|
||||
try
|
||||
{
|
||||
OMNITRACE_ROCM_SMI_CALL(::rsmi_init(0));
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_BASIC_VERBOSE(1, "Exception thrown initializing rocm-smi: %s\n",
|
||||
_e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
return _rsmi_init;
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
int
|
||||
hip_device_count()
|
||||
{
|
||||
#if OMNITRACE_USE_HIP > 0
|
||||
return ::tim::hip::device_count();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
rsmi_device_count()
|
||||
{
|
||||
#if OMNITRACE_USE_ROCM_SMI > 0
|
||||
if(!rsmi_init()) return 0;
|
||||
|
||||
static auto _num_devices = []() {
|
||||
uint32_t _v = 0;
|
||||
try
|
||||
{
|
||||
OMNITRACE_ROCM_SMI_CALL(rsmi_num_monitor_devices(&_v));
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_BASIC_VERBOSE(
|
||||
1, "Exception thrown getting the rocm-smi devices: %s\n", _e.what());
|
||||
}
|
||||
return _v;
|
||||
}();
|
||||
|
||||
return _num_devices;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
device_count()
|
||||
{
|
||||
#if OMNITRACE_USE_ROCM_SMI > 0
|
||||
// store as static since calls after rsmi_shutdown will return zero
|
||||
return rsmi_device_count();
|
||||
#elif OMNITRACE_USE_HIP > 0
|
||||
return ::tim::hip::device_count();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
void
|
||||
add_hip_device_metadata(ArchiveT& ar)
|
||||
{
|
||||
#if OMNITRACE_USE_HIP > 0
|
||||
namespace cereal = tim::cereal;
|
||||
using cereal::make_nvp;
|
||||
using intvec_t = std::vector<int>;
|
||||
|
||||
int _device_count = 0;
|
||||
int _current_device = 0;
|
||||
hipError_t _device_count_err = hipGetDeviceCount(&_device_count);
|
||||
|
||||
if(_device_count_err != hipSuccess) return;
|
||||
|
||||
hipError_t _current_device_err = hipGetDevice(&_current_device);
|
||||
|
||||
scope::destructor _dtor{ [_current_device, _current_device_err]() {
|
||||
if(_current_device_err == hipSuccess)
|
||||
{
|
||||
OMNITRACE_HIP_RUNTIME_CALL(hipSetDevice(_current_device));
|
||||
}
|
||||
} };
|
||||
|
||||
if(_current_device_err != hipSuccess || _device_count == 0) return;
|
||||
|
||||
# define OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(NAME) \
|
||||
ar(make_nvp(#NAME, _device_prop.NAME));
|
||||
|
||||
# define OMNITRACE_SERIALIZE_HIP_DEVICE_PROP_ARRAY(NAME, ...) \
|
||||
ar(make_nvp(NAME, __VA_ARGS__));
|
||||
|
||||
ar.setNextName("hip_device_properties");
|
||||
ar.startNode();
|
||||
ar.makeArray();
|
||||
|
||||
scope::destructor _prop_dtor{ [&ar]() { ar.finishNode(); } };
|
||||
for(int dev = 0; dev < _device_count; ++dev)
|
||||
{
|
||||
auto _device_prop = hipDeviceProp_t{};
|
||||
int _driver_version = 0;
|
||||
int _runtime_version = 0;
|
||||
OMNITRACE_HIP_RUNTIME_CALL(hipSetDevice(dev));
|
||||
OMNITRACE_HIP_RUNTIME_CALL(hipGetDeviceProperties(&_device_prop, dev));
|
||||
OMNITRACE_HIP_RUNTIME_CALL(hipDriverGetVersion(&_driver_version));
|
||||
OMNITRACE_HIP_RUNTIME_CALL(hipRuntimeGetVersion(&_runtime_version));
|
||||
|
||||
ar.startNode();
|
||||
ar(make_nvp("name", std::string{ _device_prop.name }));
|
||||
ar(make_nvp("driver_version", _driver_version));
|
||||
ar(make_nvp("runtime_version", _runtime_version));
|
||||
ar(make_nvp("capability.major_version", _device_prop.major));
|
||||
ar(make_nvp("capability.minor_version", _device_prop.minor));
|
||||
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(totalGlobalMem)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(totalConstMem)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(clockRate)
|
||||
|
||||
# if OMNITRACE_HIP_VERSION >= 5000
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(memoryClockRate)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(memoryBusWidth)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(l2CacheSize)
|
||||
# endif
|
||||
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(sharedMemPerBlock)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(regsPerBlock)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(warpSize)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(multiProcessorCount)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(maxThreadsPerMultiProcessor)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(maxThreadsPerBlock)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP_ARRAY(
|
||||
"maxThreadsDim",
|
||||
intvec_t{ _device_prop.maxThreadsDim[0], _device_prop.maxThreadsDim[1],
|
||||
_device_prop.maxThreadsDim[2] })
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP_ARRAY("maxGridSize",
|
||||
intvec_t{ _device_prop.maxGridSize[0],
|
||||
_device_prop.maxGridSize[1],
|
||||
_device_prop.maxGridSize[2] })
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(memPitch)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(textureAlignment)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(kernelExecTimeoutEnabled)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(integrated)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(canMapHostMemory)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(ECCEnabled)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(cooperativeLaunch)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(cooperativeMultiDeviceLaunch)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(pciDomainID)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(pciBusID)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(pciDeviceID)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(computeMode)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(computeMode)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(gcnArch)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(gcnArchName)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(isMultiGpuBoard)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(clockInstructionRate)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(pageableMemoryAccess)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(pageableMemoryAccessUsesHostPageTables)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(directManagedMemAccessFromHost)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(concurrentManagedAccess)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(concurrentKernels)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(maxSharedMemoryPerMultiProcessor)
|
||||
OMNITRACE_SERIALIZE_HIP_DEVICE_PROP(asicRevision)
|
||||
|
||||
const char* _compute_mode_descr[] = {
|
||||
"Default (multiple host threads can use ::hipSetDevice() with device "
|
||||
"simultaneously)",
|
||||
"Exclusive (only one host thread in one process is able to use "
|
||||
"::hipSetDevice() with this device)",
|
||||
"Prohibited (no host thread can use ::hipSetDevice() with this device)",
|
||||
"Exclusive Process (many threads in one process is able to use "
|
||||
"::hipSetDevice() with this device)",
|
||||
"Unknown",
|
||||
nullptr
|
||||
};
|
||||
ar(make_nvp("computeModeDescription",
|
||||
std::string{ _compute_mode_descr[_device_prop.computeMode] }));
|
||||
ar.finishNode();
|
||||
}
|
||||
#else
|
||||
(void) ar;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
add_hip_device_metadata()
|
||||
{
|
||||
if(device_count() == 0) return;
|
||||
|
||||
OMNITRACE_METADATA([](auto& ar) {
|
||||
try
|
||||
{
|
||||
add_hip_device_metadata(ar);
|
||||
} catch(std::runtime_error& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE(2, "%s\n", _e.what());
|
||||
}
|
||||
});
|
||||
}
|
||||
} // namespace gpu
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,41 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
int
|
||||
device_count();
|
||||
|
||||
int
|
||||
hip_device_count();
|
||||
|
||||
int
|
||||
rsmi_device_count();
|
||||
|
||||
void
|
||||
add_hip_device_metadata();
|
||||
} // namespace gpu
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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 "locking.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace locking
|
||||
{
|
||||
void
|
||||
atomic_mutex::lock()
|
||||
{
|
||||
while(!try_lock())
|
||||
{}
|
||||
}
|
||||
|
||||
void
|
||||
atomic_mutex::unlock()
|
||||
{
|
||||
if((m_value.load() & 1) == 1) ++m_value;
|
||||
}
|
||||
|
||||
bool
|
||||
atomic_mutex::try_lock()
|
||||
{
|
||||
auto _targ = m_value.load(std::memory_order_relaxed);
|
||||
if((_targ & 1) == 0)
|
||||
{
|
||||
return (
|
||||
m_value.compare_exchange_strong(_targ, _targ + 1, std::memory_order_relaxed));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
atomic_lock::atomic_lock(atomic_mutex& _v)
|
||||
: m_mutex{ _v }
|
||||
{
|
||||
lock();
|
||||
}
|
||||
|
||||
atomic_lock::atomic_lock(atomic_mutex& _v, std::defer_lock_t)
|
||||
: m_mutex{ _v }
|
||||
{}
|
||||
|
||||
atomic_lock::~atomic_lock() { unlock(); }
|
||||
|
||||
bool
|
||||
atomic_lock::owns_lock() const
|
||||
{
|
||||
return m_owns;
|
||||
}
|
||||
|
||||
void
|
||||
atomic_lock::lock()
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_owns = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
atomic_lock::unlock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
m_mutex.unlock();
|
||||
m_owns = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
atomic_lock::try_lock()
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
m_owns = m_mutex.try_lock();
|
||||
}
|
||||
return m_owns;
|
||||
}
|
||||
} // namespace locking
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,78 @@
|
||||
// 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 <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace locking
|
||||
{
|
||||
/// simple mutex which spins on an atomic while trying to lock.
|
||||
/// Provided for internal use for when there is low contention
|
||||
/// but we want to avoid using pthread mutexes since those
|
||||
/// are wrapped by library
|
||||
struct atomic_mutex
|
||||
{
|
||||
atomic_mutex() = default;
|
||||
~atomic_mutex() = default;
|
||||
|
||||
atomic_mutex(const atomic_mutex&) = delete;
|
||||
atomic_mutex(atomic_mutex&&) noexcept = delete;
|
||||
|
||||
atomic_mutex& operator=(const atomic_mutex&) = delete;
|
||||
atomic_mutex& operator=(atomic_mutex&&) noexcept = delete;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool try_lock();
|
||||
|
||||
private:
|
||||
std::atomic<int64_t> m_value = {};
|
||||
};
|
||||
|
||||
struct atomic_lock
|
||||
{
|
||||
atomic_lock(atomic_mutex&);
|
||||
atomic_lock(atomic_mutex&, std::defer_lock_t);
|
||||
~atomic_lock();
|
||||
|
||||
atomic_lock(const atomic_lock&) = delete;
|
||||
atomic_lock(atomic_lock&&) noexcept = delete;
|
||||
|
||||
atomic_lock& operator=(const atomic_lock&) = delete;
|
||||
atomic_lock& operator=(atomic_lock&&) noexcept = delete;
|
||||
|
||||
bool owns_lock() const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool try_lock();
|
||||
|
||||
private:
|
||||
bool m_owns = false;
|
||||
atomic_mutex& m_mutex;
|
||||
};
|
||||
} // namespace locking
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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 "mproc.hpp"
|
||||
#include "common.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace mproc
|
||||
{
|
||||
std::set<int>
|
||||
get_concurrent_processes(int _ppid)
|
||||
{
|
||||
std::set<int> _children = {};
|
||||
if(_ppid > 0)
|
||||
{
|
||||
auto _inp = JOIN('/', "/proc", _ppid, "task", _ppid, "children");
|
||||
std::ifstream _ifs{ _inp };
|
||||
if(!_ifs)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(2, "Warning! File '%s' cannot be read\n", _inp.c_str());
|
||||
return _children;
|
||||
}
|
||||
|
||||
while(_ifs)
|
||||
{
|
||||
int _v = -1;
|
||||
_ifs >> _v;
|
||||
if(!_ifs.good() || _ifs.eof()) break;
|
||||
if(_v < 0) continue;
|
||||
_children.emplace(_v);
|
||||
}
|
||||
}
|
||||
return _children;
|
||||
}
|
||||
|
||||
int
|
||||
get_process_index(int _pid, int _ppid)
|
||||
{
|
||||
auto _children = get_concurrent_processes(_ppid);
|
||||
for(auto itr = _children.begin(); itr != _children.end(); ++itr)
|
||||
{
|
||||
if(*itr == _pid) return std::distance(_children.begin(), itr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} // namespace mproc
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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 <set>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace mproc
|
||||
{
|
||||
// get the concurrent processes from /proc/<PPID>/task/<PPID>/children
|
||||
std::set<int>
|
||||
get_concurrent_processes(int _ppid = getppid());
|
||||
|
||||
int
|
||||
get_process_index(int _pid = getpid(), int _ppid = getppid());
|
||||
} // namespace mproc
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,101 @@
|
||||
// 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 "perfetto.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace perfetto
|
||||
{
|
||||
auto&
|
||||
get_config()
|
||||
{
|
||||
static auto _v = ::perfetto::TraceConfig{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_session()
|
||||
{
|
||||
static auto _v = std::unique_ptr<::perfetto::TracingSession>{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
auto args = ::perfetto::TracingInitArgs{};
|
||||
auto track_event_cfg = ::perfetto::protos::gen::TrackEventConfig{};
|
||||
auto& cfg = get_config();
|
||||
|
||||
// environment settings
|
||||
auto shmem_size_hint = config::get_perfetto_shmem_size_hint();
|
||||
auto buffer_size = config::get_perfetto_buffer_size();
|
||||
|
||||
auto _policy =
|
||||
config::get_perfetto_fill_policy() == "discard"
|
||||
? ::perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_DISCARD
|
||||
: ::perfetto::protos::gen::TraceConfig_BufferConfig_FillPolicy_RING_BUFFER;
|
||||
auto* buffer_config = cfg.add_buffers();
|
||||
buffer_config->set_size_kb(buffer_size);
|
||||
buffer_config->set_fill_policy(_policy);
|
||||
|
||||
for(const auto& itr : config::get_disabled_categories())
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Disabling perfetto track event category: %s\n",
|
||||
itr.c_str());
|
||||
track_event_cfg.add_disabled_categories(itr);
|
||||
}
|
||||
|
||||
auto* ds_cfg = cfg.add_data_sources()->mutable_config();
|
||||
ds_cfg->set_name("track_event"); // this MUST be track_event
|
||||
ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString());
|
||||
|
||||
args.shmem_size_hint_kb = shmem_size_hint;
|
||||
|
||||
if(get_backend() != "inprocess") args.backends |= ::perfetto::kSystemBackend;
|
||||
if(get_backend() != "system") args.backends |= ::perfetto::kInProcessBackend;
|
||||
|
||||
::perfetto::Tracing::Initialize(args);
|
||||
::perfetto::TrackEvent::Register();
|
||||
}
|
||||
|
||||
void
|
||||
start()
|
||||
{
|
||||
auto& cfg = get_config();
|
||||
auto& tracing_session = get_session();
|
||||
tracing_session = ::perfetto::Tracing::NewTrace();
|
||||
tracing_session->Setup(cfg);
|
||||
tracing_session->StartBlocking();
|
||||
}
|
||||
} // namespace perfetto
|
||||
|
||||
std::unique_ptr<::perfetto::TracingSession>&
|
||||
get_perfetto_session()
|
||||
{
|
||||
return ::omnitrace::perfetto::get_session();
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
|
||||
@@ -0,0 +1,155 @@
|
||||
// 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 "categories.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#if defined(TIMEMORY_USE_PERFETTO)
|
||||
# include <timemory/components/perfetto/backends.hpp>
|
||||
#else
|
||||
# include <perfetto.h>
|
||||
PERFETTO_DEFINE_CATEGORIES(OMNITRACE_PERFETTO_CATEGORIES);
|
||||
#endif
|
||||
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
std::unique_ptr<::perfetto::TracingSession>&
|
||||
get_perfetto_session();
|
||||
|
||||
template <typename Tp>
|
||||
struct perfetto_counter_track
|
||||
{
|
||||
using track_map_t = std::map<uint32_t, std::vector<::perfetto::CounterTrack>>;
|
||||
using name_map_t = std::map<uint32_t, std::vector<std::unique_ptr<std::string>>>;
|
||||
using data_t = std::pair<name_map_t, track_map_t>;
|
||||
|
||||
static auto init() { (void) get_data(); }
|
||||
static auto exists(size_t _idx, int64_t _n = -1);
|
||||
static size_t size(size_t _idx);
|
||||
static auto emplace(size_t _idx, const std::string& _v, const char* _units = nullptr,
|
||||
const char* _category = nullptr, int64_t _mult = 1,
|
||||
bool _incr = false);
|
||||
|
||||
static auto& at(size_t _idx, size_t _n) { return get_data().second.at(_idx).at(_n); }
|
||||
|
||||
private:
|
||||
static data_t& get_data()
|
||||
{
|
||||
static auto _v = data_t{};
|
||||
return _v;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
auto
|
||||
perfetto_counter_track<Tp>::exists(size_t _idx, int64_t _n)
|
||||
{
|
||||
bool _v = get_data().second.count(_idx) != 0;
|
||||
if(_n < 0 || !_v) return _v;
|
||||
return static_cast<size_t>(_n) < get_data().second.at(_idx).size();
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
size_t
|
||||
perfetto_counter_track<Tp>::size(size_t _idx)
|
||||
{
|
||||
bool _v = get_data().second.count(_idx) != 0;
|
||||
if(!_v) return 0;
|
||||
return get_data().second.at(_idx).size();
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
auto
|
||||
perfetto_counter_track<Tp>::emplace(size_t _idx, const std::string& _v,
|
||||
const char* _units, const char* _category,
|
||||
int64_t _mult, bool _incr)
|
||||
{
|
||||
auto& _name_data = get_data().first[_idx];
|
||||
auto& _track_data = get_data().second[_idx];
|
||||
std::vector<std::tuple<std::string, const char*, bool>> _missing = {};
|
||||
if(config::get_is_continuous_integration())
|
||||
{
|
||||
for(const auto& itr : _name_data)
|
||||
{
|
||||
_missing.emplace_back(std::make_tuple(*itr, itr->c_str(), false));
|
||||
}
|
||||
}
|
||||
auto _index = _track_data.size();
|
||||
auto& _name = _name_data.emplace_back(std::make_unique<std::string>(_v));
|
||||
const char* _unit_name = (_units && strlen(_units) > 0) ? _units : nullptr;
|
||||
_track_data.emplace_back(::perfetto::CounterTrack{ _name->c_str() }
|
||||
.set_unit_name(_unit_name)
|
||||
.set_category(_category)
|
||||
.set_unit_multiplier(_mult)
|
||||
.set_is_incremental(_incr));
|
||||
if(config::get_is_continuous_integration())
|
||||
{
|
||||
for(auto& itr : _missing)
|
||||
{
|
||||
const char* citr = std::get<1>(itr);
|
||||
for(const auto& ditr : _name_data)
|
||||
{
|
||||
if(citr == ditr->c_str() && strcmp(citr, ditr->c_str()) == 0)
|
||||
{
|
||||
std::get<2>(itr) = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!std::get<2>(itr))
|
||||
{
|
||||
std::set<void*> _prev = {};
|
||||
std::set<void*> _curr = {};
|
||||
for(const auto& eitr : _missing)
|
||||
_prev.emplace(
|
||||
static_cast<void*>(const_cast<char*>(std::get<1>(eitr))));
|
||||
for(const auto& eitr : _name_data)
|
||||
_curr.emplace(static_cast<void*>(const_cast<char*>(eitr->c_str())));
|
||||
std::stringstream _pss{};
|
||||
for(auto&& eitr : _prev)
|
||||
_pss << " " << std::hex << std::setw(12) << std::left << eitr;
|
||||
std::stringstream _css{};
|
||||
for(auto&& eitr : _curr)
|
||||
_css << " " << std::hex << std::setw(12) << std::left << eitr;
|
||||
OMNITRACE_THROW("perfetto_counter_track emplace method for '%s' (%p) "
|
||||
"invalidated C-string '%s' (%p).\n%8s: %s\n%8s: %s\n",
|
||||
_v.c_str(), (void*) _name->c_str(),
|
||||
std::get<0>(itr).c_str(),
|
||||
(void*) std::get<0>(itr).c_str(), "previous",
|
||||
_pss.str().c_str(), "current", _css.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return _index;
|
||||
}
|
||||
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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 "core/defines.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace config
|
||||
{
|
||||
bool
|
||||
get_debug() OMNITRACE_HOT;
|
||||
|
||||
int
|
||||
get_verbose() OMNITRACE_HOT;
|
||||
} // namespace config
|
||||
|
||||
struct redirect
|
||||
{
|
||||
redirect(std::ostream& _os, std::string _expected)
|
||||
: m_os{ _os }
|
||||
, m_expected{ std::move(_expected) }
|
||||
{
|
||||
if(!get_debug())
|
||||
{
|
||||
// save stream buffer
|
||||
m_strm_buffer = m_os.rdbuf();
|
||||
// redirect to stringstream
|
||||
_os.rdbuf(m_buffer.rdbuf());
|
||||
}
|
||||
}
|
||||
|
||||
~redirect()
|
||||
{
|
||||
if(!m_strm_buffer) return;
|
||||
// restore stream buffer
|
||||
m_os.rdbuf(m_strm_buffer);
|
||||
auto _v = m_buffer.str();
|
||||
_v = replace<3>(m_buffer.str(), { '\n', '\t', ' ' });
|
||||
auto _expect = replace<3>(m_expected, { '\n', '\t', ' ' });
|
||||
if(_v != _expect)
|
||||
{
|
||||
if(get_verbose() > 0)
|
||||
std::cerr << "[omnitrace::redirect] Expected:\n[omnitrace::redirect] "
|
||||
<< _expect
|
||||
<< "\n[omnitrace::redirect] Found:\n[omnitrace::redirect] "
|
||||
<< _v << "\n";
|
||||
if(get_verbose() <= 0 || (&m_os != &std::cerr && &m_os != &std::cout))
|
||||
m_os << m_buffer.str() << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <size_t N>
|
||||
static std::string replace(std::string _v, const std::array<char, N>& _c,
|
||||
const std::string& _s = "")
|
||||
{
|
||||
for(const auto& itr : _c)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
auto _pos = _v.find(itr);
|
||||
if(_pos == std::string::npos) break;
|
||||
_v = _v.replace(_pos, 1, _s);
|
||||
}
|
||||
}
|
||||
return _v;
|
||||
}
|
||||
|
||||
std::ostream& m_os;
|
||||
std::string m_expected = {};
|
||||
std::stringstream m_buffer{};
|
||||
std::streambuf* m_strm_buffer = nullptr;
|
||||
};
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,172 @@
|
||||
// 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 "state.hpp"
|
||||
#include "config.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "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); });
|
||||
|
||||
if(_idx >= OMNITRACE_MAX_THREADS)
|
||||
{
|
||||
static thread_local auto _tl_v = utility::get_reserved_vector<ThreadState>(32);
|
||||
return _tl_v;
|
||||
}
|
||||
|
||||
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
|
||||
to_string(omnitrace::State _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::State::PreInit: return "PreInit";
|
||||
case omnitrace::State::Init: return "Init";
|
||||
case omnitrace::State::Active: return "Active";
|
||||
case omnitrace::State::Disabled: return "Disabled";
|
||||
case omnitrace::State::Finalized: return "Finalized";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::ThreadState _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::ThreadState::Enabled: return "Enabled";
|
||||
case omnitrace::ThreadState::Internal: return "Internal";
|
||||
case omnitrace::ThreadState::Completed: return "Completed";
|
||||
case omnitrace::ThreadState::Disabled: return "Disabled";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::Mode _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::Mode::Trace: return "Trace";
|
||||
case omnitrace::Mode::Sampling: return "Sampling";
|
||||
case omnitrace::Mode::Causal: return "Causal";
|
||||
case omnitrace::Mode::Coverage: return "Coverage";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::CausalMode _v)
|
||||
{
|
||||
switch(_v)
|
||||
{
|
||||
case omnitrace::CausalMode::Line: return "Line";
|
||||
case omnitrace::CausalMode::Function: return "Function";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} // namespace std
|
||||
@@ -0,0 +1,114 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
// used for specifying the state of omnitrace
|
||||
enum class State : unsigned short
|
||||
{
|
||||
PreInit = 0,
|
||||
Init,
|
||||
Active,
|
||||
Finalized,
|
||||
Disabled,
|
||||
};
|
||||
|
||||
// used for specifying the state of omnitrace
|
||||
enum class ThreadState : unsigned short
|
||||
{
|
||||
Enabled = 0,
|
||||
Internal,
|
||||
Completed,
|
||||
Disabled,
|
||||
};
|
||||
|
||||
enum class Mode : unsigned short
|
||||
{
|
||||
Trace = 0,
|
||||
Sampling,
|
||||
Causal,
|
||||
Coverage
|
||||
};
|
||||
|
||||
enum class CausalMode : unsigned short
|
||||
{
|
||||
Line = 0,
|
||||
Function
|
||||
};
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
#define OMNITRACE_SCOPED_THREAD_STATE(STATE) \
|
||||
::omnitrace::scoped_thread_state OMNITRACE_VARIABLE(_scoped_thread_state_, __LINE__) \
|
||||
{ \
|
||||
::omnitrace::STATE \
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
std::string
|
||||
to_string(omnitrace::State _v);
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::ThreadState _v);
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::Mode _v);
|
||||
|
||||
std::string
|
||||
to_string(omnitrace::CausalMode _v);
|
||||
} // namespace std
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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 "timemory.hpp"
|
||||
|
||||
using namespace omnitrace;
|
||||
|
||||
TIMEMORY_INITIALIZE_STORAGE(comp::wall_clock, comp::user_global_bundle)
|
||||
@@ -0,0 +1,59 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/fwd.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <timemory/api.hpp>
|
||||
#include <timemory/backends/mpi.hpp>
|
||||
#include <timemory/backends/process.hpp>
|
||||
#include <timemory/backends/threading.hpp>
|
||||
#include <timemory/components.hpp>
|
||||
#include <timemory/components/gotcha/mpip.hpp>
|
||||
#include <timemory/config.hpp>
|
||||
#include <timemory/environment.hpp>
|
||||
#include <timemory/manager.hpp>
|
||||
#include <timemory/mpl.hpp>
|
||||
#include <timemory/operations.hpp>
|
||||
#include <timemory/runtime.hpp>
|
||||
#include <timemory/settings.hpp>
|
||||
#include <timemory/storage.hpp>
|
||||
#include <timemory/utility/signals.hpp>
|
||||
#include <timemory/variadic.hpp>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace audit = ::tim::audit; // NOLINT
|
||||
namespace comp = ::tim::component; // NOLINT
|
||||
namespace dmp = ::tim::dmp; // NOLINT
|
||||
namespace operation = ::tim::operation; // NOLINT
|
||||
namespace quirk = ::tim::quirk; // NOLINT
|
||||
namespace units = ::tim::units; // NOLINT
|
||||
|
||||
using settings = ::tim::settings; // NOLINT
|
||||
|
||||
using ::tim::get_env; // NOLINT
|
||||
using ::tim::set_env; // NOLINT
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,242 @@
|
||||
// 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 "concepts.hpp"
|
||||
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/utility/join.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
/// provides an alternative thread index for when using threading::get_id() is not
|
||||
/// desirable
|
||||
inline auto
|
||||
get_thread_index()
|
||||
{
|
||||
static std::atomic<int64_t> _c{ 0 };
|
||||
static thread_local int64_t _v = _c++;
|
||||
return _v;
|
||||
}
|
||||
|
||||
/// fills any array with the result of the functor
|
||||
template <size_t N, typename FuncT>
|
||||
inline auto
|
||||
get_filled_array(FuncT&& _func)
|
||||
{
|
||||
using Tp = std::decay_t<decltype(_func())>;
|
||||
std::array<Tp, N> _v{};
|
||||
for(auto& itr : _v)
|
||||
itr = std::move(_func());
|
||||
return _v;
|
||||
}
|
||||
|
||||
/// returns a vector with a preallocated buffer
|
||||
template <typename... Tp>
|
||||
inline auto
|
||||
get_reserved_vector(size_t _n)
|
||||
{
|
||||
std::vector<Tp...> _v{};
|
||||
_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;
|
||||
|
||||
template <typename Tp>
|
||||
struct generate
|
||||
{
|
||||
using type = Tp;
|
||||
|
||||
template <typename... Args>
|
||||
auto operator()(Args&&... _args) const
|
||||
{
|
||||
if constexpr(concepts::is_unique_pointer<Tp>::value)
|
||||
{
|
||||
using value_type = typename type::element_type;
|
||||
|
||||
if constexpr(use_placement_new_when_generating_unique_ptr<value_type>::value)
|
||||
{
|
||||
// create a thread-local buffer for placement-new
|
||||
static thread_local auto _buffer = std::array<char, sizeof(value_type)>{};
|
||||
if constexpr(std::is_constructible<value_type, Args...>::value)
|
||||
{
|
||||
return type{ new(_buffer.data())
|
||||
value_type{ std::forward<Args>(_args)... } };
|
||||
}
|
||||
else
|
||||
{
|
||||
return type{ new(_buffer.data())
|
||||
value_type{ invoke(std::forward<Args>(_args))... } };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr(std::is_constructible<value_type, Args...>::value)
|
||||
{
|
||||
return type{ new value_type{ std::forward<Args>(_args)... } };
|
||||
}
|
||||
else
|
||||
{
|
||||
return type{ new value_type{ invoke(std::forward<Args>(_args))... } };
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr(std::is_constructible<type, Args...>::value)
|
||||
{
|
||||
return type{ std::forward<Args>(_args)... };
|
||||
}
|
||||
else
|
||||
{
|
||||
return type{ invoke(std::forward<Args>(_args))... };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Up>
|
||||
static auto invoke(Up&& _v, int,
|
||||
std::enable_if_t<std::is_invocable<Up>::value, int> = 0)
|
||||
-> decltype(std::forward<Up>(_v)())
|
||||
{
|
||||
return std::forward<Up>(_v)();
|
||||
}
|
||||
|
||||
template <typename Up>
|
||||
static auto&& invoke(Up&& _v, long)
|
||||
{
|
||||
return std::forward<Up>(_v);
|
||||
}
|
||||
|
||||
template <typename Up>
|
||||
static decltype(auto) invoke(Up&& _v)
|
||||
{
|
||||
return invoke(std::forward<Up>(_v), 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename, typename...> class ContainerT, typename DataT,
|
||||
typename... TailT, typename PredicateT = bool (*)(const DataT&)>
|
||||
inline ContainerT<DataT, TailT...>&
|
||||
filter_sort_unique(
|
||||
ContainerT<DataT, TailT...>& _v,
|
||||
PredicateT&& _predicate = [](const auto& itr) { return !itr; })
|
||||
{
|
||||
_v.erase(std::remove_if(_v.begin(), _v.end(), std::forward<PredicateT>(_predicate)),
|
||||
_v.end());
|
||||
std::sort(_v.begin(), _v.end());
|
||||
|
||||
auto _last = std::unique(_v.begin(), _v.end());
|
||||
if(std::distance(_v.begin(), _last) > 0) _v.erase(_last, _v.end());
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename LhsT, typename RhsT>
|
||||
inline LhsT&
|
||||
combine(LhsT& _lhs, RhsT&& _rhs)
|
||||
{
|
||||
for(auto&& itr : _rhs)
|
||||
_lhs.emplace_back(itr);
|
||||
return _lhs;
|
||||
}
|
||||
|
||||
template <template <typename, typename...> class ContainerT, typename Tp,
|
||||
typename... TailT>
|
||||
std::string
|
||||
get_regex_or(const ContainerT<Tp, TailT...>& _container, const std::string& _fallback)
|
||||
{
|
||||
static_assert(tim::concepts::is_string_type<Tp>::value,
|
||||
"get_regex_or requires a container of string types");
|
||||
|
||||
if(_container.empty()) return _fallback;
|
||||
|
||||
namespace join = timemory::join;
|
||||
return join::join(join::array_config{ "|", "(", ")" }, _container);
|
||||
}
|
||||
|
||||
template <template <typename, typename...> class ContainerT, typename Tp,
|
||||
typename... TailT, typename PredicateT>
|
||||
std::string
|
||||
get_regex_or(const ContainerT<Tp, TailT...>& _container, PredicateT&& _predicate,
|
||||
const std::string& _fallback)
|
||||
{
|
||||
static_assert(tim::concepts::is_string_type<Tp>::value,
|
||||
"get_regex_or requires a container of string types");
|
||||
|
||||
if(_container.empty()) return _fallback;
|
||||
|
||||
auto _dest = std::vector<std::string>{};
|
||||
_dest.reserve(_container.size());
|
||||
for(const auto& itr : _container)
|
||||
_dest.emplace_back(_predicate(itr));
|
||||
|
||||
return get_regex_or(_dest, _fallback);
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
Tp
|
||||
convert(std::string_view _inp)
|
||||
{
|
||||
auto _iss = std::stringstream{};
|
||||
auto _ret = Tp{};
|
||||
_iss << _inp;
|
||||
_iss >> _ret;
|
||||
return _ret;
|
||||
}
|
||||
} // namespace utility
|
||||
} // namespace omnitrace
|
||||
Reference in New Issue
Block a user