Commit 35a6b6ef authored by Andrew Gaspar's avatar Andrew Gaspar
Browse files

Track per-thread function execution time

parent eb36802b
......@@ -7,6 +7,14 @@
#include <TAU.h>
#include <omp.h>
void recurse(int n) {
TAU_PROFILE("recurse", "void(int)", TAU_DEFAULT);
if (n > 0) {
recurse(n - 1);
}
}
int main(int argc, char **argv) {
Tau_init(argc, argv);
......@@ -24,13 +32,23 @@ int main(int argc, char **argv) {
int volatile N = 1000000;
std::vector<int> my_stuff(N);
std::iota(my_stuff.begin(), my_stuff.end(), 0);
#pragma omp barrier
std::cout << "Hi from thread " << omp_get_thread_num() << "!" << std::endl;
#pragma omp barrier
}
#pragma omp parallel for
for (auto i = 0; i < 1000000; i++) {
TAU_PROFILE("opemp_loop", "void(int)", TAU_DEFAULT);
}
#pragma omp parallel
{ recurse(1000); }
#pragma omp parallel
std::cout << "Hi from thread " << omp_get_thread_num() << "!" << std::endl;
}
Tau_dump();
#pragma omp parallel
Tau_dump();
return 0;
}
\ No newline at end of file
......@@ -11,6 +11,13 @@
#ifndef TAUSDSKVPLUGIN_PLUGIN_HPP_
#define TAUSDSKVPLUGIN_PLUGIN_HPP_
// STL Includes
#include <map>
#include <memory>
#include <optional>
#include <shared_mutex>
#include <vector>
// Third Party Includes
#include <Profile/TauPlugin.h>
......@@ -47,6 +54,34 @@ class Plugin {
private:
Plugin() = default;
struct FunctionState {
unsigned long total_time = 0;
std::optional<unsigned long> last_start = std::nullopt;
uint64_t count = 0;
uint32_t depth = 0;
uint32_t unpaired_exits;
};
struct ThreadState {
std::map<std::string, FunctionState> functions;
};
ThreadState &GetThreadState(int tid);
/**
* @brief Guards thread_state_
*/
std::shared_mutex mutex_;
/**
* @brief Holds per-thread state.
*
* @details
* `ThreadState` is wrapped in a unique pointer so that when thread_state_ grows, outstanding
* references are not invalidated.
*/
std::vector<std::unique_ptr<ThreadState>> thread_state_;
};
} // namespace tausdskv
......
......@@ -23,8 +23,14 @@ Plugin *Plugin::GetInstance() {
}
PluginStatus Plugin::Dump(Tau_plugin_event_dump_data_t const &data) {
std::cout << "tausdskv: Thread " << data.tid << ", Hello from " << __PRETTY_FUNCTION__
<< std::endl;
auto &thread_state = GetThreadState(data.tid);
for (auto const &f : thread_state.functions) {
std::cout << data.tid << ":" << f.first << " = "
<< "{ count = " << f.second.count << ", total_time = " << f.second.total_time
<< ", unpaired_exits = " << f.second.unpaired_exits << "}" << std::endl;
}
return PluginStatus::Success;
}
......@@ -45,40 +51,88 @@ PluginStatus Plugin::PostInit(Tau_plugin_event_post_init_data_t const &data) {
}
PluginStatus Plugin::PreEndOfExecution(Tau_plugin_event_pre_end_of_execution_data_t const &data) {
auto &thread_state = GetThreadState(data.tid);
std::cout << "tausdskv: Thread " << data.tid << ", Hello from " << __PRETTY_FUNCTION__
<< std::endl;
return PluginStatus::Success;
}
PluginStatus Plugin::EndOfExecution(Tau_plugin_event_end_of_execution_data_t const &data) {
auto &thread_state = GetThreadState(data.tid);
std::cout << "tausdskv: Thread " << data.tid << ", Hello from " << __PRETTY_FUNCTION__
<< std::endl;
return PluginStatus::Success;
}
PluginStatus Plugin::Send(Tau_plugin_event_send_data_t const &data) {
auto &thread_state = GetThreadState(data.tid);
std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl;
return PluginStatus::Success;
}
PluginStatus Plugin::Recv(Tau_plugin_event_recv_data_t const &data) {
auto &thread_state = GetThreadState(data.tid);
std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl;
return PluginStatus::Success;
}
PluginStatus Plugin::FunctionEntry(Tau_plugin_event_function_entry_data_t const &data) {
std::cout << "tausdskv: Thread " << data.tid << ", Entering " << data.timer_name
<< ", Timestamp " << data.timestamp << std::endl;
auto &thread_state = GetThreadState(data.tid);
auto &function = thread_state.functions[data.timer_name];
if (function.depth == 0) {
function.last_start = data.timestamp;
}
function.depth++;
return PluginStatus::Success;
}
PluginStatus Plugin::FunctionExit(Tau_plugin_event_function_exit_data_t const &data) {
std::cout << "tausdskv: Thread " << data.tid << ", Exiting " << data.timer_name
<< ", Timestamp " << data.timestamp << std::endl;
auto &thread_state = GetThreadState(data.tid);
auto &function = thread_state.functions[data.timer_name];
if (function.depth == 0) {
function.unpaired_exits++;
function.last_start = std::nullopt;
return PluginStatus::Success;
}
function.depth--;
if (function.depth == 0) {
function.total_time += data.timestamp - function.last_start.value();
function.last_start = std::nullopt;
function.count++;
}
return PluginStatus::Success;
}
PluginStatus Plugin::AtomicEventTrigger(Tau_plugin_event_atomic_event_trigger_data_t const &data) {
auto &thread_state = GetThreadState(data.tid);
std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl;
return PluginStatus::Success;
}
Plugin::ThreadState &Plugin::GetThreadState(int tid) {
{
// Get mutex as read first
std::shared_lock<std::shared_mutex> read_thread_state(mutex_);
if (tid < thread_state_.size()) {
return *thread_state_[tid];
}
}
{
// If this is the first time we're seeing this tid, we need to add it
std::unique_lock<std::shared_mutex> write_thread_state(mutex_);
while (tid >= thread_state_.size()) {
thread_state_.push_back(std::make_unique<ThreadState>());
}
return *thread_state_[tid];
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment