omnitrace-avail generate config (#69)

* Config updates

- See PR #69 for details

- change type of OMNITRACE_DL_VERBOSE
- add "deprecated" category to OMNITRACE_ROCM_SMI_DEVICES
- reduce size of perfetto shared memory size hint
- deprecate OMNITRACE_OUTPUT_FILE in favor of OMNITRACE_PERFETTO_FILE
- set papi event choices
- read config file after reading command line
- fix update of OMNITRACE_DL_VERBOSE
- mark several settings as hidden
- timemory update support hidden attribute for settings
- rework get_perfetto_output_filename()
- Hide settings from not available backends

* Rework omnitrace-avail to support dumping configurations

* Overwrite query, tests, output flag

- Support using -O flag when dumping config
- Support checking before overwriting existing config
- Support --force to overwrite existing config
- Fix get_component_info not including omnitrace components
- Testing for dumping config

* Update documentation on omnitrace-avail

* Fix issue with timemory format + "/__w/"

* Update output prefix keys docs

* Rename --dump-config to --generate-config

* Hide MPI related options

- OMNITRACE_PERFETTO_COMBINE_TRACES and OMNITRACE_COLLAPSE_PROCESSES are hidden w/o MPI support


[ROCm/rocprofiler-systems commit: 1877ebf47b]
This commit is contained in:
Jonathan R. Madsen
2022-06-28 01:36:04 -05:00
committed by GitHub
parent d622135c92
commit cb0b57b8e6
22 changed files with 2067 additions and 870 deletions
@@ -4,10 +4,24 @@
#
# ------------------------------------------------------------------------------#
add_executable(
add_executable(omnitrace-avail)
target_sources(
omnitrace-avail
${CMAKE_CURRENT_LIST_DIR}/avail.cpp ${CMAKE_CURRENT_LIST_DIR}/avail.hpp
$<TARGET_OBJECTS:omnitrace::omnitrace-object-library>)
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/avail.cpp
${CMAKE_CURRENT_LIST_DIR}/avail.hpp
${CMAKE_CURRENT_LIST_DIR}/common.cpp
${CMAKE_CURRENT_LIST_DIR}/common.hpp
${CMAKE_CURRENT_LIST_DIR}/component_categories.hpp
${CMAKE_CURRENT_LIST_DIR}/defines.hpp
${CMAKE_CURRENT_LIST_DIR}/enumerated_list.hpp
${CMAKE_CURRENT_LIST_DIR}/generate_config.cpp
${CMAKE_CURRENT_LIST_DIR}/generate_config.hpp
${CMAKE_CURRENT_LIST_DIR}/get_availability.hpp
${CMAKE_CURRENT_LIST_DIR}/get_categories.hpp
${CMAKE_CURRENT_LIST_DIR}/info_type.cpp
${CMAKE_CURRENT_LIST_DIR}/info_type.hpp
$<TARGET_OBJECTS:omnitrace::omnitrace-object-library>)
target_include_directories(omnitrace-avail PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_compile_definitions(omnitrace-avail PRIVATE OMNITRACE_EXTERN_COMPONENTS=0)
File diff suppressed because it is too large Load Diff
@@ -22,8 +22,7 @@
#pragma once
#define TIMEMORY_DISABLE_BANNER
#define TIMEMORY_DISABLE_COMPONENT_STORAGE_INIT
#include "defines.hpp"
#include <timemory/settings/macros.hpp>
#include <timemory/tpls/cereal/archives.hpp>
@@ -0,0 +1,393 @@
// 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 "common.hpp"
#include <timemory/mpl/apply.hpp>
#include <timemory/settings/settings.hpp>
#include <timemory/variadic/macros.hpp>
#include <string>
#include <sys/stat.h>
using settings = ::tim::settings;
std::string global_delim = std::string{ "|" };
bool csv = false;
bool markdown = false;
bool alphabetical = false;
bool available_only = false;
bool all_info = false;
bool force_brief = false;
bool debug_msg = false;
bool case_insensitive = false;
bool regex_hl = false;
bool expand_keys = false;
bool force_config = false;
int32_t max_width = 0;
int32_t num_cols = 0;
int32_t min_width = 40;
int32_t padding = 4;
str_vec_t regex_keys = {};
str_vec_t category_regex_keys = {};
str_set_t category_view = {};
std::stringstream lerr = {};
// explicit setting names to exclude
std::set<std::string> settings_exclude = {
"OMNITRACE_ENVIRONMENT",
"OMNITRACE_COMMAND_LINE",
"cereal_class_version",
"settings",
};
//--------------------------------------------------------------------------------------//
namespace
{
const auto&
get_regex_constants()
{
static auto _constants = []() {
auto _v = regex_const::egrep | regex_const::optimize;
if(case_insensitive) _v |= regex_const::icase;
return _v;
}();
return _constants;
}
const auto&
get_regex_pattern()
{
static auto _pattern = []() {
std::array<std::string, 2> _v{};
for(const auto& itr : regex_keys)
{
if(itr.empty()) continue;
std::string _pattern = {};
if(itr.at(0) == '~')
{
_pattern = itr.substr(1);
_v.at(1) += "|" + _pattern;
}
else
{
_pattern = itr;
_v.at(0) += "|" + _pattern;
}
lerr << "Adding regex key: '" << _pattern << "'...\n";
}
for(auto& itr : _v)
if(!itr.empty()) itr = itr.substr(1);
return _v;
}();
return _pattern;
}
auto
get_regex()
{
static auto _rc = std::array<std::regex, 2>{
std::regex(get_regex_pattern().at(0), get_regex_constants()),
std::regex(get_regex_pattern().at(1), get_regex_constants())
};
return _rc;
}
bool
regex_match(const std::string& _line)
{
if(get_regex_pattern().at(0).empty() && get_regex_pattern().at(1).empty())
return true;
static size_t lerr_width = 0;
lerr_width = std::max<size_t>(lerr_width, _line.length());
std::stringstream _line_ss;
_line_ss << "'" << _line << "'";
if(!get_regex_pattern().at(1).empty())
{
if(std::regex_match(_line, get_regex().at(1)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " matched negating pattern '" << get_regex_pattern().at(1)
<< "'...\n";
return false;
}
if(std::regex_search(_line, get_regex().at(1)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " found negating pattern '" << get_regex_pattern().at(1) << "'...\n";
return false;
}
}
if(!get_regex_pattern().at(0).empty())
{
if(std::regex_match(_line, get_regex().at(0)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " matched pattern '" << get_regex_pattern().at(0) << "'...\n";
return true;
}
if(std::regex_search(_line, get_regex().at(0)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " found pattern '" << get_regex_pattern().at(0) << "'...\n";
return true;
}
}
lerr << std::left << std::setw(lerr_width) << _line_ss.str() << " missing pattern '"
<< get_regex_pattern().at(0) << "'...\n";
return false;
}
std::string
regex_replace(const std::string& _line)
{
#if defined(TIMEMORY_UNIX)
if(get_regex_pattern().empty()) return _line;
if(regex_match(_line))
return std::regex_replace(_line, get_regex().at(0), "\33[01;04;36;40m$&\33[0m");
#endif
return _line;
}
const auto&
get_category_regex_pattern()
{
static auto _pattern = []() {
std::array<std::string, 2> _v{};
for(const auto& itr : category_regex_keys)
{
if(itr.empty()) continue;
std::string _pattern = {};
if(itr.at(0) == '~')
{
_pattern = itr.substr(1);
_v.at(1) += "|" + _pattern;
}
else
{
_pattern = itr;
_v.at(0) += "|" + _pattern;
}
lerr << "Adding category regex key: '" << _pattern << "'...\n";
}
for(auto& itr : _v)
if(!itr.empty()) itr = itr.substr(1);
return _v;
}();
return _pattern;
}
auto
get_category_regex()
{
static auto _rc = std::array<std::regex, 2>{
std::regex(get_category_regex_pattern().at(0), get_regex_constants()),
std::regex(get_category_regex_pattern().at(1), get_regex_constants())
};
return _rc;
}
bool
category_regex_match(const std::string& _line)
{
if(get_category_regex_pattern().at(0).empty() &&
get_category_regex_pattern().at(1).empty())
return true;
static size_t lerr_width = 0;
lerr_width = std::max<size_t>(lerr_width, _line.length());
std::stringstream _line_ss;
_line_ss << "'" << _line << "'";
if(!get_category_regex_pattern().at(1).empty())
{
if(std::regex_match(_line, get_category_regex().at(1)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " matched negating category pattern '"
<< get_category_regex_pattern().at(1) << "'...\n";
return false;
}
if(std::regex_search(_line, get_category_regex().at(1)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " found negating category pattern '"
<< get_category_regex_pattern().at(1) << "'...\n";
return false;
}
}
if(!get_category_regex_pattern().at(0).empty())
{
if(std::regex_match(_line, get_category_regex().at(0)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " matched category pattern '" << get_category_regex_pattern().at(0)
<< "'...\n";
return true;
}
if(std::regex_search(_line, get_category_regex().at(0)))
{
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " found category pattern '" << get_category_regex_pattern().at(0)
<< "'...\n";
return true;
}
}
lerr << std::left << std::setw(lerr_width) << _line_ss.str()
<< " missing category pattern '" << get_category_regex_pattern().at(0)
<< "'...\n";
return false;
}
} // namespace
//--------------------------------------------------------------------------------------//
bool
is_selected(const std::string& _line)
{
return regex_match(_line);
}
//--------------------------------------------------------------------------------------//
bool
is_category_selected(const std::string& _line)
{
return category_regex_match(_line);
}
//--------------------------------------------------------------------------------------//
std::string
hl_selected(const std::string& _line)
{
return (regex_hl) ? regex_replace(_line) : _line;
}
//--------------------------------------------------------------------------------------//
void
process_categories(parser_t& p, const str_set_t& _category_options)
{
category_view = p.get<str_set_t>("categories");
std::vector<std::function<void()>> _shorthand_patches{};
for(const auto& itr : category_view)
{
auto _is_shorthand = [&_shorthand_patches, &_category_options,
itr](const std::string& _prefix) {
auto _opt = TIMEMORY_JOIN("::", _prefix, itr);
if(_category_options.count(_opt) > 0)
{
_shorthand_patches.emplace_back([itr, _opt]() {
category_view.erase(itr);
category_view.emplace(_opt);
});
return true;
}
return false;
};
if(_category_options.count(itr) == 0)
{
if(!_is_shorthand("component") && !_is_shorthand("settings"))
throw std::runtime_error(
itr + " is not a valid category. Use --list-categories to view "
"valid categories");
}
}
for(auto&& itr : _shorthand_patches)
itr();
}
//--------------------------------------------------------------------------------------//
bool
exclude_setting(const std::string& _v)
{
if(settings_exclude.find(_v) != settings_exclude.end()) return true;
auto itr = settings::instance()->find(_v, false);
if(itr == settings::instance()->end()) return true;
return itr->second->get_hidden();
}
//--------------------------------------------------------------------------------------//
void
dump_log()
{
if(debug_msg)
{
std::cerr << lerr.str() << std::flush;
lerr = std::stringstream{};
}
}
void
dump_log_abort(int _v)
{
fprintf(stderr, "\n[omnitrace-avail] Exiting with signal %i...\n", _v);
debug_msg = true;
dump_log();
}
//--------------------------------------------------------------------------------------//
std::string
remove(std::string inp, const std::set<std::string>& entries)
{
for(const auto& itr : entries)
{
auto idx = inp.find(itr);
while(idx != std::string::npos)
{
inp.erase(idx, itr.length());
idx = inp.find(itr);
}
}
return inp;
}
//--------------------------------------------------------------------------------------//
bool
file_exists(const std::string& _fname)
{
struct stat _buffer;
if(stat(_fname.c_str(), &_buffer) == 0)
return (S_ISREG(_buffer.st_mode) != 0 || S_ISLNK(_buffer.st_mode) != 0);
return false;
}
//--------------------------------------------------------------------------------------//
@@ -0,0 +1,145 @@
// 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/components/types.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/settings/types.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/type_list.hpp>
#include <array>
#include <cstddef>
#include <regex>
#include <set>
#include <sstream>
#include <string>
#include <vector>
//--------------------------------------------------------------------------------------//
// namespaces
namespace regex_const = ::std::regex_constants; // NOLINT
namespace comp = ::tim::component; // NOLINT
using settings = ::tim::settings; // NOLINT
using tim::demangle; // NOLINT
using tim::type_list; // NOLINT
//--------------------------------------------------------------------------------------//
// aliases
template <typename Tp, size_t N>
using array_t = ::std::array<Tp, N>;
using string_t = ::std::string;
using stringstream_t = ::std::stringstream;
using str_vec_t = ::std::vector<string_t>;
using str_set_t = ::std::set<string_t>;
using info_type_base = ::std::tuple<string_t, bool, str_vec_t>;
using parser_t = ::tim::argparse::argument_parser;
//--------------------------------------------------------------------------------------//
// enums
enum : int
{
VAL = 0,
ENUM = 1,
LANG = 2,
CID = 3,
FNAME = 4,
DESC = 5,
CATEGORY = 6,
TOTAL = 7
};
//--------------------------------------------------------------------------------------//
// variables
constexpr size_t num_component_options = 7;
constexpr size_t num_settings_options = 4;
constexpr size_t num_hw_counter_options = 4;
constexpr size_t num_dump_config_options = TOTAL;
extern std::string global_delim;
extern bool csv;
extern bool markdown;
extern bool alphabetical;
extern bool available_only;
extern bool all_info;
extern bool force_brief;
extern bool debug_msg;
extern bool case_insensitive;
extern bool regex_hl;
extern bool expand_keys;
extern bool force_config;
extern int32_t max_width;
extern int32_t num_cols;
extern int32_t min_width;
extern int32_t padding;
extern str_vec_t regex_keys;
extern str_vec_t category_regex_keys;
extern str_set_t category_view;
extern std::stringstream lerr;
// explicit setting names to exclude
extern std::set<std::string> settings_exclude;
// exclude some timemory settings which are not relevant to omnitrace
// exact matches, e.g. OMNITRACE_BANNER
extern std::string settings_rexclude_exact;
// leading matches, e.g. OMNITRACE_MPI_[A-Z_]+
extern std::string settings_rexclude_begin;
//--------------------------------------------------------------------------------------//
// functions
bool
is_selected(const std::string& line);
bool
is_category_selected(const std::string& _line);
std::string
hl_selected(const std::string& line);
void
process_categories(parser_t&, const str_set_t&);
bool
exclude_setting(const std::string&);
void
dump_log();
void
dump_log_abort(int _v);
std::string
remove(std::string inp, const std::set<std::string>& entries);
bool
file_exists(const std::string&);
@@ -0,0 +1,84 @@
// 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 <timemory/components/types.hpp>
#include <timemory/enum.h>
#include <timemory/utility/types.hpp>
#include <set>
#include <string>
template <typename Type = void>
struct component_categories;
template <typename Type>
struct component_categories
{
template <typename... Tp>
void operator()(std::set<std::string>& _v, type_list<Tp...>) const
{
//
auto _cleanup = [](std::string _type, const std::string& _pattern) {
auto _pos = std::string::npos;
while((_pos = _type.find(_pattern)) != std::string::npos)
_type = _type.erase(_pos, _pattern.length());
return _type;
};
(void) _cleanup; // unused but set if sizeof...(Tp) == 0
TIMEMORY_FOLD_EXPRESSION(_v.emplace(TIMEMORY_JOIN(
"::", "component", _cleanup(tim::try_demangle<Tp>(), "tim::"))));
}
void operator()(std::set<std::string>& _v) const
{
if constexpr(!tim::concepts::is_placeholder<Type>::value)
(*this)(_v, tim::trait::component_apis_t<Type>{});
}
};
template <>
struct component_categories<void>
{
template <size_t... Idx>
void operator()(std::set<std::string>& _v, std::index_sequence<Idx...>) const
{
TIMEMORY_FOLD_EXPRESSION(component_categories<comp::enumerator_t<Idx>>{}(_v));
}
void operator()(std::set<std::string>& _v) const
{
(*this)(_v, std::make_index_sequence<TIMEMORY_COMPONENTS_END>{});
}
auto operator()() const
{
std::set<std::string> _categories{};
(*this)(_categories);
return _categories;
}
};
@@ -0,0 +1,29 @@
// 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
#define TIMEMORY_DISABLE_BANNER
#define TIMEMORY_DISABLE_COMPONENT_STORAGE_INIT
#include "library/config.hpp"
#include "library/defines.hpp"
@@ -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 "common.hpp"
#include "defines.hpp"
#include <timemory/components/properties.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/utility/type_list.hpp>
#include <cstddef>
#include <tuple>
#include <type_traits>
template <typename T, typename I>
struct enumerated_list;
template <template <typename...> class TupT, typename... T>
struct enumerated_list<TupT<T...>, std::index_sequence<>>
{
using type = type_list<T...>;
};
template <template <typename...> class TupT, size_t I, typename... T, size_t... Idx>
struct enumerated_list<TupT<T...>, std::index_sequence<I, Idx...>>
{
using Tp = tim::component::enumerator_t<I>;
static constexpr bool is_nothing = tim::concepts::is_placeholder<Tp>::value;
using type = typename enumerated_list<
std::conditional_t<is_nothing, type_list<T...>, type_list<T..., Tp>>,
std::index_sequence<Idx...>>::type;
};
@@ -0,0 +1,437 @@
// 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 "generate_config.hpp"
#include "common.hpp"
#include "defines.hpp"
#include "info_type.hpp"
#include <timemory/mpl/concepts.hpp>
#include <timemory/mpl/policy.hpp>
#include <timemory/settings.hpp>
#include <timemory/settings/types.hpp>
#include <timemory/tpls/cereal/archives.hpp>
#include <timemory/tpls/cereal/cereal.hpp>
#include <timemory/tpls/cereal/cereal/archives/json.hpp>
#include <timemory/tpls/cereal/cereal/archives/xml.hpp>
#include <timemory/tpls/cereal/cereal/cereal.hpp>
#include <timemory/utility/filepath.hpp>
#include <timemory/utility/types.hpp>
#include <cstddef>
#include <cstdlib>
#include <sstream>
#include <string>
namespace cereal = ::tim::cereal;
namespace filepath = ::tim::filepath;
using settings = ::tim::settings;
using ::tim::tsettings;
using ::tim::type_list;
using ::tim::policy::output_archive;
namespace
{
struct custom_setting_serializer
{
static std::array<bool, TOTAL> options;
};
template <typename Tp>
bool
ignore_setting(const Tp& _v)
{
if(_v->get_hidden()) return true;
if(exclude_setting(_v->get_env_name())) return true;
if(!is_selected(_v->get_env_name()) && !is_selected(_v->get_name())) return true;
if(available_only && !_v->get_enabled()) return true;
if(!category_view.empty())
{
bool _found = false;
for(auto& itr : _v->get_categories())
{
if(category_view.count(itr) > 0 ||
category_view.count(TIMEMORY_JOIN("::", "settings", itr)) > 0)
{
_found = true;
break;
}
}
if(!_found) return true;
}
if(category_view.count("deprecated") == 0 &&
category_view.count("settings::deprecated") == 0 &&
_v->get_categories().count("deprecated") > 0)
return true;
return false;
}
} // namespace
std::array<bool, TOTAL> custom_setting_serializer::options = { false };
namespace tim
{
namespace operation
{
template <typename Tp>
struct setting_serialization<Tp, custom_setting_serializer>
{
template <typename ArchiveT>
void operator()(ArchiveT&, const char*, const Tp&) const
{}
template <typename ArchiveT>
void operator()(ArchiveT&, const char*, Tp&&) const
{}
};
//
template <typename Tp>
struct setting_serialization<tsettings<Tp>, custom_setting_serializer>
{
using value_type = tsettings<Tp>;
template <typename ArchiveT>
void operator()(ArchiveT& _ar, value_type& _val) const
{
static_assert(concepts::is_output_archive<ArchiveT>::value,
"Requires an output archive");
if(ignore_setting(&_val)) return;
auto _save = std::shared_ptr<value_type>{};
if constexpr(concepts::is_string_type<Tp>::value)
{
if(_val.get_name() != "time_format")
_val.set(settings::format(_val.get(), settings::instance()->get_tag()));
if(_val.get_name() == "config_file")
{
_save = std::make_shared<value_type>(_val);
_val.set(Tp{});
}
}
if(all_info)
{
_ar(cereal::make_nvp(_val.get_env_name().c_str(), _val));
}
else
{
Tp _v = _val.get();
_ar.setNextName(_val.get_env_name().c_str());
_ar.startNode();
_ar(cereal::make_nvp("name", _val.get_name()));
_ar(cereal::make_nvp("value", _v));
if(custom_setting_serializer::options[DESC])
_ar(cereal::make_nvp("description", _val.get_description()));
if(custom_setting_serializer::options[CATEGORY])
_ar(cereal::make_nvp("description", _val.get_categories()));
if(custom_setting_serializer::options[VAL])
_ar(cereal::make_nvp("choices", _val.get_choices()));
_ar.finishNode();
}
if(_save) _val.set(_save->get());
}
};
} // namespace operation
} // namespace tim
template <typename... Tp>
void push(type_list<Tp...>)
{
OMNITRACE_FOLD_EXPRESSION(
settings::push_serialize_map_callback<Tp, custom_setting_serializer>());
OMNITRACE_FOLD_EXPRESSION(
settings::push_serialize_data_callback<Tp, custom_setting_serializer>(
type_list<std::string>{}));
}
template <typename... Tp>
void pop(type_list<Tp...>)
{
OMNITRACE_FOLD_EXPRESSION(
settings::pop_serialize_map_callback<Tp, custom_setting_serializer>());
OMNITRACE_FOLD_EXPRESSION(
settings::pop_serialize_data_callback<Tp, custom_setting_serializer>(
type_list<std::string>{}));
}
void
update_choices();
void
generate_config(std::string _config_file, const std::set<std::string>& _config_fmts,
const std::array<bool, TOTAL>& _options)
{
custom_setting_serializer::options = _options;
_config_file = settings::format(_config_file, settings::instance()->get_tag());
bool _absolute = _config_file.at(0) == '/';
auto _dirs = tim::delimit(_config_file, "/\\/");
_config_file = _dirs.back();
_dirs.pop_back();
std::string _output_dir = ".";
if(!_dirs.empty() && !(_dirs.size() == 1 && _dirs.at(0) == "."))
{
_output_dir = std::string{ (_absolute) ? "/" : "" } + _dirs.front();
_dirs.erase(_dirs.begin());
for(const auto& itr : _dirs)
_output_dir = TIMEMORY_JOIN('/', _output_dir, itr);
}
_output_dir += "/";
std::string _txt_ext = ".cfg";
for(std::string itr : { ".cfg", ".txt", ".json", ".xml" })
{
auto _pos = _config_file.rfind(itr);
if(_pos == _config_file.length() - itr.length())
{
if(itr == ".cfg" || itr == ".txt") _txt_ext = itr;
_config_file = _config_file.substr(0, _pos);
}
}
update_choices();
using json_t = cereal::PrettyJSONOutputArchive;
using xml_t = cereal::XMLOutputArchive;
// stores the original serializer and replaces it with the custom one
push(type_list<json_t, xml_t>{});
static std::time_t _time{ std::time(nullptr) };
auto _serialize = [](auto&& _ar) {
auto _settings = settings::shared_instance();
_ar->setNextName(TIMEMORY_PROJECT_NAME);
_ar->startNode();
(*_ar)(cereal::make_nvp("version", std::string{ OMNITRACE_VERSION_STRING }));
(*_ar)(cereal::make_nvp("date", tim::get_local_datetime("%F_%H.%M", &_time)));
settings::serialize_settings(*_ar);
_ar->finishNode();
};
auto _open = [](std::ofstream& _ofs, const std::string& _fname,
const std::string& _type) -> std::ofstream& {
if(file_exists(_fname))
{
if(force_config)
{
if(settings::verbose() >= 1)
std::cout << "[omnitrace-avail] File '" << _fname
<< "' exists. Overwrite force...\n";
}
else
{
std::cout << "[omnitrace-avail] File '" << _fname
<< "' exists. Overwrite? " << std::flush;
std::string _response = {};
std::cin >> _response;
if(!tim::get_bool(_response, false)) std::exit(EXIT_FAILURE);
}
}
if(filepath::open(_ofs, _fname))
{
if(settings::verbose() >= 0)
printf("[omnitrace-avail] Outputting %s configuration file '%s'...\n",
_type.c_str(), _fname.c_str());
}
else
{
throw std::runtime_error(
TIMEMORY_JOIN(" ", "Error opening", _type, "output file:", _fname));
}
return _ofs;
};
if(_config_fmts.count("json") > 0)
{
std::stringstream _ss{};
output_archive<cereal::PrettyJSONOutputArchive>::indent_length() = 4;
_serialize(output_archive<cereal::PrettyJSONOutputArchive>::get(_ss));
auto _fname = settings::compose_output_filename(_config_file, ".json", false, -1,
true, _output_dir);
std::ofstream ofs{};
_open(ofs, _fname, "JSON") << _ss.str() << "\n";
}
if(_config_fmts.count("xml") > 0)
{
std::stringstream _ss{};
output_archive<cereal::XMLOutputArchive>::indent() = true;
_serialize(output_archive<cereal::XMLOutputArchive>::get(_ss));
auto _fname = settings::compose_output_filename(_config_file, ".xml", false, -1,
true, _output_dir);
std::ofstream ofs{};
_open(ofs, _fname, "XML") << _ss.str() << "\n";
}
if(_config_fmts.count("txt") > 0)
{
std::stringstream _ss{};
auto _settings = settings::shared_instance();
size_t _w = min_width;
std::vector<std::shared_ptr<tim::vsettings>> _data{};
for(const auto& itr : *_settings)
{
if(exclude_setting(itr.second->get_env_name())) continue;
for(const auto& citr : itr.second->get_categories())
if(citr == "deprecated") continue;
if(ignore_setting(itr.second)) continue;
_data.emplace_back(itr.second);
}
if(alphabetical)
std::sort(_data.begin(), _data.end(), [](auto _lhs, auto _rhs) {
return _lhs->get_name() < _rhs->get_name();
});
else
{
std::sort(_data.begin(), _data.end(), [](auto _lhs, auto _rhs) {
auto _lomni = _lhs->get_categories().count("omnitrace") > 0;
auto _romni = _rhs->get_categories().count("omnitrace") > 0;
if(_lomni && !_romni) return true;
if(_romni && !_lomni) return false;
for(const auto* itr :
{ "OMNITRACE_CONFIG", "OMNITRACE_MODE", "OMNITRACE_USE_PERFETTO",
"OMNITRACE_USE_TIMEMORY", "OMNITRACE_USE_SAMPLING",
"OMNITRACE_USE_PROCESS_SAMPLING", "OMNITRACE_USE_ROCTRACER",
"OMNITRACE_USE_ROCM_SMI", "OMNITRACE_USE_KOKKOSP",
"OMNITRACE_USE_OMPT", "OMNITRACE_USE", "OMNITRACE_OUTPUT" })
{
if(_lhs->get_env_name().find(itr) == 0 &&
_rhs->get_env_name().find(itr) != 0)
return true;
if(_rhs->get_env_name().find(itr) == 0 &&
_lhs->get_env_name().find(itr) != 0)
return false;
}
return _lhs->get_name() < _rhs->get_name();
});
}
for(const auto& itr : _data)
{
_w = std::max(_w, itr->get_env_name().length());
}
for(const auto& itr : _data)
{
if(exclude_setting(itr->get_env_name())) continue;
auto _has_info =
(all_info || _options[DESC] || _options[CATEGORY] || _options[VAL]);
if(_has_info) _ss << "\n# name:\n# " << itr->get_name() << "\n#\n";
if(_options[DESC] || all_info)
{
_ss << "# description:\n";
auto _desc = tim::delimit(itr->get_description(), " \n");
std::stringstream _line{};
_line << "# ";
auto _write = [&_line, &_ss, _w](std::string_view _str) {
if(_line.str().length() + _str.length() + 1 >= _w)
{
_ss << _line.str() << "\n";
_line = std::stringstream{};
_line << "# ";
}
_line << " " << _str;
};
for(auto& itr : _desc)
_write(itr);
_ss << _line.str() << "\n#\n";
}
if(_options[CATEGORY] || all_info)
{
_ss << "# categories:\n";
for(const auto& itr : itr->get_categories())
_ss << "# " << itr << "\n";
_ss << "#\n";
}
if((_options[VAL] || all_info) && !itr->get_choices().empty())
{
_ss << "# choices:\n";
for(const auto& itr : itr->get_choices())
_ss << "# " << itr << "\n";
_ss << "#\n";
}
if(_has_info) _ss << "\n";
_ss << std::left << std::setw(_w + 10) << itr->get_env_name() << " = ";
auto _v = itr->as_string();
if(itr->get_name() == "config_file") _v = {};
if(!_v.empty() && expand_keys && itr->get_name() != "time_format")
_v = settings::format(_v, _settings->get_tag());
_ss << _v << "\n";
}
auto _fname = settings::compose_output_filename(_config_file, _txt_ext, false, -1,
true, _output_dir);
std::ofstream ofs{};
_open(ofs, _fname, "text")
<< "# auto-generated by omnitrace-avail (version " << OMNITRACE_VERSION_STRING
<< ") on " << tim::get_local_datetime("%F @ %H:%M", &_time) << "\n\n"
<< _ss.str() << "\n";
}
// restores the original serializer
pop(type_list<json_t, xml_t>{});
}
void
update_choices()
{
std::vector<info_type> _info = get_component_info<TIMEMORY_NATIVE_COMPONENTS_END>();
if(settings::verbose() >= 2 || settings::debug())
printf("[omnitrace-avail] # of component found: %zu\n", _info.size());
_info.erase(std::remove_if(_info.begin(), _info.end(),
[](const auto& itr) {
if(!itr.is_available()) return true;
// NOLINTNEXTLINE
for(const auto& nitr :
{ "cuda", "cupti", "nvtx", "roofline", "_bundle",
"data_integer", "data_unsigned", "data_floating",
"printer" })
{
if(itr.name().find(nitr) != std::string::npos)
return true;
}
return false;
}),
_info.end());
std::vector<std::string> _component_choices = {};
_component_choices.reserve(_info.size());
for(const auto& itr : _info)
_component_choices.emplace_back(itr.id_type());
if(settings::verbose() >= 2 || settings::debug())
printf("[omnitrace-avail] # of component choices: %zu\n",
_component_choices.size());
settings::shared_instance()
->find("OMNITRACE_TIMEMORY_COMPONENTS")
->second->set_choices(_component_choices);
}
@@ -0,0 +1,32 @@
// 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 <set>
#include <string>
void
generate_config(std::string _config_file, const std::set<std::string>& _config_fmts,
const std::array<bool, TOTAL>&);
@@ -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.hpp"
#include "defines.hpp"
#include "get_categories.hpp"
#include "info_type.hpp"
#include <timemory/components/metadata.hpp>
#include <timemory/components/properties.hpp>
#include <timemory/defines.h>
#include <timemory/enum.h>
#include <timemory/mpl/type_traits.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/type_list.hpp>
#include <timemory/variadic/macros.hpp>
//--------------------------------------------------------------------------------------//
struct unknown
{};
template <typename T, typename U = typename T::value_type>
constexpr bool
available_value_type_alias(int)
{
return true;
}
template <typename T, typename U = unknown>
constexpr bool
available_value_type_alias(long)
{
return false;
}
template <typename Type, bool>
struct component_value_type;
template <typename Type>
struct component_value_type<Type, true>
{
using type = typename Type::value_type;
};
template <typename Type>
struct component_value_type<Type, false>
{
using type = unknown;
};
template <typename Type>
using component_value_type_t =
typename component_value_type<Type, available_value_type_alias<Type>(0)>::type;
//--------------------------------------------------------------------------------------//
template <typename Type = void>
struct get_availability;
//--------------------------------------------------------------------------------------//
template <typename Type>
struct get_availability
{
using this_type = get_availability<Type>;
using metadata_t = ::tim::component::metadata<Type>;
using property_t = ::tim::component::properties<Type>;
static info_type get_info();
auto operator()() const { return get_info(); }
};
//--------------------------------------------------------------------------------------//
template <typename... Types>
struct get_availability<type_list<Types...>>
{
using data_type = std::vector<info_type>;
static data_type get_info(data_type& _v)
{
TIMEMORY_FOLD_EXPRESSION(_v.emplace_back(get_availability<Types>::get_info()));
return _v;
}
static data_type get_info()
{
data_type _v{};
return get_info(_v);
}
template <typename... Args>
decltype(auto) operator()(Args&&... _args)
{
return get_info(std::forward<Args>(_args)...);
}
};
//--------------------------------------------------------------------------------------//
template <typename Type>
info_type
get_availability<Type>::get_info()
{
using namespace tim;
using value_type = component_value_type_t<Type>;
using category_types = typename trait::component_apis<Type>::type;
auto _cleanup = [](std::string _type, const std::string& _pattern) {
auto _pos = std::string::npos;
while((_pos = _type.find(_pattern)) != std::string::npos)
_type.erase(_pos, _pattern.length());
return _type;
};
auto _replace = [](std::string _type, const std::string& _pattern,
const std::string& _with) {
auto _pos = std::string::npos;
while((_pos = _type.find(_pattern)) != std::string::npos)
_type.replace(_pos, _pattern.length(), _with);
return _type;
};
bool has_metadata = metadata_t::specialized();
bool has_properties = property_t::specialized();
bool is_available = trait::is_available<Type>::value;
bool file_output = trait::generates_output<Type>::value;
auto name = component::metadata<Type>::name();
auto label = (file_output)
? ((has_metadata) ? metadata_t::label() : Type::get_label())
: std::string("");
auto description =
(has_metadata) ? metadata_t::description() : Type::get_description();
auto data_type = demangle<value_type>();
string_t enum_type = property_t::enum_string();
string_t id_type = property_t::id();
auto ids_set = property_t::ids();
if(!has_properties)
{
enum_type = "";
id_type = "";
ids_set.clear();
}
string_t ids_str = {};
{
auto itr = ids_set.begin();
string_t db = (markdown) ? "`\"" : (csv) ? "" : "\"";
string_t de = (markdown) ? "\"`" : (csv) ? "" : "\"";
if(has_metadata) description += ". " + metadata_t::extra_description();
description += ".";
while(itr->empty())
++itr;
if(itr != ids_set.end())
ids_str = TIMEMORY_JOIN("", TIMEMORY_JOIN("", db, *itr++, de));
for(; itr != ids_set.end(); ++itr)
{
if(!itr->empty())
ids_str = TIMEMORY_JOIN(", ", ids_str, TIMEMORY_JOIN("", db, *itr, de));
}
}
string_t categories = get_categories(category_types{});
#if 0
auto _remove_typelist = [](std::string _tmp) {
if(_tmp.empty()) return _tmp;
auto _key = std::string{ "type_list" };
auto _idx = _tmp.find(_key);
if(_idx == std::string::npos) return _tmp;
_idx = _tmp.find('<', _idx);
_tmp = _tmp.substr(_idx + 1);
_idx = _tmp.find_last_of('>');
_tmp = _tmp.substr(0, _idx);
if(_tmp.empty()) return _tmp;
// strip trailing whitespaces
while((_idx = _tmp.find_last_of(' ')) == _tmp.length() - 1)
_tmp = _tmp.substr(0, _idx);
return _tmp;
};
auto apis = _remove_typelist(demangle<trait::component_apis_t<Type>>());
if(!apis.empty()) description += ". APIs: " + apis;
#endif
description = _replace(_replace(description, ". .", "."), "..", ".");
data_type = _replace(_cleanup(data_type, "::__1"), "> >", ">>");
return info_type{ name, is_available,
str_vec_t{ data_type, enum_type, id_type, ids_str, label,
description, categories } };
}
//--------------------------------------------------------------------------------------//
template <>
struct get_availability<void>
{
template <typename... Tp, typename... Args>
decltype(auto) operator()(tim::type_list<Tp...>, Args&&... _args) const
{
return get_availability<tim::type_list<Tp...>>{}(std::forward<Args>(_args)...);
}
template <typename Tp, typename... Args>
decltype(auto) operator()(Args&&... _args) const
{
return get_availability<tim::type_list<Tp>>{}(std::forward<Args>(_args)...);
}
};
@@ -0,0 +1,60 @@
// 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 <timemory/utility/demangle.hpp>
#include <timemory/utility/type_list.hpp>
#include <algorithm>
#include <sstream>
#include <string>
template <typename... Tp>
auto get_categories(type_list<Tp...>)
{
auto _cleanup = [](std::string _type, const std::string& _pattern) {
auto _pos = std::string::npos;
while((_pos = _type.find(_pattern)) != std::string::npos)
_type.erase(_pos, _pattern.length());
return _type;
};
(void) _cleanup; // unused but set if sizeof...(Tp) == 0
auto _vec = str_vec_t{ _cleanup(demangle<Tp>(), "tim::")... };
std::sort(_vec.begin(), _vec.end(), [](const auto& lhs, const auto& rhs) {
// prioritize project category
auto lpos = lhs.find("project::");
auto rpos = rhs.find("project::");
return (lpos == rpos) ? (lhs < rhs) : (lpos < rpos);
});
std::stringstream _ss{};
for(auto&& itr : _vec)
{
_ss << ", " << itr;
}
std::string _v = _ss.str();
if(!_v.empty()) return _v.substr(2);
return _v;
}
@@ -0,0 +1,57 @@
// 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 "info_type.hpp"
#include "enumerated_list.hpp"
#include "get_availability.hpp"
#include "library/api.hpp"
#include "library/components/backtrace.hpp"
#include "library/components/fork_gotcha.hpp"
#include "library/components/mpi_gotcha.hpp"
#include "library/components/omnitrace.hpp"
#include "library/components/pthread_gotcha.hpp"
#include "library/components/roctracer.hpp"
#include "library/components/user_region.hpp"
#include <timemory/components/definition.hpp>
#include <timemory/enum.h>
#include <timemory/utility/macros.hpp>
#include <utility>
template <size_t EndV>
std::vector<info_type>
get_component_info()
{
using index_seq_t = std::make_index_sequence<EndV>;
using enum_list_t = typename enumerated_list<tim::type_list<>, index_seq_t>::type;
auto _info = std::vector<info_type>{};
return get_availability<>{}(enum_list_t{}, _info);
}
template std::vector<info_type>
get_component_info<TIMEMORY_NATIVE_COMPONENTS_END>();
template std::vector<info_type>
get_component_info<TIMEMORY_COMPONENTS_END>();
@@ -0,0 +1,75 @@
// 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 <timemory/enum.h>
#include <timemory/utility/macros.hpp>
#include <utility>
struct info_type : info_type_base
{
TIMEMORY_DEFAULT_OBJECT(info_type)
template <typename... Args>
info_type(Args&&... _args)
: info_type_base{ std::forward<Args>(_args)... }
{}
const auto& name() const { return std::get<0>(*this); }
auto is_available() const { return std::get<1>(*this); }
const auto& info() const { return std::get<2>(*this); }
const auto& data_type() const { return info().at(0); }
const auto& enum_type() const { return info().at(1); }
const auto& id_type() const { return info().at(2); }
const auto& id_strings() const { return info().at(3); }
const auto& label() const { return info().at(4); }
const auto& description() const { return info().at(5); }
const auto& categories() const { return info().at(6); }
bool valid() const { return !name().empty() && info().size() >= 6; }
bool operator<(const info_type& rhs) const { return name() < rhs.name(); }
bool operator!=(const info_type& rhs) const { return !(*this == rhs); }
bool operator==(const info_type& rhs) const
{
if(info().size() != rhs.info().size()) return false;
for(size_t i = 0; i < info().size(); ++i)
{
if(info().at(i) != rhs.info().at(i)) return false;
}
return name() == rhs.name() && is_available() == rhs.is_available();
}
};
template <size_t EndV>
std::vector<info_type>
get_component_info();
extern template std::vector<info_type>
get_component_info<TIMEMORY_NATIVE_COMPONENTS_END>();
extern template std::vector<info_type>
get_component_info<TIMEMORY_COMPONENTS_END>();
@@ -125,7 +125,7 @@ omnitrace_add_bin_test(
NAME omnitrace-avail-help
TARGET omnitrace-avail
ARGS --help
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX
".*\\\[omnitrace-avail\\\] Usage:.*\\\[CATEGORIES\\\].*\\\[VIEW OPTIONS\\\].*\\\[COLUMN OPTIONS\\\].*\\\[WIDTH OPTIONS\\\].*\\\[OUTPUT OPTIONS\\\].*"
@@ -135,7 +135,7 @@ omnitrace_add_bin_test(
NAME omnitrace-avail-all-csv
TARGET omnitrace-avail
ARGS --all --csv --csv-separator "#"
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX
"COMPONENT#AVAILABLE#VALUE_TYPE#STRING_IDS#FILENAME#DESCRIPTION#CATEGORY#.*ENVIRONMENT VARIABLE#VALUE#DATA TYPE#DESCRIPTION#CATEGORIES#.*HARDWARE COUNTER#AVAILABLE#DESCRIPTION#"
@@ -145,7 +145,7 @@ omnitrace_add_bin_test(
NAME omnitrace-avail-filter-wall-clock-available
TARGET omnitrace-avail
ARGS -r wall_clock -C --available
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX
"\\\|[-]+\\\|\n\\\|[ ]+COMPONENT[ ]+\\\|\n\\\|[-]+\\\|\n\\\| (wall_clock)[ ]+\\\|\n\\\| (sampling_wall_clock)[ ]+\\\|\n\\\|[-]+\\\|"
@@ -155,7 +155,7 @@ omnitrace_add_bin_test(
NAME omnitrace-avail-category-filter-omnitrace
TARGET omnitrace-avail
ARGS --categories settings::omnitrace --brief
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE|OUTPUT_PREFIX)"
FAIL_REGEX
@@ -166,7 +166,7 @@ omnitrace_add_bin_test(
NAME omnitrace-avail-category-filter-timemory
TARGET omnitrace-avail
ARGS --categories settings::timemory --brief
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
@@ -184,7 +184,32 @@ omnitrace_add_bin_test(
~PERFETTO
--csv
--brief
LABELS omnitrace-avail
LABELS "omnitrace-avail"
TIMEOUT 45
PASS_REGEX "ENVIRONMENT VARIABLE,[ \n]+OMNITRACE_USE_PID,[ \n]+"
FAIL_REGEX "OMNITRACE_USE_PERFETTO")
string(REPLACE "+" "\\\+" _AVAIL_CFG_PATH
"${PROJECT_BINARY_DIR}/omnitrace-tests-output/omnitrace-avail/omnitrace-")
omnitrace_add_bin_test(
NAME omnitrace-avail-write-config
TARGET omnitrace-avail
ARGS -G %env{PWD}%/omnitrace-tests-output/omnitrace-avail/omnitrace-test.cfg -F txt
json xml --force --all
TIMEOUT 45
LABELS "omnitrace-avail"
PASS_REGEX
"Outputting JSON configuration file '${_AVAIL_CFG_PATH}test\\\.json'(.*)Outputting XML configuration file '${_AVAIL_CFG_PATH}test\\\.xml'(.*)Outputting text configuration file '${_AVAIL_CFG_PATH}test\\\.cfg'(.*)"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-write-config-tweak
TARGET omnitrace-avail
ARGS -G %env{PWD}%/omnitrace-tests-output/omnitrace-avail/omnitrace-tweak.cfg -F txt
json xml --force
TIMEOUT 45
LABELS "omnitrace-avail"
ENVIRONMENT "OMNITRACE_USE_PERFETTO=OFF;OMNITRACE_USE_TIMEMORY=ON"
PASS_REGEX
"Outputting JSON configuration file '${_AVAIL_CFG_PATH}tweak\\\.json'(.*)Outputting XML configuration file '${_AVAIL_CFG_PATH}tweak\\\.xml'(.*)Outputting text configuration file '${_AVAIL_CFG_PATH}tweak\\\.cfg'(.*)"
)