Skip to content

Commit

Permalink
Add loop selection in loop_monitor and loop-report (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
daboehme authored Jul 15, 2020
1 parent 4b38c2d commit 5e94fa1
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 19 deletions.
18 changes: 14 additions & 4 deletions src/mpi/controllers/LoopReportController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,13 @@ class LoopReportController : public cali::ChannelController
infovec.push_back(get_loop_info(db, rec));
});

if (!infovec.empty())
process_timeseries(c, db, stream, infovec.front());
else
if (!infovec.empty()) {
for (const LoopInfo& loopinfo : infovec)
if (loopinfo.iterations > 0)
process_timeseries(c, db, stream, loopinfo);
} else {
Log(1).stream() << channel()->name() << ": No instrumented loops found" << std::endl;

}
}

finalize_mpi();
Expand All @@ -334,6 +336,9 @@ class LoopReportController : public cali::ChannelController
else
config()["CALI_LOOP_MONITOR_TIME_INTERVAL"] = "0.5";

if (m_opts.is_set("target_loops"))
config()["CALI_LOOP_MONITOR_TARGET_LOOPS" ] = m_opts.get("target_loops").to_string();

m_opts.update_channel_config(config());
}

Expand Down Expand Up @@ -386,6 +391,11 @@ const char* loop_report_spec =
" \"name\": \"timeseries.maxrows\","
" \"type\": \"int\","
" \"description\": \"Max number of rows in timeseries display. Set to 0 to show all. Default: 20.\""
" },"
" {"
" \"name\": \"target_loops\","
" \"type\": \"string\","
" \"description\": \"List of loops to target. Default: any top-level loop.\""
" }"
" ]"
"}";
Expand Down
43 changes: 34 additions & 9 deletions src/services/monitor/LoopMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "caliper/common/RuntimeConfig.h"

#include <chrono>
#include <vector>

using namespace cali;

Expand All @@ -30,6 +31,7 @@ class LoopMonitor
static const ConfigSet::Entry s_configdata[];

int loop_level;
int target_level;
int start_iteration;
int num_iterations;
int num_snapshots;
Expand All @@ -40,10 +42,23 @@ class LoopMonitor
Attribute num_iterations_attr;
Attribute start_iteration_attr;

std::vector<std::string> target_loops;

std::chrono::high_resolution_clock::time_point last_snapshot_time;

bool is_target_loop(const Variant& value) {
if (target_loops.empty())
return true;

for (const std::string& s : target_loops)
if (strncmp(static_cast<const char*>(value.data()), s.data(), s.size()) == 0)
return true;

return false;
}

