kernel iteration filtering for counter collection (#911)
* kernel filtering for counter collection * fixing trace tests * removing print statements * fix CI fail * handling preload and updating docs * minor fix * misc fix * misc fix * Typo fix * Update rocprofv3 + input schema - "application_passes" -> "jobs" - removed nesting in YAML/JSON inputs - improved customAction (now booleanArgAction) - supports --<name> (defaults to true) - supports --<name>=<truth-value> - supports --<name> <truth-value> - added --kernel-iteration-range to command-line - automatically support new command-line options in YAML/JSON input - standardized PMC return from text input to match PMC from YAML/JSON input - added support for --log-level env - updated various input*.(yml|json) to modified schema * Update config.cpp - added recommended code to get_kernel_filter_range * Fixing iteration * misc fix * support only [-] for iteration * bug fix * Fix using-rocprofv3.rst * Update config.cpp - patch get_kernel_filter_range --------- Co-authored-by: Jonathan R. Madsen <jonathanrmadsen@gmail.com>
This commit is contained in:
@@ -27,8 +27,11 @@
|
||||
#include "lib/common/demangle.hpp"
|
||||
#include "lib/common/environment.hpp"
|
||||
#include "lib/common/filesystem.hpp"
|
||||
#include "lib/common/logging.hpp"
|
||||
#include "lib/common/utility.hpp"
|
||||
|
||||
#include <rocprofiler-sdk/cxx/details/delimit.hpp>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -132,14 +135,6 @@ handle_special_chars(std::string& str)
|
||||
str.at(pos) = ' ';
|
||||
}
|
||||
|
||||
bool
|
||||
has_kernel_name_format(std::string const& str)
|
||||
{
|
||||
return std::find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return (isalnum(ch) != 0 || ch == '_');
|
||||
}) != str.end();
|
||||
}
|
||||
|
||||
bool
|
||||
has_counter_format(std::string const& str)
|
||||
{
|
||||
@@ -149,34 +144,40 @@ has_counter_format(std::string const& str)
|
||||
}
|
||||
|
||||
// validate kernel names
|
||||
auto
|
||||
parse_kernel_names(const std::string& line)
|
||||
std::unordered_set<uint32_t>
|
||||
get_kernel_filter_range(const std::string& kernel_filter)
|
||||
{
|
||||
auto kernel_names_v = std::vector<std::string>{};
|
||||
if(line.empty()) return kernel_names_v;
|
||||
if(kernel_filter.empty()) return {};
|
||||
|
||||
auto kernel_names = std::set<std::string>{};
|
||||
trim(line);
|
||||
auto input_line = std::stringstream{line};
|
||||
auto kernel_name = std::string{};
|
||||
while(getline(input_line, kernel_name, ','))
|
||||
auto delim = rocprofiler::sdk::parse::tokenize(kernel_filter, ",");
|
||||
auto range_set = std::unordered_set<uint32_t>{};
|
||||
for(const auto& itr : delim)
|
||||
{
|
||||
if(has_kernel_name_format(kernel_name))
|
||||
if(itr.find('-') != std::string::npos && itr.find('[') != std::string::npos &&
|
||||
itr.find(']') != std::string::npos)
|
||||
{
|
||||
ROCP_INFO << "kernel name " << kernel_names.size() << ": " << kernel_name;
|
||||
kernel_names.emplace(kernel_name);
|
||||
auto drange = rocprofiler::sdk::parse::tokenize(itr, "[-] ");
|
||||
ROCP_FATAL_IF(drange.size() != 2)
|
||||
<< "bad range format for '" << itr << "'. Expected [A-B] where A and B are numbers";
|
||||
|
||||
uint32_t start_range = std::stoul(drange.front());
|
||||
uint32_t end_range = std::stoul(drange.back());
|
||||
for(auto i = start_range; i <= end_range; i++)
|
||||
range_set.emplace(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCP_ERROR << "invalid kernel name: " << kernel_name;
|
||||
auto dval = rocprofiler::sdk::parse::tokenize(itr, " ");
|
||||
ROCP_ERROR_IF(dval.empty()) << "kernel range value '" << itr << "' produced no numbers";
|
||||
for(const auto& ditr : dval)
|
||||
{
|
||||
ROCP_FATAL_IF(ditr.find_first_not_of("0123456789") != std::string::npos)
|
||||
<< "expected integer for " << itr << ". Non-integer value detected";
|
||||
range_set.emplace(std::stoul(ditr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kernel_names_v.reserve(kernel_names.size());
|
||||
for(const auto& itr : kernel_names)
|
||||
kernel_names_v.emplace_back(itr);
|
||||
|
||||
return kernel_names_v;
|
||||
return range_set;
|
||||
}
|
||||
|
||||
std::set<std::string>
|
||||
@@ -240,7 +241,8 @@ get_mpi_rank()
|
||||
}
|
||||
|
||||
config::config()
|
||||
: kernel_names{parse_kernel_names(get_env("ROCPROF_KERNEL_NAMES", std::string{}))}
|
||||
: kernel_filter_range{get_kernel_filter_range(
|
||||
get_env("ROCPROF_KERNEL_FILTER_RANGE", std::string{}))}
|
||||
, counters{parse_counters(get_env("ROCPROF_COUNTERS", std::string{}))}
|
||||
{
|
||||
auto output_format = get_env("ROCPROF_OUTPUT_FORMAT", "CSV");
|
||||
@@ -281,6 +283,7 @@ config::config()
|
||||
LOG_IF(FATAL, supported_formats.count(itr) == 0)
|
||||
<< "Unsupported output format type: " << itr;
|
||||
}
|
||||
if(kernel_filter_include.empty()) kernel_filter_include = std::string(".*");
|
||||
}
|
||||
|
||||
std::vector<output_key>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
@@ -81,8 +82,13 @@ struct config
|
||||
std::string output_path = get_env("ROCPROF_OUTPUT_PATH", fs::current_path().string());
|
||||
std::string output_file = get_env("ROCPROF_OUTPUT_FILE_NAME", std::to_string(getpid()));
|
||||
std::string tmp_directory = get_env("ROCPROF_TMPDIR", output_path);
|
||||
std::vector<std::string> kernel_names = {};
|
||||
std::set<std::string> counters = {};
|
||||
|
||||
std::string kernel_filter_include =
|
||||
get_env("ROCPROF_KERNEL_FILTER_INCLUDE_REGEX", std::string{".*"});
|
||||
std::string kernel_filter_exclude =
|
||||
get_env("ROCPROF_KERNEL_FILTER_EXCLUDE_REGEX", std::string{});
|
||||
std::unordered_set<uint32_t> kernel_filter_range = {};
|
||||
std::set<std::string> counters = {};
|
||||
};
|
||||
|
||||
template <config_context ContextT = config_context::global>
|
||||
|
||||
@@ -177,40 +177,79 @@ as_pointer()
|
||||
}
|
||||
|
||||
using code_object_data_map_t = std::unordered_map<uint64_t, rocprofiler_code_object_data_t>;
|
||||
using targeted_kernels_set_t = std::unordered_set<rocprofiler_kernel_id_t>;
|
||||
using targeted_kernels_map_t =
|
||||
std::unordered_map<rocprofiler_kernel_id_t, std::unordered_set<uint32_t>>;
|
||||
using counter_dimension_info_map_t =
|
||||
std::unordered_map<uint64_t, std::vector<rocprofiler_record_dimension_info_t>>;
|
||||
using agent_info_map_t = std::unordered_map<rocprofiler_agent_id_t, rocprofiler_agent_t>;
|
||||
using agent_info_map_t = std::unordered_map<rocprofiler_agent_id_t, rocprofiler_agent_t>;
|
||||
using kernel_iteration_t = std::unordered_map<rocprofiler_kernel_id_t, uint32_t>;
|
||||
|
||||
auto code_obj_data = as_pointer<common::Synchronized<code_object_data_map_t, true>>();
|
||||
auto* kernel_data = as_pointer<common::Synchronized<kernel_symbol_data_map_t, true>>();
|
||||
auto* marker_msg_data = as_pointer<common::Synchronized<marker_message_map_t, true>>();
|
||||
auto counter_dimension_data = common::Synchronized<counter_dimension_info_map_t, true>{};
|
||||
auto target_kernels = common::Synchronized<targeted_kernels_set_t>{};
|
||||
auto target_kernels = common::Synchronized<targeted_kernels_map_t>{};
|
||||
auto* buffered_name_info = as_pointer(get_buffer_id_names());
|
||||
auto* callback_name_info = as_pointer(get_callback_id_names());
|
||||
auto* agent_info = as_pointer(agent_info_map_t{});
|
||||
auto* tool_functions = as_pointer(tool_table{});
|
||||
auto* stats_timestamp = as_pointer(timestamps_t{});
|
||||
auto kernel_iteration = common::Synchronized<kernel_iteration_t, true>{};
|
||||
|
||||
bool
|
||||
add_kernel_target(uint64_t _kern_id)
|
||||
add_kernel_target(uint64_t _kern_id, const std::unordered_set<uint32_t>& range)
|
||||
{
|
||||
return target_kernels
|
||||
.wlock([](targeted_kernels_set_t& _targets_v,
|
||||
uint64_t _kern_id_v) { return _targets_v.emplace(_kern_id_v); },
|
||||
_kern_id)
|
||||
.wlock(
|
||||
[](targeted_kernels_map_t& _targets_v,
|
||||
uint64_t _kern_id_v,
|
||||
std::unordered_set<uint32_t> _range) {
|
||||
return _targets_v.emplace(_kern_id_v, _range);
|
||||
},
|
||||
_kern_id,
|
||||
range)
|
||||
.second;
|
||||
}
|
||||
|
||||
bool
|
||||
is_targeted_kernel(uint64_t _kern_id)
|
||||
{
|
||||
return target_kernels.rlock(
|
||||
[](const targeted_kernels_set_t& _targets_v, uint64_t _kern_id_v) {
|
||||
return (_targets_v.count(_kern_id_v) > 0);
|
||||
bool is_target_kernel = false;
|
||||
std::unordered_set<uint32_t> range = {};
|
||||
is_target_kernel = target_kernels.rlock(
|
||||
[&range](const auto& _targets_v, uint64_t _kern_id_v) {
|
||||
if(_targets_v.find(_kern_id_v) != _targets_v.end())
|
||||
{
|
||||
range = _targets_v.at(_kern_id_v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_kern_id);
|
||||
|
||||
if(is_target_kernel)
|
||||
{
|
||||
kernel_iteration.rlock(
|
||||
[&](const auto& _kernel_iter,
|
||||
uint64_t _kernel_id,
|
||||
std::unordered_set<uint32_t> _range) {
|
||||
auto itr = _kernel_iter.at(_kernel_id);
|
||||
|
||||
// If the iteration range is not given then all iterations of the kernel is profiled
|
||||
if(_range.empty())
|
||||
is_target_kernel = true;
|
||||
|
||||
else if(_range.find(itr) != _range.end())
|
||||
{
|
||||
is_target_kernel = true;
|
||||
}
|
||||
else
|
||||
is_target_kernel = false;
|
||||
},
|
||||
_kern_id,
|
||||
range);
|
||||
}
|
||||
return is_target_kernel;
|
||||
}
|
||||
|
||||
auto&
|
||||
@@ -496,34 +535,19 @@ code_object_tracing_callback(rocprofiler_callback_tracing_record_t record,
|
||||
{
|
||||
// if kernel name is provided by user then by default all kernels in the application
|
||||
// are targeted
|
||||
if(tool::get_config().kernel_names.empty())
|
||||
const auto& kernel_info = itr.first->second;
|
||||
auto kernel_filter_include = tool::get_config().kernel_filter_include;
|
||||
auto kernel_filter_exclude = tool::get_config().kernel_filter_exclude;
|
||||
auto kernel_filter_range = tool::get_config().kernel_filter_range;
|
||||
|
||||
std::regex include_regex(kernel_filter_include);
|
||||
std::regex exclude_regex(kernel_filter_exclude);
|
||||
if(std::regex_search(kernel_info.formatted_kernel_name, include_regex))
|
||||
{
|
||||
add_kernel_target(sym_data->kernel_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& kernel_info = itr.first->second;
|
||||
for(const auto& name : tool::get_config().kernel_names)
|
||||
{
|
||||
if(name == kernel_info.truncated_kernel_name)
|
||||
{
|
||||
add_kernel_target(itr.first->first);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dkernel_name = std::string_view{kernel_info.demangled_kernel_name};
|
||||
auto pos = dkernel_name.find(name);
|
||||
// if the demangled kernel name contains name and the next character is
|
||||
// '(' then mark as found
|
||||
if(pos != std::string::npos && (pos + 1) < dkernel_name.size() &&
|
||||
dkernel_name.at(pos + 1) == '(')
|
||||
{
|
||||
add_kernel_target(itr.first->first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(kernel_filter_exclude.empty())
|
||||
add_kernel_target(sym_data->kernel_id, kernel_filter_range);
|
||||
else if(!std::regex_search(kernel_info.formatted_kernel_name, exclude_regex))
|
||||
add_kernel_target(sym_data->kernel_id, kernel_filter_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -882,6 +906,18 @@ dispatch_callback(rocprofiler_profile_counting_dispatch_data_t dispatch_data,
|
||||
auto kernel_id = dispatch_data.dispatch_info.kernel_id;
|
||||
auto agent_id = dispatch_data.dispatch_info.agent_id;
|
||||
|
||||
kernel_iteration.wlock(
|
||||
[](auto& _kernel_iter, rocprofiler_kernel_id_t _kernel_id) {
|
||||
auto itr = _kernel_iter.find(_kernel_id);
|
||||
if(itr == _kernel_iter.end())
|
||||
_kernel_iter.emplace(_kernel_id, 1);
|
||||
else
|
||||
{
|
||||
itr->second++;
|
||||
}
|
||||
},
|
||||
kernel_id);
|
||||
|
||||
if(!is_targeted_kernel(kernel_id))
|
||||
{
|
||||
return;
|
||||
|
||||
Fai riferimento in un nuovo problema
Block a user