-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement asynchronous timed events * Add irecv gap time stats
- Loading branch information
Showing
13 changed files
with
391 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright (c) 2024, Lawrence Livermore National Security, LLC. | ||
// See top-level LICENSE file for details. | ||
|
||
// Example for using asynchronous timed events across threads | ||
|
||
#include <caliper/cali.h> | ||
#include <caliper/cali-manager.h> | ||
|
||
#include <caliper/AsyncEvent.h> | ||
|
||
#include <condition_variable> | ||
#include <mutex> | ||
#include <queue> | ||
#include <thread> | ||
|
||
std::queue<cali::TimedAsyncEvent> q; | ||
std::mutex q_mtx; | ||
std::condition_variable cv; | ||
bool done = false; | ||
|
||
void consumer_thread_fn() | ||
{ | ||
CALI_CXX_MARK_FUNCTION; | ||
|
||
while (true) { | ||
cali::TimedAsyncEvent evt; | ||
|
||
CALI_MARK_BEGIN("waiting"); | ||
{ | ||
std::unique_lock<std::mutex> g(q_mtx); | ||
cv.wait(g, [](){ return !q.empty() || done; }); | ||
if (!q.empty()) { | ||
evt = q.front(); | ||
q.pop(); | ||
} else | ||
return; | ||
} | ||
CALI_MARK_END("waiting"); | ||
|
||
evt.end(); | ||
|
||
CALI_CXX_MARK_SCOPE("processing"); | ||
std::this_thread::sleep_for(std::chrono::microseconds(200)); | ||
} | ||
} | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
cali::ConfigManager mgr; | ||
mgr.set_default_parameter("aggregate_across_ranks", "false"); | ||
|
||
if (argc > 1) { | ||
mgr.add(argv[1]); | ||
if (mgr.error()) { | ||
std::cerr << "ConfigManager: " << mgr.error_msg() << std::endl; | ||
return -1; | ||
} | ||
} | ||
|
||
mgr.start(); | ||
cali_init(); // initialize Caliper before creating sub-thread | ||
|
||
std::thread consumer(consumer_thread_fn); | ||
|
||
CALI_MARK_BEGIN("main_thread"); | ||
|
||
int N = 200; | ||
|
||
CALI_MARK_BEGIN("producing"); | ||
|
||
for (int i = 0; i < N; ++i) { | ||
q_mtx.lock(); | ||
q.push(cali::TimedAsyncEvent::begin("queue_wait")); | ||
q_mtx.unlock(); | ||
cv.notify_one(); | ||
std::this_thread::sleep_for(std::chrono::microseconds(100)); | ||
} | ||
|
||
CALI_MARK_END("producing"); | ||
|
||
{ | ||
std::lock_guard<std::mutex> g(q_mtx); | ||
done = true; | ||
} | ||
|
||
cv.notify_all(); | ||
|
||
CALI_MARK_BEGIN("waiting"); | ||
consumer.join(); | ||
CALI_MARK_END("waiting"); | ||
CALI_MARK_END("main_thread"); | ||
|
||
mgr.flush(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC. | ||
// See top-level LICENSE file for details. | ||
|
||
/// \file AsyncEvent.h | ||
/// %Caliper C++ interface for asynchronous events | ||
|
||
#pragma once | ||
#ifndef CALI_ASYNC_EVENT_H | ||
#define CALI_ASYNC_EVENT_H | ||
|
||
#include <chrono> | ||
#include <memory> | ||
|
||
namespace cali | ||
{ | ||
|
||
class Node; | ||
|
||
class TimedAsyncEvent | ||
{ | ||
using clock = std::chrono::steady_clock; | ||
|
||
Node* end_tree_node_; | ||
std::chrono::time_point<clock> start_time_; | ||
|
||
explicit TimedAsyncEvent(Node* node) : end_tree_node_ { node }, start_time_ { clock::now() } { } | ||
|
||
public: | ||
|
||
constexpr TimedAsyncEvent() : end_tree_node_ { nullptr } { } | ||
|
||
void end(); | ||
|
||
static TimedAsyncEvent begin(const char* message); | ||
}; | ||
|
||
} // namespace cali | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC. | ||
// See top-level LICENSE file for details. | ||
|
||
#include "caliper/AsyncEvent.h" | ||
|
||
#include "caliper/Caliper.h" | ||
#include "caliper/SnapshotRecord.h" | ||
|
||
using namespace cali; | ||
|
||
namespace | ||
{ | ||
|
||
Attribute get_async_event_begin_attr(Caliper& c) | ||
{ | ||
static std::atomic<Node*> s_attr_node { nullptr }; | ||
|
||
auto node = s_attr_node.load(); | ||
if (node) | ||
return Attribute::make_attribute(node); | ||
|
||
Attribute attr = c.create_attribute("async.begin", CALI_TYPE_STRING, CALI_ATTR_SCOPE_THREAD | CALI_ATTR_SKIP_EVENTS); | ||
s_attr_node.store(attr.node()); | ||
|
||
return attr; | ||
} | ||
|
||
Attribute get_async_event_end_attr(Caliper& c) | ||
{ | ||
static std::atomic<Node*> s_attr_node { nullptr }; | ||
|
||
auto node = s_attr_node.load(); | ||
if (node) | ||
return Attribute::make_attribute(node); | ||
|
||
Attribute attr = c.create_attribute("async.end", CALI_TYPE_STRING, CALI_SCOPE_THREAD | CALI_ATTR_SKIP_EVENTS); | ||
s_attr_node.store(attr.node()); | ||
|
||
return attr; | ||
} | ||
|
||
Attribute get_event_duration_attr(Caliper& c) | ||
{ | ||
static std::atomic<Node*> s_attr_node { nullptr }; | ||
|
||
auto node = s_attr_node.load(); | ||
if (node) | ||
return Attribute::make_attribute(node); | ||
|
||
Attribute attr = c.create_attribute("event.duration.ns", CALI_TYPE_UINT, CALI_ATTR_ASVALUE | CALI_ATTR_AGGREGATABLE | CALI_ATTR_SKIP_EVENTS); | ||
s_attr_node.store(attr.node()); | ||
|
||
return attr; | ||
} | ||
|
||
Node async_event_root_node { CALI_INV_ID, CALI_INV_ID, Variant() }; | ||
|
||
} | ||
|
||
void TimedAsyncEvent::end() | ||
{ | ||
uint64_t nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now() - start_time_).count(); | ||
|
||
Caliper c; | ||
Attribute duration_attr = ::get_event_duration_attr(c); | ||
const Entry data[2] = { | ||
{ end_tree_node_ }, { duration_attr, cali_make_variant_from_uint(nsec) } | ||
}; | ||
|
||
c.async_event(SnapshotView(2, data)); | ||
} | ||
|
||
TimedAsyncEvent TimedAsyncEvent::begin(const char* message) | ||
{ | ||
Caliper c; | ||
Attribute begin_attr = ::get_async_event_begin_attr(c); | ||
Attribute end_attr = ::get_async_event_end_attr(c); | ||
|
||
Variant v_msg(message); | ||
Node* begin_node = c.make_tree_entry(begin_attr, v_msg, &::async_event_root_node); | ||
Node* end_node = c.make_tree_entry(end_attr, v_msg, &::async_event_root_node); | ||
|
||
c.async_event(SnapshotView(Entry(begin_node))); | ||
|
||
return TimedAsyncEvent(end_node); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.