rocprofv3: summary reports + more JSON metadata (#1029)
* Move include/rocprofiler-sdk/cxx/details/delimit.hpp to tokenize.hpp
* Update docs/how-to/using-rocprofv3.rst
- fix code block indents
- reorder rocprofv3 options, limit them to important options
- add docs for `--runtime-trace`
* Update rocprofv3.py
- parser argument groups
- new `--runtime-trace` option
- new `--summary` option
- new `--summary-per-domain` option
- new `--summary-groups` option
- new `--summary-output-file` option
- new `--summary-units` option
* Update lib/rocprofiler-sdk/hsa/async_copy.cpp
- fix async copy operation names: add "MEMORY_COPY_" prefix
* lib/rocprofiler-sdk-tool: update statistics.{hpp,cpp}
- statistics<>::get_percent function
- stats_entry_t struct
- stats_formatter struct
- percentage struct
- std::to_string(::rocprofiler::tool::percentage)
* lib/rocprofiler-sdk-tool: update domain_type.{hpp,cpp}
- reorder domain_type enum values
* lib/rocprofiler-sdk-tool: update generateCSV.{hpp,cpp}
- separate writing CSV from accumulating statistics
- a lot of functionality was moved to statistics.{hpp,cpp}
* lib/rocprofiler-sdk-tool: update output_file.{hpp,cpp}
- output_stream_t struct
- get_output_stream(...) returns output_stream_t instance
* lib/rocprofiler-sdk-tool: update generateJSON.cpp
- update get_output_stream usage to output_stream_t
* lib/rocprofiler-sdk-tool: update generateOTF2.cpp
- header include order tweak
* lib/rocprofiler-sdk-tool: update buffered_output.hpp
- stats_data_t was renamed to stats_entry_t
* lib/rocprofiler-sdk-tool: update generatePerfetto.cpp
- header include tweak
* lib/rocprofiler-sdk-tool: update tmp_file_buffer.hpp
- emit warning message if write_ring_buffer fails after offloading instead of aborting
- prefer placement new instead of assignment in write_ring_buffer
* lib/rocprofiler-sdk-tool: add generateStats.{hpp,cpp}
- functions for accumulating statistics
* Update tests/rocprofv3/tracing-hip-in-libraries/CMakeLists.txt
- accommodate tweak to CSV output file name for HIP and HSA traces
* lib/rocprofiler-sdk-tool: update config.{hpp,cpp}
- new config variables
- stats_summary
- stats_summary_per_domain
- summary_output
- stats_summary_unit_value
- stats_summary_unit
- stats_summary_file
- stats_summary_groups
- support output keys for hostname: %hostname% / %h
* lib/rocprofiler-sdk-tool: update tool.cpp
- support summary output
* Documentation fixes
* Test for summary output
* Update tests/bin/transpose to use more ROCTx
- also support building with the roctracer ROCTx
* Remove roctxMark from OTF2 + fix kernel-rename tests
- following more ROCTx calls in transpose, kernel-rename validation had to be updated
* JSON metadata + JSON summary
- add serialization support for config
- add serialization support for statistics
- additions to json spec
- rocprofiler-sdk-tool/metadata/config
- rocprofiler-sdk-tool/metadata/command
- rocprofiler-sdk-tool/summary
- config output_keys support for NVIDIA %q{<ENV-VAR>} syntax
- config output_keys support keys within keys
* rocprofv3 --summary-groups warning if no domain matches
- emit warning if a regex in for summary groups did not match any domain names
* Compile fix for lib/rocprofiler-sdk-tool/tool.cpp
- get_config().scratch_memory_trace
- pass contributions to write_json
* Update rocprofv3.py to preload rocprofiler-sdk-roctx
- appended to LD_PRELOAD when args.marker_trace is enabled
* Fix ReST link errors about subtitle underline being too short
* Patch tokenization of config::stats_summary_groups
- guard against array values of empty strings
* Tweak rocprofv3 summary test
- input-summary.yaml (used by rocprofv3-test-summary-inp-yaml-execute) only provides one summary group regex
* Disable LD_PRELOAD of librocprofiler-sdk-roctx.so
- this causes problems in the sanitizers, will be addressed in another PR
Šī revīzija ir iekļauta:
revīziju iesūtīja
GitHub
vecāks
1354452cf0
revīzija
395f01b689
@@ -28,12 +28,14 @@
|
||||
#include "lib/common/environment.hpp"
|
||||
#include "lib/common/filesystem.hpp"
|
||||
#include "lib/common/logging.hpp"
|
||||
#include "lib/common/units.hpp"
|
||||
#include "lib/common/utility.hpp"
|
||||
|
||||
#include <rocprofiler-sdk/cxx/details/delimit.hpp>
|
||||
#include <rocprofiler-sdk/cxx/details/tokenize.hpp>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <linux/limits.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -44,6 +46,7 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
@@ -67,8 +70,14 @@ const auto* launch_clock = as_pointer(std::chrono::system_clock::now());
|
||||
const auto* launch_datetime =
|
||||
get_local_datetime(get_env("ROCP_TIME_FORMAT", "%F_%H.%M"), launch_time);
|
||||
const auto env_regexes =
|
||||
new std::array<std::regex, 2>{std::regex{"(.*)%(env|ENV)\\{([A-Z0-9_]+)\\}%(.*)"},
|
||||
std::regex{"(.*)\\$(env|ENV)\\{([A-Z0-9_]+)\\}(.*)"}};
|
||||
new std::array<std::regex, 3>{std::regex{"(.*)%(env|ENV)\\{([A-Z0-9_]+)\\}%(.*)"},
|
||||
std::regex{"(.*)\\$(env|ENV)\\{([A-Z0-9_]+)\\}(.*)"},
|
||||
std::regex{"(.*)%q\\{([A-Z0-9_]+)\\}(.*)"}};
|
||||
// env regex examples:
|
||||
// - %env{USER}% Consistent with other output key formats (start+end with %)
|
||||
// - $ENV{USER} Similar to CMake
|
||||
// - %q{USER} Compatibility with NVIDIA
|
||||
//
|
||||
|
||||
std::string*
|
||||
get_local_datetime(const std::string& dt_format, std::time_t*& _dt_curr)
|
||||
@@ -86,6 +95,22 @@ get_local_datetime(const std::string& dt_format, std::time_t*& _dt_curr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string
|
||||
get_hostname()
|
||||
{
|
||||
auto _hostname_buff = std::array<char, PATH_MAX>{};
|
||||
_hostname_buff.fill('\0');
|
||||
if(gethostname(_hostname_buff.data(), _hostname_buff.size() - 1) != 0)
|
||||
{
|
||||
auto _err = errno;
|
||||
ROCP_WARNING << "Hostname unknown. gethostname failed with error code " << _err << ": "
|
||||
<< strerror(_err);
|
||||
return std::string{"UNKNOWN_HOSTNAME"};
|
||||
}
|
||||
|
||||
return std::string{_hostname_buff.data()};
|
||||
}
|
||||
|
||||
inline bool
|
||||
not_is_space(int ch)
|
||||
{
|
||||
@@ -279,6 +304,34 @@ config::config()
|
||||
const auto supported_perfetto_backends = std::set<std::string_view>{"inprocess", "system"};
|
||||
LOG_IF(FATAL, supported_perfetto_backends.count(perfetto_backend) == 0)
|
||||
<< "Unsupported perfetto backend type: " << perfetto_backend;
|
||||
|
||||
if(stats_summary_unit == "sec")
|
||||
stats_summary_unit_value = common::units::sec;
|
||||
else if(stats_summary_unit == "msec")
|
||||
stats_summary_unit_value = common::units::msec;
|
||||
else if(stats_summary_unit == "usec")
|
||||
stats_summary_unit_value = common::units::usec;
|
||||
else if(stats_summary_unit == "nsec")
|
||||
stats_summary_unit_value = common::units::nsec;
|
||||
else
|
||||
{
|
||||
ROCP_FATAL << "Unsupported summary units value: " << stats_summary_unit;
|
||||
}
|
||||
|
||||
if(auto _summary_grps = get_env("ROCPROF_STATS_SUMMARY_GROUPS", ""); !_summary_grps.empty())
|
||||
{
|
||||
stats_summary_groups =
|
||||
sdk::parse::tokenize(_summary_grps, std::vector<std::string_view>{"##@@##"});
|
||||
|
||||
// remove any empty strings (just in case these slipped through)
|
||||
stats_summary_groups.erase(std::remove_if(stats_summary_groups.begin(),
|
||||
stats_summary_groups.end(),
|
||||
[](const auto& itr) { return itr.empty(); }),
|
||||
stats_summary_groups.end());
|
||||
}
|
||||
|
||||
// enable summary output if any of these are enabled
|
||||
summary_output = (stats_summary || stats_summary_per_domain || !stats_summary_groups.empty());
|
||||
}
|
||||
|
||||
std::vector<output_key>
|
||||
@@ -374,8 +427,10 @@ output_keys(std::string _tag)
|
||||
}
|
||||
|
||||
auto _launch_time = (launch_datetime) ? *launch_datetime : std::string{".UNKNOWN_LAUNCH_TIME."};
|
||||
auto _hostname = get_hostname();
|
||||
|
||||
for(auto&& itr : std::initializer_list<output_key>{
|
||||
{"%hostname%", _hostname, "Network hostname"},
|
||||
{"%pid%", _proc_id, "Process identifier"},
|
||||
{"%ppid%", _parent_id, "Parent process identifier"},
|
||||
{"%pgid%", _pgroup_id, "Process group identifier"},
|
||||
@@ -392,6 +447,7 @@ output_keys(std::string _tag)
|
||||
}
|
||||
|
||||
for(auto&& itr : std::initializer_list<output_key>{
|
||||
{"%h", _hostname, "Shorthand for %hostname%"},
|
||||
{"%p", _proc_id, "Shorthand for %pid%"},
|
||||
{"%j", _slurm_job_id, "Shorthand for %job%"},
|
||||
{"%r", _slurm_proc_id, "Shorthand for %rank%"},
|
||||
@@ -404,8 +460,10 @@ output_keys(std::string _tag)
|
||||
return _options;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string
|
||||
format(std::string _fpath, const std::string& _tag)
|
||||
format_impl(std::string _fpath, const std::vector<output_key>& _keys)
|
||||
{
|
||||
if(_fpath.find('%') == std::string::npos && _fpath.find('$') == std::string::npos)
|
||||
return _fpath;
|
||||
@@ -416,20 +474,36 @@ format(std::string _fpath, const std::string& _tag)
|
||||
_v.replace(pos, pitr.key.length(), pitr.value);
|
||||
};
|
||||
|
||||
for(auto&& itr : output_keys(_tag))
|
||||
for(auto&& itr : _keys)
|
||||
_replace(_fpath, itr);
|
||||
|
||||
// environment and configuration variables
|
||||
try
|
||||
{
|
||||
auto strip_leading_and_replace =
|
||||
[](std::string_view inp_v, std::initializer_list<char> keys, const char* val) {
|
||||
auto inp = std::string{inp_v};
|
||||
for(auto key : keys)
|
||||
{
|
||||
auto pos = std::string::npos;
|
||||
while((pos = inp.find(key)) == 0)
|
||||
inp = inp.substr(pos + 1);
|
||||
|
||||
while((pos = inp.find(key)) != std::string::npos)
|
||||
inp = inp.replace(pos, 1, val);
|
||||
}
|
||||
return inp;
|
||||
};
|
||||
|
||||
for(const auto& _re : *env_regexes)
|
||||
{
|
||||
while(std::regex_search(_fpath, _re))
|
||||
{
|
||||
auto _var = std::regex_replace(_fpath, _re, "$3");
|
||||
std::string _val = get_env<std::string>(_var, "");
|
||||
auto _beg = std::regex_replace(_fpath, _re, "$1");
|
||||
auto _end = std::regex_replace(_fpath, _re, "$4");
|
||||
_val = strip_leading_and_replace(_val, {'\t', ' ', '/'}, "_");
|
||||
auto _beg = std::regex_replace(_fpath, _re, "$1");
|
||||
auto _end = std::regex_replace(_fpath, _re, "$4");
|
||||
_fpath = fmt::format("{}{}{}", _beg, _val, _end);
|
||||
}
|
||||
}
|
||||
@@ -454,6 +528,25 @@ format(std::string _fpath, const std::string& _tag)
|
||||
return _fpath;
|
||||
}
|
||||
|
||||
std::string
|
||||
format(std::string _fpath, const std::vector<output_key>& _keys)
|
||||
{
|
||||
if(_fpath.find('%') == std::string::npos && _fpath.find('$') == std::string::npos)
|
||||
return _fpath;
|
||||
|
||||
auto _ref = _fpath;
|
||||
_fpath = format_impl(std::move(_fpath), _keys);
|
||||
|
||||
return (_fpath == _ref) ? _fpath : format(std::move(_fpath), _keys);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string
|
||||
format(std::string _fpath, const std::string& _tag)
|
||||
{
|
||||
return format(std::move(_fpath), output_keys(_tag));
|
||||
}
|
||||
|
||||
std::string
|
||||
format_name(std::string_view _name, const config& _cfg)
|
||||
{
|
||||
|
||||
Atsaukties uz šo jaunā problēmā
Block a user