void snapshot(Caliper* c, Channel* channel) {
cali_id_t attr[2] = {
cali_id_t attr[2] = {
num_iterations_attr.id(), start_iteration_attr.id()
};
Variant data[2] = {
Expand All @@ -64,10 +79,12 @@ class LoopMonitor

void begin_cb(Caliper* c, Channel* channel, const Attribute& attr, const Variant& value) {
if (attr == loop_attr) {
if (loop_level == 0)
if (target_level < 0 && is_target_loop(value)) {
target_level = loop_level + 1;
snapshot(c, channel);
}
++loop_level;
} else if (loop_level == 1 && attr.get(cali::class_iteration_attr).to_bool()) {
} else if (loop_level == target_level && attr.get(cali::class_iteration_attr).to_bool()) {
++num_iterations;
if (start_iteration < 0)
start_iteration = value.to_int();
Expand All @@ -76,10 +93,12 @@ class LoopMonitor

void end_cb(Caliper* c, Channel* channel, const Attribute& attr, const Variant& value) {
if (attr == loop_attr) {
if (loop_level == 1)
if (loop_level == target_level) {
snapshot(c, channel);
target_level = -1;
}
--loop_level;
} else if (loop_level == 1 && attr.get(cali::class_iteration_attr).to_bool()) {
} else if (loop_level == target_level && attr.get(cali::class_iteration_attr).to_bool()) {
bool do_snapshot = false;

if (iteration_interval > 0 && num_iterations % iteration_interval == 0)
Expand All @@ -103,6 +122,7 @@ class LoopMonitor

LoopMonitor(Caliper* c, Channel* channel)
: loop_level(0),
target_level(-1),
start_iteration(-1),
num_iterations(0),
num_snapshots(0),
Expand All @@ -112,19 +132,20 @@ class LoopMonitor
Variant v_true(true);

num_iterations_attr =
c->create_attribute("loop.iterations", CALI_TYPE_INT,
CALI_ATTR_SKIP_EVENTS |
c->create_attribute("loop.iterations", CALI_TYPE_INT,
CALI_ATTR_SKIP_EVENTS |
CALI_ATTR_ASVALUE,
1, &class_aggregatable_attr, &v_true);
start_iteration_attr =
c->create_attribute("loop.start_iteration", CALI_TYPE_INT,
c->create_attribute("loop.start_iteration", CALI_TYPE_INT,
CALI_ATTR_SKIP_EVENTS |
CALI_ATTR_ASVALUE);
CALI_ATTR_ASVALUE);

ConfigSet config = channel->config().init("loop_monitor", s_configdata);

iteration_interval = config.get("iteration_interval").to_int();
time_interval = config.get("time_interval").to_double();
target_loops = config.get("target_loops").to_stringlist();
}

public:
Expand Down Expand Up @@ -161,6 +182,10 @@ const ConfigSet::Entry LoopMonitor::s_configdata[] = {
"Trigger snapshot every t seconds."
"Trigger snapshot every t seconds. Set to 0 to disable."
},
{ "target_loops", CALI_TYPE_STRING, "",
"List of loops to instrument. Default: empty (any top-level loop)",
"List of loops to instrument. Default: empty (any top-level loop)"
},
ConfigSet::Terminator
};

Expand Down
29 changes: 28 additions & 1 deletion test/ci_app_tests/test_loopreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_loopreport_summary(self):
else:
self.fail('%s not found in log' % target)

""" Loop report controller (summary info) """
""" Loop report controller (timeseries info) """
def test_loopreport_timeseries(self):
target_cmd = [ './ci_test_macros', '0', 'loop-report,timeseries=true,summary=false,iteration_interval=15,output=stdout', '75' ]

Expand Down Expand Up @@ -86,5 +86,32 @@ def test_loopreport_display_all_rows(self):
self.assertGreater(len(lines), 40)
self.assertLess(len(lines), 48)

""" Loop report controller (timeseries info, target loop selection) """
def test_loopreport_target_loop_selection(self):
target_cmd = [ './ci_test_macros', '0', 'loop-report,target_loops=fooloop,timeseries=true,summary=true,iteration_interval=5,output=stdout,timeseries.maxrows=0', '20' ]

caliper_config = {
'CALI_LOG_VERBOSITY' : '0',
}

log_targets = [
'Iteration summary (fooloop):',
'mainloop/fooloop 400',
'Block Iterations Time (s)',
' 0 100',
' 5 100',
' 10 100'
]

report_out,_ = cat.run_test(target_cmd, caliper_config)
lines = report_out.decode().splitlines()

for target in log_targets:
for line in lines:
if target in line:
break
else:
self.fail('%s not found in log' % target)

if __name__ == "__main__":
unittest.main()
39 changes: 34 additions & 5 deletions test/ci_app_tests/test_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def test_loopmonitor_iter_interval(self):

self.assertTrue(len(snapshots) == 2)
self.assertTrue(cat.has_snapshot_with_attributes(
snapshots, { 'iteration#mainloop' : '4',
'loop.iterations' : '5'
snapshots, { 'iteration#mainloop' : '4',
'loop.iterations' : '5'
}))

def test_loopmonitor_time_interval(self):
Expand All @@ -49,7 +49,36 @@ def test_loopmonitor_time_interval(self):

self.assertTrue(count > 2 and count < 8)
self.assertEqual(sum, 10)


def test_loopmonitor_target_loop(self):
target_cmd = [ './ci_test_macros', '0', 'none', '10' ]

caliper_config = {
'CALI_SERVICES_ENABLE' : 'loop_monitor,trace,report',
'CALI_LOOP_MONITOR_ITERATION_INTERVAL' : '5',
'CALI_LOOP_MONITOR_TARGET_LOOPS' : 'fooloop',
'CALI_REPORT_CONFIG' : 'select * where iteration#fooloop format expand',
'CALI_REPORT_FILENAME' : 'stdout',
'CALI_LOG_VERBOSITY' : '0'
}

query_output = cat.run_test(target_cmd, caliper_config)
snapshots = cat.get_snapshots_from_text(query_output[0])

self.assertEqual(len(snapshots), 20)
self.assertTrue(cat.has_snapshot_with_attributes(
snapshots, { 'iteration#mainloop' : '3',
'iteration#fooloop' : '4',
'loop.iterations' : '5',
'loop' : 'mainloop/fooloop'
}))
self.assertTrue(cat.has_snapshot_with_attributes(
snapshots, { 'iteration#mainloop' : '7',
'iteration#fooloop' : '9',
'loop.iterations' : '5',
'loop' : 'mainloop/fooloop'
}))

def test_regionmonitor_time_interval(self):
target_cmd = [ './ci_test_macros', '5000', 'none', '5' ]

Expand All @@ -66,8 +95,8 @@ def test_regionmonitor_time_interval(self):

self.assertTrue(len(snapshots) == 4)
self.assertTrue(cat.has_snapshot_with_attributes(
snapshots, { 'loop' : 'mainloop/fooloop',
'function' : 'main/foo'
snapshots, { 'loop' : 'mainloop/fooloop',
'function' : 'main/foo'
}))
self.assertFalse(cat.has_snapshot_with_attributes(
snapshots, { 'annotation' : 'pre-loop' }))
Expand Down

0 comments on commit 5e94fa1

Please sign in to comment.