2
0

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
Este cometimento está contido em:
Jonathan R. Madsen
2022-06-28 01:36:04 -05:00
cometido por GitHub
ascendente efe1edd253
cometimento 1877ebf47b
22 ficheiros modificados com 2067 adições e 870 eliminações
+20 -2
Ver ficheiro
@@ -15,8 +15,26 @@ The full documentation for [omnitrace](https://github.com/AMDResearch/omnitrace)
### Omnitrace Settings
`omnitrace-avail -Sd` will provide a list of all the possible omnitrace settings, their current value, and a description of the setting
when running an instrumented binary.
Generate an omnitrace configuration file using `omnitrace-avail -D omnitrace.cfg`. Optionally, use `omnitrace-avail -D omnitrace.cfg --all` for
a verbose configuration file with descriptions, categories, etc. Modify the configuration file as desired, e.g. enable
[perfetto](https://perfetto.dev/), [timemory](https://github.com/NERSC/timemory), sampling, and process-level sampling by default
and tweak some sampling default values:
```console
# ...
OMNITRACE_USE_PERFETTO = true
OMNITRACE_USE_TIMEMORY = true
OMNITRACE_USE_SAMPLING = true
OMNITRACE_USE_PROCESS_SAMPLING = true
# ...
OMNITRACE_SAMPLING_FREQ = 50
OMNITRACE_SAMPLING_CPUS = all
OMNITRACE_SAMPLING_GPUS = $env:HIP_VISIBLE_DEVICES
```
Once the configuration file is adjusted to your preferences, either export the path to this file via `OMNITRACE_CONFIG_FILE=/path/to/omnitrace.cfg`
or place this file in `${HOME}/.omnitrace.cfg` to ensure these values are always read as the default. If you wish to change any of these settings,
you can override them via environment variables or by specifying an alternative `OMNITRACE_CONFIG_FILE`.
### Omnitrace Executable
+17 -3
Ver ficheiro
@@ -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)
+149 -780
Ver ficheiro
A apresentação das diferenças no ficheiro foi suprimida por ser demasiado grande Carregar diff
+1 -2
Ver ficheiro
@@ -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>
+393
Ver ficheiro
@@ -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;
}
//--------------------------------------------------------------------------------------//
+145
Ver ficheiro
@@ -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&);
+84
Ver ficheiro
@@ -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;
}
};
+29
Ver ficheiro
@@ -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"
+53
Ver ficheiro
@@ -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;
};
+437
Ver ficheiro
@@ -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);
}
+32
Ver ficheiro
@@ -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>&);
+229
Ver ficheiro
@@ -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)...);
}
};
+60
Ver ficheiro
@@ -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;
}
+57
Ver ficheiro
@@ -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>();
+75
Ver ficheiro
@@ -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>();
+31 -6
Ver ficheiro
@@ -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'(.*)"
)
+27 -21
Ver ficheiro
@@ -259,27 +259,33 @@ If you are ever doing scaling studies and specifying options via the command lin
use a common `OMNITRACE_OUTPUT_PATH`, disable `OMNITRACE_TIME_OUTPUT`,
set `OMNITRACE_OUTPUT_PREFIX="%argt%-"` and let omnitrace cleanly organize the output.
| String | Encoding |
|-----------------|-----------------------------------------------------------------------------------------------|
| `%arg<N>%` | Command line argument at position `<N>` (zero indexed), e.g. `%arg0%` for first argument. |
| `%arg<N>_hash%` | MD5 sum of `%arg<N>%` |
| `%argv%` | Entire command-line condensed into a single string |
| `%argv_hash%` | MD5 sum of `%argv%` |
| `%argt%` | Similar to `%argv%` except basename of first command line argument |
| `%argt_hash%` | MD5 sum if `%argt%` |
| `%args%` | All command line arguments condensed into a single string |
| `%args_hash%` | MD5 sum of `%args%` |
| `%tag%` | Basename of first command line argument |
| `%tag_hash%` | MD5 sum of `%tag%` |
| `%pid%` | Process identifier (i.e. `getpid()`) |
| `%job%` | Value of `SLURM_JOB_ID` environment variable if exists, else `0` |
| `%rank%` | Value of `SLURM_PROCID` environment variable if exists, else `MPI_Comm_rank` (or `0` non-mpi) |
| `%size%` | `MPI_Comm_size` or `1` if non-mpi |
| `%m` | Shorthand for `%argt_hash%` |
| `%p` | Shorthand for `%pid%` |
| `%j` | Shorthand for `%job%` |
| `%r` | Shorthand for `%rank%` |
| `%s` | Shorthand for `%size%` |
| String | Encoding |
|-----------------|--------------------------------------------------------------------------------------------------------------------|
| `%arg<N>%` | Command line argument at position `<N>` (zero indexed), e.g. `%arg0%` for first argument. |
| `%arg<N>_hash%` | MD5 sum of `%arg<N>%` |
| `%argv%` | Entire command-line condensed into a single string |
| `%argv_hash%` | MD5 sum of `%argv%` |
| `%argt%` | Similar to `%argv%` except basename of first command line argument |
| `%argt_hash%` | MD5 sum if `%argt%` |
| `%args%` | All command line arguments condensed into a single string |
| `%args_hash%` | MD5 sum of `%args%` |
| `%tag%` | Basename of first command line argument |
| `%tag_hash%` | MD5 sum of `%tag%` |
| `%pid%` | Process identifier (i.e. `getpid()`) |
| `%ppid%` | Parent process identifier (i.e. `getppid()`) |
| `%job%` | Value of `SLURM_JOB_ID` environment variable if exists, else `0` |
| `%rank%` | Value of `SLURM_PROCID` environment variable if exists, else `MPI_Comm_rank` (or `0` non-mpi) |
| `%size%` | `MPI_Comm_size` or `1` if non-mpi |
| `%launch_time%` | Launch date and time (uses `OMNITRACE_TIME_FORMAT`) |
| `%env{NAME}%` | Value of environment variable `NAME` (i.e. `getenv(NAME)`) |
| `%cfg{NAME}%` | Value of configuration variable `NAME` (e.g. `%cfg{OMNITRACE_SAMPLING_FREQ}%` would resolve to sampling frequency) |
| `$env{NAME}` | Alternative syntax to `%env{NAME}%` |
| `$cfg{NAME}` | Alternative syntax to `%cfg{NAME}%` |
| `%m` | Shorthand for `%argt_hash%` |
| `%p` | Shorthand for `%pid%` |
| `%j` | Shorthand for `%job%` |
| `%r` | Shorthand for `%rank%` |
| `%s` | Shorthand for `%size%` |
> ***Any output prefix key which contain a `/` will have the `/` characters***
> ***replaced with `_` and any leading underscores will be stripped, e.g. if `%arg0%` is `/usr/bin/foo`, this***
+129 -3
Ver ficheiro
@@ -14,6 +14,26 @@ self-updating: when new capabilities and settings are added to the omnitrace sou
propagated to `omnitrace-avail`, thus it should be viewed as the single source of truth if any conflicting
information or missing feature is found in this documentation.
It is recommended to create a default configuration file in `${HOME}/.omnitrace.cfg`. This can be done via
executing `omnitrace-avail -D ~/.omnitrace.cfg`, or optionally, use `omnitrace-avail -D ~/.omnitrace.cfg --all`
for a verbose configuration file with descriptions, categories, etc.
Modify `${HOME}/.omnitrace.cfg` as desired, e.g. enable [perfetto](https://perfetto.dev/),
[timemory](https://github.com/NERSC/timemory), sampling, and process-level sampling by default
and tweak some sampling default values:
```console
# ...
OMNITRACE_USE_PERFETTO = true
OMNITRACE_USE_TIMEMORY = true
OMNITRACE_USE_SAMPLING = true
OMNITRACE_USE_PROCESS_SAMPLING = true
# ...
OMNITRACE_SAMPLING_FREQ = 50
OMNITRACE_SAMPLING_CPUS = all
OMNITRACE_SAMPLING_GPUS = $env:HIP_VISIBLE_DEVICES
```
### Exploring Runtime Settings
In order to view the list of the available runtime settings, their current value, and descriptions for each setting:
@@ -62,7 +82,111 @@ omnitrace-avail --hw-counters --description
### omnitrace-avail Examples
#### Settings
#### Generating Default Configuration
```console
$ omnitrace-avail -D ~/.omnitrace.cfg
[omnitrace-avail] Outputting text configuration file '/home/user/.omnitrace.cfg'...
$ cat ~/.omnitrace.cfg
# auto-generated by omnitrace-avail (version 1.2.0) on 2022-06-27 @ 19:15
OMNITRACE_CONFIG_FILE =
OMNITRACE_MODE = trace
OMNITRACE_USE_PERFETTO = true
OMNITRACE_USE_TIMEMORY = false
OMNITRACE_USE_SAMPLING = false
OMNITRACE_USE_PROCESS_SAMPLING = true
OMNITRACE_USE_ROCTRACER = true
OMNITRACE_USE_ROCM_SMI = true
OMNITRACE_USE_KOKKOSP = false
OMNITRACE_USE_CODE_COVERAGE = false
OMNITRACE_USE_PID = true
OMNITRACE_OUTPUT_PATH = omnitrace-%tag%-output
OMNITRACE_OUTPUT_PREFIX =
OMNITRACE_CI = false
OMNITRACE_CRITICAL_TRACE = false
OMNITRACE_CRITICAL_TRACE_BUFFER_COUNT = 2000
OMNITRACE_CRITICAL_TRACE_COUNT = 0
OMNITRACE_CRITICAL_TRACE_DEBUG = false
OMNITRACE_CRITICAL_TRACE_NUM_THREADS = 8
OMNITRACE_CRITICAL_TRACE_PER_ROW = 0
OMNITRACE_CRITICAL_TRACE_SERIALIZE_NAMES = false
OMNITRACE_DEBUG = false
OMNITRACE_DL_VERBOSE = 0
OMNITRACE_FLAT_SAMPLING = false
OMNITRACE_INSTRUMENTATION_INTERVAL = 1
OMNITRACE_KOKKOS_KERNEL_LOGGER = false
OMNITRACE_PAPI_EVENTS = PAPI_TOT_CYC
OMNITRACE_PERFETTO_BACKEND = inprocess
OMNITRACE_PERFETTO_BUFFER_SIZE_KB = 1024000
OMNITRACE_PERFETTO_COMBINE_TRACES = true
OMNITRACE_PERFETTO_FILE = perfetto-trace.proto
OMNITRACE_PERFETTO_FILL_POLICY = discard
OMNITRACE_PERFETTO_SHMEM_SIZE_HINT_KB = 4096
OMNITRACE_ROCTRACER_FLAT_PROFILE = false
OMNITRACE_ROCTRACER_HSA_ACTIVITY = false
OMNITRACE_ROCTRACER_HSA_API = false
OMNITRACE_ROCTRACER_HSA_API_TYPES =
OMNITRACE_ROCTRACER_TIMELINE_PROFILE = false
OMNITRACE_SAMPLING_CPUS =
OMNITRACE_SAMPLING_DELAY = 0.5
OMNITRACE_SAMPLING_FREQ = 10
OMNITRACE_SAMPLING_GPUS = all
OMNITRACE_TIME_OUTPUT = true
OMNITRACE_TIMELINE_SAMPLING = false
OMNITRACE_TIMEMORY_COMPONENTS = wall_clock
OMNITRACE_TRACE_THREAD_LOCKS = false
OMNITRACE_VERBOSE = 0
OMNITRACE_COLLAPSE_PROCESSES = false
OMNITRACE_COLLAPSE_THREADS = false
OMNITRACE_COUT_OUTPUT = false
OMNITRACE_CPU_AFFINITY = false
OMNITRACE_DIFF_OUTPUT = false
OMNITRACE_ENABLE_SIGNAL_HANDLER = true
OMNITRACE_ENABLED = true
OMNITRACE_FILE_OUTPUT = true
OMNITRACE_FLAT_PROFILE = false
OMNITRACE_INPUT_EXTENSIONS = json,xml
OMNITRACE_INPUT_PATH =
OMNITRACE_INPUT_PREFIX =
OMNITRACE_JSON_OUTPUT = true
OMNITRACE_MAX_DEPTH = 65535
OMNITRACE_MAX_WIDTH = 120
OMNITRACE_MEMORY_PRECISION = -1
OMNITRACE_MEMORY_SCIENTIFIC = false
OMNITRACE_MEMORY_UNITS = MB
OMNITRACE_MEMORY_WIDTH = -1
OMNITRACE_NETWORK_INTERFACE =
OMNITRACE_NODE_COUNT = 0
OMNITRACE_PAPI_FAIL_ON_ERROR = false
OMNITRACE_PAPI_MULTIPLEXING = false
OMNITRACE_PAPI_OVERFLOW = 0
OMNITRACE_PAPI_QUIET = false
OMNITRACE_PAPI_THREADING = true
OMNITRACE_PRECISION = -1
OMNITRACE_SCIENTIFIC = false
OMNITRACE_STRICT_CONFIG = true
OMNITRACE_SUPPRESS_CONFIG = true
OMNITRACE_SUPPRESS_PARSING = true
OMNITRACE_TEXT_OUTPUT = true
OMNITRACE_TIME_FORMAT = %F_%I.%M_%p
OMNITRACE_TIMELINE_PROFILE = false
OMNITRACE_TIMING_PRECISION = 6
OMNITRACE_TIMING_SCIENTIFIC = false
OMNITRACE_TIMING_UNITS = sec
OMNITRACE_TIMING_WIDTH = -1
OMNITRACE_TREE_OUTPUT = true
OMNITRACE_WIDTH = -1
```
- Recommendations
- Use the `--all` option for descriptions, choices, etc. in the configuration file.
- If you want to create a new configuration without inheriting from an existing `${HOME}/.omnitrace.cfg`,
set `OMNITRACE_SUPPRESS_CONFIG=ON` in the environment before executing.
- If you want to create a new configuration with some minor tweaks to an existing config,
set `OMNITRACE_CONFIG_FILE=/path/to/existing/file` and define the tweaks as environment variables before generating.
#### Viewing Setting Descriptions
```console
$ omnitrace-avail -S -bd
@@ -161,7 +285,7 @@ $ omnitrace-avail -S -bd
|-----------------------------------------|-----------------------------------------|
```
#### Components
#### Viewing Components
```console
$ omnitrace-avail -C -bd
@@ -234,7 +358,7 @@ $ omnitrace-avail -C -bd
|-----------------------------------|----------------------------------------------|
```
#### Hardware Counters
#### Viewing Hardware Counters
```console
$ omnitrace-avail -H -bd
@@ -638,6 +762,8 @@ $ omnitrace-avail -H -bd
## Creating a Configuration File
[Omnitrace](https://github.com/AMDResearch/omnitrace) supports 3 configuration file formats: JSON, XML, and plain text.
Use `omnitrace-avail -D <filename> -F txt json xml` to generate default configuration files of each format and, optionally,
include the `--all` flag for descriptions, etc.
Configuration files are specified via the `OMNITRACE_CONFIG_FILE` environment variable
and by default will look for `${HOME}/.omnitrace.cfg` and `${HOME}/.omnitrace.json`.
Multiple configuration files can be concatenated via `:`, e.g.:
-2
Ver ficheiro
@@ -551,8 +551,6 @@ omnitrace_init_tooling_hidden()
perfetto::Tracing::Initialize(args);
perfetto::TrackEvent::Register();
(void) get_perfetto_output_filename();
}
auto _exe = get_exe_name();
+97 -49
Ver ficheiro
@@ -342,7 +342,7 @@ configure_settings(bool _init)
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_PERFETTO_SHMEM_SIZE_HINT_KB",
"Hint for shared-memory buffer size in perfetto (in KB)",
40960, "perfetto", "data");
4096, "perfetto", "data");
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_PERFETTO_BUFFER_SIZE_KB",
"Size of perfetto buffer (in KB)", 1024000, "perfetto",
@@ -387,8 +387,11 @@ configure_settings(bool _init)
"List of components to collect via timemory (see `omnitrace-avail -C`)",
"wall_clock", "timemory", "component");
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_OUTPUT_FILE", "Perfetto filename",
"", "perfetto", "io", "filename");
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_OUTPUT_FILE",
"[DEPRECATED] See OMNITRACE_PERFETTO_FILE", "", "perfetto",
"io", "filename", "deprecated");
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_PERFETTO_FILE", "Perfetto filename",
"perfetto-trace.proto", "perfetto", "io", "filename");
// set the defaults
_config->get_flamegraph_output() = false;
@@ -454,23 +457,20 @@ configure_settings(bool _init)
}
else
{
_add_omnitrace_category(_config->find("OMNITRACE_PAPI_EVENTS"));
auto _papi_events = _config->find("OMNITRACE_PAPI_EVENTS");
_add_omnitrace_category(_papi_events);
std::vector<std::string> _papi_choices = {};
for(auto itr : tim::papi::available_events_info())
{
if(itr.available()) _papi_choices.emplace_back(itr.symbol());
}
_papi_events->second->set_choices(_papi_choices);
}
#else
_config->find("OMNITRACE_PAPI_EVENTS")->second->set_hidden(true);
_config->get_papi_quiet() = true;
#endif
for(auto&& itr :
tim::delimit(_config->get<std::string>("OMNITRACE_CONFIG_FILE"), ";:"))
{
if(_config->get_suppress_config()) continue;
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_verbose_env() > 0,
"Reading config file %s\n", itr.c_str());
_config->read(itr);
}
settings::suppress_config() = true;
// always initialize timemory because gotcha wrappers are always used
auto _cmd = tim::read_command_line(process::get_id());
auto _cmd_env = tim::get_env<std::string>("OMNITRACE_COMMAND_LINE", "");
@@ -479,6 +479,7 @@ configure_settings(bool _init)
auto _pos = _exe.find_last_of('/');
if(_pos < _exe.length() - 1) _exe = _exe.substr(_pos + 1);
get_exe_name() = _exe;
_config->set_tag(_exe);
bool _found_sep = false;
for(const auto& itr : _cmd)
@@ -487,6 +488,16 @@ configure_settings(bool _init)
}
if(!_found_sep && _cmd.size() > 1) _cmd.insert(_cmd.begin() + 1, "--");
for(auto&& itr :
tim::delimit(_config->get<std::string>("OMNITRACE_CONFIG_FILE"), ";:"))
{
if(_config->get_suppress_config()) continue;
OMNITRACE_BASIC_VERBOSE(1, "Reading config file %s\n", itr.c_str());
_config->read(itr);
}
settings::suppress_config() = true;
if(_init)
{
using argparser_t = tim::argparse::argument_parser;
@@ -507,6 +518,7 @@ configure_settings(bool _init)
handle_deprecated_setting("OMNITRACE_ROCM_SMI_DEVICES", "OMNITRACE_SAMPLING_GPUS");
handle_deprecated_setting("OMNITRACE_USE_THREAD_SAMPLING",
"OMNITRACE_USE_PROCESS_SAMPLING");
handle_deprecated_setting("OMNITRACE_OUTPUT_FILE", "OMNITRACE_PERFETTO_FILE");
scope::get_fields()[scope::flat::value] = _config->get_flat_profile();
scope::get_fields()[scope::timeline::value] = _config->get_timeline_profile();
@@ -524,10 +536,6 @@ configure_settings(bool _init)
tim::set_env(std::string{ _dl_verbose->first }, _dl_verbose->second->as_string(),
0);
#if !defined(TIMEMORY_USE_MPI) || TIMEMORY_USE_MPI == 0
_config->disable("OMNITRACE_PERFETTO_COMBINE_TRACES");
#endif
configure_mode_settings();
configure_signal_handler();
configure_disabled_settings();
@@ -683,21 +691,34 @@ configure_disabled_settings()
_handle_use_option("OMNITRACE_USE_KOKKOSP", "kokkos");
_handle_use_option("OMNITRACE_USE_PERFETTO", "perfetto");
_handle_use_option("OMNITRACE_USE_TIMEMORY", "timemory");
_handle_use_option("OMNITRACE_CRITICAL_TRACE", "critical_trace");
_handle_use_option("OMNITRACE_USE_OMPT", "ompt");
_handle_use_option("OMNITRACE_USE_ROCM_SMI", "rocm_smi");
_handle_use_option("OMNITRACE_USE_ROCTRACER", "roctracer");
_handle_use_option("OMNITRACE_CRITICAL_TRACE", "critical_trace");
#if !defined(OMNITRACE_USE_ROCTRACER) || OMNITRACE_USE_ROCTRACER == 0
_config->disable_category("roctracer");
_config->find("OMNITRACE_USE_ROCTRACER")->second->set_hidden(true);
for(const auto& itr : _config->disable_category("roctracer"))
_config->find(itr)->second->set_hidden(true);
#endif
#if !defined(OMNITRACE_USE_ROCM_SMI) || OMNITRACE_USE_ROCM_SMI == 0
_config->disable_category("rocm_smi");
_config->find("OMNITRACE_USE_ROCM_SMI")->second->set_hidden(true);
for(const auto& itr : _config->disable_category("rocm_smi"))
_config->find(itr)->second->set_hidden(true);
#endif
#if defined(OMNITRACE_USE_OMPT) || OMNITRACE_USE_OMPT == 0
_config->disable_category("ompt");
_config->find("OMNITRACE_USE_OMPT")->second->set_hidden(true);
for(const auto& itr : _config->disable_category("ompt"))
_config->find(itr)->second->set_hidden(true);
#endif
#if !defined(TIMEMORY_USE_MPI) || TIMEMORY_USE_MPI == 0
_config->disable("OMNITRACE_PERFETTO_COMBINE_TRACES");
_config->disable("OMNITRACE_COLLAPSE_PROCESSES");
_config->find("OMNITRACE_PERFETTO_COMBINE_TRACES")->second->set_hidden(true);
_config->find("OMNITRACE_COLLAPSE_PROCESSES")->second->set_hidden(true);
#endif
_config->disable_category("throttle");
@@ -722,6 +743,37 @@ configure_disabled_settings()
_config->disable("dart_output");
_config->disable("flamegraph_output");
_config->disable("separator_freq");
// exclude some timemory settings which are not relevant to omnitrace
// exact matches, e.g. OMNITRACE_BANNER
std::string _hidden_exact_re =
"^OMNITRACE_(BANNER|DESTRUCTOR_REPORT|COMPONENTS|(GLOBAL|MPIP|NCCLP|OMPT|"
"PROFILER|TRACE|KOKKOS)_COMPONENTS|PYTHON_EXE|PAPI_ATTACH|PLOT_OUTPUT|SEPARATOR_"
"FREQ|STACK_CLEARING|TARGET_PID|THROTTLE_(COUNT|VALUE)|(AUTO|FLAMEGRAPH)_OUTPUT|"
"(ENABLE|DISABLE)_ALL_SIGNALS|ALLOW_SIGNAL_HANDLER|CTEST_NOTES|INSTRUCTION_"
"ROOFLINE|ADD_SECONDARY|MAX_THREAD_BOOKMARKS)$";
// leading matches, e.g. OMNITRACE_MPI_[A-Z_]+
std::string _hidden_begin_re =
"^OMNITRACE_(ERT|DART|MPI|UPCXX|ROOFLINE|CUDA|NVTX|CUPTI)_[A-Z_]+$";
auto _hidden_exact = std::set<std::string>{};
#if !defined(TIMEMORY_USE_CRAYPAT)
_hidden_exact.emplace("OMNITRACE_CRAYPAT");
#endif
for(const auto& itr : *_config)
{
auto _v = itr.second->get_env_name();
if(_hidden_exact.count(_v) > 0 ||
std ::regex_match(_v, std::regex{ _hidden_exact_re }) ||
std::regex_match(_v, std::regex{ _hidden_begin_re }))
{
itr.second->set_enabled(false);
itr.second->set_hidden(true);
}
}
}
void
@@ -810,6 +862,7 @@ print_settings(
_widths.fill(0);
for(const auto& itr : *get_config())
{
if(itr.second->get_hidden()) continue;
if(!itr.second->get_enabled()) continue;
if(_filter(itr.first, itr.second->get_categories()))
{
@@ -1273,36 +1326,31 @@ get_backend()
return static_cast<tim::tsettings<std::string>&>(*_v->second).get();
}
std::string&
std::string
get_perfetto_output_filename()
{
static auto _v = get_config()->find("OMNITRACE_OUTPUT_FILE");
static auto& _t = static_cast<tim::tsettings<std::string>&>(*_v->second);
static auto _generate = []() {
if(tim::dmp::is_initialized())
settings::default_process_suffix() = tim::dmp::rank();
// default name: perfetto-trace.<pid>.proto or perfetto-trace.<rank>.proto
auto _default_fname =
settings::compose_output_filename("perfetto-trace", "proto", get_use_pid());
auto _pid_patch = std::string{ "/" } + std::to_string(tim::process::get_id()) +
"-perfetto-trace";
auto _dpos = _default_fname.find(_pid_patch);
if(_dpos != std::string::npos)
_default_fname =
_default_fname.replace(_dpos, _pid_patch.length(), "/perfetto-trace");
// have the default display the full path to the output file
return tim::get_env<std::string>(
"OMNITRACE_OUTPUT_FILE",
JOIN('/', tim::get_env<std::string>("PWD", ".", false), _default_fname),
false);
};
static auto _generated = _generate();
if(_t.get().empty() || _t.get() == _generated)
static auto _v = get_config()->find("OMNITRACE_PERFETTO_FILE");
auto _val = static_cast<tim::tsettings<std::string>&>(*_v->second).get();
auto _pos_dir = _val.find_last_of('/');
auto _dir = std::string{};
auto _ext = std::string{ "proto" };
if(_pos_dir != std::string::npos)
{
_t.set(_generate());
_generated = _t.get();
_dir = _val.substr(0, _pos_dir + 1);
_val = _val.substr(_pos_dir + 1);
}
return _t.get();
auto _pos_ext = _val.find_last_of('.');
if(_pos_ext + 1 < _val.length())
{
_ext = _val.substr(_pos_ext + 1);
_val = _val.substr(0, _pos_ext);
}
_val = settings::compose_output_filename(_val, _ext, settings::use_output_suffix(),
settings::default_process_suffix(), false,
_dir);
if(!_val.empty() && _val.at(0) != '/')
return settings::format(JOIN('/', "%env{PWD}%", _val), get_config()->get_tag());
return _val;
}
size_t&
+1 -1
Ver ficheiro
@@ -244,7 +244,7 @@ std::string&
get_backend();
// make this visible so omnitrace-avail can call it
std::string&
std::string
get_perfetto_output_filename();
int64_t