From 8ec55108fbcc5f8c028b5a45c53955e949670b89 Mon Sep 17 00:00:00 2001 From: Kevin Huck Date: Thu, 28 Jun 2018 16:40:13 -0700 Subject: [PATCH 1/2] Improvements to OTF2 output. Added PAPI counters to the output when collected, and also added paradigms for known substrings, including MPI, OpenMP, Pthread and apex events. --- src/apex/otf2_listener.cpp | 74 +++++++++++++++++++++++++++------- src/apex/otf2_listener.hpp | 1 + src/apex/profiler.hpp | 2 +- src/apex/profiler_listener.hpp | 1 + 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/apex/otf2_listener.cpp b/src/apex/otf2_listener.cpp index c67b5773..77ecef5f 100644 --- a/src/apex/otf2_listener.cpp +++ b/src/apex/otf2_listener.cpp @@ -428,6 +428,13 @@ namespace apex { parent_guid_ref, parent_name_ref, parent_desc_ref, OTF2_TYPE_UINT64); } + inline void convert_upper(std::string& str, std::string& converted) + { + for(size_t i = 0; i < str.size(); ++i) { + converted += toupper(str[i]); + } + } + void otf2_listener::write_otf2_regions(void) { // only write these out once! static APEX_NATIVE_TLS bool written = false; @@ -437,14 +444,26 @@ namespace apex { string id = i.first; uint64_t idx = i.second; OTF2_GlobalDefWriter_WriteString( global_def_writer, get_string_index(id), id.c_str() ); - size_t found = id.find(string("UNRESOLVED")); + OTF2_Paradigm paradigm = OTF2_PARADIGM_USER; + string uppercase; + convert_upper(id, uppercase); + size_t found = uppercase.find(string("APEX")); + if (found != std::string::npos) { paradigm = OTF2_PARADIGM_MEASUREMENT_SYSTEM; } + found = uppercase.find(string("UNRESOLVED")); + if (found != std::string::npos) { paradigm = OTF2_PARADIGM_MEASUREMENT_SYSTEM; } + found = uppercase.find(string("OPENMP")); + if (found != std::string::npos) { paradigm = OTF2_PARADIGM_OPENMP; } + found = uppercase.find(string("PTHREAD")); + if (found != std::string::npos) { paradigm = OTF2_PARADIGM_PTHREAD; } + found = uppercase.find(string("MPI")); + if (found != std::string::npos) { paradigm = OTF2_PARADIGM_MPI; } OTF2_GlobalDefWriter_WriteRegion( global_def_writer, idx /* id */, get_string_index(id) /* region name */, get_string_index(empty) /* alternative name */, get_string_index(empty) /* description */, (found != std::string::npos) ? OTF2_REGION_ROLE_ARTIFICIAL : OTF2_REGION_ROLE_TASK, - (found != std::string::npos) ? OTF2_PARADIGM_MEASUREMENT_SYSTEM : OTF2_PARADIGM_USER, + paradigm, OTF2_REGION_FLAG_NONE, get_string_index(empty) /* source file */, get_string_index(empty) /* begin lno */, @@ -812,6 +831,22 @@ namespace apex { return; } + void otf2_listener::write_papi_counters(OTF2_EvtWriter* writer, profiler* prof, uint64_t stamp) { + // create a union for storing the value + OTF2_MetricValue omv[1]; + // tell the union what type this is + OTF2_Type omt[1]; + omt[0]=OTF2_TYPE_DOUBLE; + int i = 0; + uint64_t idx = 0L; + for (auto metric : apex::instance()->the_profiler_listener->get_metric_names()) { + omv[0].floating_point = prof->papi_start_values[i++]; + idx = get_metric_index(metric); + // write our counter into the event stream + OTF2_EC(OTF2_EvtWriter_Metric( writer, NULL, stamp, idx, 1, omt, omv )); + } + } + bool otf2_listener::on_start(std::shared_ptr &tt_ptr) { task_identifier * id = tt_ptr->get_task_id(); // don't close the archive on us! @@ -826,8 +861,9 @@ namespace apex { // create an attribute OTF2_AttributeList_AddUint64( al, 0, tt_ptr->guid ); OTF2_AttributeList_AddUint64( al, 1, tt_ptr->parent_guid ); + uint64_t idx = get_region_index(id); + uint64_t stamp = 0L; if (thread_instance::get_id() == 0) { - uint64_t idx = get_region_index(id); // Because the event writer for thread 0 is also // used for communication events and sampled values, // we have to get a lock for it. @@ -836,11 +872,15 @@ namespace apex { // profiler object. bummer. it has to be taken after // the lock is acquired, so that events happen on // thread 0 in monotonic order. - uint64_t stamp = get_time(); + stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Enter( local_evt_writer, al, stamp, idx /* region */ )); + // write PAPI metrics! + write_papi_counters(local_evt_writer, tt_ptr->prof, stamp); } else { - uint64_t stamp = get_time(); - OTF2_EC(OTF2_EvtWriter_Enter( local_evt_writer, al, stamp, get_region_index(id) /* region */ )); + stamp = get_time(); + OTF2_EC(OTF2_EvtWriter_Enter( local_evt_writer, al, stamp, idx /* region */ )); + // write PAPI metrics! + write_papi_counters(local_evt_writer, tt_ptr->prof, stamp); } // delete the attribute list OTF2_AttributeList_Delete(al); @@ -864,22 +904,26 @@ namespace apex { OTF2_AttributeList * al = OTF2_AttributeList_New(); // create an attribute OTF2_AttributeList_AddUint64( al, 0, p->guid ); + // unfortunately, we can't use the timestamp from the + // profiler object. bummer. it has to be taken after + // the lock is acquired, so that events happen on + // thread 0 in monotonic order. + uint64_t stamp = 0L; + uint64_t idx = get_region_index(p->get_task_id()); if (thread_instance::get_id() == 0) { - uint64_t idx = get_region_index(p->get_task_id()); // Because the event writer for thread 0 is also // used for communication events and sampled values, // we have to get a lock for it. std::unique_lock lock(_comm_mutex); - // unfortunately, we can't use the timestamp from the - // profiler object. bummer. it has to be taken after - // the lock is acquired, so that events happen on - // thread 0 in monotonic order. - uint64_t stamp = get_time(); + stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Leave( local_evt_writer, al, stamp, idx /* region */ )); + // write PAPI metrics! + write_papi_counters(local_evt_writer, p.get(), stamp); } else { - uint64_t stamp = get_time(); - OTF2_EC(OTF2_EvtWriter_Leave( local_evt_writer, al, stamp, - get_region_index(p->get_task_id()) /* region */ )); + stamp = get_time(); + OTF2_EC(OTF2_EvtWriter_Leave( local_evt_writer, al, stamp, idx /* region */ )); + // write PAPI metrics! + write_papi_counters(local_evt_writer, p.get(), stamp); } // delete the attribute list OTF2_AttributeList_Delete(al); diff --git a/src/apex/otf2_listener.hpp b/src/apex/otf2_listener.hpp index 2d802732..231d0469 100644 --- a/src/apex/otf2_listener.hpp +++ b/src/apex/otf2_listener.hpp @@ -160,6 +160,7 @@ namespace apex { std::map reduced_region_map; std::map reduced_metric_map; std::unique_ptr, std::map > > reduce_node_properties(std::string&& str); + void write_papi_counters(OTF2_EvtWriter* writer, profiler* prof, uint64_t stamp); public: otf2_listener (void); //~otf2_listener (void) { shutdown_event_data data(my_saved_node_id,0); on_shutdown(data); }; diff --git a/src/apex/profiler.hpp b/src/apex/profiler.hpp index 62a06b96..f499b53b 100644 --- a/src/apex/profiler.hpp +++ b/src/apex/profiler.hpp @@ -108,7 +108,7 @@ class profiler { guid(0), is_counter(false), is_resume(resume), - is_reset(reset), stopped(false) { }; + is_reset(reset), stopped(false) { task->prof = this; }; // this constructor is for resetting profile values profiler(task_identifier * id, bool resume = false, diff --git a/src/apex/profiler_listener.hpp b/src/apex/profiler_listener.hpp index c19b5626..d6d3f994 100644 --- a/src/apex/profiler_listener.hpp +++ b/src/apex/profiler_listener.hpp @@ -212,6 +212,7 @@ class profiler_listener : public event_listener { static void consumer_process_profiles_wrapper(void); void public_process_profile(std::shared_ptr &p) { process_profile(p,0); }; bool concurrent_cleanup(int i); + std::vector& get_metric_names(void) { return metric_names; }; }; } From 0128cbd747ba2c11a22a48a2e04b2c50cd353d65 Mon Sep 17 00:00:00 2001 From: Kevin Huck Date: Thu, 28 Jun 2018 17:03:23 -0700 Subject: [PATCH 2/2] Don't include PAPI code when PAPI not included in the configuration. --- src/apex/otf2_listener.cpp | 10 ++++++++++ src/apex/otf2_listener.hpp | 2 ++ src/apex/profiler_listener.hpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/apex/otf2_listener.cpp b/src/apex/otf2_listener.cpp index 77ecef5f..47f4294a 100644 --- a/src/apex/otf2_listener.cpp +++ b/src/apex/otf2_listener.cpp @@ -831,6 +831,7 @@ namespace apex { return; } +#if APEX_HAVE_PAPI void otf2_listener::write_papi_counters(OTF2_EvtWriter* writer, profiler* prof, uint64_t stamp) { // create a union for storing the value OTF2_MetricValue omv[1]; @@ -846,6 +847,7 @@ namespace apex { OTF2_EC(OTF2_EvtWriter_Metric( writer, NULL, stamp, idx, 1, omt, omv )); } } +#endif bool otf2_listener::on_start(std::shared_ptr &tt_ptr) { task_identifier * id = tt_ptr->get_task_id(); @@ -874,13 +876,17 @@ namespace apex { // thread 0 in monotonic order. stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Enter( local_evt_writer, al, stamp, idx /* region */ )); +#if APEX_HAVE_PAPI // write PAPI metrics! write_papi_counters(local_evt_writer, tt_ptr->prof, stamp); +#endif } else { stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Enter( local_evt_writer, al, stamp, idx /* region */ )); +#if APEX_HAVE_PAPI // write PAPI metrics! write_papi_counters(local_evt_writer, tt_ptr->prof, stamp); +#endif } // delete the attribute list OTF2_AttributeList_Delete(al); @@ -917,13 +923,17 @@ namespace apex { std::unique_lock lock(_comm_mutex); stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Leave( local_evt_writer, al, stamp, idx /* region */ )); +#if APEX_HAVE_PAPI // write PAPI metrics! write_papi_counters(local_evt_writer, p.get(), stamp); +#endif } else { stamp = get_time(); OTF2_EC(OTF2_EvtWriter_Leave( local_evt_writer, al, stamp, idx /* region */ )); +#if APEX_HAVE_PAPI // write PAPI metrics! write_papi_counters(local_evt_writer, p.get(), stamp); +#endif } // delete the attribute list OTF2_AttributeList_Delete(al); diff --git a/src/apex/otf2_listener.hpp b/src/apex/otf2_listener.hpp index 231d0469..227244d3 100644 --- a/src/apex/otf2_listener.hpp +++ b/src/apex/otf2_listener.hpp @@ -160,7 +160,9 @@ namespace apex { std::map reduced_region_map; std::map reduced_metric_map; std::unique_ptr, std::map > > reduce_node_properties(std::string&& str); +#if APEX_HAVE_PAPI void write_papi_counters(OTF2_EvtWriter* writer, profiler* prof, uint64_t stamp); +#endif public: otf2_listener (void); //~otf2_listener (void) { shutdown_event_data data(my_saved_node_id,0); on_shutdown(data); }; diff --git a/src/apex/profiler_listener.hpp b/src/apex/profiler_listener.hpp index d6d3f994..eeb3536c 100644 --- a/src/apex/profiler_listener.hpp +++ b/src/apex/profiler_listener.hpp @@ -212,7 +212,9 @@ class profiler_listener : public event_listener { static void consumer_process_profiles_wrapper(void); void public_process_profile(std::shared_ptr &p) { process_profile(p,0); }; bool concurrent_cleanup(int i); +#if APEX_HAVE_PAPI std::vector& get_metric_names(void) { return metric_names; }; +#endif }; }