From 498dfebb617aa24fc704de8589381e22b0c29250 Mon Sep 17 00:00:00 2001 From: Kevin Huck Date: Wed, 9 May 2018 19:59:11 -0230 Subject: [PATCH] Fixing the task dependency tracking Because HPX uses annotated tasks to "change" the name of tasks when they execute, we track the "aliases" that a task has. Then, when we track the dependencies, we use the alias rather than the HPX thread name. This requres keeping track of the task_wrapper objects inside the profiler object, and it also means that we might have either a memory leak of task_wrapper objects or that if a parent finishes before a child, that the task_wrapper won't be available to generate the dependency correctly. Either would be bad. Need more testing to see how it behaves with HPX. --- src/apex/apex.cpp | 81 +++++++++++++++++-------------- src/apex/apex_api.hpp | 10 ++-- src/apex/concurrency_handler.cpp | 4 +- src/apex/concurrency_handler.hpp | 3 +- src/apex/event_listener.cpp | 2 +- src/apex/event_listener.hpp | 2 +- src/apex/otf2_listener.cpp | 2 +- src/apex/otf2_listener.hpp | 3 +- src/apex/policy_handler.cpp | 8 +-- src/apex/policy_handler.hpp | 3 +- src/apex/profiler.hpp | 30 +++++++++++- src/apex/profiler_listener.cpp | 35 +++++++------ src/apex/profiler_listener.hpp | 4 +- src/apex/task_wrapper.hpp | 40 +++++++++++++-- src/apex/tau_listener.cpp | 6 +-- src/apex/tau_listener.hpp | 3 +- src/apex/thread_instance.cpp | 2 +- src/apex/thread_instance.hpp | 4 +- src/unit_tests/C++/CMakeLists.txt | 1 + 19 files changed, 155 insertions(+), 88 deletions(-) diff --git a/src/apex/apex.cpp b/src/apex/apex.cpp index 8e6b625b..5d5ac64a 100644 --- a/src/apex/apex.cpp +++ b/src/apex/apex.cpp @@ -424,11 +424,16 @@ inline task_wrapper * _new_task(task_identifier * id, uint64_t task_id, // was a parent passed in? if (parent_task != nullptr) { tt_ptr->parent_guid = parent_task->guid; + tt_ptr->parent = parent_task; } else { // if not, is there a current timer? profiler * p = thread_instance::instance().get_current_profiler(); if (p != nullptr) { tt_ptr->parent_guid = p->guid; + tt_ptr->parent = p->tt_ptr; + } else { + tt_ptr->parent = task_wrapper::get_apex_main_wrapper(); + // tt_ptr->parent_guid is 0 by default } } if (task_id == UINTMAX_MAX) { @@ -438,12 +443,6 @@ inline task_wrapper * _new_task(task_identifier * id, uint64_t task_id, // use the runtime provided GUID tt_ptr->guid = task_id; } - if (_notify_listeners) { - //read_lock_type l(instance->listener_mutex); - for (unsigned int i = 0 ; i < instance->listeners.size() ; i++) { - instance->listeners[i]->on_new_task(tt_ptr, parent_task); - } - } return tt_ptr; } @@ -560,7 +559,7 @@ void debug_print(const char * event, task_wrapper * tt_ptr) { << endl; fflush(stdout); } else { cout << thread_instance::get_id() << " " << event << " : " << tt_ptr->guid << " : " << - tt_ptr->task_id->get_name() << endl; fflush(stdout); + tt_ptr->get_task_id()->get_name() << endl; fflush(stdout); } } @@ -712,14 +711,16 @@ profiler* resume(profiler * p) { p->restart(); if (_notify_listeners) { try { + /* task_wrapper * tt_ptr = new task_wrapper(); tt_ptr->task_id = p->task_id; tt_ptr->prof = p; tt_ptr->guid = p->guid; + */ // skip the profiler_listener - we are restoring a child timer // for a parent that was yielded. for (unsigned int i = 1 ; i < instance->listeners.size() ; i++) { - instance->listeners[i]->on_resume(tt_ptr); + instance->listeners[i]->on_resume(p->tt_ptr); } } catch (disabled_profiler_exception e) { APEX_UTIL_REF_COUNT_FAILED_RESUME @@ -727,7 +728,7 @@ profiler* resume(profiler * p) { } } static std::string apex_process_profile_str("apex::process_profiles"); - if (p->task_id->get_name(false).compare(apex_process_profile_str) == 0) { + if (p->tt_ptr->get_task_id()->get_name(false).compare(apex_process_profile_str) == 0) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_RESUME } else { APEX_UTIL_REF_COUNT_RESUME @@ -774,7 +775,7 @@ void set_state(apex_thread_state state) { instance->set_state(thread_instance::get_id(), state); } -void stop(profiler* the_profiler) { +void stop(profiler* the_profiler, bool cleanup) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { APEX_UTIL_REF_COUNT_DISABLED_STOP @@ -806,13 +807,24 @@ void stop(profiler* the_profiler) { instance->listeners[i]->on_stop(p); } } - //cout << thread_instance::get_id() << " Stop : " << the_profiler->task_id->get_name() << endl; fflush(stdout); + //cout << thread_instance::get_id() << " Stop : " << the_profiler->tt_ptr->get_task_id()->get_name() << endl; fflush(stdout); static std::string apex_process_profile_str("apex::process_profiles"); - if (p->task_id->get_name(false).compare(apex_process_profile_str) == 0) { + if (p->tt_ptr->get_task_id()->get_name(false).compare(apex_process_profile_str) == 0) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_STOP } else { APEX_UTIL_REF_COUNT_STOP } + if (cleanup) { + if (_notify_listeners) { + //read_lock_type l(instance->listener_mutex); + for (unsigned int i = 0 ; i < instance->listeners.size() ; i++) { + instance->listeners[i]->on_task_complete(p->tt_ptr); + } + } + // TODO - need to think about how to safely do this. The parent may finish before the child. + delete(p->tt_ptr); + p->tt_ptr = nullptr; + } } void stop(task_wrapper * tt_ptr) { @@ -822,7 +834,7 @@ void stop(task_wrapper * tt_ptr) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { APEX_UTIL_REF_COUNT_DISABLED_STOP - free(tt_ptr); + delete(tt_ptr); return; } if (tt_ptr == nullptr || tt_ptr->prof == nullptr) { @@ -831,12 +843,12 @@ void stop(task_wrapper * tt_ptr) { } if (tt_ptr->prof == profiler::get_disabled_profiler()) { APEX_UTIL_REF_COUNT_DISABLED_STOP - free(tt_ptr); + delete(tt_ptr); return; // profiler was throttled. } if (tt_ptr->prof->stopped) { APEX_UTIL_REF_COUNT_DOUBLE_STOP - free(tt_ptr); + delete(tt_ptr); return; } thread_instance::instance().clear_current_profiler(tt_ptr->prof, false, nullptr); @@ -844,7 +856,7 @@ void stop(task_wrapper * tt_ptr) { // protect against calls after finalization if (!instance || _exited || _measurement_stopped) { APEX_UTIL_REF_COUNT_STOP_AFTER_FINALIZE - free(tt_ptr); + delete(tt_ptr); return; } std::shared_ptr p{tt_ptr->prof}; @@ -854,14 +866,21 @@ void stop(task_wrapper * tt_ptr) { instance->listeners[i]->on_stop(p); } } - //cout << thread_instance::get_id() << " Stop : " << tt_ptr->task_id->get_name() << endl; fflush(stdout); + //cout << thread_instance::get_id() << " Stop : " << tt_ptr->tt_ptr->get_task_id()->get_name() << endl; fflush(stdout); static std::string apex_process_profile_str("apex::process_profiles"); - if (p->task_id->get_name(false).compare(apex_process_profile_str) == 0) { + if (p->tt_ptr->get_task_id()->get_name(false).compare(apex_process_profile_str) == 0) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_STOP } else { APEX_UTIL_REF_COUNT_STOP } - free(tt_ptr); + if (_notify_listeners) { + //read_lock_type l(instance->listener_mutex); + for (unsigned int i = 0 ; i < instance->listeners.size() ; i++) { + instance->listeners[i]->on_task_complete(tt_ptr); + } + } + // TODO - need to think about how to safely do this. The parent may finish before the child. + delete(tt_ptr); } void yield(profiler* the_profiler) @@ -897,9 +916,9 @@ void yield(profiler* the_profiler) instance->listeners[i]->on_yield(p); } } - //cout << thread_instance::get_id() << " Yield : " << the_profiler->task_id->get_name() << endl; fflush(stdout); + //cout << thread_instance::get_id() << " Yield : " << the_profiler->tt_ptr->get_task_id()->get_name() << endl; fflush(stdout); static std::string apex_process_profile_str("apex::process_profiles"); - if (p->task_id->get_name(false).compare(apex_process_profile_str) == 0) { + if (p->tt_ptr->get_task_id()->get_name(false).compare(apex_process_profile_str) == 0) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_YIELD } else { APEX_UTIL_REF_COUNT_YIELD @@ -942,9 +961,9 @@ void yield(task_wrapper * tt_ptr) instance->listeners[i]->on_yield(p); } } - //cout << thread_instance::get_id() << " Yield : " << tt_ptr->prof->task_id->get_name() << endl; fflush(stdout); + //cout << thread_instance::get_id() << " Yield : " << tt_ptr->prof->tt_ptr->get_task_id()->get_name() << endl; fflush(stdout); static std::string apex_process_profile_str("apex::process_profiles"); - if (p->task_id->get_name(false).compare(apex_process_profile_str) == 0) { + if (p->tt_ptr->get_task_id()->get_name(false).compare(apex_process_profile_str) == 0) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_YIELD } else { APEX_UTIL_REF_COUNT_YIELD @@ -1033,19 +1052,9 @@ task_wrapper * update_task(task_wrapper * wrapper, const std::string &timer_name if (apex_options::disable() == true) { return nullptr; } // if APEX is suspended, do nothing. if (apex_options::suspend() == true) { return nullptr; } - if (wrapper == nullptr) { - apex* instance = apex::instance(); // get the Apex static instance - if (!instance || _exited) { return nullptr; } // protect against calls after finalization - task_identifier * id = task_identifier::get_task_id(timer_name); - wrapper = _new_task(id, UINTMAX_MAX, nullptr, instance); - } else { - wrapper->task_id = task_identifier::get_task_id(timer_name); - /* Oh, help us if a profile has started already. - * This could be a horrible idea. */ - if (wrapper->prof != nullptr) { - wrapper->prof->task_id = wrapper->task_id; - } - } + assert(wrapper); + task_identifier * id = task_identifier::get_task_id(timer_name); + wrapper->aliases.insert(id); return wrapper; } diff --git a/src/apex/apex_api.hpp b/src/apex/apex_api.hpp index 4e0d3a7d..43ec0a62 100644 --- a/src/apex/apex_api.hpp +++ b/src/apex/apex_api.hpp @@ -14,10 +14,6 @@ #include #endif -#include -#include -#include -#include #include "apex_types.h" #include "apex_options.hpp" #include "apex_export.h" @@ -26,6 +22,10 @@ #include "task_wrapper.hpp" #include #include +#include +#include +#include +#include #endif /* DOXYGEN_SHOULD_SKIP_THIS */ @@ -166,7 +166,7 @@ APEX_EXPORT profiler * start(task_wrapper * task_wrapper_ptr); \return No return value. \sa @ref apex::start, @ref apex::yield, @ref apex::resume */ -APEX_EXPORT void stop(profiler * the_profiler); +APEX_EXPORT void stop(profiler * the_profiler, bool cleanup=true); /** \brief Stop a timer. diff --git a/src/apex/concurrency_handler.cpp b/src/apex/concurrency_handler.cpp index d39206be..3f32b412 100644 --- a/src/apex/concurrency_handler.cpp +++ b/src/apex/concurrency_handler.cpp @@ -142,11 +142,11 @@ bool concurrency_handler::common_start(task_identifier *id) { } bool concurrency_handler::on_start(task_wrapper * tt_ptr) { - return common_start(tt_ptr->task_id); + return common_start(tt_ptr->get_task_id()); } bool concurrency_handler::on_resume(task_wrapper * tt_ptr) { - return common_start(tt_ptr->task_id); + return common_start(tt_ptr->get_task_id()); } void concurrency_handler::common_stop(std::shared_ptr &p) { diff --git a/src/apex/concurrency_handler.hpp b/src/apex/concurrency_handler.hpp index 52299661..c92fe060 100644 --- a/src/apex/concurrency_handler.hpp +++ b/src/apex/concurrency_handler.hpp @@ -64,9 +64,8 @@ class concurrency_handler : public handler, public event_listener { void on_stop(std::shared_ptr &p); void on_yield(std::shared_ptr &p); bool on_resume(task_wrapper * tt_ptr); - void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) { + void on_task_complete(task_wrapper * tt_ptr) { APEX_UNUSED(tt_ptr); - APEX_UNUSED(parent_ptr); }; void on_sample_value(sample_value_event_data &data) { APEX_UNUSED(data); }; void on_periodic(periodic_event_data &data) { APEX_UNUSED(data); }; diff --git a/src/apex/event_listener.cpp b/src/apex/event_listener.cpp index 15d98141..a6fba959 100644 --- a/src/apex/event_listener.cpp +++ b/src/apex/event_listener.cpp @@ -21,7 +21,7 @@ timer_event_data::timer_event_data(task_identifier * id) : task_id(id) { /* this object never actually gets instantiated. too much overhead. */ timer_event_data::timer_event_data(std::shared_ptr &the_profiler) : my_profiler(the_profiler) { - this->task_id = the_profiler->task_id; + this->task_id = the_profiler->tt_ptr->get_task_id(); } timer_event_data::~timer_event_data() { diff --git a/src/apex/event_listener.hpp b/src/apex/event_listener.hpp index c46e345d..5e8e5ce5 100644 --- a/src/apex/event_listener.hpp +++ b/src/apex/event_listener.hpp @@ -121,7 +121,7 @@ class event_listener virtual void on_stop(std::shared_ptr &p) = 0; virtual void on_yield(std::shared_ptr &p) = 0; virtual bool on_resume(task_wrapper * tt_ptr) = 0; - virtual void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) = 0; + virtual void on_task_complete(task_wrapper * tt_ptr) = 0; virtual void on_sample_value(sample_value_event_data &data) = 0; virtual void on_periodic(periodic_event_data &data) = 0; virtual void on_custom_event(custom_event_data &data) = 0; diff --git a/src/apex/otf2_listener.cpp b/src/apex/otf2_listener.cpp index b396327c..f9fcf680 100644 --- a/src/apex/otf2_listener.cpp +++ b/src/apex/otf2_listener.cpp @@ -816,7 +816,7 @@ namespace apex { } bool otf2_listener::on_start(task_wrapper * tt_ptr) { - task_identifier * id = tt_ptr->task_id; + task_identifier * id = tt_ptr->get_task_id(); // don't close the archive on us! read_lock_type lock(_archive_mutex); // not likely, but just in case... diff --git a/src/apex/otf2_listener.hpp b/src/apex/otf2_listener.hpp index 0f12e33a..a27e4533 100644 --- a/src/apex/otf2_listener.hpp +++ b/src/apex/otf2_listener.hpp @@ -181,9 +181,8 @@ namespace apex { void on_yield(std::shared_ptr &p); bool on_resume(task_wrapper * tt_ptr); void on_sample_value(sample_value_event_data &data); - void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) { + void on_task_complete(task_wrapper * tt_ptr) { APEX_UNUSED(tt_ptr); - APEX_UNUSED(parent_ptr); }; void on_periodic(periodic_event_data &data) { APEX_UNUSED(data); }; diff --git a/src/apex/policy_handler.cpp b/src/apex/policy_handler.cpp index a10763fc..114d6a8a 100644 --- a/src/apex/policy_handler.cpp +++ b/src/apex/policy_handler.cpp @@ -443,21 +443,21 @@ namespace apex { } bool policy_handler::on_start(task_wrapper * tt_ptr) { - call_policies(start_event_policies, (void *)tt_ptr->task_id, APEX_START_EVENT); + call_policies(start_event_policies, (void *)tt_ptr->get_task_id(), APEX_START_EVENT); return true; } bool policy_handler::on_resume(task_wrapper * tt_ptr) { - call_policies(resume_event_policies, (void *)tt_ptr->task_id, APEX_RESUME_EVENT); + call_policies(resume_event_policies, (void *)tt_ptr->get_task_id(), APEX_RESUME_EVENT); return true; } void policy_handler::on_stop(std::shared_ptr &p) { - call_policies(stop_event_policies, (void *)p->task_id, APEX_STOP_EVENT); + call_policies(stop_event_policies, (void *)p->tt_ptr->get_task_id(), APEX_STOP_EVENT); } void policy_handler::on_yield(std::shared_ptr &p) { - call_policies(yield_event_policies, (void *)p->task_id, APEX_YIELD_EVENT); + call_policies(yield_event_policies, (void *)p->tt_ptr->get_task_id(), APEX_YIELD_EVENT); } void policy_handler::on_sample_value(sample_value_event_data &data) { diff --git a/src/apex/policy_handler.hpp b/src/apex/policy_handler.hpp index 8e8987be..138d85f2 100644 --- a/src/apex/policy_handler.hpp +++ b/src/apex/policy_handler.hpp @@ -100,9 +100,8 @@ class policy_handler : public handler, public event_listener void on_stop(std::shared_ptr &p); void on_yield(std::shared_ptr &p); bool on_resume(task_wrapper * tt_ptr); - void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) { + void on_task_complete(task_wrapper * tt_ptr) { APEX_UNUSED(tt_ptr); - APEX_UNUSED(parent_ptr); }; void on_sample_value(sample_value_event_data &data); void on_custom_event(custom_event_data &data); diff --git a/src/apex/profiler.hpp b/src/apex/profiler.hpp index 5d07a4c3..86640008 100644 --- a/src/apex/profiler.hpp +++ b/src/apex/profiler.hpp @@ -5,13 +5,18 @@ #pragma once +// forward declaration +namespace apex { +class profiler; +}; + #include #include #include #include "apex_options.hpp" #include "apex_types.h" #include -#include "task_identifier.hpp" +#include "task_wrapper.hpp" #if defined(APEX_HAVE_HPX) #include #endif @@ -76,12 +81,30 @@ class profiler { //apex_function_address action_address; //std::string * timer_name; //bool have_name; - task_identifier * task_id; + task_wrapper * tt_ptr; // for timers + task_identifier * task_id; // for counters, timers uint64_t guid; bool is_counter; bool is_resume; // for yield or resume reset_type is_reset; bool stopped; + profiler(task_wrapper * task, + bool resume = false, + reset_type reset = reset_type::NONE) : + start(MYCLOCK::now()), +#if APEX_HAVE_PAPI + papi_start_values{0,0,0,0,0,0,0,0}, + papi_stop_values{0,0,0,0,0,0,0,0}, +#endif + value(0.0), + children_value(0.0), + tt_ptr(task), + task_id(tt_ptr->get_task_id()), + guid(0), + is_counter(false), + is_resume(resume), + is_reset(reset), stopped(false) { }; + // this constructor is for resetting profile values profiler(task_identifier * id, bool resume = false, reset_type reset = reset_type::NONE) : @@ -92,6 +115,7 @@ class profiler { #endif value(0.0), children_value(0.0), + tt_ptr(nullptr), task_id(id), guid(0), is_counter(false), @@ -105,6 +129,7 @@ class profiler { #endif value(value_), children_value(0.0), + tt_ptr(nullptr), task_id(id), is_counter(true), is_resume(false), @@ -119,6 +144,7 @@ class profiler { #endif value = in.value; children_value = in.children_value; + tt_ptr = in.tt_ptr; task_id = in.task_id; is_counter = in.is_counter; is_resume = in.is_resume; // for yield or resume diff --git a/src/apex/profiler_listener.cpp b/src/apex/profiler_listener.cpp index 00911e2f..07f42783 100644 --- a/src/apex/profiler_listener.cpp +++ b/src/apex/profiler_listener.cpp @@ -10,13 +10,13 @@ #include "profiler_listener.hpp" #include "profiler.hpp" +#include "task_wrapper.hpp" #include "thread_instance.hpp" #include #include #include #include #include "apex_options.hpp" -#include "profiler.hpp" #include "profile.hpp" #include "apex.hpp" @@ -223,7 +223,7 @@ std::unordered_set free_profiles; } #ifdef APEX_WITH_JUPYTER_SUPPORT // restart the main timer - main_timer = std::make_shared(task_identifier::get_task_id(string(APEX_MAIN))); + main_timer = std::make_shared(task_wrapper::get_apex_main_wrapper()); #endif } @@ -1107,7 +1107,7 @@ if (rc != 0) cout << "PAPI error! " << name << ": " << PAPI_strerror(rc) << endl #endif // time the whole application. - main_timer = std::make_shared(task_identifier::get_task_id(string(APEX_MAIN))); + main_timer = std::make_shared(task_wrapper::get_apex_main_wrapper()); #if APEX_HAVE_PAPI if (num_papi_counters > 0 && !apex_options::papi_suspend() && thread_papi_state == papi_running) { int rc = PAPI_read( EventSet, main_timer->papi_start_values ); @@ -1196,7 +1196,7 @@ if (rc != 0) cout << "PAPI error! " << name << ": " << PAPI_strerror(rc) << endl } #endif // restart the main timer - main_timer = std::make_shared(task_identifier::get_task_id(string(APEX_MAIN))); + main_timer = std::make_shared(task_wrapper::get_apex_main_wrapper()); if (data.reset) { reset_all(); } @@ -1270,7 +1270,7 @@ if (rc != 0) cout << "PAPI error! " << name << ": " << PAPI_strerror(rc) << endl unordered_set::const_iterator it; { read_lock_type l(throttled_event_set_mutex); - it = throttled_tasks.find(*tt_ptr->task_id); + it = throttled_tasks.find(*tt_ptr->get_task_id()); } if (it != throttled_tasks.end()) { /* @@ -1283,8 +1283,10 @@ if (rc != 0) cout << "PAPI error! " << name << ": " << PAPI_strerror(rc) << endl } #endif // start the profiler object, which starts our timers - //std::shared_ptr p = std::make_shared(tt_ptr->task_id, is_resume); - profiler * p = new profiler(tt_ptr->task_id, is_resume); + //std::shared_ptr p = std::make_shared(tt_ptr, is_resume); + // get the right task identifier, based on whether there are aliases + task_identifier * id = tt_ptr->get_task_id(); + profiler * p = new profiler(tt_ptr, is_resume); p->guid = thread_instance::get_guid(); thread_instance::instance().set_current_profiler(p); #if APEX_HAVE_PAPI @@ -1395,22 +1397,19 @@ if (rc != 0) cout << "PAPI error! " << name << ": " << PAPI_strerror(rc) << endl } } - void profiler_listener::on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) { + void profiler_listener::on_task_complete(task_wrapper * tt_ptr) { //printf("New task: %llu\n", task_id); fflush(stdout); if (!apex_options::use_taskgraph_output()) { return; } + // get the right task identifier, based on whether there are aliases + task_identifier * id = tt_ptr->get_task_id(); // if the parent task is not null, use it (obviously) - if (parent_ptr != nullptr) { - dependency_queue.enqueue(new task_dependency(parent_ptr->task_id, tt_ptr->task_id)); + if (tt_ptr->parent != nullptr) { + task_identifier * pid = tt_ptr->parent->get_task_id(); + dependency_queue.enqueue(new task_dependency(pid, id)); return; } - // get the current profiler - profiler * p = thread_instance::instance().get_current_profiler(); - if (p != NULL) { - dependency_queue.enqueue(new task_dependency(p->task_id, tt_ptr->task_id)); - } else { - task_identifier * parent = task_identifier::get_task_id(string(APEX_MAIN)); - dependency_queue.enqueue(new task_dependency(parent, tt_ptr->task_id)); - } + task_identifier * parent = task_wrapper::get_apex_main_wrapper()->task_id; + dependency_queue.enqueue(new task_dependency(parent, id)); } /* Communication send event. Save the number of bytes. */ diff --git a/src/apex/profiler_listener.hpp b/src/apex/profiler_listener.hpp index b9931ff5..321e2095 100644 --- a/src/apex/profiler_listener.hpp +++ b/src/apex/profiler_listener.hpp @@ -10,6 +10,8 @@ #endif #include "apex_api.hpp" +#include "profiler.hpp" +#include "task_wrapper.hpp" #include "event_listener.hpp" #include "apex_types.h" #include @@ -180,7 +182,7 @@ class profiler_listener : public event_listener { void on_stop(std::shared_ptr &p); void on_yield(std::shared_ptr &p); bool on_resume(task_wrapper * tt_ptr); - void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr); + void on_task_complete(task_wrapper * tt_ptr); void on_sample_value(sample_value_event_data &data); void on_periodic(periodic_event_data &data); void on_custom_event(custom_event_data &event_data); diff --git a/src/apex/task_wrapper.hpp b/src/apex/task_wrapper.hpp index 71024bf4..6362badd 100644 --- a/src/apex/task_wrapper.hpp +++ b/src/apex/task_wrapper.hpp @@ -1,8 +1,13 @@ #pragma once +namespace apex { +struct task_wrapper; +}; + #include "task_identifier.hpp" #include "profiler.hpp" #include +#include namespace apex { @@ -11,10 +16,39 @@ struct task_wrapper { profiler * prof; uint64_t guid; uint64_t parent_guid; + task_wrapper * parent; std::vector data_ptr; + std::unordered_set aliases; task_wrapper(void) : - task_id(nullptr), prof(nullptr), guid(0ull), - parent_guid(0ull) { } + task_id(nullptr), + prof(nullptr), + guid(0ull), + parent_guid(0ull), + parent(nullptr) + { } + inline task_identifier * get_task_id(void) { + if (!aliases.empty()) { + task_identifier * id = nullptr; + // find the first alias that isn't the same as the original name + for (auto tmp : aliases) { + if (tmp != id) { + id = tmp; + return id; + } + } + } + return task_id; + } + static inline task_wrapper * get_apex_main_wrapper(void) { + static task_wrapper * tt_ptr = nullptr; + if (tt_ptr != nullptr) { + return tt_ptr; + } + const std::string apex_main_str("APEX MAIN"); + tt_ptr = new task_wrapper(); + tt_ptr->task_id = task_identifier::get_task_id(apex_main_str); + return tt_ptr; + } }; // struct task_wrapper -}; // namespace apex \ No newline at end of file +}; // namespace apex diff --git a/src/apex/tau_listener.cpp b/src/apex/tau_listener.cpp index e1447648..892f1ef9 100644 --- a/src/apex/tau_listener.cpp +++ b/src/apex/tau_listener.cpp @@ -141,7 +141,7 @@ void tau_listener::on_exit_thread(event_data &data) { inline bool tau_listener::_common_start(task_wrapper * tt_ptr) { if (!_terminate) { - my_Tau_start(tt_ptr->task_id->get_name().c_str()); + my_Tau_start(tt_ptr->get_task_id()->get_name().c_str()); } else { return false; } @@ -159,10 +159,10 @@ bool tau_listener::on_resume(task_wrapper * tt_ptr) { inline void tau_listener::_common_stop(std::shared_ptr &p) { static string empty(""); if (!_terminate) { - if (p->task_id->get_name().compare(empty) == 0) { + if (p->tt_ptr->get_task_id()->get_name().compare(empty) == 0) { my_Tau_global_stop(); // stop the top level timer } else { - my_Tau_stop(p->task_id->get_name().c_str()); + my_Tau_stop(p->tt_ptr->get_task_id()->get_name().c_str()); } } return; diff --git a/src/apex/tau_listener.hpp b/src/apex/tau_listener.hpp index bf5618b7..0f2eda06 100644 --- a/src/apex/tau_listener.hpp +++ b/src/apex/tau_listener.hpp @@ -32,9 +32,8 @@ class tau_listener : public event_listener { void on_stop(std::shared_ptr &p); void on_yield(std::shared_ptr &p); bool on_resume(task_wrapper * tt_ptr); - void on_new_task(task_wrapper * tt_ptr, task_wrapper * parent_ptr) { + void on_task_complete(task_wrapper * tt_ptr) { APEX_UNUSED(tt_ptr); - APEX_UNUSED(parent_ptr); }; void on_sample_value(sample_value_event_data &data); void on_periodic(periodic_event_data &data); diff --git a/src/apex/thread_instance.cpp b/src/apex/thread_instance.cpp index e2119635..36fac5a5 100644 --- a/src/apex/thread_instance.cpp +++ b/src/apex/thread_instance.cpp @@ -320,7 +320,7 @@ void thread_instance::clear_current_profiler(profiler * the_profiler, bool save_ tt_ptr->data_ptr.push_back(tmp); /* Stop the copy. The original will get reset when the parent resumes. */ - stop(profiler_copy); // we better be re-entrant safe! + stop(profiler_copy, false); // we better be re-entrant safe! } else { // since we aren't yielding, just stop the children. stop(tmp); // we better be re-entrant safe! diff --git a/src/apex/thread_instance.hpp b/src/apex/thread_instance.hpp index 8f896db7..117be8af 100644 --- a/src/apex/thread_instance.hpp +++ b/src/apex/thread_instance.hpp @@ -97,7 +97,7 @@ class thread_instance { static void add_open_profiler(profiler* p) { std::unique_lock l(_open_profiler_mutex); std::stringstream ss; - ss << p->task_id->get_name(); + ss << p->tt_ptr->get_task_id()->get_name(); ss << p->time_point_to_nanoseconds(p->start); open_profilers.insert(ss.str()); } @@ -105,7 +105,7 @@ class thread_instance { if (p == NULL) return; std::unique_lock l(_open_profiler_mutex); std::stringstream ss; - ss << p->task_id->get_name(); + ss << p->tt_ptr->get_task_id()->get_name(); ss << p->time_point_to_nanoseconds(p->start); auto tmp = open_profilers.find(ss.str()); if (tmp != open_profilers.end()) { diff --git a/src/unit_tests/C++/CMakeLists.txt b/src/unit_tests/C++/CMakeLists.txt index 6f3af4fc..f133cacd 100644 --- a/src/unit_tests/C++/CMakeLists.txt +++ b/src/unit_tests/C++/CMakeLists.txt @@ -35,6 +35,7 @@ set(example_programs apex_shutdown_throttling apex_hpx_direct_actions apex_hpx_task_wrapper_direct_actions + apex_hpx_annotated_functions apex_profiler_guids apex_fibonacci_std_async )