diff --git a/CMakeLists.txt b/CMakeLists.txt index f08fa4cc9cb9d596407cb56f0e876f62a35957e6..2e4dea4686ad7738ecf4ddb54289c4324b4c536e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,19 +36,54 @@ if(INSTALL_WITH_RPATH) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) endif() -add_library(${PROJECT_NAME} SHARED) +add_library(nesmik SHARED) +set_property(TARGET nesmik PROPERTY OUTPUT_NAME nesmik_core) + +add_library(nesmik_lib SHARED) +set_property(TARGET nesmik_lib PROPERTY OUTPUT_NAME nesmik) +target_link_libraries(nesmik_lib PRIVATE nesmik) + +add_executable(nesmik_app) +set_property(TARGET nesmik_app PROPERTY OUTPUT_NAME nesmik) +target_link_libraries(nesmik_app PRIVATE nesmik) +target_link_libraries(nesmik_app PRIVATE nesmik_dlb_stripped) +target_link_libraries(nesmik_app PRIVATE nesmik_extrae_stripped) +target_compile_definitions(nesmik_app PRIVATE "NESMIK_APP") set(NESMIK_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(nesmik_lib PUBLIC $ $ $ $ ) +include(FetchContent) + +# Define the PathTOJson variable with an empty default value +set(NLOHMAN_JSON_PATH "" CACHE STRING "Path to the local nlohmann json release file") + +if(NLOHMAN_JSON_PATH) + FetchContent_Declare( + json + URL ${NLOHMAN_JSON_PATH} + ) +else() + FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz + ) +endif() + +# FetchContent configuration +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) +FetchContent_MakeAvailable(json) +target_link_libraries(nesmik PRIVATE nlohmann_json::nlohmann_json) +target_link_libraries(nesmik_lib PRIVATE nlohmann_json::nlohmann_json) +target_link_libraries(nesmik_app PRIVATE nlohmann_json::nlohmann_json) if(BUILD_C_FORTRAN AND SPLIT_FORTRAN_LIBRARY) add_library(nesmik_f) @@ -57,69 +92,70 @@ endif() if(WITH_MPI) find_package(MPI REQUIRED COMPONENTS CXX) - target_link_libraries(${PROJECT_NAME} PRIVATE MPI::MPI_CXX) - target_compile_definitions(nesmik PRIVATE "WITH_MPI") + target_link_libraries(nesmik_lib PRIVATE MPI::MPI_CXX) + target_compile_definitions(nesmik_lib PRIVATE "WITH_MPI") endif() if(ENABLE_EXTRAE) find_package(EXTRAE REQUIRED) if(EXTRAE_FOUND) - target_include_directories(nesmik - PRIVATE ${EXTRAE_INCLUDE_DIRS}) - # We link publicy with seqtrace, as we need it to be in the right order to libc to find malloc with dlsym .. - target_link_libraries(nesmik PUBLIC ${EXTRAE_LIBRARIES}) - target_compile_definitions(nesmik PRIVATE "ENABLE_EXTRAE") + # Create the Extrae Wrapper library + add_library(nesmik_extrae SHARED) + + #Include and link with Extrae + target_include_directories(nesmik_extrae + PRIVATE ${EXTRAE_INCLUDE_DIRS}) + # We link publicy with seqtrace, as we need it to be in the right order to + # libc to find malloc with dlsym .. + target_link_libraries(nesmik_extrae PUBLIC ${EXTRAE_LIBRARIES}) + target_compile_definitions(nesmik_lib PRIVATE "ENABLE_EXTRAE") + target_compile_definitions(nesmik_extrae PRIVATE "ENABLE_EXTRAE") + # And link libnesmik.so with it. + target_link_libraries(nesmik_lib PRIVATE nesmik_extrae) + # Link JSON library with it + target_link_libraries(nesmik_extrae PRIVATE nlohmann_json::nlohmann_json) else() - message(FATAL_ERROR "Couldn't find Extrae") + message(FATAL_ERROR "Couldn't find Extrae") endif() endif() +add_library(nesmik_extrae_stripped SHARED) +target_link_libraries(nesmik_extrae_stripped PRIVATE nlohmann_json::nlohmann_json) if(ENABLE_DLB) find_package(DLB REQUIRED) if(DLB_FOUND) - target_include_directories(nesmik - PRIVATE ${DLB_INCLUDE_DIRS}) - target_link_libraries(nesmik PRIVATE ${DLB_LIBRARIES}) - target_compile_definitions(nesmik PRIVATE "ENABLE_DLB") + # Create the DLB Wrapper library + add_library(nesmik_dlb SHARED) + + # Include and link with DLB + target_include_directories(nesmik_dlb + PRIVATE ${DLB_INCLUDE_DIRS}) + target_link_libraries(nesmik_dlb PRIVATE ${DLB_LIBRARIES}) + + # TODO: Remove when the DLB wrapper fully decouples TALP structs. + target_include_directories(nesmik_lib + PRIVATE ${DLB_INCLUDE_DIRS}) + + # Enable DLB guards + target_compile_definitions(nesmik_lib PRIVATE "ENABLE_DLB") + target_compile_definitions(nesmik_dlb PRIVATE "ENABLE_DLB") + + # Link libnesmik.so with DLB + target_link_libraries(nesmik_lib PRIVATE nesmik_dlb) + # Link JSON library with it + target_link_libraries(nesmik_dlb PRIVATE nlohmann_json::nlohmann_json) else() - message(FATAL_ERROR "Couldn't find DLB") + message(FATAL_ERROR "Couldn't find DLB") endif() endif() - - -include(FetchContent) - - -# Define the PathTOJson variable with an empty default value -set(NLOHMAN_JSON_PATH "" CACHE STRING "Path to the local nlohmann json release file") - -if(NLOHMAN_JSON_PATH) - FetchContent_Declare( - json - URL ${NLOHMAN_JSON_PATH} - ) -else() - FetchContent_Declare( - json - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz - ) -endif() - -# FetchContent configuration - -FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) -FetchContent_MakeAvailable(json) - -target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) - +add_library(nesmik_dlb_stripped SHARED) +target_link_libraries(nesmik_dlb_stripped PRIVATE nlohmann_json::nlohmann_json) add_subdirectory(src) - enable_testing() add_subdirectory(tests) - # # Install Targets for nesmik # @@ -128,11 +164,30 @@ add_subdirectory(tests) include(GNUInstallDirs) message(STATUS ${CMAKE_INSTALL_INCLUDEDIR}) +if(ENABLE_EXTRAE) +install(TARGETS nesmik_extrae + EXPORT nesmikTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + ) +endif() + +if(ENABLE_DLB) +install(TARGETS nesmik_dlb + EXPORT nesmikTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + ) +endif() if(BUILD_C_FORTRAN AND SPLIT_FORTRAN_LIBRARY) -install(TARGETS ${PROJECT_NAME} nesmik_f +install(TARGETS nesmik_lib nesmik nesmik_f EXPORT nesmikTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -140,7 +195,7 @@ install(TARGETS ${PROJECT_NAME} nesmik_f INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} ) else() -install(TARGETS ${PROJECT_NAME} +install(TARGETS nesmik_lib nesmik EXPORT nesmikTargets FILE_SET HEADERS LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3be7aed5ad0e1281d2ac3cb4bf8c0398ade2dced..f10fbeb0358a2dd73ff669f79b7d24a02d5c80a4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,20 @@ add_subdirectory(backends) add_subdirectory(utils) -target_sources(nesmik PRIVATE delegator.cpp nesmik.cpp) +target_sources(nesmik_lib PRIVATE delegator.cpp nesmik.cpp) +target_sources(nesmik_app PRIVATE nesmik_app.cpp) + +target_include_directories(nesmik PRIVATE ".") +target_include_directories(nesmik_app PRIVATE ".") + +if(ENABLE_EXTRAE) + target_include_directories(nesmik_extrae PRIVATE ".") +endif() +target_include_directories(nesmik_extrae_stripped PRIVATE ".") + +if(ENABLE_DLB) + target_include_directories(nesmik_dlb PRIVATE ".") +endif() +target_include_directories(nesmik_dlb_stripped PRIVATE ".") if(BUILD_C_FORTRAN) add_subdirectory(bindings) diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 270833aaea551917683f6f4cc9453ac016e4a6da..7aecfa2d87bc5be7615c3a38735db410741effda 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,12 +1,13 @@ add_subdirectory(default) add_subdirectory(detection) add_subdirectory(wrappers) -if(ENABLE_DLB) + +#if(ENABLE_DLB) add_subdirectory(dlb_talp) add_subdirectory(dlb_talp_tree) -endif() +#endif() -if(ENABLE_EXTRAE) +#if(ENABLE_EXTRAE) add_subdirectory(extrae_partial_tracer) add_subdirectory(extrae_type_stack) -endif() +#endif() diff --git a/src/backends/default/default.cpp b/src/backends/default/default.cpp index d3e50e3a63b7238ea9a71cd0f62590b0d7e820cb..9054829da0d424e68e2c12361ba21c1fb26bdbb2 100644 --- a/src/backends/default/default.cpp +++ b/src/backends/default/default.cpp @@ -3,11 +3,6 @@ #include #include -NPNDefault::NPNDefault() { - parallelism_descriptor_ = {.mpi_descriptor_ = MPIDescriptor::DontCare, - .thread_descriptor_ = ThreadDescriptor::Supported}; -} - void NPNDefault::RegionStart( const NotProperlyNestedRegionInformation ®ion) noexcept { std::cout << "neSmiK: DefaultBackend region_start: " << region.name diff --git a/src/backends/default/default.hpp b/src/backends/default/default.hpp index 7158c24880387e08a69638d141458b364b3ccaab..0d60ad2ccf29678adb0a7df94967ad9111d41825 100644 --- a/src/backends/default/default.hpp +++ b/src/backends/default/default.hpp @@ -1,15 +1,31 @@ +#include #include -#include "strategies.hpp" - class NPNDefault : public NotProperlyNestedAnnotationStrategy { public: - NPNDefault(); - inline static const std::string name = "Default"; + NPNDefault() : NotProperlyNestedAnnotationStrategy() {} + + inline static const struct StrategyDescription description = { + .name = "Default", + .description = "TODO", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::DontCare, + .thread_descriptor = ThreadDescriptor::Supported}}; + virtual void RegionStart(const NotProperlyNestedRegionInformation &info_to_start) noexcept override; virtual void RegionStop( const NotProperlyNestedRegionInformation &info_to_stop) noexcept override; virtual void Init() noexcept; virtual void Finalize() noexcept; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + return storage; + } }; diff --git a/src/backends/detection/CMakeLists.txt b/src/backends/detection/CMakeLists.txt index e7f49757bc39bfad000e697d20711404c9806a13..2bccf911abdd2f1f7c11ebaf9039b1540d851787 100644 --- a/src/backends/detection/CMakeLists.txt +++ b/src/backends/detection/CMakeLists.txt @@ -1 +1,2 @@ target_sources(nesmik PRIVATE detection.cpp) +target_sources(nesmik PRIVATE detection.cpp) diff --git a/src/backends/detection/detection.cpp b/src/backends/detection/detection.cpp index 2be1c928bd6b6b6cfc4b724085277ab4bbf988d4..33fc284cf0fd78ce2c51c198ccc563ccbe1a5738 100644 --- a/src/backends/detection/detection.cpp +++ b/src/backends/detection/detection.cpp @@ -56,11 +56,6 @@ double getTimeStamp() { #endif } -DetectionStrategy::DetectionStrategy() : mpi_helper_{} { - parallelism_descriptor_ = {.mpi_descriptor_ = MPIDescriptor::Aware, - .thread_descriptor_ = ThreadDescriptor::Supported}; -} - void DetectionStrategy::Init() noexcept {} void DetectionStrategy::RegionStart( diff --git a/src/backends/detection/detection.hpp b/src/backends/detection/detection.hpp index ed7f499f9acd598a33a89456939dc0ca9782ce1c..c25efd83d5a1e3429c47edfb0220675d3300b0fb 100644 --- a/src/backends/detection/detection.hpp +++ b/src/backends/detection/detection.hpp @@ -45,13 +45,34 @@ class DetectionStrategy : public ProperlyNestedAnnotationStrategy { bool has_errors_ = false; public: - DetectionStrategy(); - inline static const std::string name = "Detection"; + DetectionStrategy() : mpi_helper_{} {} + + inline static const struct StrategyDescription description = { + .name = "Detection", + .description = + "automatically detect the nesting mode (ProperlyNested or " + "NotProperlyNested) and find which regions break the ProperlyNested " + "if aplicable.", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::Aware, + .thread_descriptor = ThreadDescriptor::Supported}}; + virtual void RegionStart( const ProperlyNestedRegionInformation& region) noexcept override; virtual void RegionStopLast( const ProperlyNestedRegionInformation& region) noexcept override; virtual void Init() noexcept; virtual void Finalize() noexcept; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + storage.add(verbose_mode_); + return storage; + } }; #endif // NESMIK_DETECTION_H diff --git a/src/backends/dlb_talp/CMakeLists.txt b/src/backends/dlb_talp/CMakeLists.txt index 56f83f67ae3d5de9addaaf5ddf277b4dc2ae27cd..04b652a429c558c47a1e708668b4b6a6881bf056 100644 --- a/src/backends/dlb_talp/CMakeLists.txt +++ b/src/backends/dlb_talp/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE dlb_talp.cpp) +if (ENABLE_DLB) + target_sources(nesmik_dlb PRIVATE dlb_talp.cpp) +endif() + +target_sources(nesmik_dlb_stripped PRIVATE dlb_talp.cpp) diff --git a/src/backends/dlb_talp/dlb_talp.cpp b/src/backends/dlb_talp/dlb_talp.cpp index 3af603b3e8b0dc18714a27dded033345aab2d016..d6eb62c45b99dc828f6334ad03d49da59b260640 100644 --- a/src/backends/dlb_talp/dlb_talp.cpp +++ b/src/backends/dlb_talp/dlb_talp.cpp @@ -3,30 +3,14 @@ #include #include -#include "dlb.h" -#include "dlb_talp.h" - -DLBTalpStrategy::DLBTalpStrategy() { - parallelism_descriptor_ = { - .mpi_descriptor_ = MPIDescriptor::DontCare, - .thread_descriptor_ = ThreadDescriptor::Supported // Even though it makes - // no semantical sense - }; -} - void DLBTalpStrategy::RegionStart( const NotProperlyNestedRegionInformation ®ion) noexcept { - // we have to create a small std::string thing because we cannot assume that - // the string_view passed is properly null terminated - auto handle = DLB_MonitoringRegionRegister(std::string(region.name).c_str()); - DLB_MonitoringRegionStart(handle); + dlb_wrapper_.StartMonitoringRegion(std::string(region.name)); } void DLBTalpStrategy::RegionStop( - const NotProperlyNestedRegionInformation ®ion) noexcept { - auto handle = DLB_MonitoringRegionRegister(std::string(region.name).c_str()); - DLB_MonitoringRegionStop(handle); -} + const NotProperlyNestedRegionInformation ®ion) noexcept {} + +void DLBTalpStrategy::Init() noexcept { dlb_wrapper_.Init(0, "--talp"); } -void DLBTalpStrategy::Init() noexcept { DLB_Init(0, NULL, "--talp"); } -void DLBTalpStrategy::Finalize() noexcept { DLB_Finalize(); } +void DLBTalpStrategy::Finalize() noexcept { dlb_wrapper_.Finalize(); } diff --git a/src/backends/dlb_talp/dlb_talp.hpp b/src/backends/dlb_talp/dlb_talp.hpp index d6a4abdbf0f9d1ff4b9353a712f1c166661d1da6..ca743a9c1816ce9cce9c703089c89d639dc2634e 100644 --- a/src/backends/dlb_talp/dlb_talp.hpp +++ b/src/backends/dlb_talp/dlb_talp.hpp @@ -1,17 +1,40 @@ #ifndef NESMIK_DLB_H #define NESMIK_DLB_H +#include #include class DLBTalpStrategy : public NotProperlyNestedAnnotationStrategy { public: - DLBTalpStrategy(); - inline static const std::string name = "TALP"; + DLBWrapper dlb_wrapper_; + + DLBTalpStrategy() {} + + inline static const struct StrategyDescription description = { + .name = "TALP", + .description = "a backend that directly wraps the TALP API.", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::DontCare, + .thread_descriptor = + ThreadDescriptor::Supported // Even though it makes + // no semantical sense + }}; + virtual void RegionStart( const NotProperlyNestedRegionInformation ®ion) noexcept override; virtual void RegionStop( const NotProperlyNestedRegionInformation ®ion) noexcept override; virtual void Init() noexcept; virtual void Finalize() noexcept; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + return storage; + } }; #endif // NESMIK_DLB_H diff --git a/src/backends/dlb_talp_tree/CMakeLists.txt b/src/backends/dlb_talp_tree/CMakeLists.txt index fc44ff5ab47f2d21d7646835b9919ac1192cedbb..7622fe2185a288a1d21575a82effcd33ae8dde86 100644 --- a/src/backends/dlb_talp_tree/CMakeLists.txt +++ b/src/backends/dlb_talp_tree/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE dlb_talp_tree.cpp dlb_talp_tree_json_serializer.cpp dlb_talp_tree_ascii_serializer.cpp) +if (ENABLE_DLB) + target_sources(nesmik_dlb PRIVATE dlb_talp_tree.cpp dlb_talp_tree_json_serializer.cpp dlb_talp_tree_ascii_serializer.cpp) +endif() + +target_sources(nesmik_dlb_stripped PRIVATE dlb_talp_tree.cpp dlb_talp_tree_json_serializer.cpp dlb_talp_tree_ascii_serializer.cpp) diff --git a/src/backends/dlb_talp_tree/dlb_talp_tree.cpp b/src/backends/dlb_talp_tree/dlb_talp_tree.cpp index 50802a7a27eff0ac652c56a4f4d1e525599784e0..43b5026e4fed1c391cc9a8894f3f38701aee41e8 100644 --- a/src/backends/dlb_talp_tree/dlb_talp_tree.cpp +++ b/src/backends/dlb_talp_tree/dlb_talp_tree.cpp @@ -10,8 +10,8 @@ #include #include -#include "dlb.h" -#include "dlb_talp.h" +// #include "dlb.h" +// #include "dlb_talp.h" #include "dlb_talp_tree_ascii_serializer.hpp" #include "dlb_talp_tree_json_serializer.hpp" @@ -23,12 +23,6 @@ using json = nlohmann::json; -DLBTalpTreeStrategy::DLBTalpTreeStrategy() : mpi_helper_{} { - parallelism_descriptor_ = { - .mpi_descriptor_ = MPIDescriptor::Aware, - .thread_descriptor_ = ThreadDescriptor::Unsupported}; -} - std::string region_hash_to_string(std::size_t region_hash) { // We need to cast the std::size_t before conversion to get // decimal representation in the string. @@ -167,8 +161,8 @@ void DLBTalpTreeStrategy::Finalize() noexcept { name = top_region_; } - auto handle = DLB_MonitoringRegionRegister(name.c_str()); - int dlb_error = DLB_TALP_CollectPOPMetrics(handle, ®ion.pop_metrics); + int dlb_error = talp_profiling_strategy_.dlb_wrapper_.CollectPOPMetrics( + name, ®ion.pop_metrics); if (dlb_error != DLB_SUCCESS) { // Warn about the error trying to close region name with hash diff --git a/src/backends/dlb_talp_tree/dlb_talp_tree.hpp b/src/backends/dlb_talp_tree/dlb_talp_tree.hpp index 8cc923d4b917201795c5dbe001ed077cad690fce..46aaf05825b95186acf31f76a46e020950156a9f 100644 --- a/src/backends/dlb_talp_tree/dlb_talp_tree.hpp +++ b/src/backends/dlb_talp_tree/dlb_talp_tree.hpp @@ -8,9 +8,10 @@ #include #include -#include "../dlb_talp/dlb_talp.hpp" -#include "dlb.h" -#include "dlb_talp.h" +// #include "dlb.h" +// #include "dlb_talp.h" +#include + #include "strategies.hpp" struct TalpRegionNode { @@ -41,7 +42,7 @@ class DLBTalpTreeStrategy : public ProperlyNestedAnnotationStrategy { inline static const bool def_enable_json_ = true; EnvironmentVariable env_enable_json_ = EnvironmentVariable( - "JSON_OUTPUT", "Enables output to a JSON file.", false); + "JSON_OUTPUT", "Enables output to a JSON file. (default: on)", false); inline static const bool def_enable_ascii_ = false; EnvironmentVariable env_enable_ascii_ = EnvironmentVariable( @@ -50,14 +51,36 @@ class DLBTalpTreeStrategy : public ProperlyNestedAnnotationStrategy { false); public: - DLBTalpTreeStrategy(); - inline static const std::string name = "TALP::Tree"; + DLBTalpTreeStrategy() : mpi_helper_{} {} + + inline static const struct StrategyDescription description = { + .name = "TALP::Tree", + .description = + "creates TALP regions differantiating regions by \"callpath\", and " + "reporting the metrics values as well as the region hierarchy.", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::Aware, + .thread_descriptor = ThreadDescriptor::Unsupported}}; + void RegionStart( const ProperlyNestedRegionInformation ®ion) noexcept override; void RegionStopLast( const ProperlyNestedRegionInformation ®ion) noexcept override; virtual void Init() noexcept; virtual void Finalize() noexcept; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + storage.add(env_enable_ascii_); + storage.add(env_enable_json_); + storage.add(env_json_file_name_); + return storage; + } }; #endif // DLB_TALP_TREE_H diff --git a/src/backends/dlb_talp_tree/dlb_talp_tree_ascii_serializer.cpp b/src/backends/dlb_talp_tree/dlb_talp_tree_ascii_serializer.cpp index 10267e6e204f862d7c16e3053572244830cd61e5..1e68f31e9917c8ad3ade011853c8b2e9e913ce5f 100644 --- a/src/backends/dlb_talp_tree/dlb_talp_tree_ascii_serializer.cpp +++ b/src/backends/dlb_talp_tree/dlb_talp_tree_ascii_serializer.cpp @@ -20,6 +20,7 @@ struct RegionStackEntry { }; std::size_t DLBTalpTreeASCIISerializer::compute_tree_lines() { +#if defined(ENABLE_DLB) std::stack regions_stack; regions_stack.push({.hash = this->top_region, .level = 0, .tree_lines = ""}); @@ -65,14 +66,15 @@ std::size_t DLBTalpTreeASCIISerializer::compute_tree_lines() { tree_lines.length()); } return max_width; +#endif } std::string DLBTalpTreeASCIISerializer::generate_tree_view(int name_width) { + std::stringstream region_stream; +#if defined(ENABLE_DLB) std::stack regions_stack; regions_stack.push(this->top_region); - std::stringstream region_stream; - while (!regions_stack.empty()) { std::size_t current_region_hash = regions_stack.top(); regions_stack.pop(); @@ -117,6 +119,7 @@ std::string DLBTalpTreeASCIISerializer::generate_tree_view(int name_width) { region_stream << std::endl; } +#endif return region_stream.str(); } diff --git a/src/backends/dlb_talp_tree/dlb_talp_tree_json_serializer.cpp b/src/backends/dlb_talp_tree/dlb_talp_tree_json_serializer.cpp index 89191f907ca1eadbba641445f2708d91c2d2f646..8c653de0dc02650783611c4c6223e026e2959f14 100644 --- a/src/backends/dlb_talp_tree/dlb_talp_tree_json_serializer.cpp +++ b/src/backends/dlb_talp_tree/dlb_talp_tree_json_serializer.cpp @@ -13,6 +13,7 @@ DLBTalpTreeJSONSerializer::DLBTalpTreeJSONSerializer( void treeToJSON(const TalpRegionNode& node, json& talp_json, std::map const& regions) { +#if defined(ENABLE_DLB) talp_json["regionName"] = node.name; talp_json["metrics"] = { {"elapsedTime", node.pop_metrics.elapsed_time}, @@ -38,6 +39,7 @@ void treeToJSON(const TalpRegionNode& node, json& talp_json, treeToJSON(regions.at(child), childJSON, regions); talp_json["subregions"].push_back(childJSON); } +#endif } std::string DLBTalpTreeJSONSerializer::dump() { diff --git a/src/backends/extrae_partial_tracer/CMakeLists.txt b/src/backends/extrae_partial_tracer/CMakeLists.txt index dff45e3648439f847f603d8f4e61e1a1e8a32b73..104063fdeacd8443b9624bb74343ec539d10331f 100644 --- a/src/backends/extrae_partial_tracer/CMakeLists.txt +++ b/src/backends/extrae_partial_tracer/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE extrae_partial_tracer.cpp) +if (ENABLE_EXTRAE) + target_sources(nesmik_extrae PRIVATE extrae_partial_tracer.cpp) +endif() + +target_sources(nesmik_extrae_stripped PRIVATE extrae_partial_tracer.cpp) diff --git a/src/backends/extrae_partial_tracer/extrae_partial_tracer.cpp b/src/backends/extrae_partial_tracer/extrae_partial_tracer.cpp index b59040c59a40c8c91ebb5ad399ebcba6aeb6f5c3..1f1384e123c38584df0e312517a639c200f0075e 100644 --- a/src/backends/extrae_partial_tracer/extrae_partial_tracer.cpp +++ b/src/backends/extrae_partial_tracer/extrae_partial_tracer.cpp @@ -2,29 +2,20 @@ #include #include -#include #include extern "C" { #include } #include -ExtraePartialTracer::ExtraePartialTracer() - : mpi_helper_{}, extrae_wrapper_{state_type_} { - parallelism_descriptor_ = { - .mpi_descriptor_ = MPIDescriptor::Aware, - .thread_descriptor_ = ThreadDescriptor::Unsupported}; - - type_stack_strategy_ = std::make_unique(); - extrae_wrapper_.RegisterTypeWithDescription(type_description_, state_type_); -} - void ExtraePartialTracer::shutdown(bool annotate) noexcept { if (debug_output_.getValue().value_or(false) && mpi_helper_.IsRankNumber(0)) { std::cout << "neSmiK Partial Tracer: Shutting down" << std::endl; } if (annotate) extrae_wrapper_.StopWithTypeAndRegionName(state_type_, "ON"); +#if defined(ENABLE_EXTRAE) Extrae_shutdown(); +#endif is_shutdown_ = true; } @@ -32,9 +23,11 @@ void ExtraePartialTracer::start(bool annotate) noexcept { if (debug_output_.getValue().value_or(false) && mpi_helper_.IsRankNumber(0)) { std::cout << "neSmiK Partial Tracer: Starting up" << std::endl; } +#if defined(ENABLE_EXTRAE) Extrae_restart(); if (annotate) extrae_wrapper_.StartWithTypeAndRegionName(state_type_, "ON"); is_shutdown_ = false; +#endif } void ExtraePartialTracer::Init() noexcept { diff --git a/src/backends/extrae_partial_tracer/extrae_partial_tracer.hpp b/src/backends/extrae_partial_tracer/extrae_partial_tracer.hpp index 5b7d74d1c90982ebfc0b14b9ba3707ed46aaaf0c..dc51e4c4340a4d2b38cd9f51c58001510add6498 100644 --- a/src/backends/extrae_partial_tracer/extrae_partial_tracer.hpp +++ b/src/backends/extrae_partial_tracer/extrae_partial_tracer.hpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -35,8 +36,8 @@ class ExtraePartialTracer : public ProperlyNestedAnnotationStrategy { "should stop", true); - EnvironmentVariable debug_output_ = - EnvironmentVariable("PARTIAL_TRACER_DEBUG", "DEBUG output", false); + EnvironmentVariable debug_output_ = EnvironmentVariable( + "PARTIAL_TRACER_DEBUG", "prints debug information", false); EnvironmentVariable write_config_file_ = EnvironmentVariable( "EXTRAE_WRITE_CONFIG_FILE", @@ -61,8 +62,17 @@ class ExtraePartialTracer : public ProperlyNestedAnnotationStrategy { const std::string type_description_ = "Extrae::PartialTracer State"; public: - ExtraePartialTracer(); - inline static const std::string name = "Extrae::PartialTracer"; + ExtraePartialTracer() : mpi_helper_{}, extrae_wrapper_{state_type_} { + type_stack_strategy_ = std::make_unique(); + extrae_wrapper_.RegisterTypeWithDescription(type_description_, state_type_); + } + + inline static const struct StrategyDescription description = { + .name = "Extrae::PartialTracer", + .description = "TODO", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::Aware, + .thread_descriptor = ThreadDescriptor::Unsupported}}; virtual void RegionStart( const ProperlyNestedRegionInformation ®ion) noexcept override; @@ -70,4 +80,19 @@ class ExtraePartialTracer : public ProperlyNestedAnnotationStrategy { const ProperlyNestedRegionInformation ®ion) noexcept override; virtual void Init() noexcept override; virtual void Finalize() noexcept override; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + storage.add(region_names_env_); + storage.add(regions_start_at_env_); + storage.add(regions_stop_at_env_); + storage.add(debug_output_); + storage.add(write_config_file_); + return storage; + } }; diff --git a/src/backends/extrae_type_stack/CMakeLists.txt b/src/backends/extrae_type_stack/CMakeLists.txt index 319ef9c27d5508c01cc65f0459e4f3ff4b222c0a..63dd356168a044909cf46525bf11511b03b312b3 100644 --- a/src/backends/extrae_type_stack/CMakeLists.txt +++ b/src/backends/extrae_type_stack/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE extrae_type_stack.cpp) +if (ENABLE_EXTRAE) + target_sources(nesmik_extrae PRIVATE extrae_type_stack.cpp) +endif() + +target_sources(nesmik_extrae_stripped PRIVATE extrae_type_stack.cpp) diff --git a/src/backends/extrae_type_stack/extrae_type_stack.cpp b/src/backends/extrae_type_stack/extrae_type_stack.cpp index 7b6117779a6b1c0c467be3a8dcc79c1593413bf3..4352d861d6da1a1db73f3208b6de3b885fd68bc4 100644 --- a/src/backends/extrae_type_stack/extrae_type_stack.cpp +++ b/src/backends/extrae_type_stack/extrae_type_stack.cpp @@ -10,21 +10,16 @@ #include #include +#if defined(EXTRAE_ENABLED) extern "C" { #include } +#endif inline std::string getLevelString(const std::size_t level) { return "Level: " + std::to_string(level); } -ExtraeTypeStackStrategy::ExtraeTypeStackStrategy() - : mpi_helper_{}, extrae_wrapper_{base_type_} { - parallelism_descriptor_ = { - .mpi_descriptor_ = MPIDescriptor::Aware, - .thread_descriptor_ = ThreadDescriptor::Unsupported}; -} - void ExtraeTypeStackStrategy::Init() noexcept { // initialize the stack levels up to MAX_STACK_LEVELS for (std::size_t i = 0; i < MAX_STACK_LEVELS; i++) { diff --git a/src/backends/extrae_type_stack/extrae_type_stack.hpp b/src/backends/extrae_type_stack/extrae_type_stack.hpp index c8ccf254ee1e8e339a145ec4bbd05e8de8aa0d6f..5147043ce46e053ccedfb7c7bb95d17ddbb1e903 100644 --- a/src/backends/extrae_type_stack/extrae_type_stack.hpp +++ b/src/backends/extrae_type_stack/extrae_type_stack.hpp @@ -18,7 +18,8 @@ class ExtraeTypeStackStrategy : public ProperlyNestedAnnotationStrategy { EnvironmentVariable write_config_file_ = EnvironmentVariable( "EXTRAE_WRITE_CONFIG_FILE", - "Write corresponding Paraver .cfg file if set to True", false); + "Write corresponding Paraver .cfg file when enabled. (default: off)", + false); MPIHelper mpi_helper_; ExtraeWrapper extrae_wrapper_; @@ -28,8 +29,14 @@ class ExtraeTypeStackStrategy : public ProperlyNestedAnnotationStrategy { std::size_t max_stack_size{0}; public: - ExtraeTypeStackStrategy(); - inline static const std::string name = "Extrae::TypeStack"; + ExtraeTypeStackStrategy() : mpi_helper_{}, extrae_wrapper_{base_type_} {} + + inline static const struct StrategyDescription description = { + .name = "Extrae::TypeStack", + .description = "TODO", + .parallelism_descriptor = { + .mpi_descriptor = MPIDescriptor::Aware, + .thread_descriptor = ThreadDescriptor::Unsupported}}; virtual void RegionStart( const ProperlyNestedRegionInformation ®ion) noexcept override; @@ -37,5 +44,16 @@ class ExtraeTypeStackStrategy : public ProperlyNestedAnnotationStrategy { const ProperlyNestedRegionInformation ®ion) noexcept override; virtual void Init() noexcept override; virtual void Finalize() noexcept override; + + struct StrategyDescription getDescription() const noexcept override { + return description; + } + + EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept override { + EnvironmentVariableStorage storage; + storage.add(write_config_file_); + return storage; + } }; #endif // NESMIK_EXTRAE_TYPE_STACK_HPP diff --git a/src/backends/wrappers/CMakeLists.txt b/src/backends/wrappers/CMakeLists.txt index 9f5951d6c754021148f425cdc53c6038ec84ac80..a1258893ab06ce57609d7fd07c7f8dbc5b6ecf08 100644 --- a/src/backends/wrappers/CMakeLists.txt +++ b/src/backends/wrappers/CMakeLists.txt @@ -1,7 +1,2 @@ -if(ENABLE_DLB) - add_subdirectory(dlb) -endif() - -if(ENABLE_EXTRAE) - add_subdirectory(extrae) -endif() +add_subdirectory(dlb) +add_subdirectory(extrae) diff --git a/src/backends/wrappers/dlb/CMakeLists.txt b/src/backends/wrappers/dlb/CMakeLists.txt index 3bb584794a57516084d7d20af856288c449c2b16..1bebbfe4b2c138434245c64c35dd9f691b0aedd7 100644 --- a/src/backends/wrappers/dlb/CMakeLists.txt +++ b/src/backends/wrappers/dlb/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE dlb_wrapper.cpp) +if(ENABLE_DLB) + target_sources(nesmik_dlb PRIVATE dlb_wrapper.cpp) +endif() + +target_sources(nesmik_dlb_stripped PRIVATE dlb_wrapper.cpp) diff --git a/src/backends/wrappers/dlb/dlb_wrapper.cpp b/src/backends/wrappers/dlb/dlb_wrapper.cpp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..baf56c7e450ce8e2eaf82c701e2af1e6cf9c55c4 100644 --- a/src/backends/wrappers/dlb/dlb_wrapper.cpp +++ b/src/backends/wrappers/dlb/dlb_wrapper.cpp @@ -0,0 +1,38 @@ + +#include "dlb_wrapper.hpp" + +void DLBWrapper::Init(int ncpus, std::string dlb_args) { +#if defined(ENABLE_DLB) + DLB_Init(ncpus, NULL, dlb_args.c_str()); +#endif +} + +void DLBWrapper::Finalize() { +#if defined(ENABLE_DLB) + DLB_Finalize(); +#endif +} + +void DLBWrapper::StartMonitoringRegion(std::string region_name) { +#if defined(ENABLE_DLB) + auto handle = DLB_MonitoringRegionRegister(region_name.c_str()); + DLB_MonitoringRegionStart(handle); +#endif +} + +void DLBWrapper::StopMonitoringRegion(std::string region_name) { +#if defined(ENABLE_DLB) + auto handle = DLB_MonitoringRegionRegister(region_name.c_str()); + DLB_MonitoringRegionStop(handle); +#endif +} + +int DLBWrapper::CollectPOPMetrics(std::string region_name, + dlb_pop_metrics_t *metrics) { +#if defined(ENABLE_DLB) + auto handle = DLB_MonitoringRegionRegister(region_name.c_str()); + return DLB_TALP_CollectPOPMetrics(handle, metrics); +#else + return 0; +#endif +} diff --git a/src/backends/wrappers/dlb/dlb_wrapper.hpp b/src/backends/wrappers/dlb/dlb_wrapper.hpp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..81f326e47c40806fb8a462c1f75e34aa447a41b1 100644 --- a/src/backends/wrappers/dlb/dlb_wrapper.hpp +++ b/src/backends/wrappers/dlb/dlb_wrapper.hpp @@ -0,0 +1,25 @@ +#ifndef NESMIK_DLB_WRAPPER_H +#define NESMIK_DLB_WRAPPER_H + +#include + +#if defined(ENABLE_DLB) +#include "dlb.h" +#include "dlb_talp.h" +#else +typedef void *dlb_pop_metrics_t; +#define DLB_SUCCESS 0 +#endif + +class DLBWrapper { + public: + void Init(int ncpus, std::string dlb_args); + void Finalize(); + + void StartMonitoringRegion(std::string region_name); + void StopMonitoringRegion(std::string region_name); + + int CollectPOPMetrics(std::string region_name, dlb_pop_metrics_t *metrics); +}; + +#endif /* NESMIK_DLB_WRAPPER_H */ diff --git a/src/backends/wrappers/extrae/CMakeLists.txt b/src/backends/wrappers/extrae/CMakeLists.txt index ba3bc1114ee4223854009f9a50efcda6f6040623..4db7bba15abba6f7d04f21adf7d55acb0344c513 100644 --- a/src/backends/wrappers/extrae/CMakeLists.txt +++ b/src/backends/wrappers/extrae/CMakeLists.txt @@ -1 +1,5 @@ -target_sources(nesmik PRIVATE extrae_wrapper.cpp paraver_config.cpp) +if(ENABLE_EXTRAE) + target_sources(nesmik_extrae PRIVATE extrae_wrapper.cpp paraver_config.cpp) +endif() + +target_sources(nesmik_extrae_stripped PRIVATE extrae_wrapper.cpp paraver_config.cpp) diff --git a/src/backends/wrappers/extrae/extrae_wrapper.cpp b/src/backends/wrappers/extrae/extrae_wrapper.cpp index 1eab24e62f4b16c4a2a71c30aa1018818ae3af68..a8283a2f1d01b69780ccc199bb54afe54e5ae70b 100644 --- a/src/backends/wrappers/extrae/extrae_wrapper.cpp +++ b/src/backends/wrappers/extrae/extrae_wrapper.cpp @@ -20,6 +20,7 @@ extern "C" { ExtraeWrapper::ExtraeWrapper(actual_extrae_type base_type) : base_type_(base_type) { +#if defined(ENABLE_EXTRAE) auto isInitializedVal = Extrae_is_initialized(); if (isInitializedVal == 0) { // Extrae is not initialized yet see @@ -28,10 +29,12 @@ ExtraeWrapper::ExtraeWrapper(actual_extrae_type base_type) did_init_extrae_ = true; std::cout << "neSmiK forced to Initialize extrae" << std::endl; } +#endif } actual_extrae_value ExtraeWrapper::getValueByName(actual_extrae_type type, const std::string &name) { +#if defined(ENABLE_EXTRAE) value_map_t &value_map = string_to_value_; if (value_map.count(name) > 0) { return value_map[name]; @@ -48,45 +51,57 @@ actual_extrae_value ExtraeWrapper::getValueByName(actual_extrae_type type, value_map[name] = downcasted_hash; return downcasted_hash; } +#endif } void ExtraeWrapper::RegisterTypeWithDescription( const std::string &type_description, actual_extrae_type type) { +#if defined(ENABLE_EXTRAE) type_map_[type_description] = type; +#endif } void ExtraeWrapper::StartWithTypeAndRegionName(actual_extrae_type type, const std::string &value_str) { +#if defined(ENABLE_EXTRAE) const auto value = getValueByName(type, value_str); // write it in type specific map type_to_value_map_[type][value_str] = value; Extrae_eventandcounters(static_cast(type), static_cast(value)); +#endif } void ExtraeWrapper::StopWithTypeAndRegionName(actual_extrae_type type, const std::string &value_str) { +#if defined(ENABLE_EXTRAE) Extrae_eventandcounters(static_cast(type), 0); +#endif } void ExtraeWrapper::StopWithTypeNameAndRegionName( const std::string &type_description, const std::string &value_str) { +#if defined(ENABLE_EXTRAE) // if this assertion fails, the type with that description has not been // registered before and not started. assert(type_map_.count(type_description) > 0); return StopWithTypeAndRegionName(type_map_[type_description], value_str); +#endif } void ExtraeWrapper::StartWithTypeNameAndRegionName( const std::string &type_description, const std::string &value_str) { +#if defined(ENABLE_EXTRAE) if (type_map_.count(type_description) == 0) { const auto new_type = type_map_.size(); type_map_[type_description] = base_type_ + new_type; } return StartWithTypeAndRegionName(type_map_[type_description], value_str); +#endif } void ExtraeWrapper::Finalize() { - // for ever type define the event types: +#if defined(ENABLE_EXTRAE) + // now for every type define the event types: for (const auto &[description, type_from_map] : type_map_) { // For every type registered: extrae_type_t type = static_cast(type_from_map); @@ -127,9 +142,11 @@ void ExtraeWrapper::Finalize() { // Finalize it Extrae_fini(); } +#endif } std::string ExtraeWrapper::getParaverConfig(ExtraeParaverConfig config) { +#if defined(ENABLE_EXTRAE) ParaverConfig paraver_config(config.description); // create arrays @@ -160,4 +177,5 @@ std::string ExtraeWrapper::getParaverConfig(ExtraeParaverConfig config) { paraver_config.addTimeline(window); return paraver_config.getString(); +#endif } diff --git a/src/delegator.cpp b/src/delegator.cpp index d9e8e9c187fd5a578c3966952b3fd92476a17514..02e7f383f8ae7a42056d8b65a29700fb46053e84 100644 --- a/src/delegator.cpp +++ b/src/delegator.cpp @@ -24,29 +24,29 @@ void Delegator::InitNonProperlyNestedBackends(const std::string &backend) { // check if backend is supplied - if (backend.compare(NPNDefault::name) == 0) { + if (backend.compare(NPNDefault::description.name) == 0) { npn_annotation_strategy_ = std::make_unique(); } #ifdef ENABLE_DLB - else if (backend.compare(DLBTalpStrategy::name) == 0) { + else if (backend.compare(DLBTalpStrategy::description.name) == 0) { npn_annotation_strategy_ = std::make_unique(); } #endif } void Delegator::TryInitProperlyNestedBackend(const std::string &backend) { - if (backend.compare(DetectionStrategy::name) == 0) { + if (backend.compare(DetectionStrategy::description.name) == 0) { pn_annotation_strategy_ = std::make_unique(); } #ifdef ENABLE_EXTRAE - else if (backend.compare(ExtraeTypeStackStrategy::name) == 0) { + else if (backend.compare(ExtraeTypeStackStrategy::description.name) == 0) { pn_annotation_strategy_ = std::make_unique(); - } else if (backend.compare(ExtraePartialTracer::name) == 0) { + } else if (backend.compare(ExtraePartialTracer::description.name) == 0) { pn_annotation_strategy_ = std::make_unique(); } #endif #ifdef ENABLE_DLB - else if (backend.compare(DLBTalpTreeStrategy::name) == 0) { + else if (backend.compare(DLBTalpTreeStrategy::description.name) == 0) { pn_annotation_strategy_ = std::make_unique(); } #endif @@ -54,12 +54,12 @@ void Delegator::TryInitProperlyNestedBackend(const std::string &backend) { const std::vector Delegator::available_backends = { #ifdef ENABLE_DLB - DLBTalpTreeStrategy::name, - DLBTalpStrategy::name, + DLBTalpTreeStrategy::description.name, + DLBTalpStrategy::description.name, #endif #ifdef ENABLE_EXTRAE - ExtraeTypeStackStrategy::name, - ExtraePartialTracer::name, + ExtraeTypeStackStrategy::description.name, + ExtraePartialTracer::description.name, #endif "Default", "Detection"}; diff --git a/src/nesmik_app.cpp b/src/nesmik_app.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d99267bbd611af46004eaf2a364adcec58aeade5 --- /dev/null +++ b/src/nesmik_app.cpp @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include +#include +#include + +void printWithIndentation(int level, std::string text) { + std::string indentation = std::string(level * 4, ' '); + + std::stringstream ss(text); + std::string word; + + bool new_line = true; + int max_width = 100; + int cur_width = 0; + while (ss >> word) { + // Check if word fits + if (cur_width + word.size() > max_width) { + std::cout << std::endl; // Break the line + cur_width = 0; + new_line = true; + } + + if (new_line) { + new_line = false; + + std::cout << indentation; // Add the indentation + cur_width += indentation.size(); + // If the word still does not fit, we have a problem + if (cur_width + word.size() > max_width) { + std::cout << std::endl << std::endl; + std::cout << "Fatal: Cannot fit text with this level of indentation. " + "Next word was: " + << word << std::endl + << std::endl; + } + } + + // Add the word + std::cout << word << ' '; + cur_width += word.size() + 1; + } + std::cout << std::endl; +} + +void printStrategyUsage(struct StrategyDescription description, + EnvironmentVariableStorage variables) { + printWithIndentation(1, description.name); + std::cout << std::endl; + + printWithIndentation(2, description.description); + std::cout << std::endl; + + printWithIndentation(2, "FEATURES"); + printWithIndentation( + 3, "MPI:\t" + MPIDescriptorUsage( + description.parallelism_descriptor.mpi_descriptor) + .getName()); + printWithIndentation( + 3, + "Threading:\t" + ThreadDescriptorUsage( + description.parallelism_descriptor.thread_descriptor) + .getName()); + std::cout << std::endl; + + if (variables.getSize() > 0) { + printWithIndentation(2, "ENVIRONMENT VARIABLES"); + std::cout << std::endl; + + for (auto var_desc : variables) { + std::string indicator = ""; + if (var_desc.required_) indicator = "(required)"; + + printWithIndentation( + 2, "NESMIK_" + var_desc.variable_name_ + " " + indicator); + printWithIndentation(3, var_desc.description_); + std::cout << std::endl; + } + } +} + +void printStrategyTemplate(struct StrategyDescription description, + EnvironmentVariableStorage variables) { + std::cout << "# This is an autogenerated template for the " + << description.name << " backend." << std::endl; + std::cout << "# Optional variables are commented." << std::endl; + std::cout << std::endl; + std::cout << "export NESMIK_BACKEND=\"" << description.name << "\"" + << std::endl; + std::cout << std::endl; + + if (variables.getSize() > 0) { + for (auto var_desc : variables) { + std::cout << "# " << var_desc.description_ << std::endl; + + std::string required = "# "; + if (var_desc.required_) { + required = ""; + } + std::cout << required << "export NESMIK_" << var_desc.variable_name_ + << "=" << std::endl; + std::cout << std::endl; + } + } +} + +void showUsages() { + std::cout << std::endl; + printWithIndentation( + 0, + "To use the neSmiK annotations of your code set the NESMIK_BACKEND " + "environment variable to the desired backend name. When this variable is " + "not set calls to the neSmiK API have no effect."); + std::cout << std::endl; + std::cout << std::endl; + printWithIndentation(0, + "Following you will find all the available backends " + "names, their description and usage guide."); + std::cout << std::endl; + std::cout << std::endl; + + { + DetectionStrategy strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } + + std::cout << std::endl + << "Following you will find backends that support both kinds of " + "annotations." + << std::endl; + + { + NPNDefault strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } + + { + DLBTalpStrategy strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } + + std::cout << "Following you will find backends that require ProperlyNested " + "annotation." + << std::endl; + + { + ExtraeTypeStackStrategy strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } + { + ExtraePartialTracer strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } + + { + DLBTalpTreeStrategy strategy; + printStrategyUsage(strategy.getDescription(), + strategy.getEnvironmentVariablesDescription()); + } +} + +int main() { + // Display the ussage. + // TODO: Add command line options to pick what ussage to print. + // Options are: + // - Print all the usage. (Done) + // - Print just a lies with all backends and their theseriptions. + // - Print the usage for one backend. + // - Print a template for just one backend. + // Example of how to print a template + // std::cout << std::endl; + // { + // ExtraePartialTracer strategy; + // printStrategyTemplate(strategy.getDescription(), + // strategy.getEnvironmentVariablesDescription()); + // } + // + // ------------------------ + // + // Print all the usage! + showUsages(); +} diff --git a/src/strategies.hpp b/src/strategies.hpp index e19425dd112cf42f7572694b4e09f05c03e89acb..a84c27a4dc9b7fcbdbee90122fa310012268945b 100644 --- a/src/strategies.hpp +++ b/src/strategies.hpp @@ -5,15 +5,44 @@ #include #include #include +#include /* Describes the Strategy behavior with respect to MPI. */ -enum class MPIDescriptor { - DontCare, // Strategy does not know and does not care - Aware, // Strategy knows about MPI and can use the PMPI Interface to do e.g. - // reductions. - Required // Strategy requires MPI (should be safeguareded by build options) +enum class MPIDescriptor { DontCare, Aware, Required }; + +class MPIDescriptorUsage { + public: + MPIDescriptor descriptor; + + MPIDescriptorUsage(MPIDescriptor descriptor) : descriptor(descriptor) {} + + std::string getName() const { + switch (descriptor) { + case MPIDescriptor::DontCare: + return "Don't care"; + case MPIDescriptor::Aware: + return "Aware"; + case MPIDescriptor::Required: + return "Required"; + } + return ""; + } + + std::string getDescription() const { + switch (descriptor) { + case MPIDescriptor::DontCare: + return "the strategy does not know if MPI is present but can support " + "it."; + case MPIDescriptor::Aware: + return "the strategy will know if MPI is present and when present " + "might enable features."; + case MPIDescriptor::Required: + return "the strategy requires MPI to be present."; + } + return ""; + } }; /* @@ -23,12 +52,40 @@ enum class MPIDescriptor { */ enum class ThreadDescriptor { Supported, Unsupported }; +class ThreadDescriptorUsage { + public: + ThreadDescriptor descriptor; + ThreadDescriptorUsage(ThreadDescriptor descriptor) : descriptor(descriptor) {} + + std::string getName() const { + switch (descriptor) { + case ThreadDescriptor::Supported: + return "Supported"; + case ThreadDescriptor::Unsupported: + return "Unsupported"; + } + return ""; + } + + std::string getDescription() const { + switch (descriptor) { + case ThreadDescriptor::Supported: + return "the strategy supports starting and closing regions from " + "multiple threads."; + case ThreadDescriptor::Unsupported: + return "the strategy does NOT supports starting and closing regions " + "from multiple threads."; + } + return ""; + } +}; + /* Bundles the above enums into a nice struct */ struct ParallelismDescriptor { - MPIDescriptor mpi_descriptor_ = MPIDescriptor::DontCare; - ThreadDescriptor thread_descriptor_ = ThreadDescriptor::Unsupported; + MPIDescriptor mpi_descriptor = MPIDescriptor::DontCare; + ThreadDescriptor thread_descriptor = ThreadDescriptor::Unsupported; }; struct ProperlyNestedRegionInformation { @@ -40,9 +97,16 @@ struct NotProperlyNestedRegionInformation { std::string_view name; }; +struct StrategyDescription { + std::string name; + std::string description; + ParallelismDescriptor parallelism_descriptor; +}; + // A backend implementing the Properly Nested Profiling class ProperlyNestedAnnotationStrategy { public: + ProperlyNestedAnnotationStrategy() {} virtual ~ProperlyNestedAnnotationStrategy() = default; virtual void Init() noexcept = 0; virtual void RegionStart( @@ -51,20 +115,25 @@ class ProperlyNestedAnnotationStrategy { const ProperlyNestedRegionInformation ®ion) noexcept = 0; virtual void Finalize() noexcept = 0; - ParallelismDescriptor parallelism_descriptor_; + virtual struct StrategyDescription getDescription() const noexcept = 0; + virtual EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept = 0; }; class NotProperlyNestedAnnotationStrategy { public: - virtual void Init() noexcept = 0; + NotProperlyNestedAnnotationStrategy() {} virtual ~NotProperlyNestedAnnotationStrategy() = default; + virtual void Init() noexcept = 0; virtual void RegionStart( const NotProperlyNestedRegionInformation ®ion) noexcept = 0; virtual void RegionStop( const NotProperlyNestedRegionInformation ®ion) noexcept = 0; virtual void Finalize() noexcept = 0; - ParallelismDescriptor parallelism_descriptor_; + virtual struct StrategyDescription getDescription() const noexcept = 0; + virtual EnvironmentVariableStorage getEnvironmentVariablesDescription() + const noexcept = 0; }; #endif // NESMIK_STRATEGY_HPP diff --git a/src/utils/environment_variable.hpp b/src/utils/environment_variable.hpp index 3f6f3f4ac81295343c9e4376f34aa3d0c42c5ad2..6e466c862497c1488d5f2110b117036f9ad6b82d 100644 --- a/src/utils/environment_variable.hpp +++ b/src/utils/environment_variable.hpp @@ -24,8 +24,22 @@ template <> std::optional> fromEnvString( const std::string &env_string); +class EnvironmentVariableDescription { + public: + std::string variable_name_; + std::string description_; + bool required_; + + EnvironmentVariableDescription() {} + EnvironmentVariableDescription(std::string variable_name, + std::string description, bool required) + : variable_name_(variable_name), + description_(description), + required_(required) {} +}; + template -class EnvironmentVariable { +class EnvironmentVariable : public EnvironmentVariableDescription { inline static std::string PREFIX = "NESMIK_"; public: @@ -34,7 +48,7 @@ class EnvironmentVariable { */ EnvironmentVariable(const std::string &variable_name, const std::string &description, bool required = false) - : variable_name_(variable_name), description_(description) { + : EnvironmentVariableDescription(variable_name, description, required) { const std::string variable_to_query = EnvironmentVariable::PREFIX + variable_name_; @@ -43,17 +57,17 @@ class EnvironmentVariable { if (env_string != nullptr) { value_ = fromEnvString(std::string(env_string)); } +#ifndef NESMIK_APP if (required && !value_.has_value()) { std::cout << "neSmiK Error: " << variable_to_query << " not set, restart application and set it" << std::endl; exit(1); } +#endif } EnvironmentVariable() = delete; private: - std::string variable_name_; - std::string description_; std::optional value_{std::nullopt}; public: @@ -64,4 +78,20 @@ class EnvironmentVariable { } }; +class EnvironmentVariableStorage { + private: + std::vector storage_; + + public: + EnvironmentVariableStorage() {} + void add(EnvironmentVariableDescription description) { + storage_.push_back(description); + } + + std::size_t getSize() const { return storage_.size(); } + + auto begin() { return storage_.begin(); } + auto end() { return storage_.end(); } +}; + #endif // NESMIK_ENVIROMENT_VARIABLE_HPP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2ac8198c4567274248a759f55dc1b64ffe0cf5ce..de6a7962d3789622c00de413a094c86dd756dfea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,44 +1,53 @@ + +# +# Add generic tests +# add_executable(TestCppLink cpp/TestCppLink.cpp) -target_link_libraries(TestCppLink nesmik::nesmik) +target_link_libraries(TestCppLink nesmik_lib) target_include_directories(TestCppLink PRIVATE ${NESMIK_PUBLIC_HEADERS}) -add_test(NAME TestCppLink - COMMAND TestCppLink) - +add_test(NAME TestCppLinkDefault COMMAND TestCppLink) +add_test(NAME TestCppLinkDetection COMMAND TestCppLink) add_executable(TestRegionStopLast cpp/TestRegionStopLast.cpp) -target_link_libraries(TestRegionStopLast nesmik::nesmik) +target_link_libraries(TestRegionStopLast nesmik_lib) target_include_directories(TestRegionStopLast PRIVATE ${NESMIK_PUBLIC_HEADERS}) add_test(NAME TestRegionStopLast COMMAND TestRegionStopLast) +add_executable(TestCppNotNested cpp/TestCppNotNested.cpp) +target_link_libraries(TestCppNotNested nesmik_lib) +target_include_directories(TestCppNotNested + PRIVATE ${NESMIK_PUBLIC_HEADERS}) +add_test(NAME TestCppLinkNotNested COMMAND TestCppNotNested) if(ENABLE_DLB) add_executable(TestCppDLB cpp/TestCppDLB.cpp) -target_link_libraries(TestCppDLB nesmik::nesmik) +target_link_libraries(TestCppDLB nesmik_lib) target_include_directories(TestCppDLB PRIVATE ${NESMIK_PUBLIC_HEADERS}) add_test(NAME TestCppDLB - COMMAND TestCppDLB) + COMMAND TestCppDLB) + add_executable(TestCppTalpTree cpp/TestCppTalpTree.cpp) -target_link_libraries(TestCppTalpTree nesmik::nesmik) +target_link_libraries(TestCppTalpTree nesmik_lib) target_include_directories(TestCppTalpTree PRIVATE ${NESMIK_PUBLIC_HEADERS}) add_test(NAME TestCppTalpTree - COMMAND TestCppTalpTree) + COMMAND TestCppTalpTree) endif() if(WITH_MPI AND WITH_MPI_TESTS) add_executable(TestCppTalpTreeMPI cpp/TestCppTalpTreeMPI.cpp) - target_link_libraries(TestCppTalpTreeMPI nesmik::nesmik MPI::MPI_CXX) + target_link_libraries(TestCppTalpTreeMPI nesmik_lib MPI::MPI_CXX) target_include_directories(TestCppTalpTreeMPI PRIVATE ${NESMIK_PUBLIC_HEADERS}) @@ -46,7 +55,7 @@ if(WITH_MPI AND WITH_MPI_TESTS) COMMAND TestCppTalpTree) add_executable(TestCppTalpTreeMPI_MPMD cpp/TestCppTalpTreeMPI_MPMD.cpp) - target_link_libraries(TestCppTalpTreeMPI_MPMD nesmik::nesmik MPI::MPI_CXX) + target_link_libraries(TestCppTalpTreeMPI_MPMD nesmik_lib MPI::MPI_CXX) target_include_directories(TestCppTalpTreeMPI_MPMD PRIVATE ${NESMIK_PUBLIC_HEADERS}) @@ -59,12 +68,13 @@ endif() if(ENABLE_EXTRAE) add_executable(TestCppExtraeTypeStack cpp/TestCppExtraeTypeStack.cpp) -target_link_libraries(TestCppExtraeTypeStack nesmik::nesmik) +target_link_libraries(TestCppExtraeTypeStack nesmik_lib) target_include_directories(TestCppExtraeTypeStack PRIVATE ${NESMIK_PUBLIC_HEADERS}) add_test(NAME TestCppExtraeTypeStack - COMMAND TestCppExtraeTypeStack) + COMMAND TestCppExtraeTypeStack) + endif() @@ -81,8 +91,6 @@ if(BUILD_C_FORTRAN) COMMAND TestCLink) - - add_executable(TestFortranLink fortran/TestFortranModule.f90) if(SPLIT_FORTRAN_LIBRARY) target_link_libraries(TestFortranLink nesmik nesmik_f) @@ -95,4 +103,79 @@ if(BUILD_C_FORTRAN) add_test(NAME TestFortranLink COMMAND TestFortranLink) + +endif() + +set_property(TEST TestCppLinkDefault PROPERTY ENVIRONMENT "NESMIK_BACKEND=Default") + +set_property(TEST TestCppLinkDetection PROPERTY ENVIRONMENT "NESMIK_BACKEND=Detection") + +set_property(TEST TestRegionStopLast PROPERTY ENVIRONMENT "NESMIK_BACKEND=Detection") + +set_property(TEST TestCppLinkNotNested PROPERTY ENVIRONMENT "NESMIK_BACKEND=Detection") + +if(ENABLE_EXTRAE) + set_property(TEST TestCppExtraeTypeStack PROPERTY ENVIRONMENT "NESMIK_BACKEND=Extrae::TypeStack;EXTRAE_ON=1;LD_PRELOAD=${EXTRAE_DIR}/lib/libseqtrace.so") +endif() + +if(ENABLE_DLB) +set_property(TEST TestCppDLB PROPERTY ENVIRONMENT "NESMIK_BACKEND=TALP;DLB_ARGS=--talp;LD_PRELOAD=${DLB_HOME}/lib/libdlb.so;") +set_property(TEST TestCppTalpTree PROPERTY ENVIRONMENT "NESMIK_BACKEND=TALP::Tree;DLB_ARGS=--talp;LD_PRELOAD=${DLB_HOME}/lib/libdlb.so;") +endif() + +if(ENABLE_DLB AND WITH_MPI AND WITH_MPI_TESTS) + +endif() + +if(BUILD_C_FORTRAN) + set_property(TEST TestCLink PROPERTY ENVIRONMENT "NESMIK_BACKEND=Detection") + set_property(TEST TestFortranLink PROPERTY ENVIRONMENT "NESMIK_BACKEND=Detection") +endif() + +# +# Disable extrae autoinitialize for all the tests to avoid the malloc error +# +if(ENABLE_EXTRAE) + +set(skip_extrae "EXTRAE_SKIP_AUTO_LIBRARY_INITIALIZE=1") + +get_property(env TEST TestCppLinkDefault PROPERTY ENVIRONMENT) +set_property(TEST TestCppLinkDefault PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestCppLinkDetection PROPERTY ENVIRONMENT) +set_property(TEST TestCppLinkDetection PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestRegionStopLast PROPERTY ENVIRONMENT) +set_property(TEST TestRegionStopLast PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestCppExtraeTypeStack PROPERTY ENVIRONMENT) +set_property(TEST TestCppExtraeTypeStack PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestCppLinkNotNested PROPERTY ENVIRONMENT) +set_property(TEST TestCppLinkNotNested PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +if(ENABLE_DLB) +get_property(env TEST TestCppDLB PROPERTY ENVIRONMENT) +set_property(TEST TestCppDLB PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestCppTalpTree PROPERTY ENVIRONMENT) +set_property(TEST TestCppTalpTree PROPERTY ENVIRONMENT "${env};${skip_extrae}") +endif() + +if(ENABLE_DLB AND WITH_MPI AND WITH_MPI_TESTS) +get_property(env TEST TestCppTalpTreeMPI PROPERTY ENVIRONMENT) +set_property(TEST TestCppTalpTreeMPI PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestCppTalpTreeMPI_MPMD PROPERTY ENVIRONMENT) +set_property(TEST TestCppTalpTreeMPI_MPMD PROPERTY ENVIRONMENT "${env};${skip_extrae}") +endif() + +if(BUILD_C_FORTRAN) +get_property(env TEST TestCLink PROPERTY ENVIRONMENT) +set_property(TEST TestCLink PROPERTY ENVIRONMENT "${env};${skip_extrae}") + +get_property(env TEST TestFortranLink PROPERTY ENVIRONMENT) +set_property(TEST TestFortranLink PROPERTY ENVIRONMENT "${env};${skip_extrae}") +endif() + endif()