Fix loop-level instrumentation + more (#32)
- fix loop-level instrumentation
- support loop instrumentation w/o debug symbols via loop number
- improve module_function messages
- serialize num_basic_blocks
- serialize num_outer_loops
- serialize is_num_instructions_constrained
- serialize is_loop_num_instructions_constrained
- updated transpose example to use uniform_int_distribution
- added transpose loop test
- added fail regexes for tests which enable loop instrumentation
- use module->getFullName in get_loop_file_line_info
- use module->getFullName in get_func_file_line_info
- use module->getFullName in get_basic_block_file_line_info
[ROCm/rocprofiler-systems commit: a640fbdb29]
Cette révision appartient à :
révisé par
GitHub
Parent
5c1e6ea127
révision
2eb4b4981c
@@ -31,6 +31,7 @@ THE SOFTWARE.
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -106,12 +107,15 @@ run(int rank, int tid, hipStream_t stream, int argc, char** argv)
|
||||
std::cout << "[" << rank << "][" << tid << "] M: " << M << " N: " << N << std::endl;
|
||||
_lk.unlock();
|
||||
|
||||
std::default_random_engine _engine{ std::random_device{}() * (rank + 1) * (tid + 1) };
|
||||
std::uniform_int_distribution<int> _dist{ 0, 1000 };
|
||||
|
||||
size_t size = sizeof(int) * M * N;
|
||||
int* inp_matrix = new int[size];
|
||||
int* out_matrix = new int[size];
|
||||
for(size_t i = 0; i < M * N; i++)
|
||||
{
|
||||
inp_matrix[i] = rand() % 1002;
|
||||
inp_matrix[i] = _dist(_engine);
|
||||
out_matrix[i] = 0;
|
||||
}
|
||||
int* in = nullptr;
|
||||
|
||||
@@ -529,11 +529,9 @@ are_file_include_exclude_lists_empty()
|
||||
// the instrumented loop and formats it properly.
|
||||
//
|
||||
function_signature
|
||||
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGraph,
|
||||
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t*,
|
||||
basic_loop_t* loopToInstrument)
|
||||
{
|
||||
if(!cfGraph || !loopToInstrument || !func) return function_signature{ "", "", "" };
|
||||
|
||||
std::vector<BPatch_basicBlock*> basic_blocks{};
|
||||
loopToInstrument->getLoopBasicBlocksExclusive(basic_blocks);
|
||||
|
||||
@@ -563,7 +561,7 @@ get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGra
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getName(mname, FUNCNAMELEN);
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
auto* returnType = func->getReturnType();
|
||||
@@ -641,7 +639,8 @@ get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGra
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(typeName, fname, filename, _params);
|
||||
return function_signature(typeName, fname, filename, _params, { 0, 0 }, { 0, 0 },
|
||||
true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +660,7 @@ get_func_file_line_info(module_t* module, procedure_t* func)
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getName(mname, FUNCNAMELEN);
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
address_t base_addr{};
|
||||
@@ -727,7 +726,7 @@ get_basic_block_file_line_info(module_t* module, procedure_t* func)
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getName(mname, FUNCNAMELEN);
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
@@ -67,7 +67,7 @@ function_signature::get(bool _all, bool _save) const
|
||||
if((_all || use_return_info) && !m_return.empty()) ss << m_return << " ";
|
||||
ss << m_name;
|
||||
if(_all || use_args_info) ss << m_params;
|
||||
if(m_loop && m_info_beg)
|
||||
if(m_loop)
|
||||
{
|
||||
auto _row_col_str = [](unsigned long _row, unsigned long _col) {
|
||||
std::stringstream _ss{};
|
||||
@@ -89,8 +89,11 @@ function_signature::get(bool _all, bool _save) const
|
||||
ss << " [" << _rc1 << "]";
|
||||
else if(!m_info_end && !_rc1.empty())
|
||||
ss << " [" << _rc1 << "]";
|
||||
else if(m_loop_num < std::numeric_limits<uint32_t>::max())
|
||||
ss << " [loop#" << m_loop_num << "]";
|
||||
else
|
||||
errprintf(3, "line info for %s is empty!\n", m_name.c_str());
|
||||
errprintf(3, "line info for %s is empty! [{%s}] [{%s}]\n", m_name.c_str(),
|
||||
_rc1.c_str(), _rc2.c_str());
|
||||
}
|
||||
if((_all || use_file_info) && m_file.length() > 0) ss << " [" << m_file;
|
||||
if((_all || use_line_info) && m_row.first > 0) ss << ":" << m_row.first;
|
||||
|
||||
@@ -40,6 +40,12 @@ struct function_signature
|
||||
location_t _col = { 0, 0 }, bool _loop = false,
|
||||
bool _info_beg = false, bool _info_end = false);
|
||||
|
||||
function_signature& set_loop_number(uint32_t _n)
|
||||
{
|
||||
m_loop_num = _n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static string_t get(function_signature& sig);
|
||||
string_t get(bool _all = false, bool _save = true) const;
|
||||
string_t get_coverage(bool _is_basic_block) const;
|
||||
@@ -47,6 +53,7 @@ struct function_signature
|
||||
bool m_loop = false;
|
||||
bool m_info_beg = false;
|
||||
bool m_info_end = false;
|
||||
uint32_t m_loop_num = std::numeric_limits<uint32_t>::max();
|
||||
location_t m_row = { 0, 0 };
|
||||
location_t m_col = { 0, 0 };
|
||||
string_t m_return = {};
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "fwd.hpp"
|
||||
#include "omnitrace.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
module_function::width_t&
|
||||
module_function::get_width()
|
||||
{
|
||||
@@ -133,7 +135,8 @@ module_function::should_coverage_instrument() const
|
||||
{
|
||||
messages.emplace_back(
|
||||
2, "Skipping", "function",
|
||||
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"));
|
||||
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"),
|
||||
function_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,7 +172,8 @@ module_function::should_instrument(bool coverage) const
|
||||
{
|
||||
messages.emplace_back(
|
||||
2, "Skipping", "function",
|
||||
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"));
|
||||
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"),
|
||||
function_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -199,7 +203,7 @@ module_function::is_instrumentable() const
|
||||
{
|
||||
if(!function->isInstrumentable())
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "module", "not-instrumentable");
|
||||
messages.emplace_back(2, "Skipping", "module", "not-instrumentable", module_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -225,12 +229,14 @@ module_function::is_user_restricted() const
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "module", "module-restrict-regex");
|
||||
messages.emplace_back(2, "Forcing", "module", "module-restrict-regex",
|
||||
module_name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "module", "module-restrict-regex");
|
||||
messages.emplace_back(3, "Skipping", "module", "module-restrict-regex",
|
||||
module_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -239,17 +245,20 @@ module_function::is_user_restricted() const
|
||||
{
|
||||
if(check_regex_restrictions(function_name, func_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex",
|
||||
function_name);
|
||||
return false;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex",
|
||||
signature.get());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "function-restrict-regex");
|
||||
messages.emplace_back(3, "Skipping", "function", "function-restrict-regex",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -264,7 +273,8 @@ module_function::is_user_included() const
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "module", "module-include-regex");
|
||||
messages.emplace_back(2, "Forcing", "module", "module-include-regex",
|
||||
module_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -273,12 +283,14 @@ module_function::is_user_included() const
|
||||
{
|
||||
if(check_regex_restrictions(function_name, func_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex",
|
||||
signature.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -293,7 +305,8 @@ module_function::is_user_excluded() const
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "module", "module-exclude-regex");
|
||||
messages.emplace_back(2, "Skipping", "module", "module-exclude-regex",
|
||||
module_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -302,12 +315,14 @@ module_function::is_user_excluded() const
|
||||
{
|
||||
if(check_regex_restrictions(function_name, func_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex",
|
||||
signature.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -327,7 +342,7 @@ module_function::is_module_constrained() const
|
||||
{
|
||||
auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize;
|
||||
auto _report = [&](const string_t& _action, const string_t& _reason, int _lvl) {
|
||||
messages.emplace_back(_lvl, _action, "module", _reason);
|
||||
messages.emplace_back(_lvl, _action, "module", _reason, module_name);
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -390,7 +405,7 @@ module_function::is_routine_constrained() const
|
||||
{
|
||||
auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize;
|
||||
auto _report = [&](const string_t& _action, const string_t& _reason, int _lvl) {
|
||||
messages.emplace_back(_lvl, _action, "function", _reason);
|
||||
messages.emplace_back(_lvl, _action, "function", _reason, function_name);
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -462,7 +477,7 @@ module_function::is_overlapping_constrained() const
|
||||
{
|
||||
if(!allow_overlapping && is_overlapping())
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "overlapping");
|
||||
messages.emplace_back(2, "Skipping", "function", "overlapping", function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -482,7 +497,8 @@ module_function::is_dynamic_callsite_forced() const
|
||||
{
|
||||
if(instr_dynamic_callsites && contains_dynamic_callsites())
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "dynamic-callsites");
|
||||
messages.emplace_back(2, "Forcing", "function", "dynamic-callsites",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -496,7 +512,8 @@ module_function::is_address_range_constrained() const
|
||||
|
||||
if(address_range < min_address_range)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range");
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -509,7 +526,8 @@ module_function::is_loop_address_range_constrained() const
|
||||
|
||||
if(address_range < min_loop_address_range)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range-loop");
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range-loop",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -523,7 +541,8 @@ module_function::is_num_instructions_constrained() const
|
||||
|
||||
if(num_instructions < min_instructions)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-instructions");
|
||||
messages.emplace_back(2, "Skipping", "function", "min-instructions",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -537,7 +556,8 @@ module_function::is_loop_num_instructions_constrained() const
|
||||
|
||||
if(num_instructions < min_loop_instructions)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-instructions-loop");
|
||||
messages.emplace_back(2, "Skipping", "function", "min-instructions-loop",
|
||||
function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -554,7 +574,8 @@ module_function::can_instrument_entry() const
|
||||
|
||||
if(_num_points == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-entry-point");
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-entry-point",
|
||||
function_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -571,7 +592,8 @@ module_function::can_instrument_exit() const
|
||||
|
||||
if(_num_points == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-exit-point");
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-exit-point",
|
||||
function_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -591,7 +613,7 @@ module_function::is_entry_trap_constrained() const
|
||||
if(!instr_traps && (_num_points - _num_traps) == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function",
|
||||
"entry-point-trap-instrumentation");
|
||||
"entry-point-trap-instrumentation", function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -611,7 +633,7 @@ module_function::is_exit_trap_constrained() const
|
||||
if((_num_points - _num_traps) == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function",
|
||||
"exit-point-trap-instrumentation");
|
||||
"exit-point-trap-instrumentation", function_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -633,54 +655,62 @@ module_function::operator()(address_space_t* _addr_space, procedure_t* _entr_tra
|
||||
if(insert_instr(_addr_space, function, _entr, BPatch_entry) &&
|
||||
insert_instr(_addr_space, function, _exit, BPatch_exit))
|
||||
{
|
||||
messages.emplace_back(1, "Instrumenting", "function", "no-constraint");
|
||||
messages.emplace_back(1, "Instrumenting", "function", "no-constraint",
|
||||
function_name);
|
||||
++_count.first;
|
||||
}
|
||||
|
||||
for(auto* itr : loop_blocks)
|
||||
for(size_t i = 0; i < loop_blocks.size(); ++i)
|
||||
{
|
||||
if(!loop_level_instr) continue;
|
||||
|
||||
auto _is_constrained = [this](bool _v, const std::string& _label) {
|
||||
if(!_v)
|
||||
auto* itr = loop_blocks.at(i);
|
||||
auto _is_constrained = [this](bool _v, const std::string& _label,
|
||||
const std::string& _name) {
|
||||
if(_v)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", _label);
|
||||
messages.emplace_back(3, "Skipping", "function-loop", _label, _name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto lname =
|
||||
get_loop_file_line_info(module, function, flow_graph, itr).set_loop_number(i);
|
||||
auto _lname = lname.get();
|
||||
|
||||
size_t _points = 0;
|
||||
size_t _ntraps = 0;
|
||||
std::tie(_points, _ntraps) = query_instr(function, BPatch_entry, flow_graph, itr);
|
||||
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-entry-point")) continue;
|
||||
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
|
||||
"loop-entry-point-trap-instrumentation"))
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-entry-point", _lname))
|
||||
continue;
|
||||
if(_is_constrained(!instr_loop_traps && _points == _ntraps,
|
||||
"loop-entry-point-trap-instrumentation", _lname))
|
||||
continue;
|
||||
|
||||
std::tie(_points, _ntraps) = query_instr(function, BPatch_exit, flow_graph, itr);
|
||||
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-exit-point")) continue;
|
||||
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
|
||||
"loop-exit-point-trap-instrumentation"))
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-exit-point", _lname))
|
||||
continue;
|
||||
if(_is_constrained(!instr_loop_traps && _points == _ntraps,
|
||||
"loop-exit-point-trap-instrumentation", _lname))
|
||||
continue;
|
||||
|
||||
auto lname = get_loop_file_line_info(module, function, flow_graph, itr);
|
||||
auto _lname = lname.get();
|
||||
|
||||
messages.emplace_back(1, "Loop Instrumenting", "function", "no-constraint");
|
||||
++_count.second;
|
||||
|
||||
auto _ltrace_entr = omnitrace_call_expr(_lname.c_str());
|
||||
auto _ltrace_exit = omnitrace_call_expr(_lname.c_str());
|
||||
auto _lentr = _ltrace_entr.get(_entr_trace);
|
||||
auto _lexit = _ltrace_exit.get(_exit_trace);
|
||||
|
||||
insert_instr(_addr_space, function, _lentr, BPatch_entry, flow_graph, itr,
|
||||
instr_loop_traps);
|
||||
insert_instr(_addr_space, function, _lexit, BPatch_exit, flow_graph, itr,
|
||||
instr_loop_traps);
|
||||
if(insert_instr(_addr_space, function, _lentr, BPatch_entry, flow_graph, itr,
|
||||
instr_loop_traps) &&
|
||||
insert_instr(_addr_space, function, _lexit, BPatch_exit, flow_graph, itr,
|
||||
instr_loop_traps))
|
||||
{
|
||||
messages.emplace_back(1, "Loop Instrumenting", "function", "no-constraint",
|
||||
_lname);
|
||||
++_count.second;
|
||||
}
|
||||
}
|
||||
|
||||
return _count;
|
||||
@@ -702,7 +732,8 @@ module_function::register_source(address_space_t* _addr_space, procedure_t* _ent
|
||||
|
||||
if(insert_instr(_addr_space, _entr_points, _entr, BPatch_entry))
|
||||
{
|
||||
messages.emplace_back(1, "Code Coverage", "function", "no-constraint");
|
||||
messages.emplace_back(1, "Code Coverage", "function", "no-constraint",
|
||||
_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -721,7 +752,7 @@ module_function::register_source(address_space_t* _addr_space, procedure_t* _ent
|
||||
if(insert_instr(_addr_space, _entr_points, _entr, BPatch_entry))
|
||||
{
|
||||
messages.emplace_back(1, "Code Coverage", "basic_block",
|
||||
"no-constraint");
|
||||
"no-constraint", _name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -745,7 +776,8 @@ module_function::register_coverage(address_space_t* _addr_space,
|
||||
|
||||
if(insert_instr(_addr_space, function, _entr, BPatch_entry))
|
||||
{
|
||||
messages.emplace_back(1, "Code Coverage", "function", "no-constraint");
|
||||
messages.emplace_back(1, "Code Coverage", "function", "no-constraint",
|
||||
signature.get_coverage(false));
|
||||
++_count.first;
|
||||
}
|
||||
break;
|
||||
@@ -764,7 +796,7 @@ module_function::register_coverage(address_space_t* _addr_space,
|
||||
{
|
||||
++_count.second;
|
||||
messages.emplace_back(1, "Code Coverage", "basic_block",
|
||||
"no-constraint");
|
||||
"no-constraint", _signature.get_coverage(true));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -98,7 +98,7 @@ struct module_function
|
||||
basic_loop_vec_t loop_blocks = {};
|
||||
std::vector<std::vector<instruction_t>> instructions = {};
|
||||
|
||||
using str_msg_t = std::tuple<int, string_t, string_t, string_t>;
|
||||
using str_msg_t = std::tuple<int, string_t, string_t, string_t, string_t>;
|
||||
using str_msg_vec_t = std::vector<str_msg_t>;
|
||||
|
||||
mutable str_msg_vec_t messages = {};
|
||||
@@ -183,6 +183,8 @@ module_function::serialize(ArchiveT& ar, const unsigned)
|
||||
|
||||
if constexpr(tim::concepts::is_output_archive<ArchiveT>::value)
|
||||
{
|
||||
ar(cereal::make_nvp("num_basic_blocks", basic_blocks.size()),
|
||||
cereal::make_nvp("num_outer_loops", loop_blocks.size()));
|
||||
ar.setNextName("heuristics");
|
||||
ar.startNode();
|
||||
ar(cereal::make_nvp("should_instrument", should_instrument()),
|
||||
@@ -202,10 +204,12 @@ module_function::serialize(ArchiveT& ar, const unsigned)
|
||||
cereal::make_nvp("is_dynamic_callsite_forced", is_dynamic_callsite_forced()),
|
||||
cereal::make_nvp("is_address_range_constrained",
|
||||
is_address_range_constrained()),
|
||||
cereal::make_nvp("is_num_instructions_constrained",
|
||||
is_num_instructions_constrained()),
|
||||
cereal::make_nvp("is_loop_address_range_constrained",
|
||||
is_loop_address_range_constrained()),
|
||||
cereal::make_nvp("is_num_instructions_constrained",
|
||||
is_num_instructions_constrained()));
|
||||
cereal::make_nvp("is_loop_num_instructions_constrained",
|
||||
is_loop_num_instructions_constrained()));
|
||||
ar.finishNode();
|
||||
// instructions can inflate JSON size so only output when verbosity is increased
|
||||
// above default
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "omnitrace.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <timemory/config.hpp>
|
||||
#include <timemory/hash.hpp>
|
||||
#include <timemory/manager.hpp>
|
||||
@@ -947,7 +948,7 @@ main(int argc, char** argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
verbprintf(0, "instrumentation target: %s\n", mutname.c_str());
|
||||
verbprintf(1, "instrumentation target: %s\n", mutname.c_str());
|
||||
|
||||
// did we load a library? if not, load the default
|
||||
auto generate_libnames = [](auto& _targ, const auto& _base,
|
||||
@@ -1041,7 +1042,11 @@ main(int argc, char** argv)
|
||||
|
||||
if(app_modules && !app_modules->empty())
|
||||
{
|
||||
modules = *app_modules;
|
||||
modules.reserve(app_modules->size());
|
||||
for(auto* itr : *app_modules)
|
||||
{
|
||||
if(!itr->isSystemLib()) modules.emplace_back(itr);
|
||||
}
|
||||
for(auto* itr : modules)
|
||||
{
|
||||
auto* procedures = itr->getProcedures();
|
||||
@@ -1065,7 +1070,11 @@ main(int argc, char** argv)
|
||||
|
||||
if(app_functions && !app_functions->empty())
|
||||
{
|
||||
functions = *app_functions;
|
||||
functions.reserve(app_functions->size());
|
||||
for(auto* itr : *app_functions)
|
||||
{
|
||||
if(!itr->getModule()->isSystemLib()) functions.emplace_back(itr);
|
||||
}
|
||||
for(auto* itr : functions)
|
||||
{
|
||||
module_t* mod = itr->getModule();
|
||||
@@ -1083,7 +1092,7 @@ main(int argc, char** argv)
|
||||
verbprintf(0, "Warning! No functions in application...\n");
|
||||
}
|
||||
|
||||
verbprintf(0, "Module size before loading instrumentation library: %lu\n",
|
||||
verbprintf(1, "Module size before loading instrumentation library: %lu\n",
|
||||
(long unsigned) modules.size());
|
||||
|
||||
if(debug_print || verbose_level > 2)
|
||||
@@ -1153,7 +1162,7 @@ main(int argc, char** argv)
|
||||
{
|
||||
_libname = get_absolute_lib_filepath(_libname);
|
||||
_tried_libs += string_t("|") + _libname;
|
||||
verbprintf(0, "loading library: '%s'...\n", _libname.c_str());
|
||||
verbprintf(1, "loading library: '%s'...\n", _libname.c_str());
|
||||
result = (addr_space->loadLibrary(_libname.c_str()) != nullptr);
|
||||
verbprintf(2, "loadLibrary(%s) result = %s\n", _libname.c_str(),
|
||||
(result) ? "success" : "failure");
|
||||
@@ -1646,7 +1655,7 @@ main(int argc, char** argv)
|
||||
//----------------------------------------------------------------------------------//
|
||||
if(app_thread)
|
||||
{
|
||||
verbprintf(1, "Beginning insertion set...\n");
|
||||
verbprintf(2, "Beginning insertion set...\n");
|
||||
addr_space->beginInsertionSet();
|
||||
}
|
||||
|
||||
@@ -1670,7 +1679,7 @@ main(int argc, char** argv)
|
||||
if(instr_mode != "coverage")
|
||||
{
|
||||
std::map<std::string, std::pair<size_t, size_t>> _pass_info{};
|
||||
const int _pass_verbose_lvl = 1;
|
||||
const int _pass_verbose_lvl = 0;
|
||||
for(const auto& itr : instrumented_module_functions)
|
||||
{
|
||||
auto _count = itr(addr_space, entr_trace, exit_trace);
|
||||
@@ -1679,24 +1688,22 @@ main(int argc, char** argv)
|
||||
|
||||
for(const auto& mitr : itr.messages)
|
||||
_report_info(std::get<0>(mitr), std::get<1>(mitr), std::get<2>(mitr),
|
||||
std::get<3>(mitr),
|
||||
std::get<2>(mitr) == "module" ? itr.module_name
|
||||
: itr.function_name);
|
||||
std::get<3>(mitr), std::get<4>(mitr));
|
||||
}
|
||||
|
||||
// report the trace instrumented functions
|
||||
for(auto& itr : _pass_info)
|
||||
{
|
||||
auto _valid = (verbose_level > _pass_verbose_lvl ||
|
||||
auto _valid = (verbose_level >= _pass_verbose_lvl ||
|
||||
(itr.second.first + itr.second.second) > 0);
|
||||
if(!_valid) continue;
|
||||
verbprintf(_pass_verbose_lvl, "%4zu instrumented procedures in %s\n",
|
||||
verbprintf(_pass_verbose_lvl, "%4zu instrumented funcs in %s\n",
|
||||
itr.second.first, itr.first.c_str());
|
||||
_valid = (loop_level_instr &&
|
||||
(verbose_level > _pass_verbose_lvl || itr.second.second > 0));
|
||||
(verbose_level >= _pass_verbose_lvl || itr.second.second > 0));
|
||||
if(_valid)
|
||||
{
|
||||
verbprintf(_pass_verbose_lvl, "%4zu instrumented loops in procedure %s\n",
|
||||
verbprintf(_pass_verbose_lvl, "%4zu instrumented loops in %s\n",
|
||||
itr.second.second, itr.first.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1715,9 +1722,7 @@ main(int argc, char** argv)
|
||||
|
||||
for(const auto& mitr : itr.messages)
|
||||
_report_info(std::get<0>(mitr), std::get<1>(mitr), std::get<2>(mitr),
|
||||
std::get<3>(mitr),
|
||||
std::get<2>(mitr) == "module" ? itr.module_name
|
||||
: itr.function_name);
|
||||
std::get<3>(mitr), std::get<4>(mitr));
|
||||
}
|
||||
|
||||
// report the coverage instrumented functions
|
||||
@@ -1751,7 +1756,7 @@ main(int argc, char** argv)
|
||||
|
||||
if(app_thread)
|
||||
{
|
||||
verbprintf(1, "Finalizing insertion set...\n");
|
||||
verbprintf(2, "Finalizing insertion set...\n");
|
||||
bool modified = true;
|
||||
bool success = addr_space->finalizeInsertionSet(true, &modified);
|
||||
if(!success)
|
||||
@@ -1939,7 +1944,8 @@ main(int argc, char** argv)
|
||||
if(main_func)
|
||||
{
|
||||
verbprintf(0, "Getting linked libraries for %s...\n", cmdv0.c_str());
|
||||
verbprintf(0, "Consider instrumenting the relevant libraries...\n\n");
|
||||
verbprintf(0, "Consider instrumenting the relevant libraries...\n");
|
||||
verbprintf(0, "\n");
|
||||
|
||||
using TIMEMORY_PIPE = tim::popen::TIMEMORY_PIPE;
|
||||
|
||||
@@ -1953,9 +1959,9 @@ main(int argc, char** argv)
|
||||
if(perr != 0) perror("Error in omnitrace_fork");
|
||||
|
||||
for(const auto& itr : linked_libraries)
|
||||
printf("\t%s\n", itr.c_str());
|
||||
verbprintf(0, "\t%s\n", itr.c_str());
|
||||
|
||||
printf("\n");
|
||||
verbprintf(0, "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2080,14 +2086,29 @@ query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cf
|
||||
module_t* module = funcToInstr->getModule();
|
||||
if(!module) return { 0, 0 };
|
||||
|
||||
if(!cfGraph) cfGraph = funcToInstr->getCFG();
|
||||
|
||||
bpvector_t<point_t*>* _points = nullptr;
|
||||
|
||||
if(cfGraph && loopToInstrument)
|
||||
if((cfGraph && loopToInstrument) ||
|
||||
(traceLoc == BPatch_locLoopEntry || traceLoc == BPatch_locLoopExit))
|
||||
{
|
||||
if(traceLoc == BPatch_entry)
|
||||
if(!cfGraph) throw std::runtime_error("No control flow graph");
|
||||
if(!loopToInstrument) throw std::runtime_error("No loop to instrument");
|
||||
|
||||
if(traceLoc == BPatch_entry || traceLoc == BPatch_locLoopEntry)
|
||||
{
|
||||
_points = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, loopToInstrument);
|
||||
else if(traceLoc == BPatch_exit)
|
||||
}
|
||||
else if(traceLoc == BPatch_exit || traceLoc == BPatch_locLoopExit)
|
||||
{
|
||||
_points = cfGraph->findLoopInstPoints(BPatch_locLoopExit, loopToInstrument);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("unsupported trace location :: " +
|
||||
std::to_string(traceLoc));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2145,7 +2166,7 @@ get_absolute_exe_filepath(std::string exe_name, const std::string& env_path)
|
||||
if(file_exists(TIMEMORY_JOIN('/', pitr, exe_name)))
|
||||
{
|
||||
exe_name = get_realpath(TIMEMORY_JOIN('/', pitr, exe_name));
|
||||
verbprintf(0, "Resolved '%s' to '%s'...\n", _exe_orig.c_str(),
|
||||
verbprintf(1, "Resolved '%s' to '%s'...\n", _exe_orig.c_str(),
|
||||
exe_name.c_str());
|
||||
break;
|
||||
}
|
||||
@@ -2181,7 +2202,7 @@ get_absolute_lib_filepath(std::string lib_name, const std::string& env_path)
|
||||
if(file_exists(TIMEMORY_JOIN('/', pitr, lib_name)))
|
||||
{
|
||||
lib_name = get_realpath(TIMEMORY_JOIN('/', pitr, lib_name));
|
||||
verbprintf(0, "Resolved '%s' to '%s'...\n", _lib_orig.c_str(),
|
||||
verbprintf(1, "Resolved '%s' to '%s'...\n", _lib_orig.c_str(),
|
||||
lib_name.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -331,6 +331,7 @@ insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
|
||||
bpvector_t<point_t*>* _points = nullptr;
|
||||
auto _trace = traceFunc.get();
|
||||
|
||||
if(!cfGraph) funcToInstr->getCFG();
|
||||
if(cfGraph && loopToInstrument)
|
||||
{
|
||||
if(traceLoc == BPatch_entry)
|
||||
|
||||
@@ -406,10 +406,43 @@ omnitrace_add_test(
|
||||
TARGET transpose
|
||||
MPI ${TRANSPOSE_USE_MPI}
|
||||
NUM_PROCS ${NUM_PROCS}
|
||||
REWRITE_ARGS -e -v 2 --print-instructions
|
||||
RUNTIME_ARGS -e -v 1 --label file line return args
|
||||
REWRITE_ARGS -e -v 2 --print-instructions -E uniform_int_distribution
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
-v
|
||||
1
|
||||
--label
|
||||
file
|
||||
line
|
||||
return
|
||||
args
|
||||
-E
|
||||
uniform_int_distribution
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=ON")
|
||||
|
||||
omnitrace_add_test(
|
||||
SKIP_BASELINE SKIP_SAMPLING SKIP_RUNTIME
|
||||
NAME transpose-loops
|
||||
TARGET transpose
|
||||
LABELS "loops"
|
||||
MPI ${TRANSPOSE_USE_MPI}
|
||||
NUM_PROCS ${NUM_PROCS}
|
||||
REWRITE_ARGS
|
||||
-e
|
||||
-v
|
||||
2
|
||||
--label
|
||||
return
|
||||
args
|
||||
-l
|
||||
-i
|
||||
8
|
||||
-E
|
||||
uniform_int_distribution
|
||||
RUN_ARGS 2 100 50
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure transpose")
|
||||
|
||||
omnitrace_add_test(
|
||||
NAME parallel-overhead
|
||||
TARGET parallel-overhead
|
||||
@@ -454,6 +487,7 @@ omnitrace_add_test(
|
||||
omnitrace_add_test(
|
||||
NAME user-api
|
||||
TARGET user-api
|
||||
LABELS "loops"
|
||||
REWRITE_ARGS -e -v 2 -l --min-instructions=8 -E custom_push_region
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
@@ -469,7 +503,8 @@ omnitrace_add_test(
|
||||
return
|
||||
args
|
||||
RUN_ARGS 10 ${NUM_THREADS} 1000
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF")
|
||||
ENVIRONMENT "${_base_environment};OMNITRACE_CRITICAL_TRACE=OFF"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure")
|
||||
|
||||
omnitrace_add_test(
|
||||
SKIP_RUNTIME
|
||||
@@ -553,7 +588,7 @@ omnitrace_add_test(
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
LABELS "kokkos"
|
||||
LABELS "kokkos;loops"
|
||||
REWRITE_ARGS -e -v 2
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
@@ -575,7 +610,7 @@ omnitrace_add_test(
|
||||
TARGET lulesh
|
||||
MPI ${LULESH_USE_MPI}
|
||||
NUM_PROCS 8
|
||||
LABELS "kokkos"
|
||||
LABELS "kokkos;loops"
|
||||
REWRITE_ARGS -e -v 2 -l --dynamic-callsites --traps --allow-overlapping
|
||||
RUNTIME_ARGS
|
||||
-e
|
||||
@@ -590,7 +625,8 @@ omnitrace_add_test(
|
||||
peak_rss
|
||||
RUN_ARGS -i 10 -s 20 -p
|
||||
ENVIRONMENT
|
||||
"${_timemory_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=OFF")
|
||||
"${_timemory_environment};OMNITRACE_CRITICAL_TRACE=OFF;OMNITRACE_USE_KOKKOSP=OFF"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure")
|
||||
|
||||
omnitrace_add_test(
|
||||
SKIP_SAMPLING
|
||||
@@ -601,7 +637,8 @@ omnitrace_add_test(
|
||||
RUNTIME_ARGS -e -v 1 --label return args
|
||||
REWRITE_TIMEOUT 180
|
||||
RUNTIME_TIMEOUT 360
|
||||
ENVIRONMENT "${_ompt_environment};OMNITRACE_USE_SAMPLING=OFF")
|
||||
ENVIRONMENT "${_ompt_environment};OMNITRACE_USE_SAMPLING=OFF"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure")
|
||||
|
||||
omnitrace_add_test(
|
||||
SKIP_RUNTIME
|
||||
@@ -613,7 +650,8 @@ omnitrace_add_test(
|
||||
REWRITE_TIMEOUT 180
|
||||
RUNTIME_TIMEOUT 360
|
||||
ENVIRONMENT
|
||||
"${_ompt_environment};OMNITRACE_USE_SAMPLING=ON;OMNITRACE_SAMPLING_FREQ=100")
|
||||
"${_ompt_environment};OMNITRACE_USE_SAMPLING=ON;OMNITRACE_SAMPLING_FREQ=100"
|
||||
REWRITE_FAIL_REGEX "0 instrumented loops in procedure")
|
||||
|
||||
omnitrace_add_test(
|
||||
SKIP_BASELINE SKIP_SAMPLING
|
||||
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur