diff --git a/src/apex/CMakeLists.hpx b/src/apex/CMakeLists.hpx index 5e56c8e8..d0dbaeb8 100644 --- a/src/apex/CMakeLists.hpx +++ b/src/apex/CMakeLists.hpx @@ -51,12 +51,6 @@ if(APEX_DEBUG) target_compile_definitions(apex_flags INTERFACE APEX_DEBUG) endif() -# If TAU is used, don't allow throttling - it can potentially lead to -# overlapping timer errors in TAU. -#if((DEFINED APEX_THROTTLE) AND (APEX_THROTTLE)) -# target_compile_definitions(apex_flags INTERFACE APEX_THROTTLE) -#endif() - # Check if architecture is x86 or not message("System architecture: ${CMAKE_SYSTEM_PROCESSOR}") if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") @@ -127,10 +121,6 @@ else() set (HOST_BASENAME ${HOSTNAME}) endif() -# this will be statically linked to the core HPX library -target_compile_definitions(apex_flags INTERFACE HPX_EXPORTS) -target_compile_definitions(apex_flags INTERFACE HPX_COROUTINE_EXPORTS) - if(NOT MSVC) target_compile_options(apex_flags INTERFACE -fPIC) else() @@ -328,43 +318,18 @@ set(apex_sources ${ompt_sources} ) -#add_hpx_library(taudummy SHARED NOLIBS SOURCES tau_dummy.cpp HEADERS ${apex_headers} FOLDER "Core/Dependencies") - include(GNUInstallDirs) -# At some point, use the HPX_LIBS macro. Unfortunately, it isn't defined when -# the apex directory is included, so it isn't defined at this point. - -foreach(_module ${HPX_LIBS}) - set(_dependencies ${_dependencies} "hpx_${_module}") -endforeach() +# APEX has one dependency in HPX, just the main library. +# Unless HPXMP is also used. add_hpx_library(apex - STATIC NOLIBS EXCLUDE_FROM_ALL + DYNAMIC NOLIBS EXCLUDE_FROM_ALL NOEXPORT SOURCES ${apex_sources} HEADERS ${apex_headers} DEPENDENCIES ${_dependencies} - hpx_algorithms - hpx_allocator_support - hpx_assertion - hpx_cache - hpx_collectives - hpx_datastructures - hpx_errors - hpx_execution - hpx_format - hpx_functional - hpx_hardware - hpx_hashing - hpx_iterator_support - hpx_logging - hpx_plugin - hpx_program_options - hpx_segmented_algorithms - hpx_thread_support - hpx_topology - hpx_util + hpx ${ompt_dependency} FOLDER "Core/Dependencies") @@ -392,12 +357,6 @@ else() target_link_libraries(apex PUBLIC ${DYNAMICLIB}) endif (APEX_USE_WEAK_SYMBOLS) - -#if(APPLE) - #hpx_add_link_flag("-weak_library libhpx_taudummy.dylib -flat_namespace") -#endif(APPLE) -# add_hpx_pseudo_dependencies (apex_lib taudummy_lib project_activeharmony project_binutils project_otf2) - # TODO: see how to remove those global include directories # add the binary tree to the search path for include files # so that we will find apex_config.h diff --git a/src/apex/apex.cpp b/src/apex/apex.cpp index 7d1d2611..5bfdd535 100644 --- a/src/apex/apex.cpp +++ b/src/apex/apex.cpp @@ -10,6 +10,7 @@ * twice. So, we have a macro to make sure the macro is defined. */ #ifdef APEX_HAVE_HPX_CONFIG #include +#include #endif #include "apex.hpp" @@ -63,6 +64,7 @@ #include #include #include +#include "global_constructor_destructor.h" #ifdef APEX_HAVE_HPX_disabled static void apex_schedule_shutdown(void); #endif // APEX_HAVE_HPX_disabled @@ -457,7 +459,7 @@ string& version() { inline std::shared_ptr _new_task( task_identifier * id, const uint64_t task_id, - const std::shared_ptr &parent_task, apex* instance) { + const std::shared_ptr parent_task, apex* instance) { std::shared_ptr tt_ptr = make_shared(); tt_ptr->task_id = id; // if not tracking dependencies, don't save the parent @@ -584,7 +586,7 @@ profiler* start(const apex_function_address function_address) { return thread_instance::instance().restore_children_profilers(tt_ptr); } -void debug_print(const char * event, std::shared_ptr &tt_ptr) { +void debug_print(const char * event, std::shared_ptr tt_ptr) { if (_program_over) return; static std::mutex this_mutex; std::unique_lock l(this_mutex); @@ -600,29 +602,32 @@ void debug_print(const char * event, std::shared_ptr &tt_ptr) { } } -profiler* start(std::shared_ptr &tt_ptr) { +void start(std::shared_ptr tt_ptr) { #if defined(APEX_DEBUG)//_disabled) debug_print("Start", tt_ptr); #endif if (tt_ptr == nullptr) { APEX_UTIL_REF_COUNT_APEX_INTERNAL_START - return nullptr; + return; } // if APEX is disabled, do nothing. if (apex_options::disable() == true) { APEX_UTIL_REF_COUNT_DISABLED_START - return nullptr; + tt_ptr->prof = nullptr; + return; } apex* instance = apex::instance(); // get the Apex static instance // protect against calls after finalization if (!instance || _exited) { APEX_UTIL_REF_COUNT_START_AFTER_FINALIZE - return nullptr; + tt_ptr->prof = nullptr; + return; } // if APEX is suspended, do nothing. if (apex_options::suspend() == true) { APEX_UTIL_REF_COUNT_SUSPENDED_START - return profiler::get_disabled_profiler(); + tt_ptr->prof = profiler::get_disabled_profiler(); + return; } if (_notify_listeners) { bool success = true; @@ -636,12 +641,14 @@ profiler* start(std::shared_ptr &tt_ptr) { //cout << thread_instance::get_id() << " *** Not success! " << //id->get_name() << endl; fflush(stdout); APEX_UTIL_REF_COUNT_FAILED_START - return profiler::get_disabled_profiler(); + tt_ptr->prof = profiler::get_disabled_profiler(); + return; } } } APEX_UTIL_REF_COUNT_START - return thread_instance::instance().restore_children_profilers(tt_ptr); + thread_instance::instance().restore_children_profilers(tt_ptr); + return; } profiler* resume(const std::string &timer_name) { @@ -863,7 +870,7 @@ void stop(profiler* the_profiler, bool cleanup) { } } -void stop(std::shared_ptr &tt_ptr) { +void stop(std::shared_ptr tt_ptr) { #if defined(APEX_DEBUG)//_disabled) debug_print("Stop", tt_ptr); #endif @@ -962,7 +969,7 @@ void yield(profiler* the_profiler) } } -void yield(std::shared_ptr &tt_ptr) +void yield(std::shared_ptr tt_ptr) { #if defined(APEX_DEBUG)//_disabled) debug_print("Yield", tt_ptr); @@ -1054,16 +1061,16 @@ void sample_value(const std::string &name, double value) } std::shared_ptr new_task( - const std::string &timer_name, + const std::string &name, const uint64_t task_id, - const std::shared_ptr &parent_task) + const std::shared_ptr parent_task) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { return nullptr; } // if APEX is suspended, do nothing. if (apex_options::suspend() == true) { return nullptr; } static const std::string apex_internal("apex_internal"); - if (starts_with(timer_name, apex_internal)) { + if (starts_with(name, apex_internal)) { APEX_UTIL_REF_COUNT_NULL_TASK_WRAPPER // don't process our own events - queue scrubbing tasks. return nullptr; @@ -1073,7 +1080,7 @@ std::shared_ptr new_task( APEX_UTIL_REF_COUNT_NULL_TASK_WRAPPER return nullptr; } // protect against calls after finalization - task_identifier * id = task_identifier::get_task_id(timer_name); + task_identifier * id = task_identifier::get_task_id(name); std::shared_ptr tt_ptr(_new_task(id, task_id, parent_task, instance)); APEX_UTIL_REF_COUNT_TASK_WRAPPER @@ -1083,7 +1090,7 @@ std::shared_ptr new_task( std::shared_ptr new_task( const apex_function_address function_address, const uint64_t task_id, - const std::shared_ptr &parent_task) { + const std::shared_ptr parent_task) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { return nullptr; } // if APEX is suspended, do nothing. @@ -1099,7 +1106,7 @@ std::shared_ptr new_task( } std::shared_ptr update_task( - std::shared_ptr &wrapper, + std::shared_ptr wrapper, const std::string &timer_name) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { return nullptr; } @@ -1119,7 +1126,7 @@ std::shared_ptr update_task( } std::shared_ptr update_task( - std::shared_ptr &wrapper, + std::shared_ptr wrapper, const apex_function_address function_address) { // if APEX is disabled, do nothing. if (apex_options::disable() == true) { return nullptr; } @@ -1966,6 +1973,102 @@ extern "C" { } // extern "C" +#ifdef APEX_HAVE_HPX +DEFINE_CONSTRUCTOR(apex_register_with_hpx); + +std::shared_ptr new_task_adapter( + const std::string &name, + const uint64_t task_id, + const std::shared_ptr parent_task) +{ + return APEX_TOP_LEVEL_PACKAGE::new_task(name, task_id, + static_pointer_cast(parent_task)); +} + +std::shared_ptr new_task_adapter( + const uintptr_t address, + const uint64_t task_id, + const std::shared_ptr parent_task) +{ + return APEX_TOP_LEVEL_PACKAGE::new_task(address, task_id, + static_pointer_cast(parent_task)); +} + +std::shared_ptr update_task_adapter( + std::shared_ptr wrapper, + const std::string &timer_name) { + return APEX_TOP_LEVEL_PACKAGE::update_task( + static_pointer_cast(wrapper), + timer_name); +} + +std::shared_ptr update_task_adapter( + std::shared_ptr wrapper, + const uintptr_t address) { + return APEX_TOP_LEVEL_PACKAGE::update_task( + static_pointer_cast(wrapper), + address); +} + +void start_adapter(std::shared_ptr tt_ptr) { + APEX_TOP_LEVEL_PACKAGE::start( + static_pointer_cast(tt_ptr)); +} + +void stop_adapter(std::shared_ptr tt_ptr) { + APEX_TOP_LEVEL_PACKAGE::stop( + static_pointer_cast(tt_ptr)); +} + +void yield_adapter(std::shared_ptr tt_ptr) { + APEX_TOP_LEVEL_PACKAGE::yield( + static_pointer_cast(tt_ptr)); +} + +static void apex_register_with_hpx(void) { + hpx::util::external_timer::registration reg; + reg.type = hpx::util::external_timer::init_flag; + reg.record.init = &APEX_TOP_LEVEL_PACKAGE::init; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::finalize_flag; + reg.record.finalize = &APEX_TOP_LEVEL_PACKAGE::finalize; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::register_thread_flag; + reg.record.register_thread = &APEX_TOP_LEVEL_PACKAGE::register_thread; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::new_task_string_flag; + reg.record.new_task_string = &new_task_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::new_task_address_flag; + reg.record.new_task_address = &new_task_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::sample_value_flag; + reg.record.sample_value = &APEX_TOP_LEVEL_PACKAGE::sample_value; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::send_flag; + reg.record.send = &APEX_TOP_LEVEL_PACKAGE::send; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::recv_flag; + reg.record.recv = &APEX_TOP_LEVEL_PACKAGE::recv; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::update_task_string_flag; + reg.record.update_task_string = &update_task_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::update_task_address_flag; + reg.record.update_task_address = &update_task_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::start_flag; + reg.record.start = &start_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::stop_flag; + reg.record.stop = &stop_adapter; + hpx::util::external_timer::register_external_timer(reg); + reg.type = hpx::util::external_timer::yield_flag; + reg.record.yield = &yield_adapter; + hpx::util::external_timer::register_external_timer(reg); +} +#endif + #ifdef APEX_HAVE_HPX_disabled HPX_DECLARE_ACTION(APEX_TOP_LEVEL_PACKAGE::finalize, apex_internal_shutdown_action); diff --git a/src/apex/apex_api.hpp b/src/apex/apex_api.hpp index a0ad5418..7e1e2a30 100644 --- a/src/apex/apex_api.hpp +++ b/src/apex/apex_api.hpp @@ -162,13 +162,10 @@ APEX_EXPORT profiler * start(const apex_function_address function_address); \param task_wrapper_ptr A pointer to an apex::task_wrapper created by apex::new_task. APEX will use this to store the profiler data. - \return The handle for the profiler object in APEX. Not intended to be - queried by the application. Should be retained locally, if - possible, and passed in to the matching apex::stop - call when the timer should be stopped. + \return No return value. \sa @ref apex::stop, @ref apex::yield, @ref apex::resume @ref apex::new_task */ -APEX_EXPORT profiler * start(std::shared_ptr &task_wrapper_ptr); +APEX_EXPORT void start(std::shared_ptr task_wrapper_ptr); /** \brief Stop a timer. @@ -195,7 +192,7 @@ APEX_EXPORT void stop(profiler * the_profiler, bool cleanup=true); \return No return value. \sa @ref apex::start, @ref apex::yield, @ref apex::resume, @ref apex::new_task */ -APEX_EXPORT void stop(std::shared_ptr &task_wrapper_ptr); +APEX_EXPORT void stop(std::shared_ptr task_wrapper_ptr); /** \brief Stop a timer, but don't increment the number of calls. @@ -225,7 +222,7 @@ APEX_EXPORT void yield(profiler * the_profiler); \return No return value. \sa @ref apex::start, @ref apex::stop, @ref apex::resume */ -APEX_EXPORT void yield(std::shared_ptr &task_wrapper_ptr); +APEX_EXPORT void yield(std::shared_ptr task_wrapper_ptr); /** \brief Resume a timer. @@ -278,13 +275,10 @@ APEX_EXPORT profiler * resume(const apex_function_address function_address); \param task_wrapper_ptr A pointer to an apex::task_wrapper created by apex::new_task. APEX will use this to store the profiler data. - \return The handle for the timer object in APEX. Not intended to be - queried by the application. Should be retained locally, if - possible, and passed in to the matching apex::stop - call when the timer should be stopped. + \return No return value. \sa apex::stop, apex::yield, apex::start */ -APEX_EXPORT profiler * resume(std::shared_ptr &task_wrapper_ptr); +APEX_EXPORT void resume(std::shared_ptr task_wrapper_ptr); /* * Functions for resetting timer values @@ -357,7 +351,7 @@ APEX_EXPORT void sample_value(const std::string &name, double value); APEX_EXPORT std::shared_ptr new_task( const std::string &name, const uint64_t task_id = UINTMAX_MAX, - const std::shared_ptr &parent_task = null_task_wrapper); + const std::shared_ptr parent_task = null_task_wrapper); /** \brief Create a new task (dependency). @@ -375,7 +369,7 @@ APEX_EXPORT std::shared_ptr new_task( APEX_EXPORT std::shared_ptr new_task( const apex_function_address function_address, const uint64_t task_id = UINTMAX_MAX, - const std::shared_ptr &parent_task = null_task_wrapper); + const std::shared_ptr parent_task = null_task_wrapper); /** \brief Update a task (dependency). @@ -387,7 +381,7 @@ APEX_EXPORT std::shared_ptr new_task( */ APEX_EXPORT std::shared_ptr update_task( - std::shared_ptr &wrapper, + std::shared_ptr wrapper, const std::string &name); /** @@ -400,7 +394,7 @@ APEX_EXPORT std::shared_ptr update_task( */ APEX_EXPORT std::shared_ptr update_task( - std::shared_ptr &wrapper, + std::shared_ptr wrapper, const apex_function_address function_address); /** @@ -883,7 +877,7 @@ class scoped_timer { \param func The address of a function used to identify the timer type \param parent The parent task wrapper (if available) of this new scoped_timer */ - scoped_timer(uint64_t func, std::shared_ptr &parent) + scoped_timer(uint64_t func, std::shared_ptr parent) : twp(nullptr), timing(true) { twp = apex::new_task((apex_function_address)func, UINTMAX_MAX, parent); apex::start(twp); @@ -895,7 +889,7 @@ class scoped_timer { \param parent The parent task wrapper (if available) of this new scoped_timer */ scoped_timer(std::string func, - std::shared_ptr &parent) + std::shared_ptr parent) : twp(nullptr), timing(true) { twp = apex::new_task(func, UINTMAX_MAX, parent); apex::start(twp); @@ -950,7 +944,7 @@ class scoped_timer { /** \brief Get the internal task wrapper object */ - std::shared_ptr& get_task_wrapper(void) { + std::shared_ptr get_task_wrapper(void) { return twp; } }; diff --git a/src/apex/proc_read.cpp b/src/apex/proc_read.cpp index d4966472..3b473d3d 100644 --- a/src/apex/proc_read.cpp +++ b/src/apex/proc_read.cpp @@ -319,10 +319,10 @@ namespace apex { int retval = PAPI_read(rapl_EventSet, rapl_values); if (retval != PAPI_OK) { fprintf(stderr, "Error reading PAPI RAPL eventset.\n"); - return; - } - for (size_t i = 0 ; i < rapl_event_names.size() ; i++) { - data->rapl_metrics.push_back(rapl_values[i]); + } else { + for (size_t i = 0 ; i < rapl_event_names.size() ; i++) { + data->rapl_metrics.push_back(rapl_values[i]); + } } free(rapl_values); } @@ -331,10 +331,10 @@ namespace apex { int retval = PAPI_read(nvml_EventSet, nvml_values); if (retval != PAPI_OK) { fprintf(stderr, "Error reading PAPI NVML eventset.\n"); - return; - } - for (size_t i = 0 ; i < nvml_event_names.size() ; i++) { - data->nvml_metrics.push_back(nvml_values[i]); + } else { + for (size_t i = 0 ; i < nvml_event_names.size() ; i++) { + data->nvml_metrics.push_back(nvml_values[i]); + } } free(nvml_values); } @@ -343,10 +343,10 @@ namespace apex { int retval = PAPI_read(lms_EventSet, lms_values); if (retval != PAPI_OK) { fprintf(stderr, "Error reading PAPI lmsensors eventset.\n"); - return; - } - for (size_t i = 0 ; i < lms_event_names.size() ; i++) { - data->lms_metrics.push_back(lms_values[i]); + } else { + for (size_t i = 0 ; i < lms_event_names.size() ; i++) { + data->lms_metrics.push_back(lms_values[i]); + } } free(lms_values); } @@ -490,17 +490,20 @@ namespace apex { #endif #if defined(APEX_HAVE_PAPI) if (rapl_initialized) { - for (size_t i = 0 ; i < rapl_event_names.size() ; i++) { + // reading might have failed, so only copy if there's data + for (size_t i = 0 ; i < rapl_metrics.size() ; i++) { d->rapl_metrics.push_back(rapl_metrics[i]); } } if (nvml_initialized) { - for (size_t i = 0 ; i < nvml_event_names.size() ; i++) { + // reading might have failed, so only copy if there's data + for (size_t i = 0 ; i < nvml_metrics.size() ; i++) { d->nvml_metrics.push_back(nvml_metrics[i]); } } if (lms_initialized) { - for (size_t i = 0 ; i < lms_event_names.size() ; i++) { + // reading might have failed, so only copy if there's data + for (size_t i = 0 ; i < lms_metrics.size() ; i++) { d->lms_metrics.push_back(lms_metrics[i]); } } @@ -646,7 +649,8 @@ namespace apex { #endif #if defined(APEX_HAVE_PAPI) if (rapl_initialized) { - for (size_t i = 0 ; i < rapl_event_names.size() ; i++) { + // reading might have failed, so only iterate over the data + for (size_t i = 0 ; i < rapl_metrics.size() ; i++) { stringstream ss; ss << rapl_event_names[i]; if (rapl_event_units[i].length() > 0) { @@ -664,7 +668,8 @@ namespace apex { } } if (nvml_initialized) { - for (size_t i = 0 ; i < nvml_event_names.size() ; i++) { + // reading might have failed, so only iterate over the data + for (size_t i = 0 ; i < nvml_metrics.size() ; i++) { stringstream ss; ss << nvml_event_names[i]; if (nvml_event_units[i].length() > 0) { @@ -681,7 +686,8 @@ namespace apex { } } if (lms_initialized) { - for (size_t i = 0 ; i < lms_event_names.size() ; i++) { + // reading might have failed, so only iterate over the data + for (size_t i = 0 ; i < lms_metrics.size() ; i++) { // PAPI scales LM sensor data by 1000, // because it doesn't have floating point values.. sample_value(lms_event_names[i].c_str(), (double)lms_metrics[i]/1000.0); @@ -1020,7 +1026,7 @@ namespace apex { newData = parse_proc_stat(); periodData = newData->diff(*oldData); // save the values - if (done) break; + if (done) break; // double-check... periodData->sample_values(); // free the memory delete(oldData); diff --git a/src/apex/task_wrapper.hpp b/src/apex/task_wrapper.hpp index 352ba6fa..70e64c50 100644 --- a/src/apex/task_wrapper.hpp +++ b/src/apex/task_wrapper.hpp @@ -9,6 +9,10 @@ namespace apex { struct task_wrapper; } +#ifdef APEX_HAVE_HPX_CONFIG +#include +#include +#endif #include "task_identifier.hpp" #include "profiler.hpp" #include @@ -21,7 +25,11 @@ namespace apex { /** \brief A wrapper around APEX tasks. */ +#ifdef APEX_HAVE_HPX_CONFIG +struct task_wrapper : public hpx::util::external_timer::task_wrapper { +#else struct task_wrapper { +#endif /** \brief A pointer to the task_identifier for this task_wrapper. */ diff --git a/src/apex/utils.cpp b/src/apex/utils.cpp index 9abc500c..77f916f3 100644 --- a/src/apex/utils.cpp +++ b/src/apex/utils.cpp @@ -81,8 +81,8 @@ std::string* demangle(const std::string& timer_name) { break; case -2: printf("The demangling operation failed:"); - printf(" '%s' is not a valid name under the C++ ABI"); - printf(" mangling rules.\n", timer_name.c_str()); + printf(" '%s' is not a valid", timer_name.c_str()); + printf(" name under the C++ ABI mangling rules.\n"); break; case -3: printf("The demangling operation failed: One of the"); diff --git a/src/unit_tests/C++/apex_pthread_flood.cpp b/src/unit_tests/C++/apex_pthread_flood.cpp index bea91fbe..c0c73927 100644 --- a/src/unit_tests/C++/apex_pthread_flood.cpp +++ b/src/unit_tests/C++/apex_pthread_flood.cpp @@ -36,7 +36,7 @@ typedef void*(*start_routine_t)(void*); void* someThread(void* tmp) { - apex::scoped_thread("threadTest thread"); + apex::scoped_thread mythread("threadTest thread"); unsigned long * result = (unsigned long *)tmp; int i = 0; unsigned long total = 0;